Xml External Entities in Restify with Dynamodb
Xml External Entities in Restify with Dynamodb — how this specific combination creates or exposes the vulnerability
XML External Entity (XXE) injection occurs when an application processes XML input and allows an attacker to define external entities, which can lead to arbitrary file reads, server-side request forgery (SSRF), or exposure of metadata. In a Restify service that accepts XML payloads and interacts with Amazon DynamoDB, the combination of an XML parser that resolves external entities and DynamoDB operations can create a chain that exposes sensitive data or enables unauthorized network calls.
Consider a Restify endpoint that receives an XML document to query or update a DynamoDB table. If the XML parser is configured to resolve external entities (for example, by enabling DTD processing in Node.js xml2js or xmldom parsers without disabling external entity resolution), an attacker can supply an XML payload like the following:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >]>
<root>&xxe;</root>
If the Restify service parses this XML and later uses the extracted data as part of a DynamoDB request (for example, using the parsed value as a key condition or filtering expression), the SSRF or file-read impact can be compounded. An attacker might leverage this to read instance metadata from the EC2 metadata service (http://169.254.169.254/latest/meta-data/), which can reveal IAM instance profiles, security credentials, or other sensitive information. Because DynamoDB calls from the service often include credentials (via IAM roles or static keys), an XXE-enabled parser can facilitate unauthorized access to those credentials if they are exposed through file reads or SSRF.
Moreover, if the service logs or reflects parsed XML content in responses or errors, it can inadvertently disclose sensitive information or amplify the reach of injected entities. The DynamoDB interaction may involve operations such as GetItem or Query, where user-controlled values derived from XML are used directly. Without strict input validation and parser hardening, this creates a path where an XXE vulnerability can be leveraged to probe internal services, bypass network-level isolation, or extract data that would otherwise be protected by DynamoDB’s access controls.
In practice, this specific combination is risky when the Restify application uses XML parsing libraries that do not explicitly disable DTDs and external entity resolution, and when DynamoDB operations consume data that originates from those XML inputs. The vulnerability is not inherent to DynamoDB or Restify alone, but arises from insecure XML processing practices combined with the trust placed in parsed values used in database operations.
Dynamodb-Specific Remediation in Restify — concrete code fixes
To mitigate XXE in a Restify service that interacts with DynamoDB, harden the XML parser and ensure that any data used in DynamoDB requests is validated and sanitized. Below are concrete remediation steps with code examples for a Restify service using the AWS SDK for JavaScript v3 and a secure XML parser configuration.
1. Disable external entity resolution in XML parsing
Use a parser that does not resolve external entities. For example, with fast-xml-parser, configure the parser to disallow DOCTYPE and external entities:
const { XMLParser } = require("fast-xml-parser");
const parser = new XMLParser({
ignoreAttributes: false,
attributeNamePrefix: "_",
// Explicitly disable DTD and external entity processing
allowBooleanAttributes: true,
parseNodeValue: true,
parseAttributeValue: false,
trimValues: true,
// Reject DOCTYPE to prevent XXE
doctype: false,
});
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [ <!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "file:///etc/passwd" >] >
<root>test</root>`;
if (!parser.validate(xml)) {
throw new Error("Invalid XML");
}
const jsonObj = parser.parse(xml);
console.log(jsonObj);
2. Validate and sanitize inputs before DynamoDB operations
Ensure that values used in DynamoDB requests are strictly validated. For instance, when using the AWS SDK for JavaScript v3, construct requests with sanitized parameters:
const { DynamoDBClient, GetItemCommand } = require("@aws-sdk/client-dynamodb");
const client = new DynamoDBClient({ region: "us-east-1" });
async function getItemSafely(tableName, key) {
// Validate table name and key to prevent injection or misuse
if (!/^[a-zA-Z0-9_-]+$/.test(tableName)) {
throw new Error("Invalid table name");
}
// Assume key is already validated and shaped to DynamoDB attribute values
const command = new GetItemCommand({
TableName: tableName,
Key: key,
});
const response = await client.send(command);
return response.Item;
}
// Example usage with sanitized inputs
const tableName = "MySecureTable";
const key = { id: { S: "user123" } };
getItemSafely(tableName, key).then(console.log).catch(console.error);
3. Enforce secure defaults in Restify routes
In your Restify route handlers, avoid passing raw XML to DynamoDB. Parse defensively and extract only expected fields:
const restify = require("restify");
const server = restify.createServer();
server.post("/items", async (req, res, next) => {
try {
const parsed = parser.parse(req.body);
// Expect a specific structure; reject unexpected nodes or attributes
if (!parsed || !parsed.item || typeof parsed.item.id !== "string") {
return res.send(400, { error: "Invalid payload" });
}
const itemId = parsed.item.id;
// Use sanitized itemId in DynamoDB call
const item = await getItemSafely("ItemsTable", { id: { S: itemId } });
res.send(200, item);
} catch (err) {
res.send(500, { error: err.message });
}
return next();
});
server.listen(8080, () => {
console.log("Server listening on port 8080");
});
4. Principle of least privilege for DynamoDB access
Ensure the IAM role or credentials used by Restify have minimal permissions for the required DynamoDB operations. For example, grant dynamodb:GetItem and dynamodb:Query only on specific tables and with conditions that restrict access patterns.
5. Monitoring and testing
Use the middleBrick CLI to scan your Restify endpoints for XXE and other vulnerabilities. Run middlebrick scan <url> to get a security risk score and findings. For continuous protection, consider the Pro plan to enable continuous monitoring and integrate the GitHub Action to fail builds if a risk score drops below your threshold.