首页 > 编程语言 >Java代码审计-FileOperations

Java代码审计-FileOperations

时间:2024-01-29 16:02:10浏览次数:28  
标签:审计 Java String FileOperations req new import servlet javax

常见文件读写

常见文件读写方式

  • 通过FileInputStream读取文件并使用FileOutputStream写入另一个文件的测试方法
  • 通过BufferedInputStream读取文件并使用BufferedOutputStream写入另一个文件的测试方法
  • 通过BufferedReader读取文件并使用BufferedWriter写入另一个文件的测试方法
  • 通过FileWriterBufferedWriter将数据附加到文件末尾的测试方法
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

public class Test {

    // 通过FileInputStream读取文件并使用FileOutputStream写入另一个文件的测试方法
    @org.junit.jupiter.api.Test
    public void test1() throws IOException {
        // 字节流 对文件读取
        // 输入字节流对象
        FileInputStream in = new FileInputStream("D:\\javaweb123\\javaweb\\fileweb\\src\\main\\webapp\\test.txt");
        // 输出字节流对象
        FileOutputStream out = new FileOutputStream("D:\\m.txt");
        // 定义字节数组
        byte[] b = new byte[1024]; // 定义固定长度
        int len = -1;
        while ((len = in.read(b, 0, b.length)) != -1) {
            String s = new String(b, 0, len, "UTF-8");
            System.out.println(s);
            out.write(b, 0, len);
        }
        out.close();
        in.close();
    }

    // 通过BufferedInputStream读取文件并使用BufferedOutputStream写入另一个文件的测试方法
    @org.junit.jupiter.api.Test
    void Test02() throws IOException {
        BufferedInputStream in = new BufferedInputStream(
                new FileInputStream("D:\\javaweb123\\javaweb\\fileweb\\src\\main\\webapp\\test.txt"));
        BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream("D:\\m.txt"));
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = in.read(b, 0, b.length)) != -1) {
            String str = new String(b, 0, len, "utf-8");
            System.out.println(str);
            out.write(b, 0, len);
        }
        // 刷新缓存
        out.flush();
        // 关闭流
        in.close();
        out.close();
    }

    // 通过BufferedReader读取文件并使用BufferedWriter写入另一个文件的测试方法
    @org.junit.jupiter.api.Test
    void Test03() throws IOException {
        // 带缓存的字节流读取
        BufferedReader in = new BufferedReader(
                new InputStreamReader(new FileInputStream("D:\\javaweb123\\javaweb\\fileweb\\src\\main\\webapp\\test.txt"), "UTF-8"));
        BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("D:\\m.txt"), "UTF-8"));
        String str;
        while ((str = in.readLine()) != null) {
            System.out.println(str);
            out.write(str + "\n");
        }
        out.flush();
        in.close();
        out.close();
    }

    // 通过FileWriter和BufferedWriter将数据附加到文件末尾的测试方法
    @org.junit.jupiter.api.Test
    void Test04() throws IOException {
        String data = "插入到文件尾的内容";
        File file = new File("d:\\11.txt");
        if (!file.exists()) {
            file.createNewFile();
        }
        // 参数true为append模式
        FileWriter fw = new FileWriter(file.getAbsoluteFile(), true);
        BufferedWriter bw = new BufferedWriter(fw);
        bw.write(data);
        bw.close();
        fw.close();
    }
}

任意文件读取

任意文件读取是属于文件操作漏洞的一种,一般任意文件读取漏洞可以读取配置信息甚至系统重要文件。其中的目录遍历是由于web服务器或者web应用程序对用户输入的文件名称的安全性验证不足而导致的一种安全漏洞,使得攻击者通过利用一些特殊字符就可以绕过服务器的安全限制,访问任意的文件(可以是web根目录以外的文件),甚至执行系统命令。更严重的,导致SSRF漏洞,进而漫游至内网。

package com.example.file_operations;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;

@WebServlet("/fileread")
public class FileReadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 设置请求和响应的字符编码为UTF-8
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");

        // 获取请求参数中的文件名
        String filename = req.getParameter("filename");

        // 构建文件相对路径
//        String relativePath = "/uploads/" + filename;

        // 获取真实路径的目录
        String realDir = getServletContext().getRealPath("/uploads");

        // 构建文件路径
        String filePath = realDir + File.separator + filename;

        // 创建File对象
        File file = new File(filePath);

        // 检查文件是否存在
        if (!file.exists()) {
            resp.getWriter().write("文件不存在");
            return;
        }

        // 使用带缓冲的输入流读取文件内容
        try (BufferedInputStream in = new BufferedInputStream(new FileInputStream(file))) {
            byte[] b = new byte[1024];
            int len;

            // 逐块读取文件内容并写入响应
            while ((len = in.read(b, 0, b.length)) != -1) {
                String str = new String(b, 0, len, "utf-8");
                resp.getWriter().write(str);
            }
        }
    }
}

漏洞分析

	    // 获取请求参数中的文件名
 		String filename = req.getParameter("filename");

        // 获取真实路径的目录
        String realDir = getServletContext().getRealPath("/uploads");

        // 构建文件路径
        String filePath = realDir + File.separator + filename;

//没有对 filename 过滤,导致任意文件读取

任意文件下载

一些网站由于业务需求,往往需要提供文件查看或文件下载功能,但若对用户查看或下载的文件不做限制,则恶意用户就能够查看或下载任意敏感文件。

package com.example;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

@WebServlet("/filedown")
public class FileDownloadServlet extends HttpServlet {
    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 设置编码集(解码)
        request.setCharacterEncoding("UTF-8");
        // 设置响应的编码集
        response.setContentType("text/html;charset=utf-8");
        if(request.getParameter("filename")==null ||request.getParameter("filename").equals("") ){
            response.getWriter().write("文件不能为空");
            return;
        }
        String fileName=request.getParameter("filename");
        //通知浏览器以下载的方式打开
        response.addHeader("Content-Type", "application/octet-stream");
        response.addHeader("Content-Disposition","attachment;filename="+ URLEncoder.encode(fileName));
        //通过文件流读取文件
        String path= request.getSession().getServletContext().getRealPath("/uploads/");
        //针对要下载的文件创建了输入流
        FileInputStream in=new FileInputStream(path+fileName);
        //获取response的输出流
        ServletOutputStream out= response.getOutputStream();
        byte[]buffer=new byte[1024];
        int len=-1;
        while((len=in.read(buffer))!=-1){
            out.write(buffer, 0, len);
        }
        in.close();
        out.close();

    }
}

漏洞分析

String path= request.getSession().getServletContext().getRealPath("/uploads/");
//没有限制文件名

任意文件写入

任意文件写入漏洞(Arbitrary File Write)是一种常见的安全漏洞,攻击者可以利用此漏洞将任意数据写入到服务器上的任意位置,从而可能导致服务器上的敏感信息泄漏或系统被控制。

package com.example;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
@WebServlet("/filewrite")
public class FilewriteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String realPath = req.getSession().getServletContext().getRealPath("/");
        String filename = req.getParameter("filename");
        String content = req.getParameter("content");
        File file = new File(filename);
        FileOutputStream out = new FileOutputStream(realPath+file);
        out.write(content.getBytes());
        out.close();
        resp.getWriter().write(realPath+file);

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}

漏洞分析

	FileOutputStream out = new FileOutputStream(realPath+file);
	//没有过滤,直接写入服务器

任意文件删除

程序提供删除功能,对传入的参数过滤不严 导致可以删除任意文件。可以删除系统 网站中的文件。严重破坏网站正常运行。

package com.example;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;

@WebServlet("/filedelete")
public class FileDeleteServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String filename = req.getParameter("filename");
        String realPath = req.getSession().getServletContext().getRealPath("/");
        File file = new File(realPath+filename);
        if(file.exists()){
            file.delete();
            resp.getWriter().write("文件已经删除"+ realPath+filename);
        }

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

漏洞分析

String filename = req.getParameter("filename");
String realPath = req.getSession().getServletContext().getRealPath("/");
//文件名可控,直接拼接至realPath中处理

任意文件拷贝

对参数没有进行有效过滤。导致文件在在使用过程中可以被拷贝。例如上传文件后缀名 限制为图片类型 jpg
通过拷贝 脚本类型的jsp文件。对路径没有限制 拷贝系统敏感文件到网站目录下载。

package com.example;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

@WebServlet("/filecopy")
public class FileCopyServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String realPath = req.getSession().getServletContext().getRealPath("/");
        Path path = Files.copy(Paths.get(realPath+req.getParameter("s")), Paths.get(realPath+req.getParameter("d")));
        resp.getWriter().write(path.toString());
    }
}

漏洞分析

 Path path = Files.copy(Paths.get(realPath+req.getParameter("s")), Paths.get(realPath+req.getParameter("d")));
 //未过滤,直接拼接,参数可控制

任意文件移动

跟文件拷贝漏洞类似,对传入的参数没有进行有效过滤 在移动重名的时候产生漏洞。

package com.example;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;

@WebServlet("/filerename")
public class FileRenameServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html;charset=utf-8");
        String s = req.getParameter("s");
        String d = req.getParameter("d");
        String realPath = req.getSession().getServletContext().getRealPath("/");
        File files = new File(realPath + s);
        File filed = new File(realPath + d);
        files.renameTo(filed);
        resp.getWriter().write(filed.getAbsolutePath()+"\t"+filed.exists());

    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req,resp);
    }
}

漏洞分析

  File files = new File(realPath + s);
        File filed = new File(realPath + d);
        files.renameTo(filed);
//未过滤,直接拼接,参数可控制

目录遍历漏洞

任意目录遍历漏洞顾名思义攻击者可以通过漏洞遍历出服务器操作系统中的任意目录文件名,从而导致服务器敏感信息泄漏,某些场景下(如遍历出网站日志、备份文件、管理后台等)甚至可能会导致服务器被非法入侵。

package com.example.file_operations;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet("/filelist")
public class FileListServlet extends HttpServlet {

    public void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 设置编码集(解码)
        request.setCharacterEncoding("UTF-8");
        // 设置响应的编码集
        response.setContentType("text/html;charset=utf-8");
        if(request.getParameter("dir")==null ||request.getParameter("dir").equals("") ){
            response.getWriter().write("目录不能为空");
            return;
        }
        //根据逻辑路径获取物理路径

        //获取目录
        String  dir = request.getParameter("dir");

        //获取相对路径
        String path = request.getServletContext().getRealPath("/" + dir);

        File file=new File(path);
        File[] files= file.listFiles();
//        List<String> fileNames=new ArrayList<String>();
        for(File f:files){
            String fileName=f.getName();
            response.getWriter().write(fileName+"<br>");
        }


    }
}

漏洞分析

String path= request.getSession().getServletContext().getRealPath("/uploads/"+request.getParameter("dir"));
//直接拼接,未有效过滤

标签:审计,Java,String,FileOperations,req,new,import,servlet,javax
From: https://www.cnblogs.com/Gp3r/p/17994712

相关文章

  • Java代码审计-SSRF
    SSRF漏洞SSRF(Server-SideRequestForgery:服务器端请求伪造)是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部服务器系统。支持的协议fil......
  • Java代码审计-XXE
    一、XXE漏洞简介XXE(XML外部实体注入,XMLExternalEntity),在应用程序解析XML输入时,当允许引用外部实体时,可构造恶意内容,导致读取任意文件、探测内网端口、攻击内网网站、发起DoS拒绝服务攻击、执行系统命令等。Java中的XXE支持sun.net.www.protocol里的所有协议:http,https,file,f......
  • Java代码审计-FileUpload
    Web应用通常都会包含文件上传功能,用户可以将其本地的文件上传到Web服务器上。如果服务器端没有能够正确的检测用户上传的文件类型是否合法(例如上传了jsp后缀的WebShell)就将文件写入到服务器中就可能会导致服务器被非法入侵。漏洞成因后缀名无限制//导入必要的类库package......
  • javax.annotation.Nullable找不到
    您需要包括一个存在该类的罐子。您可以在这里找到它如果使用Maven,则可以添加以下依赖项声明:<dependency><groupId>com.google.code.findbugs</groupId><artifactId>jsr305</artifactId><version>3.0.2</version></dependency>对于Gradle:dependencies......
  • Windows下安装和配置Java JDK
    1、......
  • 配置java环境(Redhat)
    安装前准备:下载java的Jdkhttps://www.oracle.com/java/technologies/downloads/   (jdk-8u202-linux-x64.tar.gz)1.查看系统是否有java环境: java-version2.如果有版本输出则需要卸载之前的jdk,找出安装的jdk: rpm-qa|grepjdk3.根据 rpm-qa|grepjdk命令列出的......
  • JVM(Java虚拟机) 整理
    JVM整体结构本文主要说的是HotSpot虚拟机,JVM全称是JavaVirtualMachine,中文译名:Java虚拟机简化一下:Java字节码文件Class文件本质上是一个以8位字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑的排列在Class文件中,JVM根据其特定的规则解析该二进制数据,从而得到......
  • java中二分查找前提必须是升序吗?
    二分查找不必须是升序,降序排列的数组也可以执行二分查找。二分查找算法是一种高效的搜索方法,它要求数据集是有序的,无论是升序还是降序都可以。在升序排列的情况下,算法会将目标值与中间值比较,如果目标值较小,则在左半部分继续查找;如果目标值较大,则在右半部分继续查找。在降序排列的......
  • 【干货】一文掌握JavaScript检查对象空值的N种技巧!
    在开发JavaScript应用程序时,经常需要检查对象是否为空。这是因为在处理和操作对象数据时,我们需要确保对象包含有效的值或属性。以下是一些常见情况,我们需要检查JavaScript对象是否为空:防止空引用错误:当我们尝试访问或使用一个空对象时,可能会导致空引用错误(如TypeError:Cann......
  • 【干货】一文掌握JavaScript检查对象空值的N种技巧!
    在开发JavaScript应用程序时,经常需要检查对象是否为空。这是因为在处理和操作对象数据时,我们需要确保对象包含有效的值或属性。以下是一些常见情况,我们需要检查JavaScript对象是否为空:防止空引用错误:当我们尝试访问或使用一个空对象时,可能会导致空引用错误(如TypeError:Can......