PHP安全-文件系統(tǒng)跨越
無論你用什么方法使用文件,你都要在某個地方指定文件名。在很多情況下,文件名會作為fopen()函數(shù)的一個參數(shù),同時其它函數(shù)會調(diào)用它返回的句柄:
<?php
$handle = fopen(’/path/to/myfile.txt’, ’r’);
?>
當你把被污染數(shù)據(jù)作為文件名的一部分時,漏洞就產(chǎn)生了:
<?php
$handle = fopen('/path/to/{$_GET[’filename’]}.txt', ’r’);
?>
由于在本例中路徑和文件名的前后兩部分無法由攻擊者所操縱,攻擊的可能性受到了限制。可是,需要緊記的是有些攻擊會使用NULL(在URL中表示為%00)來使字符串終止,這樣就能繞過任何文件擴展名的限制。在這種情況下,最危險的攻擊手段是通過使用多個../來方問上級目錄,以達到文件系統(tǒng)跨越的目的。例如,想像一下filename的值被指定如下:
http://example.org/file.php?file ... nother/path/to/file
與許多攻擊的情況相同,在構(gòu)造一個字串時如果使用了被污染數(shù)據(jù),就會給攻擊者以機會來更改這個字串,這樣就會造成你的應(yīng)用以你不希望方式運行。如果你養(yǎng)成了只使用已過濾數(shù)據(jù)來建立動態(tài)字串的習慣,就可以防止很多類型包括很多你所不熟悉的漏洞的出現(xiàn)。
由于fopen()所調(diào)用的文件名前導的靜態(tài)部分是/path/to,所以上面的攻擊中向上跨越目錄的次數(shù)比所需的更多。因為攻擊者在發(fā)起攻擊前無法察看源碼,所以典型的策略是過多次地重復../字串。../字串使用太多次并不會破壞上面的攻擊效果,所以攻擊者沒有必要猜測目錄的深度。
在上面的攻擊中使fopen()調(diào)用以你不希望方式運行,它簡化后等價于:
<?php
$handle = fopen(’/another/path/to/file.txt’, ’r’);
?>
在意識到這個問題或遭遇攻擊后,很多開發(fā)者都會犯試圖糾正潛在的惡意數(shù)據(jù)的錯誤,有時根本不會先對數(shù)據(jù)進行檢查。正如第一章所述,最好的方法把過濾看成檢查過程,同時迫使使用者遵從你制定的規(guī)則。例如,如果合法的文件名只包含字母,下面的代碼能加強這個限制:
<?php
$clean = array();
if (ctype_alpha($_GET[’filename’]))
{
$clean[’filename’] = $_GET[’filename’];
}
else
{
/* ... */
}
$handle = fopen('/path/to/{$clean[’filename’]}.txt', ’r’);
?>
并沒有必要對filename值進行轉(zhuǎn)義,這是因為這些數(shù)據(jù)中只用在PHP函數(shù)中而不會傳送到遠程系統(tǒng)。
basename( )函數(shù)在檢查是否有不必要的路徑時非常有用:
<?php
$clean = array();
if (basename($_GET[’filename’]) == $_GET[’filename’])
{
$clean[’filename’] = $_GET[’filename’];
}
else
{
/* ... */
}
$handle = fopen('/path/to/{$clean[’filename’]}.txt', ’r’);
?>
這個流程比只允許文件名是字母的安全性要差了一些,但你不太可能要求那樣嚴格。比較好的深度防范流程是綜合上面的兩種方法,特別是你在用正則表達式檢查代碼合法性時(而不是用函數(shù)ctype_alpha( ))。
當文件名的整個尾部是由未過濾數(shù)據(jù)組成時,一個高危漏洞就產(chǎn)生了:
<?php
$handle = fopen('/path/to/{$_GET[’filename’]}', ’r’);
?>
給予攻擊者更多的靈活性意味著更多的漏洞。在這個例子中,攻擊者能操縱filename參數(shù)指向文件系統(tǒng)中的任何文件,而不管路徑和文件擴展名是什么,這是因為文件擴展名是$_GET[’filename’]的一部分。一旦WEB服務(wù)器具有能讀取該文件的權(quán)限,處理就會轉(zhuǎn)向這個攻擊者所指定的文件。
如果路徑的前導部分使用了被污染數(shù)據(jù)的話,這一類的漏洞會變得甚至更加龐大。這也是下一節(jié)的主題。
相關(guān)文章:
1. ASP常用日期格式化函數(shù) FormatDate()2. Python 操作 MySQL數(shù)據(jù)庫3. Python數(shù)據(jù)相關(guān)系數(shù)矩陣和熱力圖輕松實現(xiàn)教程4. 開發(fā)效率翻倍的Web API使用技巧5. bootstrap select2 動態(tài)從后臺Ajax動態(tài)獲取數(shù)據(jù)的代碼6. CSS3中Transition屬性詳解以及示例分享7. js select支持手動輸入功能實現(xiàn)代碼8. 什么是Python變量作用域9. vue使用moment如何將時間戳轉(zhuǎn)為標準日期時間格式10. python 如何在 Matplotlib 中繪制垂直線
