百分号后面是一个字节
%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 排查方法
- 保留浏览器发送前的原始字符串。
- 在代理中查看线上的原始请求行。
- 单独解码目标参数,不改变其他 URL 组件。
- 比较一次和两次解码结果。
- 观察服务器返回的路径、错误信息或反射内容。
- 记录每个组件可能执行解码的位置。
常见错误
- 把
decodeURI和decodeURIComponent当成完全相同。 - 忽略非法百分号序列会让不同语言或框架产生不同结果。
- 对已经解码的值再次解码,导致路径或过滤逻辑改变。
- 认为 URL 编码可以防止 XSS、SQL 注入或路径遍历;安全性取决于最终语境的验证和转义。