代码审计Day15 - $_SERVER[PHP_SELF]导致的防御失效问题
字数 1200 2025-08-18 11:37:42

PHP代码审计:$_SERVER['PHP_SELF']导致的防御失效问题

1. 漏洞概述

本教学文档将详细分析由$_SERVER['PHP_SELF']引发的安全漏洞,该漏洞可导致任意网址跳转和防护系统绕过问题。

2. 漏洞示例代码分析

2.1 示例代码

// 示例漏洞代码
if(isset($_GET['redirect'])) {
    $redirect = new Redirect();
    $redirect->startRedirect($_GET['params']);
}

class Redirect {
    public function startRedirect($params) {
        $parts = explode('/', $_SERVER['PHP_SELF']);
        $baseFile = array_pop($parts);
        $url = $baseFile . '?' . http_build_query($params);
        $this->setHeaders($url);
    }
    
    private function setHeaders($url) {
        $url = urldecode($url);
        header("Location: " . $url);
    }
}

2.2 漏洞原理

  1. $_SERVER['PHP_SELF']可控性问题

    • PHP_SELF表示当前执行脚本的路径
    • 当URL包含PATH_INFO时(如http://example.com/index.php/admin),PHP_SELF会包含用户可控部分(/admin
  2. 双编码绕过

    • 浏览器自动对URL进行一次编码
    • 服务器接收时会解码一次
    • urldecode()函数会再次解码,导致双编码可绕过某些过滤

3. 漏洞利用方式

3.1 任意URL跳转

构造Payload:

http://victim.com/index.php/http:%252f%252fattacker.com?redirect=test&params=test123

解析过程:

  1. 初始URL:http:%252f%252fattacker.com
  2. 第一次解码(服务器):http%2f%2fattacker.com
  3. 第二次解码(urldecode):http://attacker.com
  4. 最终导致跳转到攻击者控制的网站

3.2 防护系统绕过(以360webscan为例)

  1. 旧版本360webscan使用$_SERVER['PHP_SELF']进行白名单检测
  2. 白名单中包含admin目录
  3. 构造URL:
    http://victim.com/index.php/admin?test=<script>alert(1)</script>
    
  4. 系统检测到admin在白名单中,绕过XSS防护

4. 实际案例分析

4.1 360webscan防护绕过

漏洞代码片段

// 旧版360webscan中的白名单检测
$url_path = $_SERVER['PHP_SELF'];
foreach($webscan_white_directory as $value) {
    if(strpos($url_path, $value) !== false) {
        $webscan_white = true;
        break;
    }
}

问题

  • 直接使用未过滤的PHP_SELF
  • 攻击者可构造包含白名单目录的URL绕过检测

5. 修复建议

  1. 使用$_SERVER['SCRIPT_NAME']替代

    • SCRIPT_NAME只包含脚本路径,不包含PATH_INFO
    • 更安全可靠
  2. 输入验证

    $scriptPath = basename($_SERVER['SCRIPT_NAME']);
    $url = $scriptPath . '?' . http_build_query($params);
    
  3. 限制跳转目标

    $allowedDomains = ['example.com', 'trusted.com'];
    if(!in_array(parse_url($url, PHP_URL_HOST), $allowedDomains)) {
        die('Invalid redirect target');
    }
    

6. CTF题目分析

6.1 题目代码

// index.php
include "./config.php";
include "./flag.php";
error_reporting(0);

$black_list = "/admin|guest|limit|by|substr|mid|like|or|char|union|select|greatest|%00|\'|";
$black_list .= "in|<|>|-|chal|and|if|database|where|concat|insert|having|sleep/i";

if(preg_match($black_list, $_GET['user'])) exit(":P"); 
if(preg_match($black_list, $_GET['pwd'])) exit(":P"); 

$query="select user from users where user='$_GET[user]' and pwd='$_GET[pwd]'";
echo "<h1>query : <strong><b>{$query}</b></strong><br></h1>";

$result = $conn->query($query);
if($result->num_rows > 0){
    $row = $result->fetch_assoc();
    if($row['user']) echo "<h2>Welcome {$row['user']}</h2>";
}

$result = $conn->query("select pwd from users where user='admin'");
if($result->num_rows > 0){
    $row = $result->fetch_assoc();
    $admin_pass = $row['pwd'];
}

if(($admin_pass)&&($admin_pass === $_GET['pwd'])){
    echo $flag;
}

highlight_file(__FILE__);

6.2 解题思路

  1. 目标:获取flag需要满足$admin_pass === $_GET['pwd']
  2. 限制:
    • 黑名单过滤了大量SQL关键字
    • 需要绕过过滤获取管理员密码
  3. 可能的解法:
    • 使用大小写变异绕过关键字检测
    • 利用注释符/**/分割关键字
    • 使用||替代or
    • 利用=进行盲注

7. 总结

  1. $_SERVER['PHP_SELF']存在安全风险,应谨慎使用
  2. 在需要脚本路径时,优先使用$_SERVER['SCRIPT_NAME']
  3. 所有用户输入都应视为不可信的,必须进行严格验证
  4. 防护系统的实现需要考虑各种绕过方式
  5. 黑名单过滤往往不够安全,应考虑白名单机制

8. 扩展学习

  1. PHP官方文档中关于$_SERVER变量的说明
  2. OWASP关于不安全的URL重定向的指南
  3. 各种WAF绕过技术的研究
  4. SQL注入的高级绕过技术
PHP代码审计:$_ SERVER[ 'PHP_ SELF' ]导致的防御失效问题 1. 漏洞概述 本教学文档将详细分析由 $_SERVER['PHP_SELF'] 引发的安全漏洞,该漏洞可导致任意网址跳转和防护系统绕过问题。 2. 漏洞示例代码分析 2.1 示例代码 2.2 漏洞原理 $_SERVER['PHP_SELF'] 可控性问题 : PHP_SELF 表示当前执行脚本的路径 当URL包含PATH_ INFO时(如 http://example.com/index.php/admin ), PHP_SELF 会包含用户可控部分( /admin ) 双编码绕过 : 浏览器自动对URL进行一次编码 服务器接收时会解码一次 urldecode() 函数会再次解码,导致双编码可绕过某些过滤 3. 漏洞利用方式 3.1 任意URL跳转 构造Payload: 解析过程: 初始URL: http:%252f%252fattacker.com 第一次解码(服务器): http%2f%2fattacker.com 第二次解码(urldecode): http://attacker.com 最终导致跳转到攻击者控制的网站 3.2 防护系统绕过(以360webscan为例) 旧版本360webscan使用 $_SERVER['PHP_SELF'] 进行白名单检测 白名单中包含 admin 目录 构造URL: 系统检测到 admin 在白名单中,绕过XSS防护 4. 实际案例分析 4.1 360webscan防护绕过 漏洞代码片段 : 问题 : 直接使用未过滤的 PHP_SELF 攻击者可构造包含白名单目录的URL绕过检测 5. 修复建议 使用 $_SERVER['SCRIPT_NAME'] 替代 : SCRIPT_NAME 只包含脚本路径,不包含PATH_ INFO 更安全可靠 输入验证 : 限制跳转目标 : 6. CTF题目分析 6.1 题目代码 6.2 解题思路 目标:获取flag需要满足 $admin_pass === $_GET['pwd'] 限制: 黑名单过滤了大量SQL关键字 需要绕过过滤获取管理员密码 可能的解法: 使用大小写变异绕过关键字检测 利用注释符 /**/ 分割关键字 使用 || 替代 or 利用 = 进行盲注 7. 总结 $_SERVER['PHP_SELF'] 存在安全风险,应谨慎使用 在需要脚本路径时,优先使用 $_SERVER['SCRIPT_NAME'] 所有用户输入都应视为不可信的,必须进行严格验证 防护系统的实现需要考虑各种绕过方式 黑名单过滤往往不够安全,应考虑白名单机制 8. 扩展学习 PHP官方文档中关于 $_SERVER 变量的说明 OWASP关于不安全的URL重定向的指南 各种WAF绕过技术的研究 SQL注入的高级绕过技术