OFCMS 1.1.3 代码审计(Java)
OFCMS 1.1.3 代码审计(Java)
参考文章:
- 【Java代码审计】OFCMS 1.1.3 审计_ofcms-v1.1.3 idea-CSDN博客
- 奇安信攻防社区-记又一次Java代码审计 (butian.net)
- Java安全之freemarker 模板注入 - nice_0e3 - 博客园 (cnblogs.com)
- [【Java代码审计】ofcms 1.1.3 | Fan的小酒馆 (fanygit.github.io)](https://fanygit.github.io/2022/10/09/[Java代码审计]ofcms 1.1.3/)
环境搭建
项目地址:https://gitee.com/oufu/ofcms/tree/V1.1.3/
在IDEA中打开项目后,添加一个tomcat服务器

部署工件

等待maven配置后打开网站
自动安装报错

开始手动安装
首先在MySQL中创建空的ofcms数据库,然后将 ofcms-V1.1.3/doc/sql/ofcms-v1.1.3.sql文件导入到自己创建的数据库中(运行sql文件)
将数据库配置文件ofcms-V1.1.3/ofcms-admin/src/main/resources/dev/conf/db-config.properties文件名修改为db.properties,然后修改文件中的数据库配置信息

启动项目,访问程序后台地址:http://localhost:8080/ofcms_admin_war/admin/index.html
默认账号和密码:admin/123456
成功登录
审计过程
先看pom.xml文件,关注引入的依赖
此cms引入了log4j的依赖,之后可以关注一下有无利用点
打开网站时在软件介绍处可以看到使用的是mybatis,freemarker模板,shiro安全框架,mysql数据库
翻看目录结构判断控制后台登录的核心代码大概都在ofcms-admin内
搜索关键字逐个排查漏洞(白盒)+在网页寻找功能点测试(黑盒)
白盒审计时直接使用工具SAST(搜索关键字),省去逐个搜索关键字的时间

逐个排查高危与中危漏洞,与网页功能点对应
sql注入
工具审出的第一条sql注入漏洞回到源代码中找到对应点
ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/system/SystemGenerateController.java
1 | |
可以看到create()方法接收了用户输入的一条sql语句,并且无过滤
追踪getPara方法发现,此方法只是接收参数,无过滤
追踪Db.update方法,一直追踪到
jfinal/jfinal/3.2/jfinal-3.2.jar!/com/jfinal/plugin/activerecord/DbPro.class
1 | |
看到执行了传入的sql语句
虽然此方法创建预编译的 SQL 语句对象 pst,但是并未使用预编译写法(占位符,固定sql语句),而是将传入的sql语句直接作为一个参数执行
判断此处存在sql注入
在网页寻找功能点:
由于此段代码在admin文件夹下,判断为后台功能点
在后台系统设置->代码生成->增加->输入sql
测试后发现能够报错,尝试报错注入
1 | |
成功注入

注:
刚刚可以看到使用了方法PreparedStatement.executeUpdate()
executeUpdate() 适用于执行:
INSERTUPDATEDELETECREATE,DROP,ALTER等 DDL 语句
payload构造应该使用这些语句
SSTI模板注入
在一开始查看软件说明时就可以了解到此源代码使用了freemarker模板引擎
在网页后台查看功能点时看到修改模板文件的功能

在源代码中定位控制代码
ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.java
save方法

可以看到对模板内容控制的代码只有框起来的两行,下面直接使用writeString方法写入并执行
追踪红框中调用的getRequest()与getParameter()方法,发现没有任何过滤
在网上查找freemarker模板ssti注入利用
Java安全之freemarker 模板注入 - nice_0e3 - 博客园 (cnblogs.com)
payload
1 | |
不知道为什么,我的只有这个payload是可以弹出计算器的,可以尝试多种payload

前台存储型xss
在网页寻找功能点时看到前台新闻页面有评论功能
发表评论通过开发者工具->网络功能,查看消息头,判断控制此功能的代码位置

在源码中查找
ofcms-api/src/main/java/com/ofsoft/cms/ api/v1/CommentApi.java
save方法
1 | |
追踪getSqlPara函数并未发现过滤,此段代码只是直接获取评论内容随后在数据库中更新
使用xss payload:<script>alert(1)</script>测试
看到其他师傅的测试是可以正常弹窗的,我的有404报错,不知道为什么

在后台直接编辑评论是可以正常弹窗的
后台文件上传01
在网站寻找功能点找到文件上传
内容管理->栏目管理->关于我们->编辑->栏目图上传
抓取数据包

找到路由/ofcms_admin_war/admin/comn/service/upload.js
全局搜索/comn/service/
在源码中定位
ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/ComnController.java
upload方法

在此处下断点进行调试
getFile方法->getFiles方法->MultipartRequest类->wrapMultipartRequest方法->isSafeFile方法
getFiles方法
1 | |
该方法的作用是获取上传的文件列表,具体步骤如下:
1.判断当前请求是否为文件上传类型(MultipartRequest);
2.如果不是,则将其包装成一个支持文件上传的请求对象,并指定上传路径;
3.最后,从请求中获取并返回上传的文件列表(List
wrapMultipartRequest方法中可以看到调用了isSafeFile方法

isSafeFile方法方法用于判断上传的文件类型是否是.jsp或.jspx文件
将文件后缀首尾去空及转换成小写

动态调试时也可以看到经过了复杂的判断,可以看到有Content-Type和后缀验证
此处是黑名单绕过
尝试截断%00,与后缀jspx绕过,能够成功上传,但是无法识别
尝试多种后是利用了1.jsp::$DATA(windows特性,上传至windows服务器后为1.jsp)成功上传

注:
动态调试后发现上传后的图片不在网站路径下
在tomcat/apache-tomcat-9.0.98/webapps/ofcms_admin_war/upload/image路径下
后台文件上传02
感觉没想到文件上传漏洞会以这种形式呈现
如果不看文章自己肯定是想不到的
ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.java
save方法

可以看到这里对文件名及文件内容都没有限制,虽然此处控制的是网页模板修改功能,但是看代码是可以通过数据包上传文件的,是一个可利用的接口
抓取请求数据包往服务器写入webshell,在文件名中插入../路径跳转符,控制在static目录下写入恶意JSP文件
选择一个jsp恶意文件将内容url编码后写入数据包file_content中
file_name改为../../../static/shell.jsp
(原index.html在/tomcat/apache-tomcat-9.0.98/webapps/ofcms_admin_war/WEB-INF/page/default/目录下,static与WEB-INF文件夹在同一级)
不会上传到网站根目录下!!!

可以看到顺利上传
D:/tomcat/apache-tomcat-9.0.98/webapps/ofcms_admin_war/static

访问一下

可以看到是能够正常访问的,就是需要改一下编码
XXE
在外部库中可以看到是有解析xml文档的相关资源包的

尝试搜索xml关键字
在com.ofsoft.cms.admin.controller.ReprotAction类的expReport方法中,接收用户输入的j参数后,拼接生成文件路径,这里没有进行过滤,可以穿越到其它目录,但是限制了文件后缀为jrxml,接下来会调用JasperCompileManager.compileReport()方法
.jrxml 是JasperReports 报表模板源文件的文件扩展名,它是JasperReports 的 XML 格式报表模板
1 | |
分析代码后找到了一段比较关键的代码
填充并生成报表
先使用 JasperCompileManager 编译 .jrxml 文件;
然后用参数 hm 和数据库连接填充报表内容,生成 JasperPrint 对象(代表报表数据结构)。
1 | |
此段代码可能对文件内容有控制
跟进compileReport函数
compileReport->compile->JRXmlLoader.load->xmlLoader.loadXML->digester.parse(反序列化)
compile方法

xmlLoader.loadXML
此方法主要是将 .jrxml 报表模板文件从 InputStream 中读取,使用 SAX 解析方式转换为 JasperDesign 报表设计对象
可以看到代码中并没有禁用外部实体
1 | |
开始测试
利用前面发现的文件上传漏洞上传一个jrxml为后缀的文件
文件内容
1 | |
看到成功上传

访问url
1 | |

但是换了很多dns平台都没有访问记录,不知道为什么
参数未过滤(误报)
ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/cms/ContentController.java
第二条关于sql注入漏洞的代码
1 | |
扫描呈现出此代码有漏洞的原因是工具中程序认定params中参数未过滤,但是实际通过此参数无法注入恶意数据完成字符串拼接
总结
- java代码审计工具初始配置下不如php完善,很多漏洞需要手动查找(准备多换几个工具试试)
- 要黑白盒结合审计,在网站寻找功能点再对应源码测试
- 手动搜索特殊函数与关键字对搜索结果做筛选找漏洞