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行调用了yzmbase类的creat_app()文件,跟进一下,调用了_load_sys_class方法(81行)看一下,又调用了loadclass(92行)
跟进一下,发现实例化www/yzmphp/core/class路径下的$classname.class.php所以load_sys_clas**_s()函数对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文件继续,URLMODEL不为零,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查找利用此页面的控制器
构造payloadhttp://127.0.0.1:8080/member/member_message/init.html?start=11%22%3E%3Cscript%3Ealert(1)%3C%2Fscript%3E%3C%2Fscript%3E)
全局查找if(isset($_GET[还能找到许多类似的
0x05存储型xss
application\collection\controller\collectioncontent.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师傅的文章复现,未经许可禁止转载!
