URL中字符与百分编码版本等价场景及URL归一化方案咨询
URL归一化百分编码处理规则及安全边界
已验证结论的补充确认
你之前得出的7条结论完全符合主流实现和WHATWG现行规范,无需调整。
核心问题解答
1. Path段非保留字符的编码处理
path段除%、/、?、#之外的非保留字符(大小写字母、数字、-、.、_、~),其编码形式与解码形式语义完全等价。你观察到的日志记录、字符串比对结果不一致,只是上层应用未做归一化直接比对原始字符串的实现差异,不是实际处理逻辑的差异。
作为sanitiser的归一化操作,你可以安全解码这类字符的百分编码,既不会改变URL的实际请求目标,还能消除恶意攻击者利用编码绕过黑名单的可能。
2. 查询字符串的解码规则
查询字符串的处理需要分场景:
- 如果确定使用
application/x-www-form-urlencoded格式(99%的业务场景都属于此类),仅保留&、=、+、%四个字符的编码不做解码,其余非保留字符的编码均可安全解码。注意不要将+直接转换为空格,也不要解码%26、%3D、%2B,否则会破坏键值对结构。 - 如果无法确定查询串格式,仅解码非保留字符的编码即可,其余所有特殊字符的编码全部保留。
3. 片段部分的解码规则
片段仅在浏览器端生效,不会发送到服务端,也不会影响URL的路由逻辑。除#、%的编码(%23、%25)不能解码之外,其余所有字符的编码均可安全解码,不会改变URL的实际语义。
不破坏业务的归一化操作边界
你可以按照以下优先级做归一化,兼容性覆盖绝大多数业务场景:
- 域名部分:所有百分编码全部解码,再转成统一的punycode格式即可,域名本身不允许出现
%、/等特殊字符,解码不存在语义变更风险。 - Path部分:
- 永远不解码
%2F、%3F、%23、%25 - 解码所有非保留字符的百分编码
- 按规范处理
.、..相对路径
- 永远不解码
- 查询串部分:
- 永远不解码
%26、%3D、%2B、%25 - 解码所有非保留字符的百分编码
- 不做
+到空格的转换
- 永远不解码
- 片段部分:
- 永远不解码
%23、%25 - 其余所有字符的编码均可解码
- 永远不解码
高风险可拒绝的转义场景
以下转义场景几乎不存在合法业务使用的可能,大概率为恶意请求,你可以增加选项直接拦截:
- Path段出现
%2F(编码的路径分隔符):通常用于路径遍历绕过检测 - Path段出现
%2E(编码的.),尤其是连续两个%2E%2E:通常用于规避路径遍历黑名单 - 查询串出现
%26、%3D:通常用于参数注入、绕过参数值黑名单 - 域名部分出现任何百分编码:通常用于伪装域名误导用户、绕过域名黑名单
- 任意位置出现无效百分编码(如
%后不足两位十六进制字符、解码后不符合UTF-8编码规则):无合法使用场景
内容的提问来源于stack exchange,提问作者ais523
相关产品推荐
相关产品推荐

