[红日安全]代码审计Day2 - filter_var函数缺陷
字数 1606 2025-08-18 11:37:33

PHP代码审计:filter_var函数缺陷与XSS漏洞利用

1. 概述

本文基于红日安全团队的代码审计Day2内容,详细分析PHP中filter_var函数的缺陷以及如何利用这些缺陷绕过安全防护实现XSS攻击。

2. 漏洞背景

2.1 示例代码分析

原始漏洞代码来自PHP Security Calendar 2017中的Twig题目:

// 使用Twig模板引擎的escape过滤器过滤link
$link = $twig->escape($link);

// 使用filter_var函数验证URL
if (filter_var($nextSlide, FILTER_VALIDATE_URL)) {
    // 处理URL
}

2.2 双重过滤机制

  1. 第一重过滤:使用Twig的escape过滤器,底层实现为PHP的htmlspecialchars函数

    • 转换特殊字符为HTML实体
    • 默认配置转换:&, ", ', <, >
  2. 第二重过滤:使用filter_var函数配合FILTER_VALIDATE_URL过滤器

    • 验证变量是否为合法URL
    • 但不保证URL内容的安全性

3. 绕过技术分析

3.1 JavaScript伪协议绕过

有效payload

?nextSlide=javascript://comment%250aalert(1)

绕过原理

  1. URL解码过程:

    • 原始payload:javascript://comment%250aalert(1)
    • 解码后:javascript://comment%0aalert(1)
  2. JavaScript解释:

    • //表示单行注释
    • %0a是换行符的URL编码,使alert(1)在新行执行
    • 百分号编码%25确保%0a能正确传递

3.2 filter_var函数缺陷

  1. FILTER_VALIDATE_URL仅验证URL格式,不验证内容安全性
  2. 接受javascript:伪协议作为合法URL
  3. 对URL中的编码字符处理不严格

4. 实际案例分析:Anchor CMS 0.9.2

4.1 漏洞位置

themes/default/404.php中的404错误处理页面:

<code><?php echo current_url(); ?></code>

4.2 漏洞链分析

  1. current_url()函数调用链:

    function current_url() {
        return Uri::current();
    }
    
  2. Uri::current()方法:

    • 调用static::detect()获取当前URI
    • 使用filter_var($uri, FILTER_SANITIZE_URL)过滤
  3. 关键问题:

    • FILTER_SANITIZE_URL仅移除非法URL字符
    • 不进行XSS防护
    • 不过滤<script>等危险标签

4.3 漏洞利用

Payload构造

http://localhost/anchor/index.php/<script>alert('www.sec-redclub.com')</script>

利用过程

  1. 访问不存在的URL触发404页面
  2. current_url()获取并输出恶意脚本
  3. 脚本在受害者浏览器执行

5. 防御措施

5.1 输入验证强化

  1. 对URL协议进行白名单验证:

    if (!preg_match('/^https?:\/\//i', $url)) {
        die('Invalid URL protocol');
    }
    
  2. 结合parse_url()分析URL结构:

    $parts = parse_url($url);
    if ($parts['scheme'] !== 'http' && $parts['scheme'] !== 'https') {
        die('Invalid URL scheme');
    }
    

5.2 输出编码

  1. 对所有动态内容进行HTML实体编码:

    echo htmlspecialchars($user_input, ENT_QUOTES, 'UTF-8');
    
  2. 在上下文中使用适当的编码:

    • HTML属性:htmlspecialchars($var, ENT_QUOTES)
    • JavaScript:json_encode($var)
    • URL:urlencode($var)

5.3 安全函数使用建议

  1. 避免单独依赖filter_var进行安全验证
  2. 结合多种过滤方法:
    $url = filter_var($input, FILTER_SANITIZE_URL);
    if (filter_var($url, FILTER_VALIDATE_URL)) {
        $parts = parse_url($url);
        // 额外验证
    }
    

6. CTF题目分析

6.1 题目代码

// index.php
<?php 
$url = $_GET['url'];
if(isset($url) && filter_var($url, FILTER_VALIDATE_URL)){
    $site_info = parse_url($url);
    if(preg_match('/sec-redclub.com$/',$site_info['host'])){
        exec('curl "'.$site_info['host'].'"', $result);
        echo "<center><h1>You have curl {$site_info['host']} successfully!</h1></center>
              <center><textarea rows='20' cols='90'>";
        echo implode(' ', $result);
    } else{
        die("<center><h1>Error: Host not allowed</h1></center>");
    }
}else{
    echo "<center><h1>Just curl sec-redclub.com!</h1></center><br>
          <center><h3>For example:?url=http://sec-redclub.com</h3></center>";
}
?>

// f1agi3hEre.php
<?php $flag = "HRCTF{f1lt3r_var_1s_s0_c00l}"?>

6.2 解题思路

  1. 利用filter_var的URL验证缺陷
  2. 绕过主机名验证sec-redclub.com$
  3. 可能的攻击向量:
    • 使用@符号:http://evil.com@sec-redclub.com
    • 使用子域名:http://xxx.sec-redclub.com.evil.com
    • 利用URL解析差异

7. 总结

  1. filter_var函数的安全过滤器不能单独依赖
  2. JavaScript伪协议是常见的绕过手段
  3. URL验证需要结合多种方法和严格的白名单
  4. 输出编码是防御XSS的最后防线
  5. 安全应该采用纵深防御策略,多层防护

通过本文的分析,开发者应该更加谨慎地使用PHP的过滤函数,并理解其局限性,在实际开发中实施更全面的安全措施。

PHP代码审计:filter_ var函数缺陷与XSS漏洞利用 1. 概述 本文基于红日安全团队的代码审计Day2内容,详细分析PHP中 filter_var 函数的缺陷以及如何利用这些缺陷绕过安全防护实现XSS攻击。 2. 漏洞背景 2.1 示例代码分析 原始漏洞代码来自PHP Security Calendar 2017中的Twig题目: 2.2 双重过滤机制 第一重过滤 :使用Twig的 escape 过滤器,底层实现为PHP的 htmlspecialchars 函数 转换特殊字符为HTML实体 默认配置转换: & , " , ' , < , > 第二重过滤 :使用 filter_var 函数配合 FILTER_VALIDATE_URL 过滤器 验证变量是否为合法URL 但不保证URL内容的安全性 3. 绕过技术分析 3.1 JavaScript伪协议绕过 有效payload : 绕过原理 : URL解码过程: 原始payload: javascript://comment%250aalert(1) 解码后: javascript://comment%0aalert(1) JavaScript解释: // 表示单行注释 %0a 是换行符的URL编码,使 alert(1) 在新行执行 百分号编码 %25 确保 %0a 能正确传递 3.2 filter_ var函数缺陷 FILTER_VALIDATE_URL 仅验证URL格式,不验证内容安全性 接受 javascript: 伪协议作为合法URL 对URL中的编码字符处理不严格 4. 实际案例分析:Anchor CMS 0.9.2 4.1 漏洞位置 themes/default/404.php 中的404错误处理页面: 4.2 漏洞链分析 current_url() 函数调用链: Uri::current() 方法: 调用 static::detect() 获取当前URI 使用 filter_var($uri, FILTER_SANITIZE_URL) 过滤 关键问题: FILTER_SANITIZE_URL 仅移除非法URL字符 不进行XSS防护 不过滤 <script> 等危险标签 4.3 漏洞利用 Payload构造 : 利用过程 : 访问不存在的URL触发404页面 current_url() 获取并输出恶意脚本 脚本在受害者浏览器执行 5. 防御措施 5.1 输入验证强化 对URL协议进行白名单验证: 结合 parse_url() 分析URL结构: 5.2 输出编码 对所有动态内容进行HTML实体编码: 在上下文中使用适当的编码: HTML属性: htmlspecialchars($var, ENT_QUOTES) JavaScript: json_encode($var) URL: urlencode($var) 5.3 安全函数使用建议 避免单独依赖 filter_var 进行安全验证 结合多种过滤方法: 6. CTF题目分析 6.1 题目代码 6.2 解题思路 利用 filter_var 的URL验证缺陷 绕过主机名验证 sec-redclub.com$ 可能的攻击向量: 使用 @ 符号: http://evil.com@sec-redclub.com 使用子域名: http://xxx.sec-redclub.com.evil.com 利用URL解析差异 7. 总结 filter_var 函数的安全过滤器不能单独依赖 JavaScript伪协议是常见的绕过手段 URL验证需要结合多种方法和严格的白名单 输出编码是防御XSS的最后防线 安全应该采用纵深防御策略,多层防护 通过本文的分析,开发者应该更加谨慎地使用PHP的过滤函数,并理解其局限性,在实际开发中实施更全面的安全措施。