ECshop 漏洞分析
0x01 前言
这两天出来一个ECshop的全版本RCE漏洞。先感慨一下,自己怎么这么菜,当时审计的时候没发现。最近事情又多,又开始懒了,所以这里补一下这个坑。
漏洞环境
ECshop_v2.7.3
nginx
php
0x02 分析
漏洞的触发点在于ECShop系统的user.php文件中,display函数的参数可控,可以配合注入可达到远程代码执行的效果。
由于是可以不登陆的前台RCE,所以这个漏洞危害还是很高的感觉,利用成本感觉也相当的低。所以分析的时候分两部分,第一部分是SQL注入分析,第二部分是RCE分析。
SQL注入
首先漏洞的触发点在user.php文件中的Referer字段里,我们截取部分相关代码看一下。第8行中的$back_act变量从server数组中的Referer字段获取数据,众所周知,Referer字段是可控的。然后代码中的第20行以assign方法处理$back_act变量的值。第21行以display方法处理user_passport.dwr。
跟进一下assign方法,这个函数位置在/includes/cls_template.php文件中,我们截取部分相关代码,从代码中来看assign方法的作用是把可控变量传递给模版函数。
我们继续跟进一下display方法,该方法出现在/includes/cls_template.php文件中,截取部分相关代码。这里的display方法的作用应该是将模版内容展现在页面上。
而我们刚刚user.php中的代码是这样的。
所以这里display方法的使用就是读取user_passport.dwt文件的内容,然后解析变量展示为html,并且在第18行中交由_echash进行分割处理,得到的$k变量的值交由insert_mod方法进行处理。这里实际上insert_mod方法中的$val是可控的。我们跟进一下insert_mod方法。
该方法出现在/includes/cls_template.php文件中,截取部分相关代码。这个insert_mod方法在第三行以字符分割传入的内容,第四行反序列化传输入的$para,然后第五行通过字符串拼接的方式动态调用函数,最后在第7行返回调用函数处理$para变量的结果。
所以这里insert_mod方法里的函数与参数均可以被控制,我们知道注入点在/includes/lib_insert.php中的insert_ads方法,我们看一下相关代码。
这里很明显第21行和第22行的$arr[‘id’]和\$arr[‘num’]存在SQL注入。我们来验证一下漏洞。我们看一下正常的登陆过程中的序列化字符串
然后我们看看我们的sql注入的payload
远程代码执行
漏洞触发流程还是通过user.php文件中的Referer字段传递参数,然后通过display方法处理user_passport.dwr。跟进display方法,该方法在/includes/cls_template.php文件中,这次的触发点是在第16行的fetch方法。
跟进fetch方法,相关代码/includes/cls_template.php文件。这里第20行的_eval函数引起了我的主意。跟进一下_eval函数。
_eval函数出现在/includes/cls_template.php文件,我们看看相关代码,eval函数里的可控,那么就会造成RCE的问题了。
所以这里需要找一下哪里调用了这个fetch方法,回过头来,我们想想,我们的SQL注入通过动态函数调用,找到存在注入点insert_ads的函数。那么我们在找找这个函数,我们发现这个方法也存在fetch方法的调用,相关代码出现在/includes/lib_insert.php文件中。
我们看到第7行有这样一样代码,
跟进一下$position_style,该变量的取值过程也在/includes/lib_insert.php文件中写好了。该$position_style变量是从数据库中获取数据,假设这个字段可控,那么就会有RCE问题产生了。
这里我们就需要配合刚刚说的SQL注入漏洞。我们知道注入点有两处,一个是$arr[‘id’],另一个是$[‘num’]。$arr[‘id’]的位置在and后,可以构造union联合查询。而$[‘num’]位置在order by后面,所以这里可能没办法使用,我们可以截断它。
这里针对$row[‘position_id’]做了判断,所以首先我们需要绕过这里判断。
这里我们可以在id处传入这里的作用就是闭合前面的单引号,然后配合num的值注释掉。
在数据库里运行之后
这里我们前面分析过,我们可控的字段是$row[position_style],因此这里需要将payload的位置填写在$row[position_style]。
这里我们在回过头来看看fetch方法,相关代码/includes/cls_template.php文件。主要是查看是否有做一些过滤。我们看到第20行调用fetch_str函数处理传入的数据,跟进fetch_str函数。
该函数出现在/includes/cls_template.php文件中,截取相关代码,关键代码在第13行。
这个函数处理之后最终会return回一个数据,而这部代码主要的作用是假如,那么经过这行代码处理后就是返回的值。
这里继续跟进一下select函数,该函数位置也在/includes/cls_template.php文件中。我们看到第21行,出现的时候,会调用get_val函数进行处理。
跟进get_val函数,该函数位置也在/includes/cls_template.php文件中。代码第14行当我们的\$val参数没有会在第26行调用make_var函数进行处理。
跟进一下make_var函数,该函数位置也在/includes/cls_template.php文件中。这里我们的$val变量最后处理的结果实际上是个字符串。
所以这里我们下个断点看看。
这里的对应的值是
因此这里实际上,我们需要闭合这个单引号和反括号,逃逸出来然后执行我们想执行的东西。
最后会在根目录下生成一个马。
0x03 修复方式
我们可以看到最新版在$arr[‘num’]和\$arr[‘id’]中加入了intval,强制类型转换来修复。
0x04 思考
PHP下这种模板引起的RCE好像不少见了,seacms的那个好像也是因为这个引起的,但是吧,这个问题为啥自己没审计到呢,归根到底还是太菜了。
0x05 参考文章
ECShop全系列版本远程代码执行高危漏洞分析
ecshop2.x代码执行
新年快乐
领取专属 10元无门槛券
私享最新 技术干货