核心是精准识别已抵达Web服务的高置信度恶意模式,而非简单删除单引号;必须启用SecRuleEngine On、SecRequestBodyAccess On、SecResponseBodyAccess On及CRS规则,并结合归一化与上下文变量编写针对性规则拦截。

直接在 Apache 层过滤 SQL 注入字符,核心不是“删掉所有单引号”,而是精准识别并拦截已出现在请求中的高置信度恶意模式——这些模式代表攻击已抵达 Web 服务,哪怕还没触发数据库报错。
关键思路:从日志里先看见,再用 mod_security 拦住
Apache 自身不带内容检测能力,必须依赖 mod_security 模块。但很多配置失败,是因为只开了模块、没开请求体解析,或规则写得太宽泛导致误杀。
必须启用的基础配置
确保以下几项在 /etc/modsecurity/modsecurity.conf 或虚拟主机配置中显式存在且生效:
-
SecRuleEngine On(不是 DetectionOnly) -
SecRequestBodyAccess On(否则 POST 提交的password=1%27%20OR%201%3D1--根本进不到规则里) -
SecResponseBodyAccess On+SecResponseBodyMimeType text/html(防止错误页面泄露数据库结构) -
Include /usr/share/modsecurity-crs/rules/*.conf(CRS 规则路径需确认存在,且crs-setup.conf在最前加载)
针对性拦截高危字符组合
别用简单黑名单(如 SecFilter "'|;"),它既易绕过又易误杀。推荐用 CRS v3.3+ 的归一化规则,配合以下自定义轻量规则补强:
-
拦截 GET 请求中同时含单引号和注释符号的路径:
SecRule REQUEST_METHOD "@streq GET" "phase:2,deny,status:403,msg:'SQLi: quote + comment',chain" SecRule REQUEST_URI "@contains '" "t:none" SecRule REQUEST_URI "@contains --" "t:none"
-
拦截 POST body 中的 UNION SELECT 变形(大小写、空格、URL 编码):
Apache Superset Dashboard and SQL Exploration Skill下载Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
SecRule REQUEST_BODY "@rx (?i)(union\s+select|sel%65ct.*from)" "phase:2,deny,status:403,msg:'SQLi: UNION SELECT in body'"
-
对搜索类接口(如
/search?q=)单独加严,但允许中文和常规标点:SecRule REQUEST_URI "@beginsWith /search" "id:1001,phase:2,pass,nolog,ctl:ruleRemoveById=942100" SecRule ARGS:q "@rx ([';]|UNION[[:space:]]+SELECT|--|#|SLEEP\()" "phase:2,deny,status:403,msg:'SQLi in search param'"
日志里快速发现可疑请求(应急时最管用)
不用等 SIEM,直接在服务器上跑这条命令筛出已落地的试探行为:
awk '$0 ~ /\x27|UNION[[:space:]]+SELECT|AND[[:space:]]+[0-9]+=[0-9]+|--|#|SLEEP\(|WAITFOR[[:space:]]+DELAY/ {print $0}' /var/log/apache2/access.log | grep -i -E "(select|union|sleep|waitfor)"它能抓到:
-
/product?id=1' OR '1'='1(基础闭合试探) -
/api/user?uid=1 AND 1=2(布尔盲注起点) -
/search?q=test%27%20UNION%20SELECT%201,2,3--(URL 编码的联合查询)
这些不是误报,是攻击者主动投递的载荷,只要出现在 %r 字段里,就该立即响应。
不建议做的三件事
- 别全局禁用单引号或分号:正常业务参数(如
remark=张三's order)会崩 - 别只靠
grep -E "UNION.*SELECT"查日志:攻击者插个/*a*/就绕过 - 别跳过
SecUnicodeMapFile配置:否则%u0073%u0065%u006C%u0065%u0063%u0074这类 Unicode 编码完全漏检
真正有效的过滤,是让规则理解“什么上下文里出现什么字符才危险”,而不是把所有 ' 当敌人。

















