PHP变量流量层面WAF绕过
字数 1219 2025-08-27 12:33:48

PHP变量流量层面WAF绕过技术研究

简介

本文深入分析PHP在处理GET/POST/COOKIE大变量时的生成过程,以及可能用于绕过Web应用防火墙(WAF)的技术手段。研究基于PHP 7.3.4在FPM模式下的运行环境。

PHP变量处理基础

PHP变量处理的主要代码位于main/php_variables.c,其核心流程包括:

  1. 获取请求字符串
  2. 使用&分割参数
  3. 使用=分割键值对
  4. 对键和值分别进行URL解码
  5. 注册变量到相应的超全局数组(\(_GET/\)_POST/$_COOKIE)

关键特性分析

1. URL解码处理

PHP会对变量名和变量值都进行URL解码:

if (val) {
    /* have a value */
    size_t val_len;
    size_t new_val_len;
    *val++ = '\0';
    // 对key进行url解码
    php_url_decode(var, strlen(var));
    // 对value进行url解码
    val_len = php_url_decode(val, strlen(val));
    val = estrndup(val, val_len);
    if (sapi_module.input_filter(arg, var, &val, val_len, &new_val_len)) {
        php_register_variable_safe(var, val, new_val_len, &array);
    }
    efree(val);
}

安全影响:WAF可能在未解码状态下检测恶意输入,而PHP处理后可能产生不同的语义。

2. 变量名截断

PHP处理%00(空字符)时的行为:

  • 对key进行URL解码后,%00转换为\0会截断key字符串
  • 但对value处理时,使用val_len(字符串长度)进行操作,不会截断value

绕过技巧:可利用空字符截断变量名,可能绕过基于变量名的WAF规则。

3. 空格处理规则

PHP会忽略变量名前的空格:

while (*var_name == ' ') {
    var_name++;
}

URL中空格通常编码为+%20

4. 特殊字符转换

PHP会对变量名中的特定字符进行转换:

  • 空格和点号.转换为下划线_

    for (p = var; *p; p++) {
        if (*p == ' ' || *p == '.') {
            *p = '_';
        } else if (*p == '[') {
            is_array = 1;
            ip = p;
            *p = 0;
            break;
        }
    }
    
  • 方括号[处理:

    • 遇到[认为变量是数组
    • 如果找不到匹配的],则将[替换为_
    ip = strchr(ip, ']');
    if (!ip) {
        /* PHP variables cannot contain '[' in their names, so we replace the character with a '_' */
        *(index_s - 1) = '_';
        index_len = 0;
        if (index) {
            index_len = strlen(index);
        }
        goto plain_var;
        return;
    }
    

WAF绕过技巧总结

  1. URL编码绕过

    • 对关键字符进行多层URL编码
    • 利用WAF可能只解码一次而PHP会完全解码的特性
  2. 空字符截断

    • 在变量名中使用%00截断
    • 如:evil%00var=value可能被PHP解析为evil变量
  3. 空格前缀

    • 在变量名前添加空格(编码为+%20)
    • 如:%20var=value会被PHP解析为var
  4. 特殊字符转换利用

    • 使用.[等字符,利用PHP的自动转换特性
    • 如:var.name=value会被转换为var_name
  5. 数组表示法混淆

    • 使用不完整的数组表示法,如var[=value
    • PHP会将其转换为var_

防御建议

  1. 在应用层对输入进行规范化处理后再进行安全检查
  2. 实现与PHP一致的解码和转换逻辑
  3. 对变量名和值进行多重验证
  4. 考虑使用白名单而非黑名单的验证策略
  5. 在WAF规则中考虑PHP的特殊处理逻辑

实验验证

可使用以下PHP代码验证各种情况:

<?php
echo "get:"; var_dump($_GET);
echo "cookie:"; var_dump($_COOKIE);
echo "post:"; var_dump($_POST);
?>

通过构造各种特殊参数观察PHP的实际解析行为,如:

  • ?var.name=test
  • ?%20var=test
  • ?evil%00var=test
  • ?var[=test

结论

理解PHP处理HTTP变量的内部机制对于开发安全的Web应用和设计有效的WAF规则至关重要。攻击者可能利用这些特性绕过传统的安全检测,因此防御方需要在这些层面上与PHP保持一致的解析逻辑。

PHP变量流量层面WAF绕过技术研究 简介 本文深入分析PHP在处理GET/POST/COOKIE大变量时的生成过程,以及可能用于绕过Web应用防火墙(WAF)的技术手段。研究基于PHP 7.3.4在FPM模式下的运行环境。 PHP变量处理基础 PHP变量处理的主要代码位于 main/php_variables.c ,其核心流程包括: 获取请求字符串 使用 & 分割参数 使用 = 分割键值对 对键和值分别进行URL解码 注册变量到相应的超全局数组($_ GET/$_ POST/$_ COOKIE) 关键特性分析 1. URL解码处理 PHP会对变量名和变量值都进行URL解码: 安全影响 :WAF可能在未解码状态下检测恶意输入,而PHP处理后可能产生不同的语义。 2. 变量名截断 PHP处理 %00 (空字符)时的行为: 对key进行URL解码后, %00 转换为 \0 会截断key字符串 但对value处理时,使用 val_len (字符串长度)进行操作,不会截断value 绕过技巧 :可利用空字符截断变量名,可能绕过基于变量名的WAF规则。 3. 空格处理规则 PHP会忽略变量名前的空格: URL中空格通常编码为 + 或 %20 。 4. 特殊字符转换 PHP会对变量名中的特定字符进行转换: 空格和点号 . 转换为下划线 _ 方括号 [ 处理: 遇到 [ 认为变量是数组 如果找不到匹配的 ] ,则将 [ 替换为 _ WAF绕过技巧总结 URL编码绕过 : 对关键字符进行多层URL编码 利用WAF可能只解码一次而PHP会完全解码的特性 空字符截断 : 在变量名中使用 %00 截断 如: evil%00var=value 可能被PHP解析为 evil 变量 空格前缀 : 在变量名前添加空格(编码为 + 或 %20 ) 如: %20var=value 会被PHP解析为 var 特殊字符转换利用 : 使用 . 或 [ 等字符,利用PHP的自动转换特性 如: var.name=value 会被转换为 var_name 数组表示法混淆 : 使用不完整的数组表示法,如 var[=value PHP会将其转换为 var_ 防御建议 在应用层对输入进行规范化处理后再进行安全检查 实现与PHP一致的解码和转换逻辑 对变量名和值进行多重验证 考虑使用白名单而非黑名单的验证策略 在WAF规则中考虑PHP的特殊处理逻辑 实验验证 可使用以下PHP代码验证各种情况: 通过构造各种特殊参数观察PHP的实际解析行为,如: ?var.name=test ?%20var=test ?evil%00var=test ?var[=test 结论 理解PHP处理HTTP变量的内部机制对于开发安全的Web应用和设计有效的WAF规则至关重要。攻击者可能利用这些特性绕过传统的安全检测,因此防御方需要在这些层面上与PHP保持一致的解析逻辑。