看 版本 看 控制器 看 过滤器 https://forum.butian.net/share/1229 从补天看到的java 代码审计文章,跟着学习复现。
0x01 环境搭建 1.1 cms下载地址 https://gitee.com/oufu/ofcms/tree/V1.1.3/ 1.2 idea部署项目 https://blog.csdn.net/Alexz__/article/details/116229266https://forum.butian.net/share/1229https://blog.csdn.net/Alexz__/article/details/116272080?spm=1001.2014.3001.5502感谢两位师傅的笔记
1.3 服务启动成功 1.4 程序自动安装(失败)爆出语法错误
1.5 尝试手动部署 (成功) 1.5.1 创建库导入.sql文件首先在MySQL中创建空的ofcms数据库,然后将 ofcms-V1.1.3/doc/sql/ofcms-v1.1.3.sql文件导入到自己创建的数据库中
1.5.2 修改数据库配置文件并改名将数据库配置文件ofcms-V1.1.3/ofcms-admin/src/main/resources/dev/conf/db-config.properties文件名修改为db.properties,然后修改文件中的数据库配置信息
1.5.3 重新启动项目重新启动项目
1.5.4 访问后台,访问程序后台地址: http://localhost:8080/ofcms_admin_war/admin/index.html
默认账号和密码:admin/123456
0x02 漏洞挖掘拿到框架 先看
pom.xml的依赖 dependencyofcms-V1.1.3ofcms-adminsrcmainwebappWEB-INFweb.xml 过滤器 filter全局搜索关键字 配合 网页 功能点灰盒 审计 2.1 sql注入 2.1.1 漏洞位置后台->系统设置->代码生成->增加 可以输入sql语句
2.1.2 定位代码对应控制器处理方法为 com.ofsoft.cms.admin.controller.system.SystemGenerateController类的create()方法
2.1.3 分析传参处理在create方法中 先用getPara()方法 获取用户的输入sql的值 该方法位于 com.jfinal.core.Crontroller类中 getPara方法 就是使用request.getParameter(name)来获取http协议提交过来的数据 返回string类型的数据 这里并没有对用户输入的内容进行过滤
再看create方法,紧接着调用Db.update(sql); 方法执行输入的sql语句,跟进方法 跟踪到 com.jfinal.plugin.activerecord.DbPro类的update方法执行的sql语句 看到这里使用了预编译的方法,但是我们可以直接输入整条sql语句执行,不使用占位符(?, ?, ?),所以这里预编译处理将起不到作用。
2.2.4 payload update of_cms_link set link_name=updatexml(1,concat(0x7e,(user())),0) where link_id = 4
从响应包可以看到SQL语法报错信息,在报错信息中显示了当前数据库用户信息
2.2 SSTI模板注入在pom.xml文件的时候发现存在模引擎freemarker的包依赖信息,该模模板引擎存在ssti模板注入。 https://www.cnblogs.com/Eleven-Liu/p/12747908.html
2.2.1 漏洞位置后台->模板设置->模板文件->模板目录->修改index.html
2.2.2 定位代码对应的控制器处理方法为 com.ofsoft.cms.admin.controller.cms.TemplateController类的save方法
public void save() { String resPath = getPara("res_path"); File pathFile = null; if("res".equals(resPath)){ pathFile = new File(SystemUtile.getSiteTemplateResourcePath()); }else { pathFile = new File(SystemUtile.getSiteTemplatePath()); } String dirName = getPara("dirs"); if (dirName != null) { pathFile = new File(pathFile, dirName); } String fileName = getPara("file_name"); // 没有用getPara原因是,getPara因为安全问题会过滤某些html元素。 String fileContent = getRequest().getParameter("file_content"); fileContent = fileContent.replace("