从2025d3ctf——d3jtar学习tomcat文件上传绕过(详解)
字数 1334 2025-08-29 22:41:24

Tomcat文件上传绕过技术详解:基于2025 D3CTF d3jtar题目的分析

环境与源码分析

题目环境

  • 提供一个WAR包,包含三个主要路由:
    • /view:通过UUID查看上传的文件
    • /Upload:文件上传功能
    • /Backup:使用org.kamranzafar.jtar依赖进行TAR压缩/解压操作

关键代码分析

上传功能(Upload路由)

  • 使用secureUpload方法处理上传
  • 黑名单过滤以下扩展名:
    "jsp", "jspx", "jspf", "jspa", "jsw", "jsv", "jtml", "jhtml", "sh", "xml", "war", "jar"
    
  • 上传成功后返回UUID格式的文件名

备份功能(Backup路由)

  • 使用org.kamranzafar.jtar 2.3版本进行TAR操作
  • 包含taruntar两个方法:
    • tar:将webapps/ROOT/WEB-INF/views目录打包为backup.tar
    • untar:解压TAR文件,未对entry.getName()进行安全检测,存在目录穿越风险

漏洞原理分析

关键发现

漏洞存在于org.kamranzafar.jtar库的文件名处理机制中,具体在TarHeader.getNameBytes方法:

  1. 字符编码转换问题

    • Java中char类型使用UTF-16编码(每个字符2字节)
    • 当使用(byte)强制转换时,会丢弃高8位,只保留低8位
    • 中文字符的低8位可能恰好对应黑名单中禁止的字符(如j、s、p)
  2. 具体转换过程

    • 例如"你"字:
      • Unicode编码:U+4F60
      • 十进制:20320
      • 二进制拆分:
        • 高8位:01001111 (0x4F = 79)
        • 低8位:01100000 (0x60 = 96)
      • 强制转换为byte后保留低8位:96 (对应ASCII字符"`")
  3. 构造恶意文件名

    • 需要找到三个中文字符,其低8位分别对应:
      • 106 ('j')
      • 115 ('s')
      • 112 ('p')
    • 这样当文件名被处理时,实际扩展名会变为"jsp"

漏洞利用步骤

  1. 准备恶意文件

    • 创建一个包含JSP木马的文件
    • 使用特定中文字符命名文件,如"某某某.jsp"(需精确计算字符)
  2. 文件上传

    • 通过/Upload路由上传文件
    • 获取服务器返回的UUID
  3. 触发文件解压

    • 访问/Backup路由触发解压操作
    • 利用目录穿越将文件解压到可执行目录
  4. 访问Webshell

    • 通过/view?page=[UUID]访问上传的文件

防御措施

  1. 文件上传安全

    • 使用白名单而非黑名单
    • 对上传文件重命名时使用固定扩展名
    • 限制上传文件的内容而不仅是扩展名
  2. TAR处理安全

    • 解压前验证文件名,防止目录穿越
    • 对解压路径进行规范化处理
    • 限制解压后的文件权限
  3. 字符编码处理

    • 统一使用UTF-8编码处理文件名
    • 对文件名进行严格的合法性检查

总结

这个漏洞展示了文件上传安全中容易被忽视的编码转换问题,通过精心构造的中文字符文件名,可以绕过基于黑名单的扩展名检查。关键在于:

  1. Java字符编码的强制转换会丢弃高8位
  2. 中文字符的低8位可能恰好形成被禁止的扩展名
  3. TAR处理过程中缺乏对文件名的严格验证

这种类型的漏洞需要开发者对字符编码有深入理解,并在安全处理中考虑各种边界情况。

Tomcat文件上传绕过技术详解:基于2025 D3CTF d3jtar题目的分析 环境与源码分析 题目环境 提供一个WAR包,包含三个主要路由: /view :通过UUID查看上传的文件 /Upload :文件上传功能 /Backup :使用 org.kamranzafar.jtar 依赖进行TAR压缩/解压操作 关键代码分析 上传功能(Upload路由) : 使用 secureUpload 方法处理上传 黑名单过滤以下扩展名: 上传成功后返回UUID格式的文件名 备份功能(Backup路由) : 使用 org.kamranzafar.jtar 2.3版本进行TAR操作 包含 tar 和 untar 两个方法: tar :将 webapps/ROOT/WEB-INF/views 目录打包为 backup.tar untar :解压TAR文件,未对 entry.getName() 进行安全检测,存在目录穿越风险 漏洞原理分析 关键发现 漏洞存在于 org.kamranzafar.jtar 库的文件名处理机制中,具体在 TarHeader.getNameBytes 方法: 字符编码转换问题 : Java中 char 类型使用UTF-16编码(每个字符2字节) 当使用 (byte) 强制转换时,会丢弃高8位,只保留低8位 中文字符的低8位可能恰好对应黑名单中禁止的字符(如j、s、p) 具体转换过程 : 例如"你"字: Unicode编码:U+4F60 十进制:20320 二进制拆分: 高8位:01001111 (0x4F = 79) 低8位:01100000 (0x60 = 96) 强制转换为byte后保留低8位:96 (对应ASCII字符" ` ") 构造恶意文件名 : 需要找到三个中文字符,其低8位分别对应: 106 ('j') 115 ('s') 112 ('p') 这样当文件名被处理时,实际扩展名会变为"jsp" 漏洞利用步骤 准备恶意文件 : 创建一个包含JSP木马的文件 使用特定中文字符命名文件,如"某某某.jsp"(需精确计算字符) 文件上传 : 通过 /Upload 路由上传文件 获取服务器返回的UUID 触发文件解压 : 访问 /Backup 路由触发解压操作 利用目录穿越将文件解压到可执行目录 访问Webshell : 通过 /view?page=[UUID] 访问上传的文件 防御措施 文件上传安全 : 使用白名单而非黑名单 对上传文件重命名时使用固定扩展名 限制上传文件的内容而不仅是扩展名 TAR处理安全 : 解压前验证文件名,防止目录穿越 对解压路径进行规范化处理 限制解压后的文件权限 字符编码处理 : 统一使用UTF-8编码处理文件名 对文件名进行严格的合法性检查 总结 这个漏洞展示了文件上传安全中容易被忽视的编码转换问题,通过精心构造的中文字符文件名,可以绕过基于黑名单的扩展名检查。关键在于: Java字符编码的强制转换会丢弃高8位 中文字符的低8位可能恰好形成被禁止的扩展名 TAR处理过程中缺乏对文件名的严格验证 这种类型的漏洞需要开发者对字符编码有深入理解,并在安全处理中考虑各种边界情况。