【Java代码审计】目录穿越篇

2023-12-17 05:41:16

1.Java中的目录穿越

目录穿越漏洞产生的本质是路径可控,一旦涉及文件的读取问题便会涉及java.io.File类,因此在审计这类漏洞时可以优先查找java.io.File引用,并根据经验来判断Paths、path、System.getProperty("user.dir")等各类可能会用来构造路径的关键字

若项目采用Spring MVC这类框架也可以先查看一下路由,判断是否存在如path之类的路由

在这里插入图片描述


2.目录穿越漏洞审计

1、案例1:任意文件读取漏洞:

public String fileList(String filename) {
    String filePath = System.getProperty("user.dir") + "/logs/" + filename;
    StringBuilder sb = new StringBuilder();

    File f = new File(filePath);
    File[] fs = f.listFiles();

    if (fs != null) {
        for (File ff : fs) {
            sb.append(ff.getName()).append("<br>");
        }
        return sb.toString();
    }
    return filePath + "目录不存在!";
}

首先,使用System.getProperty("user.dir")获取当前工作目录并拼接上"/logs/"和传入的文件名,得到路径filePath

代码中并没有对文件名进行验证或过滤,用户可以直接传入任意文件名来读取目录下的文件

例如,当我们传递参数为:../

发现可以读取上层目录的文件列表:

在这里插入图片描述

案例2:任意文件下载:

漏洞代码如下:

public String download(String filename, HttpServletResponse response) {
    String filePath = System.getProperty("user.dir") + "/logs/" + filename;
    try (InputStream inputStream = new BufferedInputStream(Files.newInputStream(Paths.get(filePath)))) {
        response.setHeader("Content-Disposition", "attachment; filename=" + filename);
        response.setContentLength((int) Files.size(Paths.get(filePath)));
        response.setContentType("application/octet-stream");

        // 使用 Apache Commons IO 库的工具方法将输入流中的数据拷贝到输出流中
        IOUtils.copy(inputStream, response.getOutputStream());
        log.info("文件 {} 下载成功,路径:{}", filename, filePath);
        return "下载文件成功:" + filePath;
    } catch (IOException e) {
        log.error("下载文件失败,路径:{}", filePath, e);
        return "未找到文件:" + filePath;
    }
}

同样,这段代码没有对文件名进行验证或过滤,用户可以直接传入任意文件名来下载文件

例如,传入一个恶意的文件名:../../../../../../../etc/passwd


3.Java中目录穿越漏洞修复

对于目录穿越漏洞的防御相对简单,一般有以下方法:

  1. 对文件名进行过滤,防止出现“./”等特殊符号
  2. 采用ID索引的方法来下载文件,而不是直接通过文件名
  3. 对目录进行限制
  4. 合理配置权限
public String safe(String filename) {
    if (!Security.checkTraversal(filename)) {
        String filePath = System.getProperty("user.dir") + "/logs/" + filename;
        return "安全路径:" + filePath;
    } else {
        return "检测到非法遍历";
    }
}

public static boolean checkTraversal(String content) {
    return content.contains("..") || content.contains("/");
}

此时再输入恶意的payload,检测到攻击行为:

在这里插入图片描述

文章来源:https://blog.csdn.net/Gherbirthday0916/article/details/135039835
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。