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