使用OFCMSV1.1.2搭建项目环境:
1、使用idea打开项目,配置Tomcat和Deployment
2、启动tomcat,进入以下页面,点击下一步
3、输入本机数据库的信息,点击下一步
4、环境搭建成功,默认弹出首页面,本项目登录账号密码为admin/123456
二、漏洞审计思路与案例
2.1 审计流程与思路
(1)查看使用了什么框架,是ssm还是ssh,还是servlet等
(2)针对权限控制是否使用了Shiro、SpringSecurity等统一的权限控制框架,如果未使用任务权限验证框架,而是采用了手动的人工权限验证,特别是较老技术,容易存在业务逻辑漏洞
(3)通过Lib文件夹和pom.xml文件查看使用的开源组件和版本信息,作为审计开源组件通用漏洞的突破口
(4)了解平台所使用的市场上常见的成熟的CMS技术和版本,可以从供应链入手查找其他类似项目
(5)熟悉系统的源码构成,按照MVC思想,了解主要的功能模板和对应的JavaBean
(6)在1-5步的基础上针对各类漏洞源码分析发现漏洞
2.2 漏洞审计案例
2.2.1 通用型漏洞-SSTI模板注入
1、通过阅读pom.xml发现,使用了freemarker开源组件
通过该网站查看开源组件是否存在漏洞:https://vul.wangan.com/
2、找到对应的模版新增页面,注入payload,点击保存
3、调试追溯请求的路径,发现请求的API为/src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.java
通过分析相关代码发现未进行安全处理,导致payload成功注入:
4、浏览被注入的页面后,发现该页面的payload成功被执行
2.2.2 SQL注入漏洞
1、进入漏洞页面/admin/index.html,新增表功能点,随意输入内容点击新增
查看前端网络,请求的路径为:http://localhost:8080/ofcms_admin_war/admin/system/generate/create.json?sqlid=
2、进入到对应后端源码controller,通过bug调试发现调用了create方法,第47行的getPara处理sql语句
3、继续追踪getPara方法,发现该方法仅仅是直接从前端获取了name的值
4、返回到入口,接着对Db.update方法进行追踪
5、继续追踪
6、到这里,发现执行sql的逻辑
7、最后发现了sql执行的最终交互点,确定未对来自用户输入的数据安全处理,导致了注入的产生。
这一步看到虽然使用的是预编译对象,但是确未按照预编译占位符进行处理,正确的应该是以占位符的形式嵌入参数才能达到真正的预编译,例如:
8、通过在爆发点参数位置输入payload进行报错注入,发现成功返回了错误信息
攻击payload:
update of_cms_link set link_name=updatexml(1,concat(0x7e,(user())),0) where link_id=2
update of_cms_link set link_name=updatexml(1,concat(0x7e,(database())),0) where link_id=2
2.2.3 任意文件上传漏洞
1、通过对2.2.1相关代码分析,保存模板的后端程序用到dirs字段数据,猜测此字段输入数据可控来进行文件路径的重新定位,且没有对写入字符串进行过滤验证以及扩展名也没有任何限制
2、随后对该API请求的路径以及数据流进行追踪/src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.java,发现依然是模板新增或编辑页面为用户输入的关键漏洞位置。
打开模板目录下的,对404.html进行提交:
3、使用BurpSuit抓包之后修改请求,将dirs的制前边添加..%2F..%2F..%2F字符,修改文件名后缀为.jsp,同时在file_content添加payload信息
4、发送请求后,成功响应
5、最后到服务器查看,该文件上传成功,说明该漏洞存在
2.2.4 XSS漏洞
1、结合源码确定未使用了XSS全局过滤器(如果使用了需要判断是否生效),因为XSS漏洞无法针对所有的参数进行ESAPI编码,也就是说一般无全局过滤器多数存在XSS注入漏洞。
全局搜索看到本项目针对XSS防御通过前端JS中进行安全过滤,这种前端处理的手段无效:
2、以文章管理模板为例,编辑某一文章,分别在标题和内容均输入payload
3、提交后通过burpsuit获取请求的路径
4、根据请求的路径找到后端对应的API类,找到如下核心文件
5、锁定修改文件内容的核心源码如下,经过分析确定未手动对用户输入的file_content、file_name参数安全处理且无全局过滤器而直接执行了数据库update操作,故存在存储型XSS,因此也能判断出该系统存在全局XSS漏洞。
public void update() {
List<Record> list = new ArrayList<Record>();
Map<String, Object> params = getParamsMap();
try {
Record record = new Record();
record.set("title_name", params.get("title_name"));
record.set("content_id", params.get("content_id"));
Db.update("of_cms_content", "content_id",record);
for (String key : params.keySet()) {
list.add(new Record().set("name",key).set("value", params.get(key).toString()).set("content_id", params.get("content_id")));
}
Db.batchUpdate("of_cms_content_field","content_id,name",list, list.size());
rendSuccessJson();
} catch (Exception e) {
e.printStackTrace();
rendFailedJson(ErrorCode.get("9999"));
}
}
6、最后修改完成后发现成功触发XSS漏洞