前言
笔者最近在学习Java代码审计,从网上找了一套已知漏洞的开源项目进行学习,利用白加黑的形式进行审计练习。
一、项目结构
ofcms是一款基于java开发的内容管理系统,技术栈包括jfinal DB+Record mysql freemarker Encache spring等,使用前后端分离的设计思想,将各个现成组件整合而成。
- 前端:使用FreeMarker作为模板引擎渲染页面。
- 后端:使用JFinal作为Web框架,使用Spring作为IOC容器,使用Maven作为依赖管理工具。
- 数据库:使用MySQL作为数据库,使用JFinal DB + Record作为数据库操作抽象层。
- 缓存:使用Encache作为缓存。
整个项目的基本情况:
src:源码文件(包含需要被Tomcat调用的资源以及调用所需的Java方法文件,web部署文件)
target:编译后打包生成的文件
主要看src文件夹内的文件,targent内都是一些.class二进制文件以及src内文件的镜像生成文件。
src内只有一个文件夹:main文件夹,其下有java、resources、webapp文件夹。
java:存放的是java核心代码,及指导tomcat工作的java方法
resources:存放的是一些静态资源(静态html文件、Sql语句等)
webapp:web应用部署的根目录,其下存放可访问的静态html的page界面、前端css文件、上传的图片
conf:
sql:数据库SQL方言模板
dev:
conf:数据库连接配置文件
resource:一些默认界面的资源文件
static:静态资源和一些前端插件
upload:web前端所需要的图片文件
WEB-INF:Tomcat下特有的文件夹,WEB-INF文件夹是一个非常安全的文件,在页面中不能直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问
二、环境搭建
笔者是直接从cn-panda的github上直接下载的源码:
https:
//github
.com/cn-panda/JavaCodeAudit/tree/master/%E3%80%9002%E3%80%91SQL%20%E6%BC%8F%E6%B4%9E%E5%8E%9F%E7%90%86%E4%B8%8E%E5%AE%9E%E9%99%85%E6%A1%88%E4%BE%8B%E4%BB%8B%E7%BB%8D/ofcms
*左右滑动查看更多
下载之后用IDEA导入。
1. 修改数据库连接的账号密码
打开 ofcms-admin/src/main/resources/dev/conf/ 下的 db.properties文件 ,修改数据库连接的账号密码:
打开pom.xml搜索 mysql ,然后修改成⾃⼰对应的版本,然后点击import change,我这里本地mysql版本是8.0.12,但是构建的过程中会遇到问题,翻看报错需要把依赖调到8.0.15就可以了。
菜单栏->run-->edit configurations--> + -->tomcat server-->local
*左右滑动查看更多
点击
Deployment-
> +
-
>
Artifict
--
> 选择
ofcms-admin
:war
-
>修改名字
*左右滑动查看更多
连接mysql数据库,创建⼀个名为 ofcms 的数据库,导⼊ofcms/doc/sql下的 sql ⽂件。
url:http:
//localhost:8080/ofcms_admin_war/
后台地址:http:
//localhost:8006/ofcms_admin/admin/index.html
用户名/密码:admin/
123456
*左右滑动查看更多
三、漏洞审计
CVE地址:
https:
//cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2019-9615
*左右滑动查看更多
这里的Description已经说明了漏洞点
An issue was discovered in OFCMS before 1.1.3. It allows admin/system/generate/
create
?
sql
=
SQL
injection, related
to
SystemGenerateController.java
*左右滑动查看更多
漏洞点位于以下路径:
ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/
system
/SystemGenerateController.java
的create方法
*左右滑动查看更多
这里首先看入口点,getPara函数获取到sql参数的值,并赋给sql变量。
String
sql = getPara(
"sql"
);
跟进getPara()方法,这里学到的小技巧,直接指着这个函数,会弹出来一个小框,我们就可以知道这个函数是在哪儿去调用的。
右键,Edit Source就会跳转到对应函数被调用的地方。
现在已经跳转到Controller.class了,这里很明显是直接调用的ServletRequest.getParameter()方法,也未对sql参数进行什么过滤,不再赘述。
回来跟进下update()方法:
跳转到了Db.class:
继续跟进MAIN.update():
跳转到DbPro.class了:
继续跟this.update():
终于看到点有用的东西了,这里直接用getConnection连接数据库,然后再跟this.update():
终于发现了问题出在哪里了,最终定位到了DbPro.class的int update(Config config, Connection conn, String sql, Object... paras)方法:
分析一下,这里创建了一个PreparedStatement对象,来预编译sql,但是这里有个问题,正常的预编译语句是会使用占位符的。
例如:
PreparedStatement pst = con.prepareStatement("
update
users
set
name
= ?
where
id
= ?
");pst.setString(1, "
ikun
"); pst.setInt(2, 38);
*左右滑动查看更多
但是这里SystemGenerateController.create()并没有使用占位符,这就等于没有对传进来的sql语句进行预编译处理,导致了sql注入的发生。
漏洞利用
根据代码提示,我们去后台找对应的功能点系统设置->代码生成->增加。
构造恶意的sql语句形成注入:
update
of_cms_link
set
link_name=updatexml(
1
,
concat
(
0x7e
,(
user
())),
0
)
where
link_id =
4
*左右滑动查看更多
注入成功。
当然用sqlmap跑也没问题:
python
sqlmap.py -r ./
1
.txt --risk=
3
--level=
5
--dbs
*左右滑动查看更多
(未完待续)
往期回顾
原文始发于微信公众号(安恒信息安全服务):九维团队-绿队(改进)| OFCMSV1.1.2审计练习(上)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论