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

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

缺陷编号:wooyun-2014-061133

漏洞标题:最土团购注入两处 (直接提升自己权限)

相关厂商:zuitu.com

漏洞作者: ′雨。

提交时间:2014-05-17 20:33

修复时间:2014-08-12 20:34

公开时间:2014-08-12 20:34

漏洞类型:SQL注射漏洞

危害等级:高

自评Rank:20

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

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

Tags标签:

4人收藏 收藏
分享漏洞:


漏洞详情

披露状态:

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

简要描述:

又是周末。
还有一个多月就要高考了, 到时候我也就成了高三狗了。
荒废了这前面的两年, 决定高三的时候还是得拼一下。
希望能考上个自己理想的学校。

详细说明:

上次说了chinabank 把剩下的几个文件都报出来把。
主要是通过验证的问题。 执行语句的时候会转义得找没单引号的地方。
一些我没办法通过那验证,
还有一些就是把amount/100了 例如bill/return.php中的
$v_amount = ($orderAmount/100);
这个我也没办法利用了。
把能利用的写出来一下。
0x01 order/sdopay/notify.php

$amount=$_POST["Amount"];
$payamount=$_POST["PayAmount"];
$orderid=$_POST["OrderNo"];
$serialno=$_POST["serialno"];
$status=$_POST["Status"];
$merid=$_POST["MerchantNo"];
$paychannel=$_POST["PayChannel"];
$discount=$_POST["Discount"];
$signtype=$_POST["SignType"];
$paytime=$_POST["PayTime"];
$ctype=$_POST["CurrencyType"];
$prono=$_POST["ProductNo"];
$prodesc=$_POST["ProductDesc"];
$remark1=$_POST["Remark1"];
$remark2=$_POST["Remark2"];
$ex=$_POST["ExInfo"];
$mac=$_POST["MAC"];
$signString=$amount."|".$payamount."|".$orderid."|".$serialno."|".$status."|".$merid."|".$paychannel."|".$discount."|".$signtype."|".$paytime."|".$ctype."|".$prono."|".$prodesc."|".$remark1."|".$remark2."|".$ex;
if($signtype=="2")//md5
{
$md5key=$INI['sdopay']['sec'];
$mac2 =md5($signString."|".$md5key);
$ok = (strtoupper($mac)==strtoupper($mac2));
}
@list($_, $order_id, $city_id, $_) = explode('-', $orderid, 4);
if (Table::Fetch('pay', $orderid)) die('OK');
if ( $_ == 'charge' ) {
if ($ok == 1) {
@list($_, $user_id, $create_time, $_) = explode('-', $orderid, 4);
ZFlow::CreateFromCharge($amount, $user_id, $create_time, 'sdopay',$serialno);

die("OK");//必须输出且只能输出"OK"
}
}


这里 主要是让 $ok 为 1

if($signtype=="2")//md5
{
$md5key=$INI['sdopay']['sec'];
$mac2 =md5($signString."|".$md5key);
$ok = (strtoupper($mac)==strtoupper($mac2));
}


首先让signtype为2
mac2 $signString | $md5key 这里md5key默认都为空的 不用考虑。
$mac为post来的 只要$mac和$mac2相等 就能让$ok为1

static public function CreateFromCharge($money,$user_id,$time,$service='alipay',$trade_no=''){
global $option_service;
if (!$money || !$user_id || !$time) return 0;
$pay_id = "charge-{$user_id}-{$time}";
$pay = Table::Fetch('pay', $pay_id);
if ( $pay ) return 0;

$order_id = ZOrder::CreateFromCharge($money,$user_id,$time,$service);
if (!$order_id) return 0;
//insert pay record
$pay = array(
'id' => $pay_id,
'vid' => $trade_no,
'order_id' => $order_id,
'bank' => $option_service[$service],
'currency' => 'CNY',
'money' => $money,
'service' => $service,
'create_time' => $time,
);
DB::Insert('pay', $pay);
ZCredit::Charge($user_id, $money);
//end//
//update user money;

$user = Table::Fetch('user', $user_id);

Table::UpdateCache('user', $user_id, array(
'money' => array( "money + {$money}" ),
));


这里$amount 做的$money 可以看到没有被单引号 没有intval。
而且直接update的是user table 。 且可控的是在set位。。
管理和用户都是在user表里。 通过manager column 来判断是否为管理。
这里直接update manager 为1 就能直接提升自己为管理。
_________________________________________________________________________
0x02 order/gopay/return.php

$tranCode = $_REQUEST["tranCode"];
$merchantID = $_REQUEST["merchantID"];
$merOrderNum = $_REQUEST["merOrderNum"];
$tranAmt = $_REQUEST["tranAmt"];
$ticketAmt = $_REQUEST["ticketAmt"];
$tranDateTime = $_REQUEST["tranDateTime"];
$currencyType = $_REQUEST["currencyType"];
$merURL = $_REQUEST["merURL"];
$customerEMail = $_REQUEST["customerEMail"];
$authID = $_REQUEST["authID"];
$orgOrderNum = $_REQUEST["orgOrderNum"];
$orgtranDateTime = $_REQUEST["orgtranDateTime"];
$orgtranAmt = $_REQUEST["orgtranAmt"];
$orgTxnType = $_REQUEST["orgTxnType"];
$orgTxnStat = $_REQUEST["orgTxnStat"];
$msgExt = $_REQUEST["msgExt"];
$virCardNo = $_REQUEST["virCardNo"];
$virCardNoIn = $_REQUEST["virCardNoIn"];
$tranIP = $_REQUEST["tranIP"];
$isLocked = $_REQUEST["isLocked"];
$feeAmt = $_REQUEST["feeAmt"];
$respCode = $_REQUEST["respCode"];
$VerficationCode = $INI['gopay']['code'];
$signValue = $_REQUEST["signValue"];
$orderId = preg_replace('/_/', '-', $merOrderNum);
$str = "tranCode=[$tranCode]merchantID=[$merchantID]merOrderNum=[$merOrderNum]tranAmt=[$tranAmt]ticketAmt=[$ticketAmt]tranDateTime=[$tranDateTime]currencyType=[$currencyType]merURL=[$merURL]customerEMail=[$customerEMail]authID=[$authID]orgOrderNum=[$orgOrderNum]orgtranDateTime=[$orgtranDateTime]orgtranAmt=[$orgtranAmt]orgTxnType=[$orgTxnType]orgTxnStat=[$orgTxnStat]msgExt=[$msgExt]virCardNo=[$virCardNo]virCardNoIn=[$virCardNoIn]tranIP=[$tranIP]isLocked=[$isLocked]feeAmt=[$feeAmt]respCode=[$respCode]VerficationCode=[$VerficationCode]";
$newSign = MD5($str);
@list($_, $order_id, $city_id, $_) = explode('-', $orderId, 4);
if (Table::Fetch('pay', $orderId)) die('SUCCESS');
if( $newSign == $signValue && $respCode == '0000' ) {
/* charge */
if ( $_ == 'charge' ) {
@list($_, $user_id, $create_time, $_) = explode('-', $orderId, 4);
ZFlow::CreateFromCharge($tranAmt, $user_id, $create_time, 'gopay',$tranCode);
Session::Set('notice', "国付宝充值{$tranAmt}元成功!");


这里验证了
$newSign == $signValue && $respCode == '0000'
$newSign 又是Md5来的。 所以能通过验证了。。
ZFlow::CreateFromCharge($tranAmt 然后又进这函数 不多说了。
_________________________________________________________________

漏洞证明:

第一处

z2.jpg


第二处

z3.jpg


update。

z4.jpg


修复方案:

intval money
加强验证。

版权声明:转载请注明来源 ′雨。@乌云


漏洞回应

厂商回应:

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

忽略时间:2014-08-12 20:34

厂商回复:

此产品已不再维护,原站已经下线,感谢白帽子提交漏洞,中国因你们更精彩

最新状态:

暂无