LIMIT子句中的盲 SQL注入漏洞利用
字数 1042 2025-08-26 22:11:57
LIMIT子句中的盲SQL注入漏洞利用技术详解
漏洞概述
本文详细分析了一种特殊的盲SQL注入漏洞,该漏洞存在于SQL查询的LIMIT子句中。攻击者通过控制LIMIT子句的参数值,利用PostgreSQL数据库的特性,实现了数据泄露。
漏洞发现环境
- 目标系统:基于PHP的Web应用
- 数据库:PostgreSQL
- 漏洞位置:相册分页功能
- 触发参数:
num_max - 原始SQL查询:
或等效形式:Select * from tbl_albums where page=2 order by album_date asc LIMIT 0,{{INPUT}}Select * from tbl_albums where page=2 order by album_date asc LIMIT {{INPUT}} OFFSET 0
漏洞确认
-
通过输入特殊字符测试SQL注入:
- 单引号(
') - 双引号(
") - 反斜杠(
\)
- 单引号(
-
观察到PostgreSQL错误信息,确认存在SQL注入漏洞
技术难点
- 当ORDER BY与LIMIT一起使用时,无法使用UNION语句注入
- MySQL中可使用基于错误的注入,但目标为PostgreSQL
- LIMIT和OFFSET要求参数必须是数字
漏洞利用技术
前置条件
- 创建足够多的相册记录(至少127个)
- 使用Burp Intruder批量创建约200个相册
核心原理
利用ASCII函数将字符转换为数字,通过控制返回的记录数量来泄露数据:
- 将想要查询的数据的第一个字符转换为ASCII码
- 使用该ASCII码作为LIMIT参数值
- 返回的记录数等于该字符的ASCII码值
- 通过计算返回的记录数反推出原始字符
具体步骤
-
提取数据库版本第一个字符的PoC:
Select * from tbl_albums where page=2 order by album_date asc LIMIT 0,ascii(substr((Select version()),1,1)) -
工作流程:
substr((select version()),1,1)获取版本字符串的第一个字符ascii()将该字符转换为ASCII码- 查询返回的记录数等于该ASCII码值
-
示例:
- 如果版本是"PostgreSQL 9.6.2"
- 第一个字符'P'的ASCII码是80
- 查询将返回80条记录
自动化提取
-
使用JavaScript计算返回的相册数量:
document.querySelectorAll('.ALBUM_CLASS').length -
将数量转换回字符:
String.fromCharCode(80) // 返回'P' -
重复此过程提取后续字符
防御措施
- 参数化查询:使用预处理语句而非直接拼接SQL
- 输入验证:确保LIMIT参数为有效数字
- 范围限制:限制LIMIT参数的最大值
- 错误处理:避免显示详细的数据库错误信息
- 权限最小化:数据库用户只应具有必要权限
总结
这种技术展示了即使在看似受限的SQL注入场景(LIMIT子句)中,通过创造性思维仍可能实现数据泄露。关键在于:
- 理解数据库函数的行为(如ASCII())
- 利用返回记录数与数据值的关联
- 准备足够多的测试数据
- 自动化提取和转换过程
该技术不仅适用于PostgreSQL,经过适当调整也可应用于其他数据库系统。