网站地图    收藏   

主页 > 入门引导 > 黑客攻防 >

ecshop漏洞分析 - 网站安全 - 自学php

来源:自学PHP网    时间:2015-04-15 15:00 作者: 阅读:

[导读] 昨天在wooyun上看了看 以前blue大牛发的ecshop的洞, 还有一些其他的不过有些没给出利用方法 自己来做个分析把。 新版本的应该都补了把。if (!get_magic_quotes_gpc()){ if (!empty($_GET))...

 

 昨天在wooyun上看了看 以前blue大牛发的ecshop的洞, 还有一些其他的
不过有些没给出利用方法 自己来做个分析把。 新版本的应该都补了把。

 
if (!get_magic_quotes_gpc())
{
    if (!empty($_GET))
    {
        $_GET  = addslashes_deep($_GET);
    }
    if (!empty($_POST))
    {
        $_POST = addslashes_deep($_POST);
    }
 
    $_COOKIE   = addslashes_deep($_COOKIE);
    $_REQUEST  = addslashes_deep($_REQUEST);
}
在Magic_quotes_gpc 为off的情况下

用addslashes_deep 对 GET POST COOKIE REQUEST 进行处理
0×01:alipay 注入漏洞
需要启用支付宝的支付方式才行。 无视一切。
Respond 中

?[Copy to clipboard]View Code PHP
 
 
$pay_code = !empty($_REQUEST['code']) ? trim($_REQUEST['code']) : '';
省略省略
$sql = "SELECT COUNT(*) FROM " . $ecs->table('payment') . " WHERE pay_code = '$pay_code' AND enabled = 1";
    if ($db->getOne($sql) == 0)
    {
        $msg = $_LANG['pay_disabled'];
    }
    else
    {
        $plugin_file = 'includes/modules/payment/' . $pay_code . '.php';

 

这里还包含了。 不过由于addslashes 不能截断 所以基本无用 长文件截断也不行。。
如果allow_url_include 为On的话 当然又是另外一种情况。
这里code为alipay 的话 就包含了alipay进来。 然后跟进。

function respond()
    {
        if (!empty($_POST))
        {
            foreach($_POST as $key => $data)
            {
                $_GET[$key] = $data;
            }
        }
        $payment  = get_payment($_GET['code']);
        $seller_email = rawurldecode($_GET['seller_email']);
        $order_sn = str_replace($_GET['subject'], '', $_GET['out_trade_no']);
        $order_sn = trim($order_sn);
 
        /* 检查支付的金额是否相符 */
        if (!check_money($order_sn, $_GET['total_fee']))
        {
            return false;
        }
204行。
来看看check_money的方法
function check_money($log_id, $money)
{
    $sql = 'SELECT order_amount FROM ' . $GLOBALS['ecs']->table('pay_log') .
              " WHERE log_id = '$log_id'";
    $amount = $GLOBALS['db']->getOne($sql);
 
    if ($money == $amount)
    {
        return true;
    }
    else
    {
        return false;
    }
}

 

 当然有单引号。 是把order_sn 带入了这个函数中。

 
$order_sn = str_replace($_GET['subject'], '', $_GET['out_trade_no']);
要查找的值和被搜索的字符串都是可控的。 而且是替换为空

因为addslashes 是会对Null 也转义的。
所以 %00 会转义成\0 %00’ 就是 \0\’
因为要查询的是可控的而且是替换成空。 就把0替换成空就行了。
$order_sn = str_replace(0,””, %00′)
把0替换成空后 $oder_sn 就成了\\’ 两个闭合 单引号出来了。
后面的写语句就行了。
0X02 flow
1808 行

 
elseif ($_REQUEST['step'] == 'update_cart')
{
    if (isset($_POST['goods_number']) && is_array($_POST['goods_number']))
    {
        flow_update_cart($_POST['goods_number']);
    }
 
    show_message($_LANG['update_cart_notice'], $_LANG['back_to_cart'], 'flow.php');
    exit;
}
只要 设置了$_POST['goods_number'] 和这个是个数组 就进flow_update_cart

跟进去看看

 
{
    /* 处理 */
    foreach ($arr AS $key => $val)
    {
        $val = intval(make_semiangle($val));
        if ($val <= 0 || !is_numeric($key))
        {
            continue;
        }
 
        //查询:
        $sql = "SELECT `goods_id`, `goods_attr_id`, `product_id`, `extension_code` FROM" .$GLOBALS['ecs']->table('cart').
               " WHERE rec_id='$key' AND session_id='" . SESS_ID . "'";
        $goods = $GLOBALS['db']->getRow($sql);
把数组 以key=>value 遍历出来。

然后value 被转整。 但是key没有被过滤、 只要 value 大于1 或者key不是数字就好 肯定是满足前面的个。
QQ图片20140125213435
POST 把key修改成注入语句就好。

0×03 依旧flow.php 二次猪肉。
222

INSERT INTO `ecshop`.`ecs_cart` (user_id, session_id, goods_id, goods_sn, product_id, goods_name, market_price, goods_price, goods_number, goods_attr, is_real, extension_code, parent_id, rec_type, is_gift, is_shipping, goods_attr_id) VALUES ('0', '8bf4348243d6ceae0845e95705e9c4be', '1', 'xxxxxxxxx', '0', 'xxxxxxxxxxxxxxxxxxx', '0', '0', '1', '', '1', '', '0', '0', '0', '0', 'yu,yu\'')

添加商品到购物车所执行的语句, 单引号当然会被转义。

// 更新:添加到购物车
        if (addto_cart($goods->goods_id, $goods->number, $goods->spec, $goods->parent))
        {   
            if ($_CFG['cart_confirm'] > 2)
            {
                $result['message'] = '';
            }
            else
            {
                $result['message'] = $_CFG['cart_confirm'] == 1 ? $_LANG['addto_cart_success_1'] : $_LANG['addto_cart_success_2'];
            }
 
            $result['content'] = insert_cart_info();
            $result['one_step_buy'] = $_CFG['one_step_buy'];
 
继续跟。  代码太多了 我就复制下大概的。
                }
            }
        }       
    }
 
    /* 计算商品的促销价格 */
    $spec_price             = spec_price($spec);
    $goods_price            = get_final_price($goods_id, $num, true, $spec);
    $goods['market_price'] += $spec_price;
    $goods_attr             = get_goods_attr_info($spec);
$goods_attr_id          = join(',', $spec);
 
$spec 是可控的, 
 
function get_final_price($goods_id, $goods_num = '1', $is_spec_price = false, $spec = array())
{
    $final_price   = '0'; //ÉÌÆ•×îÖÕ¹ºÂò¼Û¸ñ
    $volume_price  = '0'; //ÉÌÆ•ÓŻݼ۸ñ
    $promote_price = '0'; //ÉÌÆ•´ÙÏú¼Û¸ñ
    $user_price    = '0'; //ÉÌÆ•»áÔ±¼Û¸ñ
 
省略省略
   if ($is_spec_price)
    {
        if (!empty($spec))
        {
            $spec_price   = spec_price($spec);
            $final_price += $spec_price;
        }
}
继续跟。
function spec_price($spec)
{
    if (!empty($spec))
    {   
 
 
        $where = db_create_in($spec, 'goods_attr_id');
 
 
 
 
        $sql = 'SELECT SUM(attr_price) AS attr_price FROM ' . $GLOBALS['ecs']->table('goods_attr') . " WHERE $where";
 
看看db_create_in
 
if (empty($item_list))
    {
        return $field_name . " IN ('') ";
    }
    else
    {
        if (!is_array($item_list))
        {
            $item_list = explode(',', $item_list);
        }
        $item_list = array_unique($item_list);
        $item_list_tmp = '';
 
        foreach ($item_list AS $item)
        {
            if ($item !== '')
            {
                $item_list_tmp .= $item_list_tmp ? ",'$item'" : "'$item'";
 
            }
        }
 
        if (empty($item_list_tmp))
        {   
            return $field_name . " IN ('') ";
        }
        else
        {  
            return $field_name . ' IN (' . $item_list_tmp . ') ';
        }
    }
}

 

 如果不是数组就以逗号来切割成为数组 然后去重复。然后循环遍历 赋值。

是数组的话就直接去重复然后循环。
goods_attr_id 无过滤的就进入数据库了 只是转义了。
在更新这个商品的时候会出库 造成了二次注入。
只是因为这里不能用逗号 所以麻烦了点。
Laterain牛说的是 提交数组然后就可以绕过切割了。

测试了很久 不知道是不是我无法理解啊, 还是没搞定。3333333
我把db_create_in处理过后的 输出了出来。添加商品的时候 逗号成功的存在。
因为 如果不是数组 才会用逗号来切割形成数组 如果是直接提交的数组的话就不会用来切割了。 还能用来生成逗号。

但是当更新的时候
34444444
又变回去了。 好像是 在更新的时候 从数据库中取出来的
又用db_create_in 来处理一下了
55555555555555
应该是我没搞对把。

那就试试直接提交 不用逗号的把。
666666666666
可以不用逗号来Union 但是NULL 排在第一去了 所以不能显示密码出来。 给它降序。
777777777777
好像可以了 放到网站中去搞搞试试。
88888888888888
但是没显示完全, 一开始还是以为显示字符只能显示6个。 所以想到的是substr
6位6位的 一次一次的来。
后面测试的时候才想到 substr 也有逗号。。
从花开那里看到, substr 还可以 substr from 1 for 1
就可以不用逗号了。 然后我就
9999
但是还是没显示出来 难道不是字符长度的原因。 后面我显示第八位 都可以显示出来。
后来看了看密码793702c53af95c46fb4657722daf5587
原来第7位是字母, 后面才知道是这个显示位不能显示字符的。
那就给他转换成hex把。啊
但是Hex 位数也不能太多, 太多了 直接999999999999了。
一次 From 1 for 3 或者4 差不多才能出来。 这样搞10次 密码也就出来了把。
阿坝办法
擦
是可以还原回来的
超级老的ecshop 的漏洞。

Demo/index.php
在新的版本中 这个文件都判断了lock

 
if(file_exists(ROOT_PATH ."data/install.lock"))
{
    die('You have installed! ');
}
如果存在lock 就会退出了。 不过找到了个超级老的ecshop 还是没判断lock的。

而且这个在管理进入后台后 就会提示手动要删掉demo 所以很多都没咯。

 
case 'setup_ucenter' :
 
    include_once(ROOT_PATH . 'includes/cls_json.php');
    $json = new JSON();
    $result = array('error' => 0, 'message' => '');
 
    $app_type   = 'ECSHOP';
    $app_name   = $db->getOne('SELECT value FROM ' . $ecs->table('shop_config') . " WHERE code = 'shop_name'");
    $app_url    = url();
    $app_charset = EC_CHARSET;
    $app_dbcharset = strtolower((str_replace('-', '', EC_CHARSET)));
    $ucapi = !empty($_POST['ucapi']) ? trim($_POST['ucapi']) : '';//可控
    $ucip = !empty($_POST['ucip']) ? trim($_POST['ucip']) : '';//可控
$dns_error = false;
省略。
$ucconfig = dfopen($ucapi.'/index.php', 500, $postdata, '', 1, $ucip);
省略。
elseif(($succeed = save_uc_config($ucconfig."|$ucapi|$ucip")))
 
function save_uc_config($config)
{   print_r ($config);exit;
    global $db, $ecs;
    $success = false;
 
    list($appauthkey, $appid, $ucdbhost, $ucdbname, $ucdbuser, $ucdbpw, $ucdbcharset, $uctablepre, $uccharset, $ucapi, $ucip) = explode('|', $config);
 
    $config_file = ROOT_PATH . 'data/config.php';
    $s = file_get_contents($config_file);
    $s = insertconfig($s, "/\?\>/","");
 
    $link = mysql_connect($ucdbhost, $ucdbuser, $ucdbpw, 1);
    $uc_connnect = $link && mysql_select_db($ucdbname, $link) ? 'mysql' : 'post';
    $s = insertconfig($s, "/define\('EC_CHARSET',\s*'.*?'\);/i", "define('EC_CHARSET', '" . EC_CHARSET . "');");
 
    $s = insertconfig($s, "/\/\*\=*UCenter\=*\*\//","/*=================UCenter=======================*/");
    $s = insertconfig($s, "/define\('UC_CONNECT',\s*'.*?'\);/i", "define('UC_CONNECT', '$uc_connnect');");
    $s = insertconfig($s, "/define\('UC_DBHOST',\s*'.*?'\);/i", "define('UC_DBHOST', '$ucdbhost');");
    $s = insertconfig($s, "/define\('UC_DBUSER',\s*'.*?'\);/i", "define('UC_DBUSER', '$ucdbuser');");
    $s = insertconfig($s, "/define\('UC_DBPW',\s*'.*?'\);/i", "define('UC_DBPW', '$ucdbpw');");
    $s = insertconfig($s, "/define\('UC_DBNAME',\s*'.*?'\);/i", "define('UC_DBNAME', '$ucdbname');");
    $s = insertconfig($s, "/define\('UC_DBCHARSET',\s*'.*?'\);/i", "define('UC_DBCHARSET', '$ucdbcharset');");
    $s = insertconfig($s, "/define\('UC_DBTABLEPRE',\s*'.*?'\);/i", "define('UC_DBTABLEPRE', '`$ucdbname`.$uctablepre');");
    $s = insertconfig($s, "/define\('UC_DBCONNECT',\s*'.*?'\);/i", "define('UC_DBCONNECT', '0');");
    $s = insertconfig($s, "/define\('UC_KEY',\s*'.*?'\);/i", "define('UC_KEY', '$appauthkey');");
    $s = insertconfig($s, "/define\('UC_API',\s*'.*?'\);/i", "define('UC_API', '$ucapi');");
    $s = insertconfig($s, "/define\('UC_CHARSET',\s*'.*?'\);/i", "define('UC_CHARSET', '$uccharset');");
    $s = insertconfig($s, "/define\('UC_IP',\s*'.*?'\);/i", "define('UC_IP', '$ucip');");
    $s = insertconfig($s, "/define\('UC_APPID',\s*'?.*?'?\);/i", "define('UC_APPID', '$appid');");
    $s = insertconfig($s, "/define\('UC_PPP',\s*'?.*?'?\);/i", "define('UC_PPP', '20');");
    $s = insertconfig($s, "/\?\>/","?>");
 
    return file_put_contents($config_file, $s);
以| 来分割, 然后内容加上 UC_KEY UC API 这些。

然后写入data/config.php

打发
放大放大
大幅度
掉


#Webvul团队原创   #www.webvul.com #雨@webvul.com #yu@webvul.com

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论