WeChall - Light in the Darkness
Challenge
Light in the Darkness (MySQL, Exploit) — score 6, by Mawekl.
This challenge is the sequel to the "Blinded by the lighter" challenge. Again your mission is to extract an md5 password hash out of the database. This time your limit for this sql injection are 2 queries. Also you have to accomplish this task 3 times consecutively, to prove you have solved the challenge. Again you are given the sourcecode of the vulnerable script, also as highlighted version. To restart the challenge, you can execute a reset. Thanks to Mawekl for his motivation! Good luck!
前作 "Blinded by the lighter" 的升级版。同样是 SQL 注入提取 MD5 password hash,但限制更严:最多 2 次查询(整个挑战生命周期),且需要 连续 3 轮成功 才算通关。
源码分析
完整源码在 gizmore/gwf3 GitHub 仓库:
www/challenge/Mawekl/light_in_the_darkness/vuln.php— 注入点www/challenge/Mawekl/light_in_the_darkness/index.php— 表单逻辑www/challenge/Mawekl/light_in_the_darkness/install.php— 挑战初始化
vuln.php — 注入点:
1 | function blightVuln($password) |
关键点:
- 注入点在 WHERE 子句,
password列来自子查询别名b - 过滤器:禁止
/*(堵多行注释截断)和blight(堵直接引用表名) setVerbose(true):SQL 错误会完整回显到页面 —— 这是报错注入的前提条件queryFirst()使用mysqli_query()(不支持堆叠查询)- SLEEP/BENCHMARK 未被过滤,但 2 次查询限制让时间/布尔盲注都不可行
index.php — 表单逻辑:
injection+inject→blightVuln($password)thehash+mybutton→blightGetHash()从 DB 读 hash 并比对reset=me→ 显示旧 hash(如果有),然后生成新 hash
限制: 常数 BLIGHT3_ATTEMPS =
2(源码中的拼写,非笔误),最大允许 attempt = 3。每次 inject 或 hash
提交消耗 1 次 attempt。每次成功提交 hash 后 attempt 重置为 0,同时
consecutive 计数器 +1。连续 3 轮成功后 challenge solved。
solution
核心思路:利用 MySQL GROUP BY 对非确定性表达式
FLOOR(RAND(0)*2) 的求值 bug,触发
Duplicate entry 错误,在错误信息中泄露
CONCAT(password, FLOOR(RAND(0)*2)) 的值。
1 | ' or (select count(*) from information_schema.COLLATIONS group by concat(password,floor(rand(0)*2))) -- |
为什么用 RAND(0)(有种子)而不是
RAND():
RAND(0)产生确定序列:0, 1, 1, 0, 1, 0, 0, 1, ...- 第 2 行和第 3 行都得到值 1,导致 GROUP BY 临时表唯一键冲突,触发报错
RAND()(无种子)每次序列随机,不可靠- 注意:序列依赖 MySQL 版本(5.x vs 8.x 可能不同)
为什么用
information_schema.COLLATIONS:
- 比
information_schema.TABLES更轻量,不会锁 MyISAM 表 - 需要至少 3 行的表(RAND(0) 的重复在行 2-3 出现,所以要求表 >= 3 行)
密码提取: Duplicate entry 显示的是
CONCAT(password, FLOOR(RAND(0)*2)),即
password0 或 password1(尾部数字是 RAND
输出)。 密码 = Duplicate entry 值的前 32 字符(MD5 hex 正好 32
位)。
攻击流程
每轮 2 次操作:1 次注入提取(消耗 1 attempt)+ 1 次 hash 提交(消耗 1 attempt),共 3 轮。
reset=me→ 重置挑战,attempt=0,生成新 hash- 注入提取 → attempt=1,错误信息中拿到 password
- 提交 hash → attempt=2,成功 → attempt 归零,新 hash 生成
- 重复步骤 2-3 两次
1 | # Round 1 |