前言
MCMS为java免费开源商用的CMS内容管理系统/基于SpringBoot 2/前端Vue3/element plus/提供上百套模板,同时提供实用的插件,适合上手练习。
搭建
代码下载地址https://gitee.com/mingSoft/MCMS/tree/5.2.6/
下载完修改一下数据库配置文件,添加mcms数据库即可启动
审计
1、SQL注入
1、第一处
方法名是queryChildren,追踪哪个用了这个方法,在最上面
继续追谁调用了这个方法
可以看到有四个地方调用了这个方法
查看第一个方法
可以看到_category的id来自于category.getid()方法,追踪这个category来源于哪里。
可以看到@ModelAttribute注解,这个注解告诉 Spring MVC 应用程序,方法参数 category 应该从 HTTP 请求的查询参数或者表单数据中自动绑定。Spring MVC 会尝试将请求中的参数名与 CategoryEntity 类的属性名匹配,并填充 CategoryEntity 对象。
根据代码看到只校验了title是否为空,那么我们可以构造测试数据包
尝试注入
2、第二处
经过分析第二个调用的方法是不存在注入的,我们查看第三个调用
可以看到目录为{categoryid},可以看到下面存在一个@PathVariable String categoryId,@PathVariable 是一个 Spring 框架中的注解,用于将 URL 中的模板变量绑定到控制器方法的参数上。当你定义了一个带有占位符(如 {categoryId})的路由时,Spring 会将实际 URL 中这部分的值传递给带有 @PathVariable 注解的方法参数。所以在此处categoryid既作为目录又作为参数传入数据库进行操作
可以看到上述参数不存在过滤操作,尝试找到功能点进行注入。
其中这个0就是我们传入的参数,尝试注入
3、第三处
追踪第三处调用的方法可以看到方法大致和第二处注入一样,唯一区别是校验了传入的是否为0,所以我们需要修改一下数字
将包拿出来尝试注入
4、第四处
在DAO文件中搜索$,一个个参数的追,可以看到${categoryId},id是query,追踪是关联了哪个接口
可以看到最上面IContentDao为他的映射器,继续追IContentDao
进入IContentDao未查找到id为query的方法,继续看他的父类IBaseDao
追进IBaseDao,发现IBaseDao为编译好的class文件。
这个时候我们不能直接点击追踪query方法,因为当前我们所在的文件是编译好的,如果直接点击跳转容易发生错误跳转回mingsoft.cms的代码中,此时我们在的位置为ms-base-2.1.12.jar包下
根据代码分层思想,我们去找与IBaseDao对应的service
IBaseBiz:这是一个接口(Interface),定义了一组方法签名,这些方法是所有实现了该接口的类必须实现的。接口提供了抽象方法的定义,但不包含具体的实现细节,所以我们点击上述指向的1 implementation追踪是哪个接口实现了BaseBiz 接口的具体类
这时候就可以点击谁调用了这个方法
可以看到有两个调用了此方法先追踪第二个查看
可以看到未经过滤直接传入查询方法为post请求,查看接口,发现是前端可以不用登录直接访问
拼接进行访问
直接将数据包丢进sqlmap进行注入
可以看到注入成功。
5、第五处
点击第一个contentaction
可以看到和第四处的注入差不多,只不过这个注入是后台的注入
这里就不做演示了,和第四处一样,只不过需要登录的情况下。
同理此处也存在,依旧是query方法,只不过传入的参数不同,这里所接受的参数是contentType
6、第六处
在审计的时候发现存在一个,这个标签用于包含另一个SQL片段,而refid是指向这个SQL片段的ID
我们追踪这个sqlwhere,可以看到多处未进行预编译
再次追进query查看调用情况,可以看到五处调用了categoryBiz的query方法
分析后有两处传入的数据受用户控制,其中一个接口为后台一个为前台,我们就分析一个前台,后台的操作是一样的
根据接口分析,传入的数据直接受用户的影响
拼接URL进行访问
查找sqlwhere的来源,追categoryEntity发现不存在,发现继承了BaseEntity
跟进BaseEntity查看,
xml文件里验证的sqlwherelist,查看sqlwherelist来源于哪里
在BaseEntity可以看到sqlwherelist来源于sqlwhere
所以我们传入的参数应该为sqlwhere,根据需要的数据进行构造,可以看到首先是校验了item.el然后multiple,最后查询了item.value和item.field
那么我们就需要4个参数,构造测试(在这里构造的时候出了很多问题,在进行post方法传参数的时候不知道为什么直接把数据包放下面不行,只能放在上面的时候才能测试)
而我将这个数据包放在URL的时候就可以进行注入了
另一处后台相同注入的就可以通过第一种方式进行注入
看代码除了一个可以用get和post两种方法,一个只能用post方法,就没什么区别了。
这个sqlwhere存在的地方利用点的方法都差不多,这个存在于编译好的idictDao.xml文件里了
追踪到IDictDao.class后续就需要自己手动查找了,根据分层思想可以最终找到他的应用层DictAction.class
未经过过滤直接接收
构造语句进行注入
相同的id为query的也存在,过程一样就不做演示了
7、第七处
在审计sqlwhere时候看到存在一个orderBy
根据上述的流程,直接构造注入尝试是否成功
除了queryExcludeApp还有query也存在,审计方法一样就不做演示
8、第八处
全局搜$在ibaseDao文件里发现第一处$
可以看到id为queryBySQL,再次朝上追,查看调用情况
到这一步无法点击追踪了,只能根据分层思想手动往上查找
经过手动查找调用了queryBySQL的应用层查询到在基础应用层的父类里存在方法调用
在这里我们需要再次手动查找谁调用了validated,一共查到两处调用
根据分析第一张图片不存在注入,因为根据追踪,最后在xml里处理的wheres来源于where.put(fieldName, fieldValue);所以对应的key应该就是fieldName,而第一张图片的的key为写死了的,所以无法注入
查看第二处可以看到参数均来自于用户输入
构造语句进行测试
ibaseDao其他处也存在$,但是由于过多且不好搜索,大致审计过程如上图所示。
2、xss
可以看到存在xss过滤器,进去看一下过滤器怎么写的
过滤器要不走xss过滤则需要(!this.handleIncludeURL(req, resp))为true,那么说明this.handleIncludeURL(req, resp)返回的信息需要为false才能进入下一个过滤器,从而不走xss过滤那么分析如何让返回的结果为false,可以看到有两种方式返回结果为false,首先是最外层检验includes是否为空,那么追踪这个includes来源
追踪includes来到webconfig配置文
可以看到includes添加了*/search.do,所以这一步无法走到false
回到刚才,查看第二种情况,可以看到就是确认请求的路径是否是includes里面的,如果是返回true,否则返回false,所以这个过滤器存在问题,只对search.do进行了过滤
那么我们去访问查看一下search.do页面,那么既然拦截了search.do页面的请求,那么我们在其他页面插入xss即可绕过
修改标题
3、文件上传
1、第一处
全局搜索upload查看结果
查看/file/upload接口
可以看到上述代码未有对上传进行限制,查看配置文件可以看到禁止上传此类后缀结尾
但是在后端发现存在基础接口解压接口
zip结尾的不在该配置文件中,可以上传一个带有jsp文件的压缩包,再调用此接口解压
上传成功,查看如何进行解压,get方式传入我们上传的路径即可进行解压
查看解压后内容
但是尝试了访问都不解析,了解到如果是springboot启动的情况,虽然能访问到jsp⽂件但是不能解析,只有在tomcat部署的情况下才能解析成功。其中有一处上传为此接口后台上传基础接口,就不复现了。
2、第二处
在审计第一处上传时发现,存在写入文件内容的地方
发现getRealTemplatePath,追进去查看
发现该方法里也存在校验路径是否存在../等路径,黑名单包括了exe,jsp,抓包测试,发现可以构造WEB-INF/manager/cms/category/form.ftl,覆盖模板文件form.ftl,然后执行我们的危险命令%3C%23assign%20ex%3D%22freemarker.template.utility.Execute%22%3Fnew%28%29%3E%24%7Bex%28%22ipconfig%22%29%7D(<#assign ex=”freemarker.template.utility.Execute”?new()>${ex(“ipconfig”)})
这种情况需要我们进行热部署,大多数系统都是采用的热部署,热部署可以在进行部署时,不需要关闭整个应用程序,从而减少了因部署引起的停机时间。可以随时进行更新,无需计划性的维护窗口。我们上传成功后就要去找到哪个action使用了该接口
访问该接口
我们的命令执行成功。
2、第三处
不存在过滤,直接点击进行上传
同理访问此文件
命令执行成功。
结尾:会不定时更新审计文章,审计思路。
原文始发于微信公众号(Bi8bo安全):mcms审计