Auth Bypass in Dynamodb
How Auth Bypass Manifests in Dynamodb
Auth bypass in DynamoDB manifests through several unique attack vectors that stem from its NoSQL architecture and AWS-specific access patterns. Unlike traditional SQL databases where row-level security is often enforced through complex joins and views, DynamoDB's flat key-value structure creates distinct vulnerabilities.
The most common DynamoDB auth bypass occurs through improper partition key handling. When applications construct DynamoDB queries using client-supplied partition keys without proper validation, attackers can simply modify the key value to access any item in the table. For example:
const params = {
TableName: 'Users',
Key: { userId: req.query.userId } // ⚠️ Client-controlled partition key
};
const result = await dynamodb.get(params).promise();This pattern allows authenticated users to access any user record by changing the userId parameter. The vulnerability becomes critical when combined with DynamoDB's eventual consistency model - a user might see data from another user's item during propagation delays.
Another DynamoDB-specific auth bypass vector involves global secondary indexes (GSIs). Applications often implement authorization checks on the base table but forget to apply the same logic when querying GSIs. An attacker can exploit this by querying the GSI directly:
// Vulnerable: checking permissions on base table only
const baseParams = {
TableName: 'Users',
Key: { userId: 'attacker' },
};
const result = await dynamodb.query(baseParams).promise(); // Passes auth check
// But GSI can be queried directly without auth
const gsiParams = {
TableName: 'Users',
IndexName: 'OwnerIndex',
};
const gsiResult = await dynamodb.query(gsiParams).promise(); // Bypasses authScan operations without proper filters represent another critical DynamoDB auth bypass pattern. Since DynamoDB scans examine every item in a table, a missing or improperly implemented filter can expose all data:
// Dangerous: scan without partition key constraint
const params = {
TableName: 'SensitiveData',
};
const result = await dynamodb.scan(params).promise(); // Returns ALL items, then filtersThe final major DynamoDB auth bypass involves conditional writes. When applications use conditional expressions that reference user-controlled data without proper validation, attackers can bypass authorization:
// Vulnerable conditional write
const params = {
TableName: 'Orders',
Key: { orderId: req.body.orderId },
UpdateExpression: 'set status = :s',
ConditionExpression: 'userId = :u',
ExpressionAttributeValues: {
':s': 'cancelled',
':u': req.body.userId // ⚠️ Client-controlled value
}
};
await dynamodb.update(params).promise(); // Can be bypassed by setting userId to attacker's IDDynamodb-Specific Detection
Detecting auth bypass vulnerabilities in DynamoDB requires understanding its unique query patterns and access control model. The most effective detection approach combines static code analysis with runtime scanning.
Static analysis should flag these DynamoDB-specific patterns:
// Pattern 1: Client-controlled partition keys
function isVulnerable(key) {
return key.includes('req.') || // req.query, req.body, req.params
key.includes('input.') || // GraphQL inputs
key.includes('event.') || // Lambda event
key.includes('context.'); // Context objects
}Runtime detection with middleBrick specifically targets DynamoDB's unique attack surface. The scanner tests for:
- Parameter injection in Key objects for get, delete, and update operations
- Index name manipulation in query and scan operations
- ExpressionAttributeValues injection in filter and condition expressions
- UpdateExpression injection for update and put operations
- ProjectionExpression manipulation to access unintended attributes
- Scan operations without proper partition key constraints
- Conditional write bypass through expression manipulation
middleBrick's DynamoDB scanning methodology includes active probing of these endpoints with crafted payloads designed to trigger auth bypass conditions. The scanner attempts to:
// Test for partition key injection
const testParams = {
TableName: 'Users',
Key: { userId: 'test OR userId = :attacker' }
};
// If this returns data for userId 'attacker', auth bypass existsThe scanner also validates DynamoDB-specific security configurations like IAM policies, VPC endpoints, and encryption settings. A complete auth bypass assessment includes verifying that:
- Least-privilege IAM policies are enforced
- VPC endpoints restrict access to authorized sources
- Encryption at rest and in transit is properly configured
- Access logging is enabled and monitored
- Global tables don't create cross-region data exposure
middleBrick provides a DynamoDB-specific security report showing which endpoints are vulnerable to auth bypass, with severity ratings based on the potential data exposure and ease of exploitation.
Dynamodb-Specific Remediation
Remediating DynamoDB auth bypass requires a defense-in-depth approach that combines proper architecture patterns with AWS-native security features. The foundation is implementing strict attribute-based access control (ABAC) at the application layer.
Always validate and sanitize partition keys before using them in DynamoDB operations:
function validatePartitionKey(userId, requestedId) {
if (userId !== requestedId) {
throw new Error('Unauthorized access to partition key');
}
// Additional validation: ensure ID format is correct
throw new Error('Invalid partition key format');
}
return requestedId;
}For query operations, always include partition key constraints and use filter expressions for additional authorization checks:
// Secure pattern: partition key constraint + filter
const params = {
TableName: 'Users',
KeyConditionExpression: 'userId = :userId',
FilterExpression: 'ownerId = :owner',
ExpressionAttributeValues: {
':userId': validatePartitionKey(req.user.id, req.query.userId),
':owner': req.user.ownerId
}
};
const result = await dynamodb.query(params).promise();When using GSIs, implement authorization checks on both the base table and index queries:
// Secure pattern: check both base and GSI
async function secureQuery(userId, ownerId, useGsi = false) {
if (!validatePartitionKey(userId, userId)) return null;
// Check base table permissions first
const baseCheck = await dynamodb.get({
TableName: 'Users',
Key: { userId },
ProjectionExpression: 'ownerId'
}).promise();
if (baseCheck.Item.ownerId !== ownerId) {
throw new Error('Authorization failed');
}
// Only query GSI if base check passes
if (useGsi) {
return await dynamodb.query({
TableName: 'Users',
IndexName: 'OwnerIndex',
KeyConditionExpression: 'ownerId = :owner',
ExpressionAttributeValues: { ':owner': ownerId }
}).promise();
}
return baseCheck;
}For scan operations, which are particularly dangerous, implement pagination with strict filters and consider using DynamoDB's PartiQL for more secure querying:
// Secure scan pattern with pagination
async function secureScan(userId, pageSize = 100) {
let lastKey = null;
while (true) {
const params = {
TableName: 'SensitiveData',
FilterExpression: 'userId = :userId',
ExpressionAttributeValues: { ':userId': userId },
Limit: pageSize
};
if (lastKey) {
params.ExclusiveStartKey = lastKey;
}
const result = await dynamodb.scan(params).promise();
results.push(...result.Items);
if (!result.LastEvaluatedKey) break;
lastKey = result.LastEvaluatedKey;
}
return results;
}Implement DynamoDB's fine-grained access control using IAM policies with conditions:
const securePolicy = {
Version: '2012-10-17',
Statement: [
{
Effect: 'Allow',
Action: [
'dynamodb:GetItem',
'dynamodb:Query',
'dynamodb:Scan'
],
Resource: 'arn:aws:dynamodb:region:account:table/Users',
Condition: {
'ForAllValues:StringEquals': {
'dynamodb:LeadingKeys': ['${aws:username}']
}
}
}
]
}Finally, enable DynamoDB Streams with Lambda triggers to audit all data access patterns and detect anomalous behavior that might indicate auth bypass attempts.
Related CWEs: authentication
| CWE ID | Name | Severity |
|---|---|---|
| CWE-287 | Improper Authentication | CRITICAL |
| CWE-306 | Missing Authentication for Critical Function | CRITICAL |
| CWE-307 | Brute Force | HIGH |
| CWE-308 | Single-Factor Authentication | MEDIUM |
| CWE-309 | Use of Password System for Primary Authentication | MEDIUM |
| CWE-347 | Improper Verification of Cryptographic Signature | HIGH |
| CWE-384 | Session Fixation | HIGH |
| CWE-521 | Weak Password Requirements | MEDIUM |
| CWE-613 | Insufficient Session Expiration | MEDIUM |
| CWE-640 | Weak Password Recovery | HIGH |