本文目录导读:

研判SQL注入日志的核心是区分正常访问与恶意攻击行为,攻击者通常会利用Web应用未对用户输入进行充分过滤的漏洞,将恶意的SQL代码拼接到原有查询中。
以下是研判SQL注入日志的系统性方法,分为关键特征识别、工具辅助分析和误报排除三个维度。
关键特征识别(从日志中寻找“异常”)
当你查看访问日志或数据库审计日志时,重点寻找以下模式:
特殊的HTTP请求方法
- GET请求中的异常参数:
?id=1'、?id=1 AND 1=1、?id=1 UNION SELECT...。 - POST请求体中的SQL关键字:如
username=admin'--、password=123' OR '1'='1。 - User-Agent或Referer头携带SQL:某些工具会将Payload藏在头部,例如
User-Agent: Mozilla/5.0' OR '1'='1。
高频关键字与符号(核心特征)
日志中出现以下字符或关键词,几乎可以判定为SQL注入尝试(尤其是连续出现时):
- SQL注释符:、、、。
- 恒真/假条件:
1=1、1=2、'a'='a'、1=1--。 - UNION与联合查询:
UNION SELECT、UNION ALL SELECT、NULL(用于判断字段数)。 - 特殊函数:
@@version(数据库版本)、user()(当前用户)、database()、load_file()。 - 时间延迟函数:
SLEEP(5)、WAITFOR DELAY '0:0:5'、BENCHMARK()。 - 报错注入语法:
extractvalue()、updatexml()、EXP(~)、1' AND (SELECT 1 FROM (SELECT COUNT(*),...) ...)。 - 文件操作:
INTO OUTFILE、INTO DUMPFILE、LOAD_FILE。 - 十六进制编码:
0x...(如0x61646D696E代表admin)。
异常的状态码与响应长度
- 状态码 200 + 大篇幅异常内容:攻击成功,可能返回了数据库表结构、账号密码等敏感信息。
- 状态码 500/404 + 特定Payload:盲注尝试(如时间注入、布尔注入),服务器虽报错但攻击者在统计一页内容是否返回。
- 响应长度突变:对于同一个URL(如
?id=1),正常返回200字节,当参数变为?id=1'时返回500字或包含大量异常字符,高度可疑。
扫描器特征(自动化工具)
- 高频、连续、非人为的请求:同一IP在几秒内发送数十个不同参数值的请求(如
?id=1,?id=2,?id=3,或者?id=1',?id=1",?id=1 AND 1=1)。 - 特定工具User-Agent:
sqlmap、sqlmap/1.6、OWASP ZAP、Burp Suite、Nikto、Acunetix。 - 非标准HTTP版本:
HTTP/1.0或HTTP/1.1混杂。 - 参数名异常:某些扫描器会携带自定义参数如
?q=1、?s=1(其实是在探测通用的注入点)。
逻辑研判步骤(如何判断“是否是攻击”)
不要只看单个请求,要结合上下文分析。
行为模式分析
- 常规访问链:正常用户:
/index.html -> /product/1 -> /cart。 - SQL注入链:攻击者:
/product?id=1->/product?id=1'(报错,确认注入) ->/product?id=1' UNION SELECT ...--(提取数据) ->/product?id=1' INTO OUTFILE ...(写shell)。 - 如果日志中出现连续的、递增的试探性请求(如上例),基本可判定为恶意。
请求来源分析
- IP地址:是否来自已知的恶意IP库、Tor出口节点、国外IP(针对国内站)、数据中心IP(非家庭宽带)。
- 地理位置:与业务目标用户群体不符(如一个地方性政务网站被来自俄罗斯或美国的IP访问)。
- 请求时间:是否在非正常工作时间(如凌晨3点)发起大量请求。
白名单法
- 正常参数:
?id=123(纯数字)。关键判断:对于参数id,正常值应为数字,出现 、AND、OR等字符,直接判定为恶意。 - 恶意参数:
?id=123' OR '1'='1、?id=123 UNION SELECT...。
误报排除(常见的非攻击情况)
不是所有包含SQL关键字的请求都是攻击,需要排除以下情况:
- 网站自身功能:
- 搜索框:
?q=O'Brien(包含单引号,但这是正常搜索姓氏)。 ?text=SELECT * FROM users(用户评论或文章中包含了SQL语句案例)。
- 搜索框:
- 安全产品误判:CDN、WAF、IPS等设备可能对正常参数(如
?name=tom中的tom包含1=1的变体)产生误报。 - 外部链接爬虫:某些SEO工具在抓取含SQL关键字的URL(如博客文章的示例代码)时,可能触发规则。
- 开发测试流量:开发人员或测试人员的本地调试请求,如
?debug=1、?id=test。
如何排除?
- 检查Referer:是否来自站内页面(如搜索框)。
- 检查URL路径:
/blog/2023/SELECT通常是文章URL,而非注入点。 - 检查:如果返回的是HTML、图片、JSON等正常业务数据,而非SQL语句错误或数据库信息,则可能是误报。
深度研判(实战分析示例)
一个真实的SQL注入日志条目:
2024-05-20 03:15:23 GET /product?id=1' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT @@version),FLOOR(RAND()*2))x FROM information_schema.tables GROUP BY x)a) HTTP/1.1
192.168.1.100 - - [20/May/2024:03:15:23 +0000] "GET /product?id=1' AND (SELECT 1 FROM (SELECT COUNT(*), CONCAT((SELECT @@version),FLOOR(RAND()*2))x FROM information_schema.tables GROUP BY x)a) HTTP/1.1" 200 5432
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
研判过程:
- 攻击特征:包含
AND (SELECT...、@@version(获取版本)、information_schema.tables(查询表)、FLOOR(RAND()*2)(双查询报错注入)。这是典型的报错注入Payload。 - 行为模式:凌晨3点,针对单个参数
id,明显是自动化扫描或手动攻击。 - IP与User-Agent:User-Agent伪装成了Chrome,但行为与正常用户不符(正常用户不会在凌晨3点发起这种长串恶意请求)。
- 状态码与长度:返回200,长度为5432字节(可能包含报错信息或成功返回了版本号)。
- 判定为恶意SQL注入攻击,且攻击者可能已经确认了注入点(因为返回了200)。
研判检查清单
| 项目 | 正常访问 | SQL注入攻击 |
|---|---|---|
| 请求路径 | 符合网站URL规范 | 参数值中出现 、%27、AND、OR、UNION、 等 |
| 参数数量 | 固定(如 ?id=1) |
参数值短、中含空格或特殊符号(URL编码) |
| 请求频率 | 低频、符合用户行为 | 高频、连续、自动化特征明显 |
| 响应数据 | 正常HTML、JSON、图片 | 空白、错误信息、数据库表数据、大段异常字符 |
| User-Agent | 常见浏览器、爬虫 | 可能带有 sqlmap、gobuster、Burp Suite 等 |
| IP归属 | 符合业务用户范围 | 高频访问、异常地理/网络环境 |
| 时间 | 工作日/白天为主 | 凌晨、节假日、非工作时间 |
最终行动建议:一旦确认日志条目为SQL注入攻击,应立即:
- 封锁源IP:在WAF、防火墙或Web服务器上临时或永久封锁该IP。
- 检查受影响范围:查看该IP是否访问过其他URL,以及该注入点是否成功返回了数据(响应长度异常)。
- 审查代码:定位到对应的代码行(如
product?id=),修复参数化查询或过滤。 - 记录并追溯:保留日志作为证据,分析攻击者可能获取了哪些数据。
宁可误报,不可漏报,对于不确定的请求,可以先提升监控级别或手动验证,再决定是否封锁。