任意文件讀取與下載漏洞
環境:windows-s-2008、phpstudy2016、攻擊機
成因:
web開放了文件讀取及下載的功能(存在讀取文件/下載的函數),並且用戶端可控制路徑,對於用戶端輸入的路徑沒有做到完全的過濾。
危害:
1、查看敏感文件;
2、下載源代碼做代碼審計,查找更多的漏洞;
3、與其他漏洞結合;
1、文件讀取的PHP函數
readfile()
file_get_contents()
fopen()
特殊的是fopen()
$fileName = "name.php";
$f = fopen($fileName,'r');#r是讀,w是寫
echo fread($f,filesize($fileName));
fclose($f); #需要關閉
介紹完特殊的函數我們就開始測試
建立一個fileRead.php文件
然后再建立一個test.txt文件,內容隨便
readfile()
<?php
$fileName = $_GET['path'];
readfile($fileName);
?>
亂碼是因為瀏覽器編碼的原因。
讀取成功!
file_get_contents()
<?php
$fileName = $_GET['path'];
echo file_get_contents($fileName);
?>
打開,讀取,關閉!
2、文件讀取的攻防
既然讀取文件的函數都展現了一遍,按照最特殊的fopen進行攻防講解
原因既然講到是對客戶輸入的路徑沒有進行過濾,那其實就是對get獲取的值進行過濾
思路:讀取文件需要什么條件
定位文件位置,用什么定位,就是路徑path,路徑分為相對路徑和絕對路徑。
由相對路徑來說,就是由本目錄為起點,../filename
像本文一樣的放在同一目錄下只用文件名test.txt就好可是放在別的目錄下就會用到../
所以我們過濾掉../不就可以?
先模擬一下真實環境,因為正常情況下,肯定是點擊鏈接去訪問某個指定的文件,那我們就在文件頂部加一個<a>
標簽
<a href = "./fileRead.php?path=test.txt ">111</a>
那點擊就會
../過濾
之后那我們把新建test1.txt(內容為123)文件放到上一級目錄下的test文件夾里,所以訪問目錄就變成了../test/tes1t.txt
后修改代碼過濾用str_replace(),將../過濾成空,將
<a href = "./fileRead.php?path=test.txt ">111</a>
<?php
$fileName = $_GET['path'];
$fileName = str_replace("$fileName","../","");
$f = fopen($fileName,"r");
echo fread($f,filesize($fileName));
fclose($f);
?>
因為../test/test1.txt,經過過濾為了test/test1.txt,所謂訪問不到文件,報錯。
由上面的代碼可以知道我們只過濾了一遍../,所以雙寫../就可以繞過,..././
所以可以訪問!
看下面
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\"" ), "", $file );
所以大家想過濾什么就可以將其添加到數組之中,這是黑名單過濾。
白名單過濾
既然這樣可以繞過那我們換一種思路,因為都是訪問的都是固定的,那我們就檢測訪問該文件的文件名是否為我們想讓他看的文件。
因為無論是相對路徑還是絕對路徑,開頭必定是../或者C:\,所以我們是不是檢測開頭是不是我們的文件名就好
<a href = "./fileRead.php?path=test.txt ">111</a>
<?php
$fileName = $_GET['path'];
if($fileName != "test.txt")
{
echo "not found!";
exit;
}
$f = fopen($fileName,"r");
echo fread($f,filesize($fileName));
fclose($f);
?>
拓展:fnamtch函數是檢測fileName是否是test開頭的字符串,是就返回1,不是0。
這就是白名單過濾,想讓誰允許就在if條件語句中添加,這基本就無法繞過了。
3、漏洞修復
1、只讓web用戶訪問指定的文件(上面介紹的白名單)
2、讓⽤戶不能訪問Web 根⽬錄以外的路徑。(在Apache的httpd.conf中)
只需將 Option 中的 Indexes 去掉即可
3、讓⽤戶不能訪問Web 根⽬錄以外的路徑。
在php.ini中設定。
將分號去掉,並等於你想制定只能瀏覽的目錄即可。