Home | 簡體中文 | 繁體中文 | 雜文 | 知乎專欄 | Github | OSChina 博客 | 雲社區 | 雲棲社區 | Facebook | Linkedin | 視頻教程 | 打賞(Donations) | About
知乎專欄多維度架構 微信號 netkiller-ebook | QQ群:128659835 請註明“讀者”

32.28. 信息安全

SQL注入,OS命令注入,緩衝溢出、跨站腳本、缺少驗證、缺少認證、使用硬編碼證書、敏感數據忘記加密、不受限制上傳檔案類型、依賴不可信的輸入、用不必要的高級權限執行任務、跨站請求偽造....

32.28.1. CSRF(Cross-site request forgery)跨站請求偽造

CSRF(Cross-site request forgery),中文名稱:跨站請求偽造,也被稱為:one click attack/session riding,縮寫為:CSRF/XSRF

32.28.2. Session 撰改演示

這是一個計數器的例子

		
<?php
session_start();

if(isset($_SESSION['count'])){
	$_SESSION['count']++;
}else{
	$_SESSION['count'] = 1;
}
print($_SESSION['count']);
		
		

首先在IE瀏覽器上訪問該檔案,查看目前計數器數值。

現在開始演示如果更改用戶的Session數據

通過Firebug等工具,查看PHPSESSID的值,例如我的是 75ff0dd6a0824a2b607777b58c27f78a

cat /tmp/sess_75ff0dd6a0824a2b607777b58c27f78a
count|i:100;
		

將 count|i:100; 改為 count|i:1000; 再次去瀏覽器刷新看看現在計數器的數值是多少。

通過這種方法可以實現,提升權限,繞過登錄等等。

由於session 存儲在 tmp 目錄下,一旦網站被注入就來帶安全隱患

32.28.3. 用戶註冊與登錄安全

用戶註冊與登錄除了使用圖片驗證外,還應該記錄來源IP,同時限制用戶使用自動註冊工具

32.28.4. 目錄檔案與權限

32.28.4.1. 讀寫權限

Apache進程所有者: nobody

程序所有者: www

apache 可以讀取程序並運行,但apache 無法改寫代碼,/tmp等特殊目錄可以寫入操作

重置權限命令

chown www:www -R /www
chown nobody:nobody -R /www/www.example.com/tmp

find /www/ -type d -exec chmod 755 {} \;
find /www/ -type f -exec chmod 644 {} \;
chmod 744 -R /www/www.example.com/tmp
				

32.28.4.2. 訪問權限

屏蔽訪問權限

				
<Directory>
<DirectoryMatch>
<Files>
<FilesMatch>
<Location>
<LocationMatch>
			
			

並不是所有目錄和檔案都需要提供給用戶的,例如早期PHP項目中沒有使用框架,常常有include, config等等目錄需要屏蔽

例 32.3. Example for ECSHOP

				
<VirtualHost *:80>
    ServerAdmin webmaster@example.com
    DocumentRoot /www/www.example.com/
    ServerName www.example.com
    ServerAlias example.com
    DirectoryIndex index.html index.php
    CustomLog "|/srv/httpd/bin/rotatelogs /www/logs/www.example.com/access.%Y-%m-%d.log 86400 480" combined

    <Location /data/>
	    Order allow,deny
	    Deny from all
    </Location>
    <Location /images/upload/>
            Order allow,deny
            Deny from all
    </Location>
    <Location /temp/>
            Order allow,deny
            Deny from all
    </Location>
    <Location /includes/>
            Order allow,deny
            Deny from all
    </Location>
    <Location /library/>
            Order allow,deny
            Deny from all
    </Location>
    <Location /plugin/>
            Order allow,deny
            Deny from all
    </Location>

    <Directory /www/www.example.com/images/>
        <Files *.php>
            Order allow,deny
            Deny from all
        </Files>
    </Directory>
    <Directory /www/www.example.com/js/>
        <Files *.php>
            Order allow,deny
            Deny from all
        </Files>
    </Directory>

    <Directory /www/www.example.com/themes/>
        <Files *.php>
	    Order allow,deny
	    Deny from all
        </Files>
    </Directory>

</VirtualHost>
               
				

32.28.5. 密碼安全

雖然md5摘要算法作為密碼仍不能保證安全。我一般採用加入干擾詞的方法避免被猜中

password = md5/sha1(password + salt)

32.28.6. 注入檢查

我們需要在框架的URL(PATHINFO)對象中加入檢查功能

/news/%d.html		只能匹配數字ID /news/123.html 合法,如果/news/abc.html 非法
/login/%s.html 		只能匹配字元串	/login/neo.html
/product/[0-9/a-z].html		可以配置數字已經字元
		

post 數據還有上傳檔案也做同樣檢查

這裡僅僅給你一個思路,實現起來也並不難

32.28.7. 防止惡意刷新與重複提交

在開發中會經常會遇到這樣的需求,例如投票模組,要防止惡意刷票,下面來介紹幾種解決方按:

1、來源IP / MAC地址限制
      這個是使用最多也是最廣泛的方式,通過獲取訪問用戶的來源IP地址,來限制在一段時間內所能使用的票數。
經常用電腦的老手是很容易繞出這種限制的。PPP/PPPoE撥號用戶,可以通過斷線重撥來更換IP地址;
 		每個網絡位置會有一個全球唯一的MAC位址。所以我們也可以根據MAC地址限制用戶訪問

2、Cookies / Session驗證
      這種方式用的也比較多,清除瀏覽器Cookies,就可以很容易的繞過這種限制了
	  關閉瀏覽器,Session就會被銷毀;客戶端禁用Cookie,Session也會失效;

4、驗證碼,包括圖像,語音,電話,郵件以及回答問題
	首先說圖片驗證碼,有些變態的網站,大家可以看到用戶的註冊、登錄、回覆、發帖等等,都會使用驗證碼,但是這種方式會讓用戶有時感覺很噁心,隨着OCR(Optical Character Recognition,光學字元識別)技術的成熟,圖片驗證碼已經不再安全,識別率可能達到90%以上甚至100%
	語音有播放方式和電話方式,聽喇叭中讀取字元,然後輸入驗證碼。不要以為這是最安全的,語音是一種波形,通過DSP(Digital Signal Processing,數字信號處理)技術很容易識別
	手機短信與電子郵件,不多說了

	回答問題
	如果沒有足夠海量的題庫,很快問題的內容和答案就會被收集。反而讓正常投票的用戶,覺得投票很噁心、麻煩,產生厭噁心理。漸漸的也被我們拋棄了。


5、註冊用戶可能投票模組
	遊客不能參與,必須註冊了賬戶才能進行投票,並且限制新註冊用戶,在一段時間內不能參與投票。

6、隨機投票地址
	讓每一個訪問頁面的用戶得到一個隨機唯一的KEY可能通過UUID/GUID生成,通過這個KEY,生成一個投票地址,該地址只能訪問一次,使用過後便作廢。

總結:很快就會有新的應對方式。我們只能通過上面幾種方案的組合方式,增加用戶刷新難度,讓用戶在無法在短期內實現應對方案,你沒想出一種新方式。

		

32.28.8. 屏蔽出錯信息

32.28.8.1. 屏蔽php出錯信息

			
; Error handling and logging ;
; 出錯控制和登記 ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; 錯誤報告是按位的。或者將數字加起來得到想要的錯誤報告等級。
; E_ALL - 所有的錯誤和警告
; E_ERROR - 致命性運行時錯
; E_WARNING - 運行時警告(非致命性錯)
; E_PARSE - 編譯時解析錯誤
; E_NOTICE - 運行時提醒(這些經常是是你的代碼的bug引起的,
;也可能是有意的行為造成的。(如:基于未初始化的變數自動初始化為一個
;空字元串的事實而使用一個未初始化的變數)

; E_CORE_ERROR - 發生於PHP啟動時初始化過程中的致命錯誤
; E_CORE_WARNING - 發生於PHP啟動時初始化過程中的警告(非致命性錯)
; E_COMPILE_ERROR - 編譯時致命性錯
; E_COMPILE_WARNING - 編譯時警告(非致命性錯)
; E_USER_ERROR - 用戶產生的出錯消息
; E_USER_WARNING - 用戶產生的警告消息
; E_USER_NOTICE - 用戶產生的提醒消息
; 例子:
; error_reporting = E_ALL & ~E_NOTICE ; 顯示所有的錯誤,除了提醒
; error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR ; 僅顯示錯誤
error_reporting = E_ALL & ~E_NOTICE ; 顯示所有的錯誤,除了提醒
display_errors = On ; 顯示出錯誤信息(作為輸出的一部分)
; 在最終發佈的web站點上,強烈建議你關掉這個特性,並使用
; 錯誤日誌代替(參看下面)。
; 在最終發佈的web站點繼續讓 display_errors 有效可能
; 暴露一些有關安全的信息,例如你的web服務上的檔案路徑、
; 你的資料庫規劃或別的信息。
display_startup_errors = Off ; 甚至當display_erroes打開了,發生於PHP的啟動的步驟中
; 的錯誤也不會被顯示。
; 強烈建議保持使 display_startup_errors 關閉,
; 除了在改錯過程中。
log_errors = Off ; 在日誌檔案裡記錄錯誤(伺服器指定的日誌,stderr標准錯誤輸出,或error_log(下面的))
; 正如上面說明的那樣,強烈建議你在最終發佈的web站點以日誌記錄錯誤
; 取代直接錯誤輸出。

track_errors = Off ; 保存最近一個 錯誤/警告 消息于變數 $php_errormsg (boolean)
;error_prepend_string = "<font color=ff0000>;" ; 于錯誤信息前輸出的字元串
;error_append_string = "</font>;" ; 于錯誤信息後輸出的字元串
;error_log = filename ; 記錄錯誤日誌于指定檔案
;error_log = syslog ; 記錄錯誤日誌于系統日誌 syslog (NT 下的事件日誌, Windows 95下無效)
warn_plus_overloading = Off ; 當將‘+’用於字元串時警告

這項去掉
; E_WARNING - 運行時警告(非致命性錯)