跳转至

编码与转换 (Encoding and Transformations)

编码与转换是在不改变核心含义的情况下,改变数据的表示或传输方式的技术。常见的例子包括 URL 编码、Base64、HTML 实体编码和 Unicode 转换。攻击者利用这些方法作为“组件 (gadgets)”来绕过输入过滤器、避开 Web 应用程序防火墙 (WAF) 或破坏清理 (sanitization) 程序。

摘要 (Summary)

Unicode

Unicode 是一种通用字符编码标准,用于表示世界上几乎所有书写系统的文本。每个字符(字母、数字、符号、表情符号)都被分配了一个唯一的码点(例如,“A”的码点是 U+0041)。UTF-8 和 UTF-16 等 Unicode 编码格式指定了这些码点如何以字节形式存储。

Unicode 归一化 (Unicode Normalization)

Unicode 归一化是将 Unicode 文本转换为标准化、一致形式的过程,以便在内存中以相同的方式表示等效字符。

Unicode 归一化参考表

  • NFC (Normalization Form Canonical Composition):尽可能将分解的序列组合成预组合字符。
  • NFD (Normalization Form Canonical Decomposition):将字符拆分为其分解形式(基准字符 + 组合标记)。
  • NFKC (Normalization Form Compatibility Composition):类似于 NFC,但还会将字符替换为兼容等效项(可能会改变外观/格式)。
  • NFKD (Normalization Form Compatibility Decomposition):类似于 NFD,但也会分解兼容字符。
字符 Payload 归一化后
(U+2025) ‥/‥/‥/etc/passwd ../../../etc/passwd
(U+FE30) ︰/︰/︰/etc/passwd ../../../etc/passwd
(U+FF07) ' or '1'='1 ' or '1'='1
(U+FF02) " or "1"="1 " or "1"="1
(U+FE63) admin'﹣﹣ admin'--
(U+3002) domain。com domain.com
(U+FF0F) //domain.com //domain.com
(U+FF1C) <img src=a> <img src=a/>
(U+FE5B) ﹛﹛3+3﹜﹜ {{3+3}}
(U+FF3B) [[5+5]] [[5+5]]
(U+FF06) &&whoami &&whoami
(U+FF50) shell.pʰp shell.php
ʰ (U+02B0) shell.pʰp shell.php
ª (U+00AA) ªdmin admin
import unicodedata
string = "ᴾᵃʸˡᵒᵃᵈˢ𝓐𝓵𝓵𝕋𝕙𝕖𝒯𝒽𝒾𝓃ℊ𝓈"
print ('NFC: ' + unicodedata.normalize('NFC', string))
print ('NFD: ' + unicodedata.normalize('NFD', string))
print ('NFKC: ' + unicodedata.normalize('NFKC', string))
print ('NFKD: ' + unicodedata.normalize('NFKD', string))

Punycode

Punycode 是一种仅使用有限的 ASCII 字符集(字母、数字和连字符)来表示 Unicode 字符(包括非 ASCII 字母、符号和文字)的方法。

它主要用于域名系统 (DNS),该系统传统上仅支持 ASCII。Punycode 允许使用国际化域名 (IDN),通过将其转换为安全的 ASCII 形式,使域名可以包含来自许多语言的字符。

浏览器中可见 (支持 IDN) 实际 ASCII (Punycode)
раypal.com xn--ypal-43d9g.com
paypal.com paypal.com

在 MySQL 中,相似字符被视为相等。这种行为可以在密码重置、忘记密码和 OAuth 提供程序部分被利用。

SELECT 'a' = 'ᵃ';
+-------------+
| 'a' = 'ᵃ'   |
+-------------+
|           1 |
+-------------+

如果 SQL 查询使用 COLLATE utf8mb4_0900_as_cs,则此技巧不成立:

SELECT 'a' = 'ᵃ' COLLATE utf8mb4_0900_as_cs;
+----------------------------------------+
| 'a' = 'ᵃ' COLLATE utf8mb4_0900_as_cs   |
+----------------------------------------+
|                                      0 |
+----------------------------------------+

Base64

Base64 编码是将二进制数据(如图片或文件)或包含特殊字符的文本转换为仅使用 ASCII 字符(A-Z, a-z, 0-9, +, 和 /)的可读字符串的方法。输入的每 3 个字节分为 4 组,每组 6 位,并映射到 4 个 Base64 字符。如果输入不是 3 字节的倍数,则输出使用 = 字符进行填充。

echo -n admin | base64                            
YWRtaW4=

echo -n YWRtaW4= | base64 -d
admin

实验环境 (Labs)

参考资料 (References)