关键不是解码后再拦,而是apache在请求解析最前端识别并阻断编码变形攻击载荷;必须整行扫描未解码的%r字段匹配%2e%2e%2f、%c0%ae%c0%ae%2f等变种,mod_security规则须置于全局作用域、启用secunicodemapfile并用t:urldecodeuni归一化,在phase:2精准拦截。

关键不是“解码后再拦”,而是让 Apache 在请求解析最前端就识别并阻断编码变形的攻击载荷——尤其是路径穿越、SQL 注入和 XSS 这三类高频绕过场景。
盯紧原始 URI 字段,别只扫明文
Apache 的 %r 字段默认记录的是未解码的原始请求行,比如:
GET /download?file=%2e%2e%2fetc%2fshadow HTTP/1.1POST /search HTTP/1.1<br>body: q=select%20*%20from%20users
这些 URL 编码字符(%2e%2e%2f、%20)会原样保留在日志里。所以日志监控必须整行扫描 %r,不能只切出路径或参数再 grep —— 攻击常藏在 query string 或 POST body 中。
Apache Superset 是一个广泛采用的开源 BI 平台,用于 SQL 探索、图表构建和仪表板交付。当代理需要查询仓库数据、组装仪表板或使用成熟的分析界面解释指标而不是临时笔记本代码时,此技能非常有用。
用 mod_security 在 phase:2 主动拦截编码变种
仅靠日志告警是事后补救。真正有效的防御要落在请求进入应用前,且规则必须作用于已归一化的 REQUEST_URI 变量:
- 启用
SecUnicodeMapFile并配置 UTF-8 映射,否则%c0%ae%c0%ae%2f类双字节绕过会被放过 - 规则必须放在全局作用域(如
<directory></directory>),不能只写在<locationmatch></locationmatch>里,否则 query 参数不参与匹配 - 推荐写法:
SecRule REQUEST_URI "@rx \.\./|\.\.%2[fF]|%2e%2e%2[fF]|%c0%ae%c0%ae%2[fF]" "id:1001,phase:2,deny,status:403,msg:'Path traversal attempt'"
处理编码斜杠 %2F 要分清 On 和 NoDecode
Apache 默认拒绝含 %2F 的路径(防路径穿越),但某些业务确实需要它。这时不能简单开 AllowEncodedSlashes On,因为会把 %2F 自动解成 /,反而让绕过更隐蔽:
- 选
AllowEncodedSlashes NoDecode:保留原始编码形式,便于 mod_security 规则精准匹配%2f而非误杀合法/ - 配合
t:urlDecodeUni转换函数,在规则中统一解码归一化,避免大小写、多层编码等绕过
别让后端二次解码毁掉防线
很多绕过发生在“Apache 拦了一次,PHP/Java 又解一次”:
- PHP 中手动调用
urldecode()处理已由 Apache 解析过的参数,等于白名单失效 - Java 的
request.getParameter()默认自动解码,若再调一次URLDecoder.decode()就可能触发双重解码绕过 - 防御建议:服务端直接使用原始参数(如 PHP 的
$_SERVER['QUERY_STRING'])、或确保只解码一次,并用realpath()+ 白名单根目录做最终校验









