[红日安全]代码审计Day16 - 深入理解$_REQUESTS数组
字数 1391 2025-08-18 11:37:46

深入理解PHP中的$_REQUEST数组与安全审计

1. $_REQUEST数组基础

1.1 $_REQUEST数组的定义

$_REQUEST是PHP中的一个超全局数组,它包含了$_GET$_POST$_COOKIE数据的合集。但需要注意以下几点:

  • 数据是复制过去的,不是引用
  • 默认情况下不包含$_FILES信息
  • 数据顺序和覆盖规则由php.ini中的request_ordervariables_order决定

1.2 $_REQUEST与过滤问题

常见的安全问题是开发者只过滤了$_GET$_POST$_COOKIE,但却使用了$_REQUEST中的数据,导致过滤被绕过。

示例漏洞代码

function cleanInput($data) {
    return (int)$data;
}

$id = cleanInput($_GET['id']);  // 过滤GET参数
$mode = $_REQUEST['mode'];      // 但使用未过滤的REQUEST参数

2. 实际案例分析

2.1 示例1:FTP命令注入

漏洞代码

$mode = $_REQUEST['mode'];  // 直接从REQUEST获取未过滤的数据
ftp_login($conn, $ftp_user, $ftp_pass);
ftp_raw($conn, "MODE $mode");  // 直接拼接未过滤的数据

攻击payload

?mode=1%0a%0dDELETE%20test.file

漏洞原理

  1. 程序过滤了GET/POST/COOKIE数据,但使用了REQUEST数据
  2. 通过CRLF注入(%0a%0d)可以在FTP命令中注入新命令
  3. 最终可执行删除文件等恶意操作

2.2 示例2:WordPress插件XSS漏洞

漏洞代码

function render_tab3() {
    $tab = $this->get_current_tab();  // 获取过滤后的tab值
    echo '<div class="aiowps_ad_intro">'.$_REQUEST['tab'].'</div>';  // 但输出未过滤的REQUEST值
}

攻击payload

POST /wp-admin/admin.php?page=aiowpsec&tab=tab3
tab="><script>alert(1)</script>

漏洞原理

  1. 插件有过滤函数处理$tab变量
  2. 但直接输出$_REQUEST['tab']导致XSS
  3. 由于request_order设置为"GP",POST值会覆盖GET值

3. $_REQUEST相关配置

3.1 request_order配置

php.ini中的request_order决定了$_REQUEST数组中变量的来源和顺序:

  • 默认值:通常为"GP" (GET和POST)
  • 可能的值:G, P, C, 或其组合(如"GPC")
  • 顺序从左到右,后面的会覆盖前面的同名变量

示例

request_order = "GP"  # 先GET后POST,POST会覆盖GET

3.2 variables_order

request_order未设置时,会使用variables_order的值来决定$_REQUEST的内容。

4. 安全防护措施

4.1 最佳实践

  1. **避免直接使用\(_REQUEST**:明确使用`\)_GET\(_POST`或`\)_COOKIE`
  2. 统一过滤:如果必须使用$_REQUEST,确保所有来源都经过相同过滤
  3. 输出编码:输出前使用htmlentities()等函数进行编码

4.2 修复方案

错误方式

$input = $_REQUEST['input'];

正确方式

// 方案1:明确来源
$input = $_POST['input'] ?? $_GET['input'] ?? '';

// 方案2:统一过滤
function cleanInput($data) {
    // 实现过滤逻辑
}
$input = cleanInput($_REQUEST['input']);

// 方案3:输出编码
echo htmlentities($input, ENT_QUOTES, 'UTF-8');

5. 相关CTF题目分析

5.1 题目概述

题目提供了一个SSRF(Server Side Request Forgery)漏洞场景,要求访问本地flag.php获取flag。

关键代码

function check_inner_ip($url) {
    // 检查是否为内网IP
    return ip2long('127.0.0.0')>>24 == $int_ip>>24 
        || ip2long('10.0.0.0')>>24 == $int_ip>>24 
        || ip2long('172.16.0.0')>>20 == $int_ip>>20 
        || ip2long('192.168.0.0')>>16 == $int_ip>>16 
        || ip2long('0.0.0.0')>>24 == $int_ip>>24;
}

function safe_request_url($url) {
    if (check_inner_ip($url)) {
        echo $url.' is inner ip';
    } else {
        // 发起请求
    }
}

5.2 解题思路

  1. 需要绕过内网IP检测
  2. 利用URL解析差异或特殊协议
  3. 可能的解法:
    • 使用0代替127.0.0.1(如http://0/flag.php)
    • 使用域名重定向
    • 利用DNS解析特性

6. 总结

  1. $_REQUEST数组是安全审计中常被忽视的风险点
  2. 确保过滤逻辑覆盖所有数据来源
  3. 明确变量来源比使用$_REQUEST更安全
  4. 输出前必须进行适当的编码处理
  5. 理解request_ordervariables_order的影响

通过深入理解$_REQUEST的特性和相关安全问题,可以在代码审计和开发过程中有效避免此类漏洞。

深入理解PHP中的$_ REQUEST数组与安全审计 1. $_ REQUEST数组基础 1.1 $_ REQUEST数组的定义 $_REQUEST 是PHP中的一个超全局数组,它包含了 $_GET 、 $_POST 和 $_COOKIE 数据的合集。但需要注意以下几点: 数据是复制过去的,不是引用 默认情况下不包含 $_FILES 信息 数据顺序和覆盖规则由 php.ini 中的 request_order 或 variables_order 决定 1.2 $_ REQUEST与过滤问题 常见的安全问题是开发者只过滤了 $_GET 、 $_POST 或 $_COOKIE ,但却使用了 $_REQUEST 中的数据,导致过滤被绕过。 示例漏洞代码 : 2. 实际案例分析 2.1 示例1:FTP命令注入 漏洞代码 : 攻击payload : 漏洞原理 : 程序过滤了GET/POST/COOKIE数据,但使用了REQUEST数据 通过CRLF注入( %0a%0d )可以在FTP命令中注入新命令 最终可执行删除文件等恶意操作 2.2 示例2:WordPress插件XSS漏洞 漏洞代码 : 攻击payload : 漏洞原理 : 插件有过滤函数处理 $tab 变量 但直接输出 $_REQUEST['tab'] 导致XSS 由于 request_order 设置为"GP",POST值会覆盖GET值 3. $_ REQUEST相关配置 3.1 request_ order配置 php.ini 中的 request_order 决定了 $_REQUEST 数组中变量的来源和顺序: 默认值:通常为"GP" (GET和POST) 可能的值:G, P, C, 或其组合(如"GPC") 顺序从左到右,后面的会覆盖前面的同名变量 示例 : 3.2 variables_ order 当 request_order 未设置时,会使用 variables_order 的值来决定 $_REQUEST 的内容。 4. 安全防护措施 4.1 最佳实践 避免直接使用$_ REQUEST :明确使用 $_GET 、 $_POST 或 $_COOKIE 统一过滤 :如果必须使用 $_REQUEST ,确保所有来源都经过相同过滤 输出编码 :输出前使用 htmlentities() 等函数进行编码 4.2 修复方案 错误方式 : 正确方式 : 5. 相关CTF题目分析 5.1 题目概述 题目提供了一个SSRF(Server Side Request Forgery)漏洞场景,要求访问本地flag.php获取flag。 关键代码 : 5.2 解题思路 需要绕过内网IP检测 利用URL解析差异或特殊协议 可能的解法: 使用 0 代替 127.0.0.1 (如 http://0/flag.php ) 使用域名重定向 利用DNS解析特性 6. 总结 $_REQUEST 数组是安全审计中常被忽视的风险点 确保过滤逻辑覆盖所有数据来源 明确变量来源比使用 $_REQUEST 更安全 输出前必须进行适当的编码处理 理解 request_order 和 variables_order 的影响 通过深入理解 $_REQUEST 的特性和相关安全问题,可以在代码审计和开发过程中有效避免此类漏洞。