Java代码审计篇 - ofcms系统审计思路讲解 - 篇3 - 文件上传漏洞审计

news/2024/9/23 1:55:40/文章来源:https://www.cnblogs.com/leyilea/p/18426195

Java代码审计篇 | ofcms系统审计思路讲解 - 篇3 | 文件上传漏洞审计

1 文件上传代码审计【有1处】

文件上传漏洞我们需要着重关注的是文件在被java代码解析到保存下来之间有无验证过滤,因此什么样的上传方式,什么样的保存方式都不重要,大家着重关注代码对文件的验证过滤手段即可。

文件上传代码审计常搜索的关键字如下:

file
upload
write
fileName
filePath
getPart
FileOutputStream
transferTo
getRealPath
FileItem
ServletFileUpload
DiskFileItemFactory
....

1.1 可疑点1【无漏洞】

1.1.1 直接搜索upload关键字

1.1.2 选择第一个,点进去分析一下

类名为UeditorAction

可以在当前页面搜索upload关键字,也可以同时参考该类的所有方法名称。

大概看一下,四个方法的写法是差不多的:

  • getFile()方法的第2个参数不太相同,通过参数名称uploadPath可以大概判断出来,这个参数表示的是文件上传路径,也就是说调用不同的方法会保存到不同的目录。

通过下方的msg.put("url", "/upload/image/" + file.getFileName())也可以大体确定这一点;

当然msg.put不是用来保存文件用的,只是返回的信息而已。

uploadImage()方法为例进行分析,可以看到,这个方法内部与保存文件相关的代码就前面两行(后面的都是关于返回的消息相关了),即

  UploadFile file = this.getFile("file", "image");file.getFile().createNewFile();

我们先分析下this.getFile()方法

1.1.3 分析this.getFile()方法

点击进入看一下:

getFile()方法,首先调用了getFiles(uploadPath),跟进之下:就在上面

可以看到这里先做了个判断,判断request对象是否是MultipartRequest类型的对象,如果不是则创建一个新的MultipartRequest类型的对象,总之就是保证request对象是MultipartRequest类型的对象。

然后调用.getFiles()方法。

额外的:其中request对象就是HttpServletRequest,相关代码如下:

这里目前来看,需要有两个点需要分析:

  • 1)new MultipartRequest(request, uploadPath)
  • 2)request.getFiles()

接下来先分析new MultipartRequest(request, uploadPath)

1.1.4 分析new MultipartRequest(request, uploadPath)

点击进入:

一个构造方法,先调用了父类,然后调用了wrapMultipartRequest()

  • 父类可以点击去看看,其实没啥
  • 着重看下wrapMultipartRequest()

点击进入wrapMultipartRequest(),代码比较长,大概意思已标注:

其中我们需要关注的是文件的过滤代码,也就是图中红框位置:

if (isSafeFile(uploadFile)) {uploadFiles.add(uploadFile);
}

这里面调用了一个isSafeFile()方法,进去看一看:

1.1.5 分析isSafeFile()方法

发现这里有了验证过滤:

  • 首先是对文件名去空白字符,然后转成小写
  • 其次是文件名如果是.jsp或者.jspx结尾则删除,返回false

师傅们可以想一下有无绕过手段

如果没有问题,则将文件add进入uploadFiles列表中。

1.1.6 分析request.getFiles()方法

然后接下来点进2.1.3步骤中的this.getFile()方法中的getFiles()方法进行分析

进来之后,发现方法中没有太多语句,只是直接返回了uploadFiles,也就是上一步所说的uploadFiles列表,这里面存放的是经过过滤的文件。

到此为止,其实已经差不多了,已经找到了文件的过滤方式:

  • 首先是对文件名去空白字符,然后转成小写
  • 其次是文件名如果是.jsp或者.jspx结尾则删除,返回false

刚开始所说的uploadImage()方法中的第2条语句 file.getFile().createNewFile();这里没什么,就是通过返回的经过过滤的file对象来创建一个新的文件。

那么接下来可以验证一下:

1.1.7 验证文件的过滤方式,并尝试找到绕过之法(毕竟是黑名单[\偷笑])

根据前面所说的路由机制,可以确定此uploadImage()方法的调用需要访问admin/ueditor/uploadImage.json

前端找一下呗。怎么找?搜呗...哎真麻烦,说实话好难找啊

根据路径大致判断范围:ueditor,貌似在哪见过这个词?

原来是个富文本编辑器,还好我“见多识广”哈哈

那就在前端找一下哪里有富文本,同时在控制台搜索着ueditor:

经过了九九八十一天,终于找到了。

admin/ueditor/uploadImage.json应该就是在富文本上传图片时触发的吧:尝试一下

uploadImage()方法打上断点,yakit也开启抓包拦截

先来个普通图片试一试

大事不妙!之前分析的路由机制不太对,这里怎么是/admin/ueditor/handler.html?action=uploadImage

  • 这里我懒得分析了,懂的师傅可以留个言~么么哒

不过没关系,放包!uploadImage()方法触发了。也就是功能和方法对上了!

在下面也可以看到上传路径在:D:\Program Files\tomcat\apache-tomcat-8.0.17\webapps\ofcms_admin_war\upload\image

当然在返回包中,也可以看到上传路径

访问一下,可以访问到。

接下来尝试绕过一下,已知文件过滤方式

  • 首先是对文件名去空白字符,然后转成小写
  • 其次是文件名如果是.jsp或者.jspx结尾则删除,返回false

绞尽脑汁~貌似只有一个方式:文件名后面加.绕过,但是这种好像只适用于windows。

来都来了,试一下吧,谁让我现在用的电脑是windows。

这里我直接修改了数据包,将文件名改成了.jsp.,文件内容用的是冰蝎生成的jsp马子。

这里idea就先不debug了,直接放包,上传成功。

可以到目录中看一下,有没有上传成功:

嘿嘿,成功,同时后缀是.jsp。

接下来就是看看能不能连接了...

测试了下,不太行,虽然能上传,但是不能解析。

这里为了避免中文问题,我改成了webshell.jsp

怎么办?目录穿越试一试,哈哈哈

经过三天三夜的调试,找到了文件名处理的源码(这里过程就不粘出来了,自己可以调一下,如果想看过程,评论区留个言,给兄弟们安排上[\狗头])

  • 先计算/的位置
  • 然后进行原始文件名的截取

即文件名为../../../webshell.jsp.,最终文件名也将变为webshell.jsp.

1.1.8 这里,这个点就到此结束,总结一下:

  • 该位置的文件上传可以任意上传除.jsp.jspx的文件,但是没什么luan用。
  • 当然如果是windows是可以通过加.绕过的,不过解析不了。
  • 尝试目录穿越,有代码会将路径接取掉。

成果:0day无,分析经验+1

1.2 可疑点2【无漏洞】

分析第二个ComnController类中的:

进来之后发现,写法和之前是差不多的,同样使用了getFile()方法,怎么办?放弃!

后面使用了getFile()方法的,直接放弃就好了。

换目标!

这里多说一下,其实我们搜的这些,都是jfinal组件中的upload,漏洞基本没有,如果有,那就是组件0Day了。不过分析分析源码也是好的,赞同请点赞。

1.3 可疑点3【跑偏的漏洞-路径遍历读取.xml文件】

通过upload搜索的,翻了一圈,不是UeditorAction类,就是ComnController类,没有别的可疑的了。换关键字搜索。

1.3.1 搜索file关键字

找到一个TemplateController类中导入了File。进入看看

文件中搜索下file,85个,真不少

进来之后,大概浏览一遍,该类中其中两个方法getTemplates() save()方法中存在文件相关的功能代码,所以这里分开来分析下。先分析getTemplates()

【其实这里不需要分析的,因为它是获取文件用的,没有写入文件保存文件的功能,和文件上传无关】。
既然来都来了,看一下吧~

1.3.2 分析getTemplates()方法

方法代码如下:

首先看前面三行,getPara()方法获取参数值,获取不到,会有默认值:

点进getPara()方法,进来一看:欣喜若狂啊

直接通过request.getParameter(name)获取参数值,也就是说,目录可控啊~

继续往下分析

这一块就没啥了,就是将String类型的路径,封装一下,变成对象。顺便还做了一下验证处理。

  • 其中画红框位置表示:pathFile.listFiles表示目录下的文件或目录,然后通过FileFilter做了一下验证,判断是否是目录,是目录的放入dirs列表中。

  • 其中的setAttr()方法,是将目录对象保存到request对象中。

继续向下分析:这里和之前的差不多,只不过是通过FileFilter限制了白名单文件,即将.html.xml.css.js的文件放入到了files列表中。

继续向下分析:这段代码作用就是页面上默认显示的模版文件,传入的文件名如果没有则显示files列表中的第一个(所以没有任意文件读取~哈哈哈)

最后返回resource.html或者是index.html

没有文件上漏洞!

1.3.3 柳暗花明又一村

但是别急,回想下,最开始说该方法获取的前端参数可控,即目录可控,那我们能不能不去获取默认路径下的.html.xml.css.js文件。

直接验证了,前端找到对应功能点,还是那个熟悉的模版~

随便点个模版,yakit拦截下~

默认参数是这样的:

  • file_name=contact.html
  • dir=/
  • dir_name=/

对照下源码,dir是当前目录,file_name是查看的文件

那么修改一下,读取网站下的web.xml试一试

而默认读取的根目录是webapps\ofcms_admin_war\WEB-INF\page\default

所以我们构造dir=../../../../ROOT/WEB-INFfile_name=web.xml

成功读取!经验+1

1.3.4 多点脑洞

既然这里可以读取web.xml,并且下方可以保存,那我们是不是就可以修改web.xml文件了呢?

尝试修改保存一下,出现请求异常~

直接调试下,在save()方法处打个断点,发现是因为dirs参数值即dirName中存在../因此被拒绝了。

这里其实很好绕过,聪明的你一点发现了,前面还有个参数:res_path

我们可以修改res_path的值和dirs参数的值,来达到修改web.xml的目的。

这里师傅们可以自己尝试下,因为这里和下面的save()方法的分析是一样的,就放一起说了。

1.4 可疑点4【有漏洞】

从上一个分析,发现save()方法其实是有问题的,接下来着重分析一下。

1.4.1 分析save()方法

代码就这么长:

首先看:

这里从前端获取“res_path”的参数值,前面也说过,getPara()获取的值是可控的。

然后通过res_path的值决定pathFile是什么内容,这里其实不用管,因为不管res_path是什么,pathFile都是固定的,不是SystemUtile.getSiteTemplateResourcePath()就是SystemUtile.getSiteTemplatePath(),没有可变的地方。

接下来是这段,也是核心:

首先从前端获取“dirs”参数的值,不过这个值中不能存在../,也就是说这个参数不能是利用点了。

然后从前端获取“file_name”参数的值,没有任何限制。

最后从前端获取“file_content”参数的值,仅仅对<>做了转义。

然后就是新建文件,调用FileUtils.writeString(file, fileContent)写入内容。

writeString方法如下:直接调用FileOutputStream.write()写的,没有别的过滤。

分析下来之后,可以利用的点为:file_name和file_content。

文件名和文件内容都可控,这不就是妥妥的任意文件写入(可以理解为任意文件上传)。

1.4.2 利用漏洞写入jsp马

那直接写个jsp马进去!当然,可能解析不了。

file_name和file_content都替换掉,最后别忘了file_content的值使用URL编码一下

  • 这里我用的是冰蝎jsp马

成功写入:

访问连接:但是会发现连接失败,看来当前目录下不能直接访问,或者是jsp不解析

继续尝试别的目录:file_name=../../../webshell.jsp

也是失败。

这里尝试在static目录,是可以的。file_name=../../../static/webshell.jsp

小tips:static目录是静态目录,一般文件是可以直接访问。

命令成功执行!撒花~

1.5 最后结尾

最后搜索了其他的类和关键字,没有可以分析利用的点了。师傅们看看就好。

1.5.1 例1:SystemUtile类下

1.5.2 例2:GenUtils类下,都是创建固定名称的文件,并非文件上传

1.5.3 例3:换关键字write搜索,基本都是分析过的,要不就是无用的

文件上传漏洞代码审计到此为止,希望师傅们有所收获,如有问题,评论区留言~
也可扫码加好友,一起进步~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/801840.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java代码审计篇 - ofcms系统审计思路讲解 - 篇4 - XXE漏洞审计

Java代码审计篇 | ofcms系统审计思路讲解 - 篇4 | XXE漏洞审计 1. XXE代码审计【有1处】 XXE代码审计常搜索的关键字如下: XMLReader SAXBuilder SAXReader SAXParserFactory Digester DocumentBuilderFactory ...还有一个特殊的,用于加载.jrxml 文件,这是 JasperReports 特…

Java反序列化利用链篇 | CC6链分析(通用版CC链)

CC6 CC6和CC1之间的区别 在CC1的LazyMap链中,调用链如下: AnnotationInvocationHandler.readObject() Map(Proxy).entrySet() LazyMap.get() ChainedTransformer.transform() InvokerTransformer.transform() Runtime.exec()而在CC1链中,对CommonsCollections和jdk版本是有限…

Java反序列化利用链篇 | CC3链分析、TemplatesImpl类中的调用链、TrAXFilter、InstantiateTransformer类的transform()【本系列文章的分析重点】

CC3链分析 1. CC3链背景 前面介绍了CC1和CC6,这两条链子虽然前面的入口类不同CC1入口类是AnnotationInvocationHandler CC6入口类是HashMap但是其触发恶意代码的方式是相同的,都是InvokerTransformer.transform()触发Runtime.getRuntime().exec()实现命令执行。而在很多情况下…

VUE学习day one

学习来源:【前端最新Vue2+Vue3基础入门到实战项目全套教程,自学前端vue就选黑马程序员,一套全通关!】https://www.bilibili.com/video/BV1HV4y1a7n4?vd_source=6dac49feb8d7fd76b147c8cf8c0c2b5a Vue是什么?Vue是一个用于构建用户界面(基于数据动态渲染出用户看到的页面)…

全网最适合入门的面向对象编程教程:51 Python 函数方法与接口-使用 Zope 实现接口

在 Python 中,Zope 提供了一种机制来定义和实现接口。Zope 的接口模块通常用于创建可重用的组件,并确保组件遵循特定的接口规范。全网最适合入门的面向对象编程教程:51 Python 函数方法与接口-使用 Zope 实现接口摘要: 在 Python 中,Zope 提供了一种机制来定义和实现接口。…

Java反序列化利用链篇 | CC1链的第二种方式-LazyMap版调用链【本系列文章的分析重点】

CC1链的第二种方式-LazyMap版调用链 目录LazyMap构造payloadCC1的调用链参考链接LazyMap 在之前的CC1链中分析,其实是其中一种方式(国内版本),还有另外一种方式,也是ysoserial中的CC1链的方式(国外版本)。 区别在于调用transform的类是不同的。 在寻找transform调用的时…

瑞云科技AIGC云平台:重塑电商设计流程!

在快节奏的电商市场中,商品更新换代的速度越来越快,而电商设计团队传统的设计流程和工作模式却难以满足当前行业对快速响应、高效发展和降低成本的实际需求.对此,瑞云科技针对电商设计行业的痛点,提供了全新的AIGC创作云平台.从2022年ChatGPT的发布到,AI正以惊人的速度席卷全球…

学习高校课程-软件工程-敏捷开发(ch5)

WHAT IS AGILITY 什么是敏捷性 An agile team is a nimble team able to appropriately respond to changes. Change is what software development is very much about. Changes in the software being built, changes to the team members, changes because of new technolog…

从零开始一个git操作实例,图文并茂

徒弟不懂git怎么用, 于是写了篇文章, 把本地git操作从头写了一遍, 自己去看吧!0、基本概念 •Git是一个免费、开源的、分布式版本控制系统 •它使用一个特殊的叫做仓库的数据库来记录文件的变化 •仓库中的每个文件都有一个完整的版本历史记录 1)安装 sudo apt-update sud…

Java反序列化利用链篇 | JdbcRowSetImpl利用链分析

JdbcRowSetImpl利用链 前言 首先说明一下:利用链都有自己的使用场景,要根据场景进行选择不同的利用链。 JdbcRowSetImpl利用链用于fastjson反序列化漏洞中。 为什么? 因为fastjson会在反序列化类时自动调用set开头的方法(不一定是setter方法),而JdbcRowSetImpl中存在一个…

Java反序列化调用链分析系列 | URLDNS链

URLDNS链 URLDNS链是java通过反序列化发起dns请求的利用链。一般用于测试反序列化漏洞。 该链比较简单,利用链也比较短。 其中入口类为 HashMap,执行类为URLStreamHandler的hashCode()方法。 整个调用链如下: HashMap.readObject() HashMap.putVal() HashMap.hash()URL.hash…

控制请求并发数量:p-limit 源码解读

p-limit 是一个控制请求并发数量的库,他的整体代码不多,思路挺好的,很有学习价值; 举例 当我们同时发起多个请求时,一般是这样做的 Promise.all([requestFn1,requestFn2,requestFn3 ]).then(res =>{})或者 requestFn1() requestFn2() requestFn3()而使用 p-limit 限制并…