URL 编码
1. 原理与本质
URL 编码(百分号编码)是统一资源标志符 (URI) 的编码机制。由于 HTTP 协议在传输 URL 时,只能使用安全的 ASCII 字符集,部分具有特殊语法含义的字符(保留字符)或不可见字符,必须进行转义处理,以避免被底层解析器(Lexer/Parser)误识别为控制指令。
-
编码规则: 将字符的 ASCII 码或 UTF-8 字节的十六进制表示,加上前缀
%。例如,空格的 ASCII 码是 32(十六进制20),编码后为%20。 -
非保留字符 (Unreserved):
A-Z,a-z,0-9,-,_,.,~。绝对不需要进行 URL 编码。 -
保留字符 (Reserved):
! * ' ( ) ; : @ & = + $ , / ? % # [ ]。作为数据载荷传输时必须编码。
2. 常用 URL 编码
在 Web 安全方向的实战与靶机环境中,熟练掌握高频特殊字符的十六进制映射,是构造 Payload 的基础。
2.1 注入类与闭合高频字符 ([[SQL注入]], [[命令注入]], [[XSS]])
| 字符 | URL 编码 | 攻击场景与作用说明 |
|---|---|---|
' (单引号) |
%27 |
SQL 注入闭合字符串;命令注入屏蔽解析;XSS 闭合属性。 |
" (双引号) |
%22 |
同上。 |
< |
%3C |
XSS 标签注入;命令注入中的输入重定向。 |
> |
%3E |
XSS 标签闭合;命令注入中的输出重定向(写 WebShell)。 |
# |
%23 |
SQL 注入截断/注释后续查询语句;URL 锚点(防截断)。 |
\ (反斜杠) |
%5C |
路径穿越;转义符注入。 |
2.2 控制流与分隔符 ([[命令执行 RCE]], [[CRLF注入]])
| 字符 | URL 编码 | 攻击场景与作用说明 |
|---|---|---|
\n (换行) |
%0A |
Unix/Linux 换行符,绕过正则;分割多条 Shell 命令。 |
\r (回车) |
%0D |
HTTP 响应拆分攻击 (CRLF Injection %0D%0A)。 |
; (分号) |
%3B |
Shell 顺序执行多条命令;PHP 代码单行语句结束符。 |
\| (管道符) |
%7C |
Shell 命令管道,将前一条命令输出作为后一条命令输入。 |
& |
%26 |
Shell 后台执行;URL 参数分隔符(需注意在传递 Payload 时可能被解析为参数分割,需提前编码)。 |
2.3 特殊占位符与绕过
| 字符 | URL 编码 | 攻击场景与作用说明 |
|---|---|---|
| 空格 | %20 或 + |
参数分割。在应用层过滤 %20 时,常尝试使用 %09 (Tab)、%0A 替代空格绕过。 |
\0 (空字符) |
%00 |
Poison Null Byte(%00 截断)。在旧版 PHP 或 C 语言底层处理中,作为字符串终止符,截断 .php 后缀判断。 |
% |
%25 |
双重编码构造基础(见下文)。 |
3. 实战进阶:CTF 编码绕过策略
在业务逻辑与底层抽象存在信息差时,常通过以下方式绕过 WAF 或正则引擎。
3.1 双重 URL 编码 (Double Encoding)
-
原理: 攻击者对 Payload 进行两次 URL 编码。
-
场景: 当 WAF 或前端代理只进行一次 URL 解码并执行安全检查,而脆弱的后端业务逻辑(如二次代入 SQL 查询)会触发第二次 URL 解码时使用。
-
构造示例:
-
单引号
'-> 一次编码%27-> 二次编码%2527(因为%的编码是%25)。 -
Payload:
1 %2527 UNION SELECT...
-
3.2 罕见编码与 Unicode 欺骗
-
当标准 ASCII 特殊字符被过滤时,利用目标系统底层解析库(如某些 Web 容器或数据库驱动)处理全角字符或宽字节时的降级特性。
-
示例 (宽字节注入): 在 GBK 编码环境下,使用
%df%27。反斜杠转义符%5C会与%df结合成一个合法的中文字符(餟),从而让后续的单引号%27逃逸并生效。