由00截断造成的文件读取(CVE-2023-47473分析)
字数 1493 2025-08-24 07:48:22

CVE-2023-47473分析:由00截断造成的文件读取漏洞教学文档

漏洞概述

CVE-2023-47473是一个由于Java JDK早期版本中未正确处理空字符(00截断)导致的文件读取漏洞。攻击者可以利用该漏洞绕过文件类型检查,读取服务器上的任意文件。

漏洞背景

该漏洞存在于一个Web应用程序中,具体涉及以下关键组件:

  • 一个名为getuploadimage.jsp的JSP文件
  • JDK 1.7.0_40之前的版本
  • 文件上传和读取功能

鉴权机制分析

过滤器配置

通过web.xml配置文件查看过滤器,所有路由都会经过SessionControl_UserLogin过滤器。

鉴权绕过机制

SessionControl_UserLogin过滤器的doFilter方法中:

  1. 创建了一个迭代器检查请求URI
  2. 如果当前请求URI不在迭代器中,会从会话中获取用户认证信息进行校验
  3. 如果当前请求URI在迭代器中,则跳过校验

默认免校验URL列表:包含特定后缀的URL(如.jsp)可以绕过SessionControl_UserLogin过滤器的校验。

漏洞点定位

漏洞存在于getuploadimage.jsp文件中,该文件包含image.jsp可以绕过SessionControl_UserLogin过滤器的校验。

漏洞代码分析

关键代码段

String imageURL = request.getParameter("imageURL");
System.out.println(imageURL);
if (!ValidateUtil.isNull(imageURL)) {
    try {
        String fileName = StringUtil.getFileName(imageURL);
        String fileType = StringUtil.getFileType(fileName, "unkown");
        
        if ("gif".equals(fileType) || "png".equals(fileType) || 
            "bmp".equals(fileType) || "jpg".equals(fileType) || 
            "jpeg".equals(fileType)) {
            // 通过校验
        } else {
            return; // 文件类型不符合则直接返回
        }
        
        response.setCharacterEncoding("UTF-8");
        response.resetBuffer();
        response.setContentType("image/jpeg");
        
        File uploadedFile = new File(imageURL);
        DataInputStream is = new DataInputStream(new FileInputStream(uploadedFile));
        DataOutputStream os = new DataOutputStream(response.getOutputStream());
        
        byte[] readBytes = new byte[128];
        int buffflag = -1;
        while ((buffflag = is.read(readBytes)) > -1) {
            os.write(readBytes, 0, buffflag);
        }
        
        os.close();
        is.close();
        os = null;
        response.flushBuffer();
        out.clear();
        out = pageContext.pushBody();
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
    }
}

文件处理流程

  1. 从请求参数获取imageURL
  2. 使用StringUtil.getFileName()获取文件名
  3. 使用StringUtil.getFileType()获取并校验文件类型
  4. 如果文件类型是图片(gif/png/bmp/jpg/jpeg),则读取文件内容并返回

关键工具方法

getFileName方法

public static String getFileName(String fileName) {
    int pos = fileName.lastIndexOf("\\");
    return pos > 0 ? fileName.substring(pos + 1) : fileName;
}

getFileType方法

public static String getFileType(String fileName, String defaultType) {
    String fileType = "";
    if (fileName != null && fileName.length() > 0) {
        int i = fileName.lastIndexOf(46); // 46是'.'的ASCII码
        if (i > -1 && i < fileName.length() - 1) {
            fileType = fileName.substring(i + 1).toLowerCase();
        }
    }
    
    if (!"pdf".equals(fileType) && !"doc".equals(fileType) && 
        !"bmp".equals(fileType) && !"xls".equals(fileType) && 
        !"exe".equals(fileType) && !"ppt".equals(fileType) && 
        !"gif".equals(fileType) && !"html".equals(fileType) && 
        !"xls".equals(fileType) && !"jpg".equals(fileType) && 
        !"png".equals(fileType) && !"jpeg".equals(fileType) && 
        !"xml".equals(fileType) && !"wav".equals(fileType) && 
        !"wma".equals(fileType) && !"mp3".equals(fileType) && 
        !"rar".equals(fileType) && !"txt".equals(fileType) && 
        !"htm".equals(fileType) && !"zip".equals(fileType) && 
        !"rm".equals(fileType) && !"swf".equals(fileType) && 
        !"flv".equals(fileType) && !"docx".equals(fileType) && 
        !"pptx".equals(fileType) && !"xlsx".equals(fileType)) {
        fileType = defaultType;
    }
    return fileType;
}

漏洞原理

00截断问题

在JDK 1.7.0_40之前的版本中,Java没有对空字符(\u0000)进行有效检查,导致可以构造特殊的文件名绕过安全检查:

  1. 文件类型检查阶段getFileType方法检查最后一个点(.)后的扩展名
  2. 实际文件读取阶段File类在JDK 1.7.0_40之前会忽略空字符后的内容

利用方式
构造如/etc/passwd%00.jpg这样的文件名:

  • 文件类型检查时:获取.jpg扩展名,通过校验
  • 实际读取文件时:%00被解析为空字符,实际读取/etc/passwd

JDK修复

JDK 1.7.0_40及之后版本增加了对空字符的检查:

final boolean isInvalid() {
    if (status == null) {
        status = (this.path.indexOf('\u0000') < 0) ? 
                PathStatus.CHECKED : PathStatus.INVALID;
    }
    return status == PathStatus.INVALID;
}

漏洞利用

攻击步骤

  1. 确认目标系统使用JDK 1.7.0_40之前的版本
  2. 构造恶意请求,在文件名后添加%00和合法的图片扩展名
    GET /getuploadimage.jsp?imageURL=/path/to/sensitive/file%00.jpg
    
  3. 服务器会返回目标文件内容

利用条件

  1. 目标系统使用JDK 1.7.0_40之前的版本
  2. 攻击者能够访问getuploadimage.jsp或类似功能
  3. 服务器上存在可读的目标文件

修复建议

  1. 升级JDK:将JDK升级到1.7.0_40或更高版本
  2. 输入验证
    • 在文件操作前检查路径中是否包含空字符
    • 使用白名单严格限制允许的文件扩展名
  3. 路径规范化:在处理文件路径前进行规范化处理
  4. 权限控制:限制应用程序的文件系统访问权限

防御代码示例

// 检查空字符
if (imageURL.indexOf('\u0000') >= 0) {
    throw new IllegalArgumentException("Invalid file path");
}

// 规范化路径
String normalizedPath = new File(imageURL).getCanonicalPath();

// 检查路径是否在允许的目录下
if (!normalizedPath.startsWith(ALLOWED_DIRECTORY)) {
    throw new SecurityException("Access denied");
}

总结

CVE-2023-47473是一个典型的文件读取漏洞,其核心问题在于:

  1. JDK早期版本对空字符处理不当
  2. 文件类型检查与实际文件操作之间存在不一致
  3. 缺乏严格的输入验证和路径处理

通过深入理解该漏洞,我们可以更好地防御类似的安全问题,特别是在文件操作相关的功能开发中。

CVE-2023-47473分析:由00截断造成的文件读取漏洞教学文档 漏洞概述 CVE-2023-47473是一个由于Java JDK早期版本中未正确处理空字符(00截断)导致的文件读取漏洞。攻击者可以利用该漏洞绕过文件类型检查,读取服务器上的任意文件。 漏洞背景 该漏洞存在于一个Web应用程序中,具体涉及以下关键组件: 一个名为 getuploadimage.jsp 的JSP文件 JDK 1.7.0_ 40之前的版本 文件上传和读取功能 鉴权机制分析 过滤器配置 通过 web.xml 配置文件查看过滤器,所有路由都会经过 SessionControl_UserLogin 过滤器。 鉴权绕过机制 在 SessionControl_UserLogin 过滤器的 doFilter 方法中: 创建了一个迭代器检查请求URI 如果当前请求URI不在迭代器中,会从会话中获取用户认证信息进行校验 如果当前请求URI在迭代器中,则跳过校验 默认免校验URL列表 :包含特定后缀的URL(如 .jsp )可以绕过 SessionControl_UserLogin 过滤器的校验。 漏洞点定位 漏洞存在于 getuploadimage.jsp 文件中,该文件包含 image.jsp 可以绕过 SessionControl_UserLogin 过滤器的校验。 漏洞代码分析 关键代码段 文件处理流程 从请求参数获取 imageURL 使用 StringUtil.getFileName() 获取文件名 使用 StringUtil.getFileType() 获取并校验文件类型 如果文件类型是图片(gif/png/bmp/jpg/jpeg),则读取文件内容并返回 关键工具方法 getFileName方法 : getFileType方法 : 漏洞原理 00截断问题 在JDK 1.7.0_ 40之前的版本中,Java没有对空字符( \u0000 )进行有效检查,导致可以构造特殊的文件名绕过安全检查: 文件类型检查阶段 : getFileType 方法检查最后一个点(.)后的扩展名 实际文件读取阶段 : File 类在JDK 1.7.0_ 40之前会忽略空字符后的内容 利用方式 : 构造如 /etc/passwd%00.jpg 这样的文件名: 文件类型检查时:获取 .jpg 扩展名,通过校验 实际读取文件时: %00 被解析为空字符,实际读取 /etc/passwd JDK修复 JDK 1.7.0_ 40及之后版本增加了对空字符的检查: 漏洞利用 攻击步骤 确认目标系统使用JDK 1.7.0_ 40之前的版本 构造恶意请求,在文件名后添加 %00 和合法的图片扩展名 服务器会返回目标文件内容 利用条件 目标系统使用JDK 1.7.0_ 40之前的版本 攻击者能够访问 getuploadimage.jsp 或类似功能 服务器上存在可读的目标文件 修复建议 升级JDK :将JDK升级到1.7.0_ 40或更高版本 输入验证 : 在文件操作前检查路径中是否包含空字符 使用白名单严格限制允许的文件扩展名 路径规范化 :在处理文件路径前进行规范化处理 权限控制 :限制应用程序的文件系统访问权限 防御代码示例 总结 CVE-2023-47473是一个典型的文件读取漏洞,其核心问题在于: JDK早期版本对空字符处理不当 文件类型检查与实际文件操作之间存在不一致 缺乏严格的输入验证和路径处理 通过深入理解该漏洞,我们可以更好地防御类似的安全问题,特别是在文件操作相关的功能开发中。