YzmCMS v5.7审计
YzmCMS v5.7
链接:https://pan.baidu.com/s/1187RR0NDJ0TH9UdWlC_XBA
提取码:upua
0x00了解MVC架构
进入入口文件./index.php,先把defind定义的常量取出来
这里引用heihu师傅的代码,放在index.php的最后
foreach(get_defined_constants(true)['user'] as $k=>$v){
echo $k.'---'.$v."\r\n";
}
查看源码复制出来,记在小本本上(文章下面的红体加粗的函数也建议拿出来记在小本本上)

继续看index,加载了个yzm.php文件,通过小本本可以知道是WWW/yzmphp/yzmphp.php

跟进看一下(当进入另一个文件时可以通过设断点来记一下位置,防止忘记),第33行用了个调用了个load_sys_func静态函数

不慌查一下就在下面129-134行,可以看到这个load_sys_func()函数是确认./yzmphp/core/function/路径下的$func.func.php文件是否存在,如果存在则引入

回到33行,说明是引入了global.func.php文件,做个标记跟进一下,发现global.func.php定义了一些方法

回到yzmphp.php文件,往下读,48-54将当前文件名定义为常量,63-67将gpc状态定义为常量

70行调用了load_common方法,找到load_common方法142-156行,此函数概括为若m未定义则引入WWW/common/$path文件,若m定义则引入WWW/$m/common/$path文件

所以回到70行,加载了WWW/common/function/system.func.php文件,跟进一下,里面同样定义了一些方法,粗略的读一下

71、72同理,一个是加载用户自定义函数的,一个是加载版本的,到这yzmcms.php文件就读完了,回来我们再看index.php文件21行调用了yzm_base类的creat_app()文件,跟进一下,调用了load_sys_class方法(81行)看一下,又调用了_load_class(92行)

跟进一下,发现实例化www/yzmphp/core/class路径下的$classname.class.php所以load_sys_class()函数对www/yzmphp/core/class/$classname.class.php进行包含并实例化

所以回到81行,对www/yzmphp/core/class/application.class.php进行了实例化,打开看一下,实例化时会执行构造函数

我们看一下都做了啥,第16-19行做了debug设置,20行加载了param类

跟进www/yzmphp/core/class/param.class.php类,15-16获取配置信息,调用了C方法,这个函数在我们之前global.func.php公共函数库941-964行。如果key存在则返回config[key]的值,否则返回$configs['config'],简单点说C方法就是获取config.php内的配置参数的值

回到param.php文件继续,URL_MODEL不为零,19行为空,执行pathinfo_url()

跟进pathinfo_url(),是对参数s或者$_SERVER['PATH_INFO']进行路由解析

param.class.php类解析完,回到application.class.php类看第21-23行,执行了param.class.php的route_m/a/c方法

跟进看一下,获取m参数,经过了safe_deal()函数过滤(里面用了个addslashes()函数并过滤了引号和反斜杠),参数a和参数c同理

回到application.class.php继续看24行,调用了init(),看一下(31-46),32行调用了load_controller()

跟进load_controller(),作用是包含/WWW/application/$m/controller/$c.class.php文件并实例化即加载控制器类

回到32行,加载控制器类后,在确定ROUTE_A方法是否存在,然后通过回调函数执行此方法

读完init()函数application.class.php文件就读完了,对整个mvc框架有了大概的了解
大概是加载公共函数库,加载系统函数库,配置debug,解析路由,再通过解析到的a、c、m参数加载相应的方法
一:http://www.XXX.com/模块名/控制器/方法
所对应的文件路径为 ./application/模块名/controller/控制器.php 所对应的方法则是传递过来的方法。
二:http://www.XXX.com/?s=模块名/控制器名/方法名
所对应的文件路径为 ./application/模块名/controller/控制器.php 所对应的方法则是传递过来的方法。
三:http://www.XXX.com/?m=模块名&c=控制器名&a=方法名
所对应的文件路径为 ./application/模块名/controller/控制器.php 所对应的方法则是传递过来的方法
我们在application下的admin模块下的controller下建一个dd.class.php文件方法为test

0x01解密admin/con.../index.class.php
将最后的eval换成echo输出出来


将输出出来的内容复制到下一行,并将之前的echo换回eval,将复制内容的最后的eval函数再换为echo,用burp发送请求。明文就出来了将密文替换为明文重新执行一边看看是否正确

可以看到执行成功

0x02过滤机制
看了这么多还没看到过滤机制,打开application/admin/controller/下的任意文件找个sql语句跟一下,此处用的是admin_manage.class.php,跟一下13行
此处调用了www/yzmphp/core/function/global.fun.php下的D方法870-877行

873加载了db_factory类,然后调用了get_instance()方法看一下配置文件下的db_type为pdo所以走37行,加载db_pdo.class.php并返回一个对象

看下这个对象下的connect(),用调用pdo连接数据库

回到D方法总结下就是连接指定的数据库,默认为pdo方式连接。看下执行的select方法

跟进339行,做了预处理,框架默认编码为为utf-8,所以就不考虑SQL注入了

0x03CSRF漏洞
application\admin\controller\common.class.php文件
第11行有个检测登录的函数,我们跟进一下

29行,是检测referer的我们继续跟进

81行判断了HTTP_REFERER,如果没有的话会返回true,在poc中加入
<meta name="referrer" content="never">
发送请求时则不会携带HTTP_REFERER

我选择管理员的权限管理请求来测试csrf,将权限点满然后抓取请求

右键构造CSRF POC

我们先不添加<meta name="referrer" content="never">来测试,点击下面test,生成url

进入浏览器点击submit request后,被拦截了

我们再加上<meta name="referrer" content="never">来测试,不要忘记加上head标签,并把之前打勾的取消掉

显示操作成功,进入后已经修改成功了


0x04反射型xss
application\member\view\message_list.html

此处为管理员后台,测试时需要先登录有个cookie,我们先全局搜索message_list查找利用此页面的控制器


全局查找if(isset($_GET[还能找到许多类似的

0x05存储型xss
application\collection\controller\collection_content.class.php
第28行,插入数据跟进看一下

之前我们已经看过了数据库操作都在./yzmphp/core/class/db_pdo.class.php,找到insert(),有个过滤函数safe_data()跟进一下

$chars默认为false,从insert()中传入的参数filter也默认为false,所以没有经过htmlspecialchars()函数过滤

我们测试一下,

点击列表测试信息,测试成功

但是经过进一步测试发现有20个字符限制,查找发现是在数据库中限制的

那我们再找一个全局搜索个差不多的关键词 )->insert($_

根据之前的路由方法找到相关的利用模块

测试

这个也有字数限制,比之前的稍微多点。。。。。。

0x06 SSRF漏洞
application\collection\controller\collection_content.class.php
此处直接将url放入get_content方法中,跟进

方法中未进行过滤,传进来的url也未进行过滤,存在ssrf

测试


0x07总结
对于不同的漏洞要有不同的检测方式,像本文中csrf要着重看它公共类中的referer的检测机制,xss去view层去找未过滤就输出的变量,ssrf去找curl关键词,看到预编译sql语句的话,可以去检查他们的编码方式,若是宽字节的话,有可能绕过。
参考文章:
https://www.freebuf.com/vuls/248912.html
*本文根据heihu师傅的文章复现,未经许可禁止转载!

浙公网安备 33010602011771号