Skip to content

Bug: XML External Entity (XXE) in datagrip/navicat connection import #1836

Description

@fakebug111

Chat2DB Version

v0.3.7

Describe the bug

XML External Entity (XXE) in datagrip/navicat connection import

Project: chat2db/chat2db
Severity: High · CWE: CWE-611 (Improper Restriction of XML External Entity Reference)
Affected versions: v0.3.7

Summary

The connection-import endpoints parse attacker-controlled XML with a DocumentBuilderFactory that sets neither FEATURE_SECURE_PROCESSING nor disallow-doctype-decl. A logged-in user can submit an XML document with an external entity / DOCTYPE declaration, causing the server to disclose local files, perform SSRF, or exhaust resources. A hardened parser (XMLUtils.parseDocument) already exists in the codebase but is not used on the vulnerable paths.

This issue requires an authenticated user (the import endpoints are under the normal session-based API), so the attacker needs a valid Chat2DB account; there is no unauthenticated vector here.

Vulnerability chain

Stage Component Location
Source (datagrip) POST /api/converter/datagrip/upload binds @RequestParam("text") ConverterController.java:77-78
Source (ncx) POST /api/converter/ncx/upload uploads an .ncx file ConverterController.java:42-43
Parse sink (datagrip) DocumentBuilderFactory.newInstance()db.parse(inputStream), no hardening ConverterServiceImpl.java:296-302
Parse sink (ncx) same pattern on the uploaded file ConverterServiceImpl.java:104-109
Existing hardening (unused here) XMLUtils.parseDocument sets FEATURE_SECURE_PROCESSING + disallow-doctype-decl XMLUtils.java:62-72

The datagrip path splits the submitted text on the #BEGIN# marker, prepends an XML header to each chunk, and parses each chunk with a freshly created, unhardened DocumentBuilderFactory. The ncx path parses the uploaded .ncx file the same way. In both cases a DOCTYPE / external-entity declaration in the input is honored by the default parser, so file:// / http:// URIs are resolved server-side.

Key code

Vulnerable datagrip parse (ConverterServiceImpl.datagripUploadFile):

// ConverterServiceImpl.java:294-302
for (String config : configs) {
    //1、Create a DocumentBuilderFactory object
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();   // :296 — no secure features
    //2、Create a DocumentBuilder object
    DocumentBuilder db = dbf.newDocumentBuilder();
    //3、Load the xml file into the current project ...
    try (InputStream inputStream = new ByteArrayInputStream(config.getBytes(StandardCharsets.UTF_8))) {
        Document document = db.parse(inputStream);                        // :302 — external entities honored

Same flaw on the ncx path (ConverterServiceImpl.uploadFile):

// ConverterServiceImpl.java:104-109
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse(file);

The hardened parser that is already present but not used on these paths:

// XMLUtils.java:62-68
public static Document parseDocument(InputSource source) throws XMLException {
    try {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        DocumentBuilder xmlBuilder = dbf.newDocumentBuilder();
        return xmlBuilder.parse(source);

Proof of Concept

Authenticated. Replace host/port and the session cookie / token with a valid Chat2DB login. No full exploit payload is included — only the request shape showing the entry point.

Datagrip path (the body must start with the #DataSourceSettings# header followed by a #BEGIN# marker, after which the XML chunk is parsed):

POST /api/converter/datagrip/upload HTTP/1.1
Host: <target>:<port>
Content-Type: application/x-www-form-urlencoded
Cookie: <authenticated session>

text=%23DataSourceSettings%23%0A%23BEGIN%23%0A<... XML with DOCTYPE / external-entity declaration ...>

Ncx path (upload an .ncx-named file whose body contains the XML):

POST /api/converter/ncx/upload HTTP/1.1
Host: <target>:<port>
Content-Type: multipart/form-data; boundary=----boundary
Cookie: <authenticated session>

------boundary
Content-Disposition: form-data; name="file"; filename="poc.ncx"
Content-Type: application/xml

<... XML with DOCTYPE / external-entity declaration ...>
------boundary--

In each case an XML body containing an external entity declaration referencing a file:// URI causes the server to resolve and inline local file contents; http:// URIs enable SSRF, and resource-bomb entities enable denial of service.

Impact

An authenticated Chat2DB user can read arbitrary files readable by the server process (configuration, credentials, the H2/datasource store), perform server-side requests to internal/external hosts (SSRF), or cause resource exhaustion via entity expansion. Impact is bounded by the authentication requirement — it is not reachable without a valid user session.

Remediation

Route both parse paths through the existing hardened parser XMLUtils.parseDocument, which already sets FEATURE_SECURE_PROCESSING and disallow-doctype-decl. Concretely, in ConverterServiceImpl, replace the raw DocumentBuilderFactory.newInstance() blocks at lines 296 and 104 with calls to XMLUtils.parseDocument(...) (taking an InputSource/InputStream/File). Additionally, set dbf.setXIncludeAware(false) and dbf.setExpandEntityReferences(false) for defense in depth.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions