Xml External Entities in Axum with Cockroachdb
Xml External Entities in Axum with Cockroachdb — how this specific combination creates or exposes the vulnerability
XML External Entity (XXE) injection occurs when an application processes XML input that references external entities, allowing an attacker to force the parser to disclose local files, trigger SSRF, or amplify denial of service. In an Axum service that accepts XML payloads and interacts with CockroachDB, the risk emerges at the intersection of Axum’s XML parsing choices and CockroachDB’s behavior as a network-accessible database endpoint.
Axum does not include XML parsing by default; developers add it explicitly (for example via the quick-xml crate with a custom deserializer or via xml-rs). If the parser is configured to resolve external entities and the application constructs SQL statements or passes data to CockroachDB without strict input validation, an attacker can supply a malicious XML document that causes the parser to read files such as /etc/hosts or to make HTTP requests to internal CockroachDB SQL ports (typically 26257).
Cockroachdb-specific exposure can occur when an XXE leads to SSRF against the database port. Unlike a traditional SQL injection that returns query results, CockroachDB may return connection-level errors or status information that reveals whether a network endpoint is reachable. An attacker can use this behavior to confirm internal service exposure or to infer network topology. Even when XML payloads are not directly used in SQL strings, logging or error handling in Axum that echoes parsed XML content into responses can disclose paths or internal hostnames that aid further attacks against CockroachDB.
Consider a handler that deserializes an XML body and builds a SQL string for Cockroachdb without sanitization:
use axum::{routing::post, Router};
use quick_xml::de::from_str;
use serde::Deserialize;
use std::net::SocketAddr;
#[derive(Deserialize)]
struct User {
username: String,
email: String,
}
async fn create_user(xml_body: String) -> Result {
let user: User = from_str(&xml_body).map_err(|e| (axum::http::StatusCode::BAD_REQUEST, e.to_string()))?;
// WARNING: naive string concatenation used for illustration; do not emulate.
let sql = format!("INSERT INTO users (username, email) VALUES ('{}', '{}')", user.username, user.email);
// Assume execute_cockroachdb is a function that sends the query to Cockroachdb.
execute_cockroachdb(&sql).await?;
Ok("ok".to_string())
}
async fn execute_cockroachdb(query: &str) -> Result<(), (axum::http::StatusCode, String)> {
// Placeholder: send query to Cockroachdb via a safe driver with prepared statements.
Ok(())
}
#[tokio::main]
async fn main() {
let app = Router::new().route("/users", post(create_user));
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr).serve(app.into_make_service()).await.unwrap();
}
In this example, if quick-xml is configured to process external entities, an attacker can submit an XML document that references a file entity or an HTTP entity pointing at the Cockroachdb port. Even though the SQL is built via string concatenation (which is also unsafe), the primary vector here is XXE-enabled parsing. The fix is to disable external entity resolution in the XML parser and to use strongly typed queries (e.g., with sqlx or diesel) rather than string interpolation.
Another scenario involves OpenAPI/Swagger-driven clients that accept XML and forward it to backend services using Axum. If the backend re-sends user-controlled XML to Cockroachdb-adjacent tooling without disabling DTDs and external entities, the scan surface expands. middleBrick’s LLM/AI Security checks and its OpenAPI spec analysis can highlight such risky integrations by cross-referencing spec definitions with runtime behavior, emphasizing that unauthenticated endpoints accepting XML must be hardened against XXE.
Remediation in Axum centers on parser configuration and query handling. Ensure XML parsers are created with entity resolution disabled. Avoid constructing SQL via string formatting; instead use parameterized queries. If you must process XML, validate and sanitize all inputs and treat parsed content as untrusted data.
Cockroachdb-Specific Remediation in Axum — concrete code fixes
To mitigate XXE against Cockroachdb in Axum, focus on two layers: (1) XML parser hardening and (2) safe database interaction. Below are concrete, idiomatic examples that you can adopt directly in your Axum service.
1) Disable external entities in XML parsing
If you use quick-xml for deserialization, configure it to not load external DTDs. For crates that allow parser customization, ensure that entity expansion and DOCTYPE processing are turned off. With xml-rs, avoid Feature::external_entity_loading and similar options.
2) Use parameterized SQL with a Cockroachdb driver
Instead of building SQL by string interpolation, use prepared statements. Here is an example using sqlx with Cockroachdb:
use axum::{routing::post, Json, Router};
use serde::Deserialize;
use sqlx::postgres::PgPoolOptions;
use std::net::SocketAddr;
#[derive(Deserialize)]
struct CreateUser {
username: String,
email: String,
}
async fn create_user(
Json(payload): Json,
pool: sqlx::PgPool,
) -> Result {
sqlx::query(
"INSERT INTO users (username, email) VALUES ($1, $2)",
)
.bind(&payload.username)
.bind(&payload.email)
.execute(&pool)
.await
.map_err(|e| (axum::http::StatusCode::INTERNAL_SERVER_ERROR, e.to_string()))?;
Ok("created".to_string())
}
#[tokio::main]
async fn main() -> Result<(), Box> {
let pool = PgPoolOptions::new()
.connect("postgresql://user:password@localhost:26257/dbname?sslmode=require")
.await?;
let app = Router::new().route("/users", post(create_user));
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
axum::Server::bind(&addr).serve(app.into_make_service()).await?;
Ok(())
}
This approach eliminates SQL injection risks and ensures that XML-derived data is treated strictly as parameter values, not executable code. It also aligns with best practices for interacting with Cockroachdb via its PostgreSQL-compatible wire protocol.
3) Validate and limit XML features if you must parse XML
If your application legitimately needs XML, restrict what the parser can do:
- Disable DTDs and external entity resolution.
- Set strict limits on entity expansion depth to prevent billion laughs attacks.
- Do not allow external schemas or imports that could pull in remote resources.
For runtime visibility, middleBrick’s CLI can scan endpoints that accept XML to verify that XXE vectors are not present. Its GitHub Action can enforce a security score threshold in CI/CD, failing builds if risky configurations are detected.
Finally, prefer JSON-based APIs where possible. JSON does not have the same entity resolution complexities as XML, reducing the attack surface when working with Cockroachdb through Axum.