【Java代码审计】文件上传篇

【Java代码审计】文件上传篇

  • 1.Java常见文件上传方式
  • 2.文件上传漏洞修复

1.Java常见文件上传方式

1、通过文件流的方式上传

public static void uploadFile(String targetURL, String filePath) throws IOException {
    File file = new File(filePath);
    FileInputStream fileInputStream = new FileInputStream(file);
    
    URL url = new URL(targetURL);
    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
    connection.setDoOutput(true);
    connection.setRequestMethod("POST");
    
    // 设置请求头,根据实际需求进行更改
    connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=---boundary");

    // 创建文件流输出流
    OutputStream outputStream = connection.getOutputStream();
    
    // 写入文件数据
    byte[] buffer = new byte[4096];
    int bytesRead;
    while ((bytesRead = fileInputStream.read(buffer)) != -1) {
        outputStream.write(buffer, 0, bytesRead);
    }
    
    // 关闭文件流和连接
    fileInputStream.close();
    outputStream.flush();
    outputStream.close();
    
    // 获取服务器返回的响应
    int responseCode = connection.getResponseCode();
    if (responseCode == HttpURLConnection.HTTP_OK) {
        // 上传成功
        System.out.println("文件上传成功!");
    } else {
        // 上传失败
        System.out.println("文件上传失败!错误代码:" + responseCode);
    }
}

2、通过ServletFileUpload方式上传

protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    // 检查请求是否为multipart/form-data类型
    boolean isMultipart = ServletFileUpload.isMultipartContent(request);

    if (isMultipart) {
        FileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload upload = new ServletFileUpload(factory);

        try {
            // 解析请求,获取所有表单项
            List<FileItem> items = upload.parseRequest(request);

            // 遍历表单项
            for (FileItem item : items) {
                if (!item.isFormField()) { // 如果是文件字段
                    String fileName = item.getName();
                    InputStream fileContent = item.getInputStream();

                    // 进行文件保存操作,可以根据实际需求自行实现
                    saveFile(fileName, fileContent);
                }
            }

            response.getWriter().write("文件上传成功!");
        } catch (Exception e) {
            response.getWriter().write("文件上传失败!");
            e.printStackTrace();
        }
    } else {
        response.getWriter().write("请求未包含文件!");
    }
}

3、通过MultipartFile方式上传

public String singleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
    try {
        byte[] bytes = file.getBytes();
        Path dir = Paths.get(UPLOADED_FOLDER);
        Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());

        Files.write(path, bytes);
        redirectAttributes.addFlashAttribute("message","上传文件成功:" + path + "");
    } catch (Exception e) {
         return e.toString();
    }
    return "redirect:upload_status";
}

该代码没有对上传文件的后缀类型等进行限制,现在我们可以上传一个恶意的jsp脚本到服务器解析执行:

在这里插入图片描述

上传成功:

在这里插入图片描述

一个非常有效的防御方法是对上传文件后缀名做白名单处理:

public String singleFileUploadSafe(@RequestParam("file") MultipartFile file,
                                   RedirectAttributes redirectAttributes) {
    try {
        byte[] bytes = file.getBytes();
        String fileName = file.getOriginalFilename();
        Path dir = Paths.get(UPLOADED_FOLDER);
        Path path = Paths.get(UPLOADED_FOLDER + file.getOriginalFilename());

        // 获取文件后缀名
        String Suffix = fileName.substring(fileName.lastIndexOf("."));

        String[] SuffixSafe = {".jpg", ".png", ".jpeg", ".gif", ".bmp", ".ico"};
        boolean flag = false;

        for (String s : SuffixSafe) {
            if (Suffix.toLowerCase().equals(s)) {
                flag = true;
                break;
            }
        }

        if (!flag) {
            return "只允许上传图片,[.jpg, .png, .jpeg, .gif, .bmp, .ico]";
 }       

此时继续上传恶意脚本,已经成功拦截:

在这里插入图片描述

在审计文件上传漏洞时,关注的重点往往是在上传表单的代码段。我们可以总结出以下一些经典的关键字:

在这里插入图片描述


2.文件上传漏洞修复

对于文件上传漏洞的修复一般最有效的方法是限制上传类型并对文件进行重命名,采取白名单策略限制运行上传的类型;对文件名字进行重命名;去除文件名中的特殊字符;上传图片时,通过图片库检测上传文件是否为图片

通过“String Suffix=fileName.substring(fileName.lastIndexOf("."))”中的“fileName.lastIndexOf(".")”获取文件的真实后缀,避免了上文中通过“fileName.substring(fileName.indexOf("."))”获取文件后缀,以.jpg.jsp的方式绕过检测的情况。通过“String whitetype[]={"image/gif","image/jpeg","image/jpg","image/png"}”对文件的类型进行判断,虽然可以通过抓包的方式修改Content-Type来绕过,但也有一定限制作用。通过验证后,在文件存储时将文件进行了随机重命名,且重命名后的文件要保证不可预测,不显示在回包和日志文件中,避免上传的文件被恶意利用

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

node.js 启一个前端代理服务

文章目录 前言一、分析技术二、操作步骤2.1、下载依赖2.2、创建一个 serve.js 文件2.3、js 文件中写入以下代码 三、运行&#xff1a; node serve四、结果展示五、总结六、感谢 前言 有时候我们需要做一些基础的页面时&#xff0c;在研发过程中需要代理调用接口避免浏览器跨域…

设计模式——桥接模式(结构型)

引言 桥接模式是一种结构型设计模式&#xff0c; 可将一个大类或一系列紧密相关的类拆分为抽象和实现两个独立的层次结构&#xff0c; 从而能在开发时分别使用。 问题 抽象&#xff1f; 实现&#xff1f; 听上去挺吓人&#xff1f; 让我们慢慢来&#xff0c; 先考虑一个简单的…

Docker Swarm编排:构建简单集群

Docker Swarm 是 Docker 官方提供的容器编排工具&#xff0c;通过它可以轻松构建和管理多个 Docker 容器的集群。本文将深入探讨 Docker Swarm 的基础概念、构建集群的步骤&#xff0c;并提供更为丰富和实际的示例代码&#xff0c;帮助大家全面了解如何使用 Docker Swarm 搭建一…

PyQt6 使用Qt Designer实现简单的界面,以及ui文件转py文件

前言&#xff0c;主要通过参考并总结两篇文章中的部分内容&#xff0c;参考文章一 && 参考文章二 Qt 设计师简单例子 一、需求分析二、界面设计三、生成ui文件四、ui文件转py文件1、命令行 执行 uic 生成 py代码2、PyCharm 配置 Pyuic工具2.1 配置Pyuic工具2.2 测试是否…

Linux---查看文件内容命令

1. 查看文件内容命令的使用 命令说明cat查看小型文件more分屏查看大型文件 cat命令的效果图 说明: cat命令结合重定向可以完成多个文件的合并gedit 文件编辑命令&#xff0c;可以查看和编辑文件 more命令的效果图 当查看内容信息过长无法在一屏上显示时&#xff0c;可以使…

C# WPF上位机开发(属性页面的设计)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 在软件开发中&#xff0c;属性或者参数设置是很重要的一个部分。这个时候如果不想通过动态添加控件的方法来处理的话&#xff0c;那么可以通过tab控…

Python将已标注的两张图片进行上下拼接并修改、合并其对应的Labelme标注文件(v2.0)

Python将已标注的两张图片进行上下拼接并修改、合并其对应的Labelme标注文件&#xff08;v2.0&#xff09; 前言前提条件相关介绍实验环境上下拼接图片并修改、合并其对应的Labelme标注文件代码实现输出结果 前言 此版代码&#xff0c;相较于Python将已标注的两张图片进行上下拼…

Android通过listview实现输入框自定义提示栏(代替AutoCompleteTextView自动完成文本框)

效果图 背景 本人因为一些需求初次接触android&#xff0c;需要实现一个类似android自带的AutoCompleteTextView&#xff08;自动完成文本框&#xff09;&#xff0c;但和其不同的是通过后端接口直接筛选数据&#xff08;自己的分词处理规则&#xff09;&#xff0c;然后返回前…

虚幻学习笔记17—C++委托(单播)

一、前言 相比“代理”这个名词我更喜欢叫“委托”&#xff0c;虚幻的委托分为三类&#xff0c;分别为单播、多播和动态多播。单播顾名思义就是一次只能绑定一个函数的委托&#xff0c;多播能一次性绑定多个&#xff0c;动态多播即可以在蓝图中进行动态的绑定且可以绑定多个。 …

MySQL进阶2 - 索引

MySQL进阶1 - 索引 1. 索引概述2. 索引结构2.1 二叉树2.2 B-Tree(多路平衡查找树)2.3 BTree2.4 Hash 3. 索引分类4. 索引语法5. SQL性能分析5.1 SQL执行频率5.2 慢查询日志5.3 profile5.4 explain执行计划5.3.1 EXPLAIN执行计划各字段含义&#xff1a; 6. 索引使…

服务器一直掉线怎么回事?

随着网络的高速发展&#xff0c;不管是网站还是游戏&#xff0c;如果遇到服务器卡顿的情况&#xff0c;会造成用户访问网站或进游戏&#xff0c;网站页面长时间无法打开&#xff0c;游戏页面运行卡顿&#xff0c;这样就很容易会造成用户的流失&#xff0c;从而导致业务亏损极大…

Redis设计与实现之跳跃表

目录 一、跳跃表 1、跳跃表的实现 2、跳跃表的应用 3、跳跃表的时间复杂度是什么&#xff1f; 二、跳跃表有哪些应用场景&#xff1f; 三、跳跃表和其他数据结构&#xff08;如数组、链表等&#xff09;相比有什么优点和缺点&#xff1f; 四、Redis的跳跃表支持并发操作吗…

消除非受检警告

在Java中&#xff0c;有一些情况下编译器会生成非受检警告&#xff08;Unchecked Warnings&#xff09;。这些警告通常与泛型、类型转换或原始类型相关。消除这些警告可以提高代码的可读性和安全性。以下是一些常见的非受检警告以及如何消除它们的例子&#xff1a; 1. 泛型类型…

0基础学习VR全景平台篇第128篇:720VR全景拍摄设备推荐

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; 本篇教程&#xff0c;小编为大家推荐720VR全景拍摄所需要的设备器材。上节我们提到&#xff0c;理论上任意相机和镜头都能够拍摄全景&#xff0c;但为了标准化制作流程&#xff0…

oracle 锁表解决办法

相关表介绍 V$LOCKED_OBJECT&#xff08;记录锁信息的表&#xff09;v$session&#xff08;记录会话信息的表&#xff09;v$sql&#xff08;记录 sql 执行的表&#xff09;dba_objects&#xff08;用来管理对象&#xff0c;表、库等等&#xff09; 查询锁表的 SID select b.…

t-io 程序执行后,jvm不退出的原因

基于t-io 1.7.3 版本分析源码 1、设定当前时间&#xff0c;每10毫秒执行一次 (非守护线程) 2、对应线程池的核心线程在AioServer启动时全部激活&#xff0c;并且添加空任务到阻塞队列&#xff0c;让核心线程(非守护线程)一直存活

等等Domino 14.0FP1

大家好&#xff0c;才是真的好。 节奏确实太快了&#xff0c;有时候我深感我也追不上。 以前Notes Domino是三年磨一剑&#xff0c;也就说每三年才发一个大版本&#xff0c;从2019年开始&#xff0c;进行了高频提速&#xff0c;居然一年一个大版本&#xff01; 周末&#xf…

使用opencv的Sobel算子实现图像边缘检测

1 边缘检测介绍 图像边缘检测技术是图像处理和计算机视觉等领域最基本的问题&#xff0c;也是经典的技术难题之一。如何快速、精确地提取图像边缘信息&#xff0c;一直是国内外的研究热点&#xff0c;同时边缘的检测也是图像处理中的一个难题。早期的经典算法包括边缘算子方法…

Linux--Docker容器(1)

这里写目录标题 简介名词解释作用 指令在本地创建容器的过程&#xff1a;&#xff08;这里以tomcat为例&#xff09;访问容器端口映射目录挂载验证端口映射验证目录挂载 删除镜像多小组访问容器mysql容器 简介 名词解释 Docker镜像&#xff1a;可以将镜像理解为面向对象的类&a…

黑豹程序员-axios+springmvc传递数组

问题 奇怪的现象&#xff0c;axios在往后台传递数组时&#xff0c;springmvc竟然接收不到 解决 尝试多次无果&#xff0c;突然看一篇文章写vue中的数组不是真正的数组需要强转转化JSON.stringify 将信将疑下测试了一把&#xff0c;还真的传递成功了。 不光要JSON.stringify…