$mod 通過構造輸?mod=…%2F…%2F…%2F…%2Fetc%2Fpasswd%00 ,我們看結果將是:
居然include(“/etc/passwd”)文件了。
怎麼逃脫了我參數限制呢?
首先:做參數過濾類型去限制用戶輸入本來就不是一個好方法,一般規則是:能夠做檢測的,不要做替換 只要是檢測不通過的,直接pass 掉!這是我們的一個原則。過濾失敗情況,舉不勝舉,我們來看看,實際過程。
1、輸入”…/…/…/” 通過把”..” 替換為”.”後
2、結果是”../../../” 就變成了這個了
有朋友就會說,如果我直接替換為空格是不是就好了?在這個裡面確實可以替換掉。但是不代表以後你都替換為空格就好了。再舉例子下。如:有人將字符串裡面javascript替換掉。代碼如下:
復制代碼 代碼如下:
……
$msg = str_replace(“javascript”,””,$msg);
看似不會出現了javascript了,但是,如果輸入:jjavascriptavascript 替換,會替換掉中間一個變為空後。前面的”j” 跟後面的會組成一個新的javascript了。
其次:我們看看,怎麼逃脫了,後面的.php 限制呢。用戶輸入的參數有:”etc/passwd\0” ,\0字符非常特殊,一段連接後,文件名稱變成了”……etc/passwd\0.php”,你打印出該變量時候,還是正確的。但是,一段放入到文件讀寫操作方法裡面,\0後面會自動截斷。操作系統,只會讀取……etc/passwd文件了。 “\0”會出現在所有文件系統讀寫文件變量中。都會同樣處理。這根c語言\0作為字符串完整標記有關系。
通過上面分析,大家發現做文件類型操作時候,一不注意將產生大的漏洞。而且該漏洞就可能引發一系列安全問題。
該怎麼做文件類操作呢?
到這裡,估計有人就會思考這個,做文件讀寫操作時候,如果路徑裡面有變量時候,我該怎麼樣做呢?有人會說,替換可以嗎? “可以”,但是這個方法替換不嚴格,將會出現很多問題。而且,對於初寫朋友,也很難杜絕。 做正確的事情,選擇了正確的方法,會從本身杜絕問題出現可能了。 這裡,我建議:對於變量做白名單限制。
1.什麼是白名單限制
復制代碼 代碼如下:
舉例來說:
$mod = isset($_GET['m'])?trim($_GET['m']):'index'; ///讀取模塊名稱後
mod變量值范圍如果是枚舉類型那麼:
if(!in_array($mod,array(‘user','index','add','edit'))) exit(‘err!!!');
完全限定了$mod,只能在這個數組中,夠狠!!!!
2.怎麼做白名單限制
通過剛才例子,我們知道如果是枚舉類型,直接將值放到list中即可,但是,有些時候,這樣不夠方面。我們還有另外一個白名單限制方法。就是限制字符范圍
復制代碼 代碼如下:
舉例來說:
$mod = isset($_GET['m'])?trim($_GET['m']):'index'; ///讀取模塊名稱後
我限制知道$mod是個目錄名稱,對於一般站點來說,就是字母加數字下劃線之類。
if(!preg_match(“/^\w+$/”,$mod)) exit(‘err!!!');
字符只能是:[A-Za-z0-9_] 這些了。夠狠!!!
總結:是不是發現,白名單限制方法,做起來其實很簡單,你知道那個地方要什麼,就對輸入檢測必須是那些。而且,檢測自己已知的,比替換那些未知的字符,是不是簡單多了。 好了,先到這裡,正確的解決問題方法,會讓文件簡單,而且更安全!!