hexforge / guides / url-encoding

GUIDE 06 / WEB

URL 编码实战

百分号编码处理的是字节表示,不是安全过滤。分析 Web 题时,关键是弄清每一层组件在什么时候解码、解码几次。

百分号后面是一个字节

%2F 表示十六进制字节 2F,对应 ASCII 斜杠。非 ASCII 字符通常先编码为 UTF-8 多字节,再逐字节写成百分号形式。例如中文字符会对应多个 %xx 片段。

原字符常见编码含义
空格%20通用百分号编码
空格+表单查询编码中常见
/%2F路径分隔符
?%3F查询起始符
=%3D参数名值分隔
%%25再次编码的关键线索

路径、查询和表单不是同一语境

在 URL 查询参数中,某些解析器把 + 当空格;在路径中它可能只是加号。把整条 URL 一次性解码会破坏边界,因此应分别保存 scheme、host、path、query 和 fragment。

/download?name=report%2F2026.txt
path:  /download
name:  report/2026.txt

如果服务端先解码参数,再把结果拼进文件路径,编码后的斜杠可能影响路径结构。这是理解题目数据流的信号,不代表可以在未授权系统中测试。

识别双重编码

%252F 第一次解码得到 %2F,第二次才得到 /。看到大量 %25 时,应怀疑当前字符串包裹了另一层百分号编码。

解码次数必须来自证据

代理、框架、路由器和业务代码可能各解码一次。CTF 中要结合请求与响应确定实际层数,而不是默认“解到没有百分号为止”。

CTF 排查方法

  1. 保留浏览器发送前的原始字符串。
  2. 在代理中查看线上的原始请求行。
  3. 单独解码目标参数,不改变其他 URL 组件。
  4. 比较一次和两次解码结果。
  5. 观察服务器返回的路径、错误信息或反射内容。
  6. 记录每个组件可能执行解码的位置。

常见错误

  • decodeURIdecodeURIComponent 当成完全相同。
  • 忽略非法百分号序列会让不同语言或框架产生不同结果。
  • 对已经解码的值再次解码,导致路径或过滤逻辑改变。
  • 认为 URL 编码可以防止 XSS、SQL 注入或路径遍历;安全性取决于最终语境的验证和转义。