【Java代码审计 | 第八篇】文件操作漏洞成因及防范

未经许可,不得转载。

文章目录

  • 文件操作漏洞
    • 文件读取漏洞
      • 基于 InputStream 的读取
      • 基于 FileReader 的读取
    • 文件下载漏洞
    • 文件删除漏洞
    • 防范

在这里插入图片描述

文件操作漏洞

分为文件读取漏洞、文件下载漏洞与文件删除漏洞。

文件读取漏洞

在Java中,文件读取通常有两种常见方式:一种是基于InputStream,另一种是基于FileReader

漏洞成因:未对用户输入做过滤,导致读取敏感文件并返回至客户端。

以下两种代码形式都存在路径遍历问题。

基于 InputStream 的读取

String filename = request.getParameter("filename");  // 假设这是用户输入的文件名
File file = new File(filename);  // 创建文件对象,未进行任何路径验证
InputStream inputStream = new FileInputStream(file);  // 创建输入流
int len;
while (-1 != (len = inputStream.read())) {  // 循环读取文件内容outputStream.write(len);  // 将读取的字节写入输出流
}

基于 FileReader 的读取

String filename = request.getParameter("filename");  // 假设这是用户输入的文件名
String fileContent = "";  // 存储文件内容
FileReader fileReader = new FileReader(filename);  // 创建FileReader对象,未进行任何路径验证
BufferedReader bufferedReader = new BufferedReader(fileReader);  // 包装为BufferedReader
String line;
while (null != (line = bufferedReader.readLine())) {  // 逐行读取文件fileContent += (line + "\n");  // 拼接每一行内容
}

文件下载漏洞

漏洞成因:未对用户输入做过滤,导致用户端可下载敏感文件。

filename 参数未经过任何验证或过滤,攻击者可以通过构造恶意路径下载系统敏感文件。

String filename = request.getParameter("filename");  // 获取文件名
File file = new File(filename);  // 创建文件对象
response.reset();  // 重置响应
response.addHeader("Content-Disposition", "attachment;filename=" + new String(filename.getBytes("utf-8")));  // 设置下载文件名
response.addHeader("Content-Length", "" + file.length());  // 设置文件大小
response.setContentType("application/octet-stream; charset=utf-8");  // 设置响应内容类型为二进制流InputStream inputStream = new FileInputStream(file);  // 创建输入流读取文件
OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());  // 获取输出流
int len;
while (-1 != (len = inputStream.read())) {  // 读取文件并写入响应outputStream.write(len);
}
inputStream.close();  // 关闭输入流
outputStream.close();  // 关闭输出流

文件删除漏洞

漏洞成因:未对用户输入做过滤,导致敏感文件被删除。

filename 参数未经过任何验证或过滤,攻击者可以通过构造恶意路径删除系统关键文件。

String filename = request.getParameter("filename");  // 获取文件名
File file = new File(filename);  // 创建文件对象
if (file != null && file.exists() && file.delete()) {  // 检查文件存在并删除response.getWriter().println("Delete success");  // 删除成功
} else {response.getWriter().println("Delete failed");  // 删除失败
}

防范

1、使用 getCanonicalPath() 方法获取文件的规范路径,并与预期的基路径进行比较,确保文件路径在允许的范围内。

String basePath = "/allowed/directory/";  // 允许访问的基路径
File file = new File(basePath, filename);  // 拼接文件路径
if (!file.getCanonicalPath().startsWith(new File(basePath).getCanonicalPath())) {throw new SecurityException("非法文件路径");  // 路径不在允许范围内,抛出异常
}

对以下语句进行解读:

if (!file.getCanonicalPath().startsWith(new File(basePath).getCanonicalPath())) {

file.getCanonicalPath():这个方法返回文件的规范化路径,即将路径中的 .(当前目录)和 …(上级目录)等符号解析成实际的绝对路径。

1、假设:basePath = “/allowed/directory/”
2、用户输入 filename = “…/…/etc/passwd”
3、new File(basePath):创建 /allowed/directory/ 的 File 对象。
4、file = new File(basePath, filename):用户提供的路径是 …/…/etc/passwd,所以拼接后的 file 实际路径为 /allowed/directory/…/…/etc/passwd,这是一个潜在的路径遍历。
5、file.getCanonicalPath():获取文件的规范化路径,经过解析后变为 /etc/passwd(因为路径 …/…/ 会使路径跳转到根目录)。
6、new File(basePath).getCanonicalPath():获取 /allowed/directory/ 的规范化路径,即 /allowed/directory/。
7、在这种情况下,file.getCanonicalPath()(即 /etc/passwd)不会以 /allowed/directory/ 开头,因此会进入 if 语句块,阻止访问该文件。

其次是检查文件后缀是否在允许的后缀白名单中,举个例子:

// 定义允许的文件后缀白名单
Set<String> allowedExtensions = new HashSet<>(Arrays.asList("txt", "pdf", "jpg", "png", "doc", "xls"
));String filename = request.getParameter("filename");  // 获取文件名
String fileExtension = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase();  // 提取后缀并转为小写// 检查后缀是否在白名单中
if (!allowedExtensions.contains(fileExtension)) {throw new SecurityException("非法文件类型");  // 文件类型不在白名单中,抛出异常
}File file = new File(filename);  // 创建文件对象// 使用 try-with-resources 读取文件
try (InputStream inputStream = new FileInputStream(file);OutputStream outputStream = new BufferedOutputStream(response.getOutputStream())) {int len;while (-1 != (len = inputStream.read())) {outputStream.write(len);}
} catch (IOException e) {e.printStackTrace();
}

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

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

相关文章

与rkipc通信

rkipc的通信方式 在ipcweb中&#xff0c;程序是通过/var/tmp/rkipc和rkipc进行通信&#xff0c;并且网络和客户端的函数封装在luckfox-pico/project/app/ipcweb/ipcweb-backend/src/socket_client文件夹中&#xff0c; client.cpp是客户端命令 socket.cpp是网络命令 编写rkip…

NLP常见任务专题介绍(2)-多项选择任务(MultipleChoice)训练与推理模板

一、 使用 BigBird 进行多项选择任务训练与推理 本示例展示如何使用 BigBirdForMultipleChoice 训练一个多项选择模型,适用于考试答题、阅读理解、常识推理等任务。 1️⃣ 任务描述 目标:给定一个问题和多个选项,模型预测正确答案。 数据格式:输入包含 (问题, 选项1, 选项…

【论文解读】MODEST 透明物体 单目深度估计和分割 ICRA 2025

MODEST是一种用于透明物体的单目深度估计和分割的方法&#xff0c;来自ICRA 2025。 它通过单张RGB图像作为输入&#xff0c;能够同时预测透明物体的深度图和分割掩码。 由深度图生成点云数据&#xff0c;然后采用GraspNet生成抓取位姿&#xff0c;开展透明物体抓取实验。 论文…

【网络安全工程】任务11:路由器配置与静态路由配置

目录 一、概念 二、路由器配置 三、配置静态路由CSDN 原创主页&#xff1a;不羁https://blog.csdn.net/2303_76492156?typeblog 一、概念 1、路由器的作用&#xff1a;通过路由表进行数据的转发。 2、交换机的作用&#xff1a;通过学习和识别 MAC 地址&#xff0c;依据 M…

深入理解隐式类型转换:从原理到应用

C⽀持内置类型隐式类型转换为类类型对象&#xff0c;需要有相关内置类型为参数的构造函数。 构造函数前⾯加explicit就不再⽀持隐式类型转换。 类类型的对象之间也可以隐式转换&#xff0c;需要相应的构造函数⽀持。 内置类型隐式类型转换为类类型对象 在 C 中&#xff0c;如果…

垃圾收集算法与收集器

在 JVM 中&#xff0c;垃圾收集&#xff08;Garbage Collection, GC&#xff09;算法的核心目标是自动回收无用对象的内存&#xff0c;同时尽量减少对应用性能的影响。以下是 JVM 中主要垃圾收集算法的原理、流程及实际应用场景的详细介绍&#xff1a; 一、标记-清除算法&#…

如何为服务设置合理的线程数

1. 首先&#xff0c;要确定最大线程数的限制因素。通常&#xff0c;线程数量受限于内存、CPU和操作系统限制。比如&#xff0c;每个线程都需要一定的栈内存&#xff0c;默认情况下Java线程的栈大小是1MB&#xff08;64位系统可能更大&#xff09;&#xff0c;所以如果内存不足&…

内容中台:元数据驱动管理新范式

元数据驱动智能管理中枢 现代企业内容管理正经历从碎片化存储向结构化治理的范式转变&#xff0c;元数据驱动机制在此过程中展现出核心枢纽价值。通过构建多维属性标签体系&#xff0c;Baklib等内容中台解决方案实现了对文本、音视频等数字资产的精准定义&#xff0c;其动态分…

在mac中设置环境变量

步骤一&#xff1a;打开终端 步骤二&#xff1a;输入printenv&#xff0c;查看当前已有的环境变量&#xff1b; 步骤三&#xff1a;输入&#xff1a;nano ~/.zshrc 打开环境变量编辑页面&#xff1b; 步骤四&#xff1a;输入新的变量&#xff1a;export DEEPSEEK_API_KEY&qu…

扩散模型的算法原理及其在图像生成领域的优势与创新

目录 一、引言 二、扩散模型的加噪过程 &#xff08;一&#xff09;前向扩散过程 &#xff08;二&#xff09;噪声调度策略 三、扩散模型的去噪过程 &#xff08;一&#xff09;反向扩散过程 &#xff08;二&#xff09;去噪网络架构 四、扩散模型的训练和推理机制 &am…

技术领域,有许多优秀的博客和网站

在技术领域&#xff0c;有许多优秀的博客和网站为开发者、工程师和技术爱好者提供了丰富的学习资源和行业动态。以下是一些常用的技术博客和网站&#xff0c;涵盖了编程、软件开发、数据科学、人工智能、网络安全等多个领域&#xff1a; 1. 综合技术博客 1.1 Medium 网址: ht…

mysql经典试题共34题

1、准备数据 -- drop drop table if exists dept; drop table if exists emp; drop table if exists salgrade;-- CREATE CREATE TABLE dept (deptno int NOT NULL COMMENT 部门编号,dname varchar(14) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMM…

2025 - GDB 盲调笔记--调试 “无调试符号“ “无调试信息“ 的三方程序

环境&#xff1a; arm64-ubuntu 相关&#xff1a;strace、ltrace、readelf、patchelf、strings、ldd -v 1). 使用 gdb 启动目标程序(不能直接用gdb启动的&#xff0c;可以先单独启动&#xff0c;再 gdb attach 强制调试) DIR_APP/opt/test gdb --args env LANGUAGE LD_LIBRA…

OCPP扩展机制与自定义功能开发:协议灵活性设计与实践 - 慧知开源充电桩平台

OCPP扩展机制与自定义功能开发&#xff1a;协议灵活性设计与实践 引言 OCPP作为开放协议&#xff0c;其核心价值在于平衡标准化与可扩展性。面对不同充电桩厂商的硬件差异、区域能源政策及定制化业务需求&#xff0c;OCPP通过**扩展点&#xff08;Extension Points&#xff09…

【项目】nnUnetv2复现

作者提出一种nnUNet(no-new-Net)框架,基于原始的UNet(很小的修改),不去采用哪些新的结构,如相残差连接、dense连接、注意力机制等花里胡哨的东西。相反的,把重心放在:预处理(resampling和normalization)、训练(loss,optimizer设置、数据增广)、推理(patch-based…

代码随想录算法训练营第八天|Leetcode 151.翻转字符串里的单词 卡码网:55.右旋转字符串 字符串总结 双指针回顾

151.翻转字符串里的单词 建议&#xff1a;这道题目基本把 刚刚做过的字符串操作 都覆盖了&#xff0c;不过就算知道解题思路&#xff0c;本题代码并不容易写&#xff0c;要多练一练。 题目链接/文章讲解/视频讲解&#xff1a;代码随想录 我们这道题的思路是&#xff0c;先将整…

【计算机网络】计算机网络的性能指标——时延、时延带宽积、往返时延、信道利用率

计算机网络的性能指标 导读 大家好&#xff0c;很高兴又和大家见面啦&#xff01;&#xff01;&#xff01; 在上一篇内容中我们介绍了计算机网络的三个性能指标——速率、带宽和吞吐量。用大白话来说就是&#xff1a;网速、最高网速和实时网速。 相信大家看到这三个词应该就…

Refreshtoken 前端 安全 前端安全方面

网络安全 前端不需要过硬的网络安全方面的知识,但是能够了解大多数的网络安全,并且可以进行简单的防御前两三个是需要的 介绍一下常见的安全问题,解决方式,和小的Demo,希望大家喜欢 网络安全汇总 XSSCSRF点击劫持SQL注入OS注入请求劫持DDOS 在我看来,前端可以了解并且防御前…

vue3框架的响应式依赖追踪机制

当存在一个响应式变量于视图中发生改变时会更新当前组件的所以视图显示&#xff0c;但是没有视图中不写这个响应式变量就就算修改该变量也不会修改视图&#xff0c;这是为什么&#xff1f;我们能否可以理解宽泛的理解为vue组件的更新就是视图的更新&#xff0c;单当视图中不存在…

C#核心(22)string

前言 我们在之前的学习中已经学习过了很多数字类型的数据结构,但一直没有讲解除了char以外的字符串相关的知识点,这也是我们继继承,封装,重载这些知识点之后要补充讲解的核心知识点。 你也发现了,其实在密封函数之后我们就已经开始进入更底层的方面为你讲解知识点了,这…