从RFC看如何使用Base64编码绕过WAF
字数 2303 2025-08-09 15:23:10

利用Base64编码不规范特性绕过WAF的技术分析

1. Base64编码基础

Base64编码是一种将二进制数据转换为ASCII字符的编码方式,基本原理是将3个字节(24bit)的数据分割为4个6bit的部分,每个6bit部分对应一个Base64字母表中的字符。

标准Base64字母表:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

当数据长度不足3字节时,使用=作为填充字符(padding):

  • 剩余1字节:补2个=
  • 剩余2字节:补1个=

2. WAF拦截机制分析

Web应用防火墙(WAF)对Base64编码数据的拦截主要有两种方式:

  1. 直接匹配编码数据:不进行解码,直接匹配Base64编码后的特征

    • 例如匹配QGluaV9zZXQo(即ini_set(的Base64编码)
  2. 解码后匹配:先解码Base64数据,再匹配解码后的特征

    • 例如直接匹配ini_set(关键字

3. Base64解码器差异性分析

测试了5种常见语言的Base64解码实现:

  1. PHP: base64_decode()
  2. Python: base64.b64decode()
  3. Go: encoding/base64.StdEncoding.DecodeString()
  4. Java1: java.util.Base64.getDecoder().decode()
  5. Java2: sun.misc.BASE64Decoder().decode()

3.1 换行符处理

测试数据:dG\nVzdA== (标准编码dGVzdA==中插入换行符)

解码器 结果
PHP 成功解码为"test"
Python 成功解码为"test"
Go 成功解码为"test" (仅支持\r\n)
Java1 报错
Java2 解码失败

绕过应用:在Base64数据中插入换行符,可能使部分WAF解码失败而绕过检测,而后端PHP/Python仍能正常解码。

3.2 非字母表字符处理

测试数据:dG~-VzdA== (插入非Base64字母表字符~-)

解码器 结果
PHP 成功解码为"test" (忽略非字母字符)
Python 成功解码为"test" (忽略非字母字符)
Go 报错
Java1 报错
Java2 解码失败

绕过应用:插入非字母表字符可使严格遵循RFC的解码器失败,而PHP/Python仍能正常解码。

3.3 Padding不足处理

测试数据:dGVzdA (缺少2个=填充)

解码器 结果
PHP 成功解码为"test"
Python 报错
Go 报错
Java1 成功解码为"test"
Java2 解码失败

绕过应用:去除必要的padding可能使部分WAF解码失败,而后端PHP/Java1仍能正常解码。

3.4 Padding过多处理

测试数据:dGVzdA=== (多1个=)

解码器 结果
PHP 成功解码为"test"
Python 成功解码为"test"
Go 报错
Java1 报错
Java2 成功解码为"test"

3.5 Padding后增加数据

测试数据:dGVzdA==dGVzdA== (padding后追加相同编码)

解码器 结果
PHP 解码为"testFW7@" (异常)
Python 解码为"test" (忽略padding后数据)
Go 报错
Java1 报错
Java2 解码为"testtest"

绕过应用:构造形如dGVzdA==payload的数据,WAF可能只解码前部分无害数据,而后端解码完整payload。

4. 绕过WAF的具体技术

基于上述解码器差异,可总结以下绕过技术:

  1. 插入换行符:在Base64数据中插入\n\r\n

    • 适用场景:WAF使用Java1/Go等严格解码器,后端使用PHP/Python
  2. 插入非字母字符:在Base64数据中插入~!@#$等非字母表字符

    • 适用场景:WAF使用严格解码器,后端使用PHP/Python
  3. 减少padding:去除必要的=填充字符

    • 适用场景:WAF使用Python/Go等,后端使用PHP/Java1
  4. 增加padding:添加多余的=字符

    • 适用场景:WAF使用严格解码器,后端使用PHP/Python/Java2
  5. padding后追加数据:在padding后追加有效payload

    • 适用场景:WAF类似Python会忽略后续数据,后端类似Java2会完整解码

5. 防御建议

  1. 统一解码标准:前后端使用相同Base64解码实现
  2. 严格校验:拒绝包含非字母字符、换行符的Base64数据
  3. padding检查:验证padding数量是否正确
  4. 多层检测:同时检测编码前后数据
  5. 规范化处理:解码前先去除非常规字符并修复padding

6. 参考

  • RFC4648: Base64编码规范
  • 各语言Base64解码实现源码分析
利用Base64编码不规范特性绕过WAF的技术分析 1. Base64编码基础 Base64编码是一种将二进制数据转换为ASCII字符的编码方式,基本原理是将3个字节(24bit)的数据分割为4个6bit的部分,每个6bit部分对应一个Base64字母表中的字符。 标准Base64字母表: 当数据长度不足3字节时,使用 = 作为填充字符(padding): 剩余1字节:补2个 = 剩余2字节:补1个 = 2. WAF拦截机制分析 Web应用防火墙(WAF)对Base64编码数据的拦截主要有两种方式: 直接匹配编码数据 :不进行解码,直接匹配Base64编码后的特征 例如匹配 QGluaV9zZXQo (即 ini_set( 的Base64编码) 解码后匹配 :先解码Base64数据,再匹配解码后的特征 例如直接匹配 ini_set( 关键字 3. Base64解码器差异性分析 测试了5种常见语言的Base64解码实现: PHP: base64_decode() Python: base64.b64decode() Go: encoding/base64.StdEncoding.DecodeString() Java1: java.util.Base64.getDecoder().decode() Java2: sun.misc.BASE64Decoder().decode() 3.1 换行符处理 测试数据: dG\nVzdA== (标准编码 dGVzdA== 中插入换行符) | 解码器 | 结果 | |--------|------| | PHP | 成功解码为"test" | | Python | 成功解码为"test" | | Go | 成功解码为"test" (仅支持 \r\n ) | | Java1 | 报错 | | Java2 | 解码失败 | 绕过应用 :在Base64数据中插入换行符,可能使部分WAF解码失败而绕过检测,而后端PHP/Python仍能正常解码。 3.2 非字母表字符处理 测试数据: dG~-VzdA== (插入非Base64字母表字符 ~- ) | 解码器 | 结果 | |--------|------| | PHP | 成功解码为"test" (忽略非字母字符) | | Python | 成功解码为"test" (忽略非字母字符) | | Go | 报错 | | Java1 | 报错 | | Java2 | 解码失败 | 绕过应用 :插入非字母表字符可使严格遵循RFC的解码器失败,而PHP/Python仍能正常解码。 3.3 Padding不足处理 测试数据: dGVzdA (缺少2个 = 填充) | 解码器 | 结果 | |--------|------| | PHP | 成功解码为"test" | | Python | 报错 | | Go | 报错 | | Java1 | 成功解码为"test" | | Java2 | 解码失败 | 绕过应用 :去除必要的padding可能使部分WAF解码失败,而后端PHP/Java1仍能正常解码。 3.4 Padding过多处理 测试数据: dGVzdA=== (多1个 = ) | 解码器 | 结果 | |--------|------| | PHP | 成功解码为"test" | | Python | 成功解码为"test" | | Go | 报错 | | Java1 | 报错 | | Java2 | 成功解码为"test" | 3.5 Padding后增加数据 测试数据: dGVzdA==dGVzdA== (padding后追加相同编码) | 解码器 | 结果 | |--------|------| | PHP | 解码为"testFW7@" (异常) | | Python | 解码为"test" (忽略padding后数据) | | Go | 报错 | | Java1 | 报错 | | Java2 | 解码为"testtest" | 绕过应用 :构造形如 dGVzdA==payload 的数据,WAF可能只解码前部分无害数据,而后端解码完整payload。 4. 绕过WAF的具体技术 基于上述解码器差异,可总结以下绕过技术: 插入换行符 :在Base64数据中插入 \n 或 \r\n 适用场景:WAF使用Java1/Go等严格解码器,后端使用PHP/Python 插入非字母字符 :在Base64数据中插入 ~!@#$ 等非字母表字符 适用场景:WAF使用严格解码器,后端使用PHP/Python 减少padding :去除必要的 = 填充字符 适用场景:WAF使用Python/Go等,后端使用PHP/Java1 增加padding :添加多余的 = 字符 适用场景:WAF使用严格解码器,后端使用PHP/Python/Java2 padding后追加数据 :在padding后追加有效payload 适用场景:WAF类似Python会忽略后续数据,后端类似Java2会完整解码 5. 防御建议 统一解码标准 :前后端使用相同Base64解码实现 严格校验 :拒绝包含非字母字符、换行符的Base64数据 padding检查 :验证padding数量是否正确 多层检测 :同时检测编码前后数据 规范化处理 :解码前先去除非常规字符并修复padding 6. 参考 RFC4648: Base64编码规范 各语言Base64解码实现源码分析