通读审计之ShangFanCMS – 作者:Heihu577

0x00 前言

在之前几篇的通读MVC的文章中,访问的控制器大部分是由外部参数来决定的,那么本篇文章所通读的MVC框架与之前的一系列MVC框架不太一样,它的路由是由程序本身的路由表来决定的。

我们本次通读的CMS为ShangFanCMS,算得上比较冷门的CMS。

源码下载地址:https://www.jb51.net/codes/673736.html

0x01 MVC的了解

老样子,整个故事从index.php开始说起。

图片[1]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

从图中我们看到,其他CMS都是用常量来定义常量让整个程序拿来运用,而它却是定义全局变量。这里我们直接在底部var_dump即可。

图片[2]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

提取到程序主要变量之后,我们直接把目光放到第14行中。

图片[3]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到。/framework/Application.php文件中只是定义了一个类而已,我们看到index.php文件中的第15行直接调用了Application类下的run静态方法。我们看一下run静态方法是怎么玩的。

图片[4]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

我们可以看到,run方法的前三行是分别用来定义时区,服务器返回的header头以及屏蔽错误用的。

那么第Application.php文件的第28行包含进来一个function.php,该文件定义了许多公共的函数,这些函数可能在程序的应用上所用到。

而在Application.php文件的第29 – 34行中,使用spl_autoload_register函数来动态的包含类文件,这个函数我们可以暂时先放到这里不管,当我们审计到不认识的类文件时,再来看一下也无妨。

现在我们把目光放在Application.php文件的第35行:return static::runContext();

self与static的区别笔者在一篇文章有了解过,贴出链接:https://blog.csdn.net/qmhball/article/details/77369457

图片[5]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

在Application.php文件的第44 – 46行中,我们看到调用了appPath()函数,想必是在我们包含function.php文件中的。

图片[6]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到,appPath与rootPath函数无非就是将$GLOBALS[‘app’][‘app_path’]与$GLOBALS[‘app’][‘root_path’]给封装了起来。如图:

图片[7]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

我们转回头来继续看Application.php文件中的逻辑。

图片[8]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

将 ./shangfan/function/mall.php、./shangfan/function/member.php、./shangfan/function/merchant.php文件统统包含进来,我们分别看一下这三个文件是怎么玩的。

图片[9]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

都是分别定义了一些方法而已。那么我们继续往下通读。

图片[10]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

register_shutdown_function函数是在整个程序运行结束后调用的,可以看到回调函数中return了一个Exception类下的fastCgiCatchError方法,看到第7行use framework\Exception,然后调用spl_autoload_register函数来进行包含,现在我们了解spl_autoload_register比较清晰。

从spl_autoload_register函数中的回调函数中我们看到,只是包含 ./命名空间/类名.php 文件。这里我们打开./framework/Exception.php文件看一下fastCgiCatchError方法是怎么玩的。

图片[11]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

fastCgiCatchError方法的$_error是用来得到程序最终运行的错误信息,我们可以看到第34行中调用了configSystem方法,我们看一下这个方法是怎么玩的。

图片[12]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

configSystem只是封装了\framework\config命名空间下的Config类下的make方法,并且我们注意到这个第三个参数的true。

当调用不存在的类文件时,会进入到spl_autoload_register方法,spl_autoload_register方法之前我们有了解过,这里我们直接包含 /framework/config/Config.php 文件看下make静态方法是怎么玩的。

图片[13]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

代码的逻辑在图中详细的写出了,这里只是获取到./config.php文件debug的值。

图片[14]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

这里可以为true或false,但两者还是有区别的。

图片[15]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到如果debug为true,则进入到View类的output函数,如果debug为false,则进入到File类的writeStorageLog函数,我们通过类的命名方式可以猜测到,View是程序出Bug时的回显,而File则是写入错误日志,当然这只是猜测,我们还要进一步通读。

在第38行调用了stringFormat方法,将错误信息依次传入进去了,这里我们看一下stringFormat方法是怎么玩的。

图片[16]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到stringFormat方法只是将错误信息都整理成字符串。这里我们目光直接转移到39行的return File::writeStorageLog($message);

跟进File类看一下writeStorageLog方法是怎么玩的。(./framework/file/File.php文件)

图片[17]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

通过这里我们可以了解到,如果config.php文件的debug定义为false,则会开启错误日志记录,会记录到 ./storage/log/当前日期.log 中。

这里笔者进行测试。

图片[18]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

好,debug机制我们了解完毕后我们回到./framework/Application.php文件中继续读取。

图片[19]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

在第37行中调用了RouteDriver::driverReady(),我们跟进./framework/route/Driver.php文件看一下driverReady方法是怎么玩的。

图片[20]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

将图中左侧中/shangfan/route/base/h5、/shangfan/route/base/web目录中的所有文件统统包含进来。

我们看一下是怎么玩的。

图片[21]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

简单打开两个文件后,我们看到有那么多行代码在我们面前,都是调用了Route::get、Route::post以及Route::any,这里我们打开一下./framework/route/Route.php文件是怎么玩的。

图片[22]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

从图中我们可以看到,get、post、any都调用了restful方法,区别只是第三个参数的传递不同,在restful方法中,我们可以看到,原来上一张那么多代码是用来生成路由表的。从第63行的@符的分隔,再加上第70行的method下标我们可以猜测出默认调用的方法是什么。

我们回到./framework/Application.php文件。

图片[23]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

从第38行看到,这里并不是使用$_SERVER[REQUEST_URI]来接收,而是使用filter_input(INPUT_SERVER, REQUEST_URI),这两种接收方式理论上都是可以的。随后调用到Route类中的search方法,我们看一下search方法都做了一些什么。

图片[24]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

用来处理REQUEST_URI来使网站支持静态化、参数接收、请求类型检测等功能。

我们回到Application.php文件。

图片[25]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

什么?要删除路由表?这里我们要在unset之前提取出路由表来,方便我们后期的审计!

图片[26]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

将路由表扒出来后继续通读。

图片[27]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

这里callBeforeMiddleware方法与callAfterMiddleware方法在开发中其实都是new到了\framework\Middleware类,我们看一下/framework/Middleware.php文件中Middleware类的context方法。
图片[28]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

这里直接return一个true,所以进入不到上张图的80-82 / 91-93行中。

图片[29]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到47行的操作是用来处理Controller的。随后使用call_user_func_array方法来回调控制器下的某个方法。

这里还有最后的第55行,我们看一下View是从哪儿来的。

图片[30]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

这里第55行,View并没有被use,那么就是当前namespace下,包含./framework/View.php文件,看一下output方法是怎么玩的。

图片[31]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

使用了php://output来输出内容(View)。

我们整个路由清晰,自定义一个自己的路由器~

笔者在./shangfan/route/base/h5/mall.php文件中,添加一个这样的代码。

Route::get(‘/h5/mall/Heihu’, ‘\shangfan\controller\develop\h5\mall\HeihuController@index’);

图片[32]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

创建./shangfan/controller/develop/h5/mall/HeihuController.php文件内容如下:

<?php

namespace shangfan\controller\develop\h5\mall;

class HeihuController {

public function index(){

echo ‘Hello, World!’;

}

}

访问:

图片[33]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

我们路由清晰,开始挖掘漏洞~

0x02 管理员密码重置漏洞

在./install/action.php文件中,并没有执行exit。

图片[34]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

这导致了可以进行系统重装。

图片[35]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

在第54行中,可以看到先执行删除admin用户而又在55行insert了一条新的admin用户,这样会导致admin密码被修改。

POST提交:install/action.php

Payload:type=setup3&passwd1=admin123&passwd2=admin123

图片[36]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

成功修改admin密码。

0x03 无数个SQL注入漏洞

为什么说是无数个SQL注入呢?我们详细说一下。

图片[37]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

跟进./shangfan/controller/develop/web/admin/LoginController.class.php文件。

图片[38]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

WTF?是一个空壳,我们这个时候注意extends关键字,再次跟进extends后的./shangfan/controller/base/web/admin/LoginController.php文件。

图片[39]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

我们从37行可以看到,调用出SystemAdminUser下的login方法将request扔进去了。

我们先跟进framework/Request.php文件,看一下是怎么玩的。

图片[40]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

果然是用来处理外部请求的。

那么我们跟进SystemAdminUser模型(shangfan\model\base\SystemAdminUser.php文件),看一下处理逻辑。

图片[41]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到28与29行调用了request类下的post方法,我们看一下post是否有做过滤。

图片[42]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

$validator默认为true,这里我们进入到了一个过滤方法fliterParam,跟进看一下是如何过滤的。

图片[43]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到最终数组或字符串都会被进行stringRemoveXss静态方法处理,我们跟进。

图片[44]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

只是对XSS进行过滤处理,SQL注入却没有考虑!此时我们回到SystemAdminUser模型中,看一下其他处理逻辑,是否有过滤的情况。

图片[45]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到直接将未过滤的POST请求拼接成SQL语句,最后执行first方法,这种SQL语句结构预处理也救不了它!

我们不妨看一下first方法是怎么玩的。通读嘛,就得通读个遍。

图片[46]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

在该类中并没有找到first方法,那么必定是父类继承下来的,BaseModel没有被use进来,那么就在该命名空间下,我们跟进./shangfan/model/base/BaseModel.php文件查找first方法。

图片[47]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

BaseModel下也没有任何方法,Model类被use,我们跟进./framework/Model.php文件查找first方法。

图片[48]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

221行调用了db方法,没关系,我们跟进他,db方法在169行有return Database::getInstance方法,我们跟进Database类。

图片[49]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

跟进./framework/database/Database.php文件看一下getInstance方法。

图片[50]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

单例模式,返回Database类自己本身。

我们的初衷是找first方法,看一下first方法的逻辑。

图片[51]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到81行有mysqli_query方法。那么SQL注入无疑~

图片[52]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

可以看到成功盲注,这里笔者构造一下万能密码。

Payload:?user=’ UNION SELECT 1,2,3,’d6a6bc0db10694a2d90e3a69648f3a03′,5,6,7,8 #&passwd=hacker

图片[53]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

这种程序只要外部参数提交进SQL中,一般都存在SQL注入。

0x04 存储型XSS漏洞

刚刚不是程序存在过滤吗?为什么会导致XSS漏洞?我们再认真看一遍XSS处理逻辑。

./shangfan.com/framework/Request.php文件下的stringRemoveXss方法。

图片[54]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

看一下360行与367行,只有在正则匹配到“<内容>”才会进入到第367行,那么如果我们的XSS点本身就在标签之内,就可以执行事件形XSS。

图片[55]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

笔者找到一处a标签内的可控点,单击保存。

在首页单击。

图片[56]-通读审计之ShangFanCMS – 作者:Heihu577-安全小百科

0x05 读后感

为什么有时间写框架,却没时间写安全的代码。

来源:freebuf.com 2020-10-29 18:13:31 by: Heihu577

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论