本次审计的CMS系统为UJCMS最新版。立足于我现在的审计水平暂时是没有发现该系统的漏洞的,拉胯。本来今天晚上跟一个SQL注入的点跟的本来都要大功告成了,结果被当头棒喝,学会了什么叫人生的参差。废话不多说直接开干。
直接在整个项目中搜索关键字 order by ${
那么如果这个queryInfo.orderBy
可控的话就皆大欢喜了,目前来看有很大机会
这里注意到order by 是在一条id为Select_ALL
的语句中,对应的mybatis
文件名为SeqMapper.xml
,最开始的时候我就去找对应名称的DAO
层实现类,结果一直没有找到。最后迫不得已直接来了个全局搜索
注意到Select_ALL
出现在其他的mybatis
映射文件的include
标签里,这个标签就和php里的include或者require一个功能,用作代码复用。那么我们随便进入一个mapper.xml
,这里以Article.mapper
为例。
这里的sql语句id为selectAll
,返回值类型为ResultMap
,然后找到对应的DAO
层实现类
注意到这里是个接口而不是实现类,这是因为@Mapper @Repository
这两个注解的功劳@Mapper可以使接口在编译时自动生成器实现类,@Repositry注解帮助实现自动注入。然后就是取找对应的Services
层,这里也是去找对应文件名,不出意外是ArticleService.java
看到这里注入了AticleMapper
,然后在在当前文件搜索哪里调用了selectAll
方法
然后就是找对应的控制器
这么多,根据命名的规则,我们直接进入ArticleController
然后搜索有没有调用AritcleService.selectAll
方法的语句,一搜,啪,没有咋整,不要换,在回去ArticleService
里面看看有没有类本地的调用selectList
方法调用了,再回到ArticleController
看看有没有调用selectList
方法
这儿调用了,对应的路由为/api/article
然后就是看参数是否可控了,这里我么你可以控制的参数有三个,分别是params,queryMap,customsQueryMap
看看这三个参数怎么来的,跟到对应的query函数
在query
函数中为上述三个参数赋值,params
来自客户端传的参,queryMap
与customsMap
同样来自于客户端传的参,不过有要求,参数中前缀为Q_
的参数会被添加到queryMap
,前缀为custom
的参数会被添加到customsMap
中,然后调用ArticleListDirective.assemble
对queryMap
参数进行处理,跟进去看看
该函数前面都不重要,直到最后一条语句
这里就有处理orderBy
了,注意到有一个默认值,如果搞不好就得使用这个默认值,我们当然是不想的。
调用getString
函数进行处理,然后把结果添加到queryMap
中,跟进getString
重点来了,敲黑板,要考,注意到如果value为空则使用默认值,不为空则使用从param中获取的值,简直皆大欢喜啊。。。。
这时候我们只需要传参orderBy=xxxx
就可以控制value的值了,简直完美,然后接着往下走。接下来queryMap会被传入到selectList
函数
然后传入selectAll
然后mybatis从queryInfo中获取到orderBy的值,然后拼接到sql语句中,注入完成,于是我就试了下,然后就报错了。。。。。
哦豁,白名单,完蛋。到这里基本上就失败了,不过我们还要去看一看怎么拦的,这里报错注意到是在QueryParser
解析的时候限制了白名单,最后定位到这里
跟进去
继续到parse函数最后一行
跟进parseOrderBy
他妈的,我一眼就注意到这里的preventInjection
,进去看看
。。。。根源在这里