Out Of Bounds Write in Dynamodb
How Out Of Bounds Write Manifests in DynamoDB
DynamoDB is a schema‑less NoSQL store, but applications often treat it as if it had a fixed structure. When user‑controlled data is used to build attribute names or values in an UpdateExpression without validation, an attacker can supply attribute names that fall outside the intended “bounds” of the data model. This is analogous to an out‑of‑bounds write in a buffer: the write lands in memory (or, here, in the item’s attribute set) that the developer did not anticipate.
Typical vulnerable patterns include:
- Concatenating raw request parameters into the
SETpart of anUpdateExpression, e.g.SET #attr = :valwhere#attris derived directly fromreq.body.field. - Using
AttributeUpdates(legacy API) with dynamic attribute names taken from the client. - Failing to check the resulting item size before writing; DynamoDB rejects items larger than 400 KB, but an attacker can repeatedly add large attributes to cause throttling or consume write capacity.
- Writing to reserved internal attributes (such as those prefixed with
aws:) when the application does not sanitize names, which can interfere with DynamoDB Streams or trigger unexpected behavior in Lambda functions that process the stream.
Because DynamoDB stores items as JSON‑like maps, an out‑of‑bounds write does not corrupt memory in the traditional sense, but it can:
- Cause denial‑of‑service by inflating item size or consuming provisioned throughput.
- Lead to data leakage if the unexpected attribute is later returned in a response.
- Enable privilege escalation when the application later treats the injected attribute as a signal for access control (e.g., interpreting a user‑supplied
roleattribute).
Real‑world analogues include CVE‑2020‑10663 (improper validation of user input in a NoSQL update operation) and various OWASP API Security Top 10 findings under “Broken Object Property Authorization” and “Injection”.
DynamoDB‑Specific Detection
Detecting this class of flaw requires observing whether user‑supplied data influences attribute names or values in a DynamoDB write operation without an intermediate allowlist or sanitization step. middleBrick’s unauthenticated black‑box scan checks the API surface for exactly this condition.
When you submit a URL to middleBrick, it:
- Sends a series of crafted payloads (e.g., attribute names with special characters, extremely long strings, or names that match reserved prefixes) to every endpoint that accepts
POST,PUT, orPATCHwith a JSON body. - Monitors the responses for signs of successful writes: HTTP 200 with an updated item, error messages that reveal attribute validation failures, or changes in response latency that indicate throttling due to oversized items.
- Flags the finding under the Input Validation and Property Authorization checks, providing a severity rating, the exact parameter that was abused, and remediation guidance.
Example of a CLI detection run:
middlebrick scan https://api.example.com/items
The output might include:
| Check | Severity | Finding |
|---|---|---|
| Input Validation | High | User‑controlled attribute name passed directly to UpdateExpression without ExpressionAttributeNames. |
| Property Authorization | Medium | Possible write to unintended attribute “admin_flag”. |
Because the scan is agentless and requires only the public URL, it can be integrated into CI pipelines (see the GitHub Action) to catch the issue before code reaches production.
DynamoDB‑Specific Remediation
Fixing an out‑of‑bounds write in DynamoDB centers on strict input validation and using DynamoDB’s built‑in mechanisms for safe attribute handling.
1. **Validate attribute names against an allowlist** – never concatenate raw user input into the expression. Define the set of permissible attributes (e.g., ["title", "description", "price"]) and reject anything else.
2. **Use ExpressionAttributeNames** – this separates the attribute name from the expression syntax, preventing injection of reserved words or malicious prefixes.
3. **Limit item size** – before writing, check the serialized item size (AWS SDK provides JSON.stringify length) and reject if it approaches the 400 KB limit.
4. **Apply ConditionExpression** – ensure the item exists or that you are not unintentionally creating a new item with malicious attributes.
5. **Leverage the DynamoDB DocumentClient’s marshall/unmarshall helpers** – they enforce proper typing and reduce the chance of malformed attribute maps.
Below is a vulnerable Node.js example (AWS SDK v3) followed by the corrected version.
Vulnerable code:
const { DynamoDBClient, UpdateItemCommand } = require("@aws-sdk/client-dynamodb");
const client = new DynamoDBClient({});
async function updateItem(req) {
const { id, attrName, attrValue } = req.body; // ← attrName from user
const params = {
TableName: "Products",
Key: { id: { S: id } },
UpdateExpression: `SET #${attrName} = :val`, // ← direct concatenation
ExpressionAttributeNames: { "#attrName": attrName }, // ← WRONG: still user‑controlled
ExpressionAttributeValues: { ":val": { S: attrValue } },
ReturnValues: "ALL_NEW"
};
const cmd = new UpdateItemCommand(params);
return client.send(cmd);
}
Remediated code:
const { DynamoDBClient, UpdateItemCommand } = require("@aws-sdk/client-dynamodb");
const client = new DynamoDBClient({});
const ALLOWED_ATTRIBUTES = new Set(["title", "description", "price", "stock"]);
async function updateItem(req) {
const { id, attrName, attrValue } = req.body;
// 1. Validate attribute name
if (!ALLOWED_ATTRIBUTES.has(attrName)) {
throw new Error(`Attribute ${attrName} is not allowed`);
}
// 2. Use ExpressionAttributeNames safely
const params = {
TableName: "Products",
Key: { id: { S: id } },
UpdateExpression: `SET #attr = :val`,
ExpressionAttributeNames: { "#attr": attrName }, // safe because attrName is validated
ExpressionAttributeValues: { ":val": { S: attrValue } },
ReturnValues: "ALL_NEW",
// 3. Optional size check (approx)
ConditionExpression: "attribute_exists(id)"
};
const cmd = new UpdateItemCommand(params);
return client.send(cmd);
}
When using the higher‑level DynamoDB.DocumentClient, the same validation applies before constructing the UpdateExpression.
By applying these controls, you eliminate the vector that allows an attacker to write outside the intended attribute set, thereby mitigating denial‑of‑service, data corruption, and potential privilege‑escalation scenarios specific to DynamoDB-backed APIs.