Ssrf Server Side in Express with Dynamodb
Ssrf Server Side in Express with Dynamodb — how this specific combination creates or exposes the vulnerability
Server-side request forgery (SSRF) in an Express service that interacts with Amazon DynamoDB typically occurs when user-controlled input is used to form network requests or to construct DynamoDB parameters that trigger external calls. In this stack, risk arises not only from classic SSRF patterns (for example, SSRF via the AWS SDK or HTTP request helpers), but also from DynamoDB-specific features that can cause the server to reach unintended endpoints.
One common scenario: an attacker provides a malicious DynamoDB table ARN or a crafted condition that causes the backend to make an HTTP request to an internal metadata service (169.254.169.254), a container instance metadata endpoint, or another internal service. Because the scan tests unauthenticated attack surfaces, middleBrick detects whether input validation around DynamoDB identifiers is insufficient and whether outbound HTTP calls can be abused to reach internal resources.
Another vector involves DynamoDB Streams and AWS SDK configurations. If Express code passes a user-supplied URL or host into SDK customizations—for example, overriding endpoint URLs for DynamoDB or constructing an HTTP agent based on user data—an attacker can direct traffic to internal services. MiddleBrick’s checks for SSRF and Inventory Management include verifying that DynamoDB-related parameters (table names, ARNs, condition expressions) are validated against allowlists and that no unauthenticated endpoints are leveraged to infer internal network topology.
Because middleBrick runs 12 security checks in parallel, it can surface SSRF-related findings in categories such as Input Validation, Property Authorization, and SSRF itself, alongside DynamoDB-specific concerns in Inventory Management. The scanner also examines OpenAPI specs and runtime behavior to see whether DynamoDB resource identifiers are reflected in ways that enable path or parameter manipulation.
Dynamodb-Specific Remediation in Express — concrete code fixes
Remediation focuses on strict input validation, avoiding reflection of user input into DynamoDB parameters, and hardening the Express service’s network egress. Below are concrete examples using the AWS SDK for JavaScript (v3) in an Express route.
1. Validate table names and ARNs against an allowlist
Never directly use user input as a DynamoDB table name or ARN. Instead, map allowed tables via a whitelist and enforce naming conventions.
import { DynamoDBClient, DescribeTableCommand } from "@aws-sdk/client-dynamodb";
const client = new DynamoDBClient({ region: "us-east-1" });
const ALLOWED_TABLES = new Set(["users", "products", "orders"]);
async function getTableDescription(tableName) {
if (!ALLOWED_TABLES.has(tableName)) {
throw new Error("Table not allowed");
}
const cmd = new DescribeTableCommand({ TableName: tableName });
return client.send(cmd);
}
app.get("/table/:name", async (req, res) => {
try {
const data = await getTableDescription(req.params.name);
res.json(data);
} catch (err) {
res.status(400).json({ error: err.message });
}
});
2. Avoid dynamic endpoint configuration from user input
Do not construct custom endpoints for the DynamoDB client based on user data. If you must override endpoints, use a strict allowlist of internal host patterns and reject any user-controlled hostname or protocol overrides.
import { DynamoDBClient, DynamoDBClientConfig } from "@aws-sdk/client-dynamodb";
function buildClientConfig(override) {
// Reject dangerous overrides; only permit known internal endpoints
const forbidden = ["http://169.254.169.254", "http://metadata"];
if (override && forbidden.some((f) => override.endpoint?.includes(f))) {
throw new Error("Endpoint not permitted");
}
const config = { region: "us-east-1" };
if (override && override.endpoint) {
config.endpoint = override.endpoint;
}
return new DynamoDBClient(config);
}
3. Sanitize conditions and expression attribute values
DynamoDB conditions and expression attribute values should be strongly typed and never built by concatenating raw user input. Use parameterization and schema validation to prevent injection-like behavior that could lead to SSRF via malicious condition expressions.
import { DynamoDBClient, QueryCommand } from "@aws-sdk/client-dynamodb";
const ddb = new DynamoDBClient({ region: "us-east-1" });
app.post("/query", async (req, res) => {
const { tableName, partitionKey } = req.body;
if (!ALLOWED_TABLES.has(tableName)) {
return res.status(400).json({ error: "Invalid table" });
}
const cmd = new QueryCommand({
TableName: tableName,
KeyConditionExpression: "pk = :pk",
ExpressionAttributeValues: {
":pk": { S: partitionKey },
},
});
try {
const data = await ddb.send(cmd);
res.json(data.Items);
} catch (err) {
res.status(400).json({ error: err.name });
}
});
4. Harden network and metadata service access
Ensure that the runtime environment blocks or restricts access to instance metadata endpoints where possible, and configure the SDK to use standard AWS credential resolution without falling back to insecure endpoints.
import { HttpRequest } from "@aws-sdk/protocol-http";
// Example of rejecting requests to metadata service
const isMetadataRequest = (req) => {
const host = req?.hostname || "";
return host === "169.254.169.254" || host.endsWith("amazonaws.com");
};
app.use((req, res, next) => {
if (isMetadataRequest(req)) {
return res.status(403).json({ error: "Blocked" });
}
next();
});
By combining these patterns—allowlisting table names, avoiding dynamic endpoint configuration, validating conditions, and blocking metadata service access—you reduce the risk that user input can lead to SSRF when the application interacts with DynamoDB. MiddleBrick can verify that these controls are effective by scanning unauthenticated attack surfaces and mapping findings to relevant frameworks such as OWASP API Top 10 and compliance requirements.