天目MVC审计一

前言

我们今天来从零开始审计一款CMS:天目CMS
本文章由二农戏猪编辑

天目CMS 官网

MVC架构的了解

  • MVC架构一般包括三个部分:M是指业务模型,V是指用户界面,C则是控制器。具体情况大家可以百度查看。

  • 根据我们对于MVC的了解。我一般有两种审计模式:

直接审计控制器

也就C的内容,再追踪一些函数。全局搜索一下filt__,因为 filt 的英文意思为过滤,可以通过全局搜索这样式的函数来查看一下过滤规则。这种一般是比较快速审计。

但是这种情况一般建立在你可以清晰明白该款CMS的路由规则,适合老鸟,方便根据审计出来的漏洞的点去回溯验证

从index页面通读审计

这种审计方式是我认为像我这样的菜鸡比较合适的。也不容易忽略一些漏洞。该篇文章就是以这种方式审计的!

开始审计

准备

在审计开始时,我一般习惯于观察一下目录列表,从而可以对整个CMS有一个大概的了解:

app -----------------------------------  主程序目录
attachment ---------------------------- 附加目录
public -------------------------------- 公共程序
runtime ------------------------------- 一般为日志文件
temmoku ------------------------------- 一些插件,配置文件等
view ---------------------------------- 视图
index.php ----------------------------- 程序入口

index.php

我们可以看到的是index.php就是定义了一些常量,并且包含了 ‘temmoku’.DS.’run.php’ 这个文件。

image-20210210211353917

对于这些常量,我看到过一个表哥有一种方法,就是在index.php末尾去添加,将常量打印出来,保存到一个.txt中查找

记得点赞收藏哦!

foreach(get_defined_constants(true)['user'] as $k=>$v){
echo $k.'---'.$v."\r\n";
}

所以我们可以发现,DS就是\ ,它其实是包含了 temmoku\run.php 这个文件

run.php

然后我们进行跟进 ==>

image-20210210212409069

image-20210210212827281

好的,又是一堆常量和包含了 C:\phpstudy_pro\WWW\temmoku\temmoku\functions.php

C:\phpstudy_pro\WWW\temmoku\temmoku\app.php

这两个php文件,并且实例化app这个类中的run方法。

functions.php

跟入functions.php,发现里面定义的一脸的各种方法,先放着,等审计控制器中的某些地方具体调用时,再具体审计。

app.php

跟入app.php,开头看到namespaceuse这两个东西,不明白,好的,百度一下我们了解到: use 从同一个 namespace 中导入类、函数和常量。然后发现再run.php中调用了app这个类中的run方法,我们找一下。

image-20210210213836989

spl_autoload_register函数其实简单来讲就是自动实例化类。

Load_Class,就是将传进来的$class里面含有的\\转为/,判断存在就包含

image-20210215203905374

再跟进str_caps_look这个函数,前面我们传进来的$caps=1,将$class:xxx/xx,先分为xxx、xx转换为小写以后合并

image-20210215204247840

回到app.php,接下来就是调用setReporting()方法,简单看一下,不怎么重要,大概就是一些错误报告等级之类的东西。

default_config()方法,判断了caching.php这个文件是否存在,并且包含,看了一下就是去加载一个高速缓存的东西,这里我们注意一下,看看后面$setting['caching']会不会可控。

image-20210210214554200

冒险继续,这里定义了一个配置信息和一个路由信息,并且放入了Load_conf进行处理,我们跟进

image-20210210214911924

这里将末尾的conf 和 route单独拿了出来,并且将目录读取,将文件也读取,大概就是这么一个意思,也就是加载了conf配置和路由信息

image-20210210215340521

然后我们回到app.php中继续审计,在124行我们看到一个C方法,跟进,冲!!!!!!发现C方法其实就是加载了一些程序变量,对于这个东西,我还是采用看到的一篇文章中提到的方法,就是给C方法添加一个形式参数,然后去index.php末尾调用,然后将得到的程序变量保存在一个txt中,需要的时候去搜索。

后面就是去加载了一下版本信息

~,发现了个getRealIP这个方法,盲猜就是获取真实IP,啊哈哈哈哈哈

image-20210210222530227

嘿!好家伙,果然是这样的。我们发现,如果对CLIENT-IP进行伪造是不会成功的,但是是可以对X-FORWARDED-FOR参数进行伪造,这…..看不懂这个操作,这个就可以先记录,等完事儿看看会不会getRealIP给我们带来惊喜。审计就是这样,你永远不知道后面会发生什么。

image-20210210222740047

到这里基本default_config方法就看完了,后面就是对一些常量的定义了。

接着我们回到app.php中继续继续,20行实例化了一个route,我们回想起前面use temmoku\route,去文件夹里找一下,当看到对类进行实例化时候,我们一般是需要关注魔术方法,看到它先是对C:\phpstudy_pro\WWW\temmoku\app\module_route.php判断是否存在该文件,然后传入Load_file处理,就是在加载一些静态数组,并且定义了两个常量。

image-20210215205456471

接着是调用Route()这个方法,然后对这个方法里面往下看,前面以get方式获取到的PATH_INFO进行分割,遍历

image-20210215210707668

在接下来这个if分支,我们发现ROUTE这个数组默认为空,所以先放下不看

image-20210215211048571

这个就是定义了伪静态的方式

image-20210215211156798

如果给$_SERVER['PATH_INFO']传入了值,会以/分割,变成包含两个元素的数组,例如xxx/xx,变为xxx、xx,$test_module也就是传入的再第一个/以前的内容,然后就是将xxx转换为小写,之后判断是否安装,也就是$lock是否存在,存在则为已安装

image-20210215211409458

紧接着就是如果判断是否有 $test_module,如果没有,则定义MODULE为home

image-20210215212644510

接着我看到了熟悉的m、c、a,if条件语句里前面C(‘URL_RULES’)晓得是啥,后面'admin'!==MODULE,我们尝试一下用这种方式访问一下,看到是可以的,但是admin模块是不可以用这种方式访问。

image-20210215214837246

image-20210215215026742

139行就是如果没有定义模块,则默认为home模块,141-142行说的是admin模块是进行特殊的一个路由,就是Admin_Route()这个方法,这个一会儿再看。

image-20210215223322004

接着是加载插件和各个模块下的私有函数

image-20210215223659642

在159-174行,将$_SERVER['PATH_INFO']/分割,定义路由,例如home/index/index,指的就是home模块下,index控制器下,index方法。

image-20210215223757919

然后我们回过头来看Admin_Route(),也就是admin模块下的路由规则,同样也是将$_SERVER['PATH_INFO']/分割,然后去遍历,并且分别判断控制器是否为modular或plugin

image-20210215224629802

然后我紧接着发现了个大宝贝。这。。。。这就是过滤?

image-20210215225323616

我们追一下filtering这个函数,在functions.php这里面定义了过滤规则。将'id','aid','cid','uid','mid','cmid','iid','nid','cityid','proviceid','countyid','townid','upcid','state','reply_id','lid','iddb'都强制转换为int类型,然后放入htmlspecialchars进行实体化编码。

EMMMMM…….这里好像是杜绝了XSS的攻击,如果SQL注入的话,必须参数不能为上述,且为数字类型。又或者是同时查询两个参数,用\去绕过。不急。先继续看app.php

image-20210215225423683

self::log();这个函数发现是记录日志的个东西,先放着。

然后跟一下self::Load_Controller(),在app.php 63-75行,$home这个变量是否等为admin、user、install、home,如果是:$home为空,如果不是:$home=’\home’。

然后判断是否为插件。

判断控制器是否存在。如果存在,对这个controller进行实例化。

image-20210215230026372

跟进class controller,里面就是去验证了下会员状态

image-20210215231106913

返回上面跟入app.php 71行的函数,发现它是判断了一下是否存在方法

image-20210215232418607

==> 通过上面的审计,我们发现了有三种路由规则。

路由规则

  • 127.0.0.1/模块名/控制器/方法 所对应的文件路径为 ./app/模块名/controller/控制器.php所对应的方法则是传递过来的方法。

  • 127.0.0.1/?temmoku_dirs=模块名/控制器名/方法名所对应的文件路径为 ./app/模块名/controller/控制器.php

==> 所对应的方法则是传递过来的方法。

127.0.0.1/?m=模块名&c=控制器名&a=方法名 所对应的文件路径为 ./app/模块名/controller/控制器.php

所对应的方法则是传递过来的方法。该种规则不能用于admin模块

尝试一下,好的 ,没问题,就是这样的路由规则,接下来我们开始正式审计控制器。

image-20210215233138485

image-20210215233200839

image-20210215233218770