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

news2024/11/25 20:46:58

文章目录

  • 0. 前言
  • 1. 文件上传代码审计【有1处】
    • 1.1 可疑点1【无漏洞】
      • 1.1.1 直接搜索upload关键字
      • 1.1.2 选择第一个,点进去分析一下
      • 1.1.3 分析this.getFile()方法
      • 1.1.4 分析new MultipartRequest(request, uploadPath)
      • 1.1.5 分析isSafeFile()方法
      • 1.1.6 分析request.getFiles()方法
      • 1.1.7 验证文件的过滤方式,并尝试找到绕过之法(毕竟是黑名单\[\偷笑])
      • 1.1.8 这里,这个点就到此结束,总结一下:
    • 1.2 可疑点2【无漏洞】
    • 1.3 可疑点3【跑偏的漏洞-路径遍历读取.xml文件】
      • 1.3.1 搜索file关键字
      • 1.3.2 分析getTemplates()方法
      • 1.3.3 柳暗花明又一村
      • 1.3.4 多点脑洞
    • 1.4 可疑点4【有漏洞】
      • 1.4.1 分析save()方法
      • 1.4.2 利用漏洞写入jsp马
    • 1.5 最后结尾
      • 1.5.1 例1:SystemUtile类下
      • 1.5.2 例2:GenUtils类下,都是创建固定名称的文件,并非文件上传
      • 1.5.3 例3:换关键字write搜索,基本都是分析过的,要不就是无用的

0. 前言

我发现很多文章包括教程,大概套路是:只说有漏洞的点,将有漏洞的点指出,然后分析代码;或者黑盒测试出漏洞之后,然后分析代码。

我认为这是在分析漏洞代码,而非代码审计。代码审计文章或教程应该是从0开始找到漏洞所在,包括思路!

所以这里不管有没有漏洞,我都会把审计过程写出来,因此篇幅会很长,但我认为这样对你会很有帮助。

知其然亦知所以然。

由于篇幅较长,因此我会分几篇进行,本篇是整个系列的第3篇,讲解1个内容:

  • 文件上传漏洞审计

本系列文章:

  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇1 | 环境搭建、路由机制
  • Java代码审计篇 | ofcms系统审计思路讲解 - 篇2 | SQL注入漏洞审计
  • 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.coloradmin.cn/o/2123519.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

连锁管理系统如何兼批发和零售 连锁收银系统如何配合做好财务

在现代零售环境中&#xff0c;信息化管理系统对连锁企业的运营至关重要。连锁管理系统通过先进的信息技术解决了批发和零售中的众多挑战&#xff0c;同时为财务管理提供了有力支持。商淘云分享如何提高连锁企业的运营效率和财务管理水平&#xff0c;大家点赞收藏。 1、统筹批发…

算法知识点————背包问题

万能头文件#include<bits/stdc.h> 01 背包 定义&#xff1a; 物品只能用1次。01对应选还是不选第i个物品 .N个物品、V容量的最大价值。 思路&#xff1a; &#xff08;1&#xff09;f[ i ] [j] 表示前i个物品容量j的最大价值。 &#xff08;2&#xff09;当前背包容量…

在WPF中使用矢量图标

使用SVG/Path WPF支持绘图&#xff0c;在WPF中定义了一些基本图形&#xff0c;如Line、Rectangle、Ellipse、Path等 其中Path支持使用路径来进行绘图&#xff0c;所以大部分的图标可以通过Path来进行绘制。 因为本文主要是介绍矢量图标&#xff0c;所以不对绘图进行详细介绍…

opencv之图像梯度

图像梯度 图像梯度计算的是图像变化的速度。对于图像的边缘部分&#xff0c;其灰度值变化较大&#xff0c;梯度值也较大&#xff1b;相反&#xff0c;对于图像中比较平滑的部分&#xff0c;其灰度值变化较小&#xff0c;相应的梯度值也较小。一般情况下&#xff0c;图像梯度计…

重命名工具 | Advanced Renamer v4.03 绿色版

Advanced Renamer 是一款专为 Windows 平台设计的强大文件批量重命名工具。它提供了多种重命名方法&#xff0c;包括指定新文件名、改变大小写、移动字符、移除字符串、重编文件名序号、替换字符、添加内容、使用列表或列表文件替换文件名、交换字符位置、去除头部或尾部多余空…

百度Apollo打通与ROS的通信,扩展自动驾驶系统生态

技术文档&#xff5c;打通与ROS的通信&#xff0c;扩展自动驾驶系统生态_Apollo开发者社区 (baidu.com)

-顺序表-

一、小概述 二、代码解析 下面利用顺序表实现增删改查的功能&#xff1a; //动态顺序表 #include <iostream> using namespace std; typedef int SLDataType;//适用于多种类型 typedef struct SeqList {SLDataType* a;//数组int size;//表示数组中存储了多少个元素int …

【车载开发系列】ParaSoft单元测试环境配置(一)

【车载开发系列】ParaSoft单元测试环境配置(一) ParaSoft单元测试环境配置 【车载开发系列】ParaSoft单元测试环境配置(一)一. 什么是bdf文件二. bdf文件构成三. 新规做成bdf文件四. 导入bdf文件创建测试工程五. 获取编译器信息六. 新增自定义编译器Step1:打开向导Step2:…

Xcode 16 RC (16A242) 发布下载,正式版下周公布

Xcode 16 RC (16A242) - Apple 平台 IDE IDE for iOS/iPadOS/macOS/watchOS/tvOS/visonOS 请访问原文链接&#xff1a;https://sysin.org/blog/apple-xcode-16/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Xcode 16 的新功…

【拓扑系列】拓扑排序

【拓扑系列】拓扑排序 前言认识有向无环图认识AOV网&#xff1a;顶点活动图拓扑排序 1. 课程表1.1 题目来源1.2 题目描述1.3 题目解析 2. 课程表 II2.1 题目来源2.2 题目描述2.3 题目解析 3. LCR 114. 火星词典3.1 题目来源3.2 题目描述3.3 题目解析 前言 认识有向无环图 图中…

AI基础 L13 Constraint Satisfaction Problems I约束满足问题

Defining Constraint Satisfaction Problems A constraint satisfaction problem (CSP) consists of three components, X, D, and C: • X is a set of variables, {X1, . . . , Xn}. • D is a set of domains, {D1, . . . , Dn}, one for each variable • C is a set of co…

STM32+ESP8266 WiFi连接机智云平台APP远程控制教程

本文档将介绍如何用STM32ESP8266 WiFi模块从零开始连接上机智云&#xff0c;并通过APP进行远程控制。 机智云官网&#xff1a;机智云|智能物联网操作系统 (gizwits.com) 准备&#xff1a;STM32、ESP8266、手机、可上网的WiFi。 1.创建设备 1.1 注册登陆 请自行注册账号并登陆…

脱离八股文,真实开发中的延时处理需求实现思路(超时订单处理为例)

前言 咱们聊聊那些在开发过程中经常遇到的延时处理需求吧。比如说&#xff0c;网购时那些迟迟不付款的订单&#xff0c;或者是社交软件里那些需要稍后处理的消息&#xff0c;再或者是金融交易中那些需要等待确认的交易。这些都是咱们得搞定的活儿。 不过&#xff0c;很多时候&a…

JS面试真题 part3

JS面试真题 part3 11、bind、call、apply区别&#xff1f;如何实现一个bind12、JavaScript中执行上下文和执行栈是什么13、说说JavaScript中的事件模型14、解释下什么是事件代理&#xff1f;应用场景&#xff1f;15、说说你对闭包的理解&#xff1f;闭包使用场景 11、bind、cal…

make 程序规定的 makefile 文件的书写语法

&#xff08;1&#xff09; 常用的 gcc 选项&#xff1a; &#xff08;2&#xff09; make 的作用&#xff1a; &#xff08;3&#xff09; 搭建 make 的实验环境 &#xff0c; linux 的很简单&#xff0c; windows 的复杂一点&#xff1a; windows 上 make 环境的搭建&#…

python爬虫基础:了解html

编辑器vscode <!DOCTYPE html> <html><head><title>第一个网页</title></head><body><h1>字体</h1><h2>字体</h2><h3>字体</h3><p>Lorem, ipsum dolor sit amet consectetur adipisicing…

电商平台如何实现自动监控订单签收状态,加快资金划拨进程?

资金划拨作为交易流程的核心环节之一&#xff0c;直接关系到商家资金回笼的速度、消费者购物体验的满意度以及平台自身的信誉与稳定性。 区别于自营电商&#xff0c;电商平台入驻了许多第三方商家&#xff0c;为了保障交易安全和控制风险&#xff0c;在交易未完成之前&#xff…

Java 入门指南:Java 并发编程 —— 同步工具类 Semephore(信号量)

文章目录 同步工具类Semephore核心功能限制并发访问量公平与非公平策略灵活性与适应性 常用方法使用示例 同步工具类 JUC&#xff08;Java.util.concurrent&#xff09;是 Java 提供的用于并发编程的工具类库&#xff0c;其中包含了一些通信工具类&#xff0c;用于在多个线程之…

Spring和MyBatis常见面试题总结

文章目录 1 Spring 基础1.1 说一下你对 Spring 的理解&#x1f525;1.2 Spring,Spring MVC,Spring Boot 之间什么关系?1.3 Spring 框架中用到了哪些设计模式&#xff1f;&#x1f525;1.4 说说自己对于 Spring MVC 了解?1.5 Spring MVC 的核心组件有哪些&#xff1f;1.6 Spri…

flutter开发实战-GoRouter路由go与push区别实践

flutter开发实战-GoRouter路由go与push区别实践 GoRouter是一个flutter的声明性路由包&#xff0c;使用路由器API提供一个方便的、基于url的API&#xff0c;用于在不同屏幕之间导航。可以定义URL模式、使用URL导航、处理深度链接以及许多其他与导航相关的场景。 之前使用了Go…