Ssrf Server Side in Dynamodb
How SSRF Manifests in DynamoDB
Server-Side Request Forgery (SSRF) in DynamoDB contexts typically occurs when applications use user-controlled input to construct DynamoDB API requests or when DynamoDB endpoints are used as part of request processing. The most common DynamoDB-specific SSRF patterns include:
- Using user-supplied table names or partition keys that resolve to internal DynamoDB endpoints
- Constructing DynamoDB URLs from untrusted input for the AWS SDK's endpoint configuration
- Exposing DynamoDB's DynamoDB Streams or Global Tables endpoints to untrusted users
- Using DynamoDB as a proxy for internal service discovery
A classic DynamoDB SSRF scenario involves an application that accepts a table name parameter and uses it to construct a DynamoDB endpoint URL:
# Vulnerable DynamoDB SSRF pattern
import boto3
def get_user_data(table_name):
# User-controlled input used to construct endpoint
endpoint = f'https://dynamodb.{region}.amazonaws.com/{table_name}'
# This can be exploited to access internal services
client = boto3.client('dynamodb', endpoint_url=endpoint)
return client.scan(TableName=table_name)Attackers can exploit this by providing table names like ../../../internal-service or using AWS metadata endpoints (http://169.254.169.254) to access internal resources. Another common pattern is when applications use DynamoDB as a configuration store for other services:
// Vulnerable pattern: DynamoDB as configuration store
const AWS = require('aws-sdk');
const docClient = new AWS.DynamoDB.DocumentClient();
async function getServiceConfig(serviceName) {
const params = {
TableName: 'service_configs',
Key: { name: serviceName }
};
const result = await docClient.get(params).promise();
// User-controlled config value used to make requests
const client = new AWS.S3({
endpoint: result.Item.endpoint_url
});
return client.listBuckets().promise();
}This pattern is dangerous because DynamoDB's flexibility allows storing arbitrary URLs that can point to internal services, bypassing network security controls.
DynamoDB-Specific Detection
Detecting SSRF vulnerabilities in DynamoDB requires examining both the application code and the DynamoDB configuration. Key detection strategies include:
Code Analysis Patterns
# Detection: Look for these dangerous patterns
import re
def detect_ssrf_vulnerabilities(code):
patterns = [
r'endpoint_url.*=.*[^"\w]', # Dynamic endpoint construction
r'TableName.*=.*[^"\w]', # Dynamic table names
r'http://169\.254\.169\.254', # Metadata endpoint access
r'localhost|127\.0\.0\.1', # Localhost access
r'0\.0\.0\.0|10\.|172\.1[6-9]|192\.168' # Private IP ranges
]
matches = []
for pattern in patterns:
matches.extend(re.findall(pattern, code))
return matches
# Scan with middleBrick for automated detection
# The middleBrick CLI can scan your API endpoints for SSRF patterns
# Example: middlebrick scan https://api.example.com/dynamodbNetwork Configuration Analysis
Check DynamoDB VPC endpoints and security groups for overly permissive configurations:
# AWS CLI commands to audit DynamoDB access
# List VPC endpoints
aws ec2 describe-vpc-endpoints --filter Name=service-name,Values=*dynamodb*
# Check security group rules
aws ec2 describe-security-groups --filters Name=group-name,Values='*dynamodb*'
# Review IAM policies for SSRF-prone permissions
aws iam get-policy-version --policy-arn arn:aws:iam::123456789012:policy/DynamoDBFullAccess
middleBrick Security Scanning
middleBrick's SSRF detection specifically identifies DynamoDB-related vulnerabilities through its black-box scanning approach. The scanner tests for:
- Access to internal DynamoDB endpoints
- Metadata service exposure
- Private IP address access through DynamoDB APIs
- Cross-region DynamoDB endpoint manipulation
The scanner provides a security score (0-100) with specific findings for DynamoDB SSRF issues, including severity levels and remediation guidance. Unlike manual code review, middleBrick can identify runtime SSRF vulnerabilities that only manifest during actual API calls.
DynamoDB-Specific Remediation
Remediating SSRF vulnerabilities in DynamoDB contexts requires a defense-in-depth approach combining input validation, AWS security best practices, and architectural controls.
Input Validation and Whitelisting
# Secure DynamoDB client initialization
import boto3
import re
from botocore.exceptions import ClientError
# Whitelist of allowed table names
ALLOWED_TABLES = {'users', 'products', 'orders', 'inventory'}
def create_secure_dynamodb_client(table_name):
# Validate table name against whitelist
if table_name not in ALLOWED_TABLES:
raise ValueError(f'Invalid table name: {table_name}')
# Use default endpoint (no user-controlled endpoint_url)
return boto3.client('dynamodb')
# Safe DynamoDB operations
client = create_secure_dynamodb_client('users')
try:
result = client.scan(TableName='users')
except ClientError as e:
if e.response['Error']['Code'] == 'ResourceNotFoundException':
print('Table does not exist')
else:
raise
AWS Security Controls
# Restrict DynamoDB access with IAM policies
cat > dynamodb-restrictive-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"dynamodb:DeleteItem",
"dynamodb:Scan",
"dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/users"
}
]
}
EOF
# Apply the restrictive policy
aws iam put-user-policy --user-name app-user --policy-name DynamoDBUsersPolicy --policy-document file://dynamodb-restrictive-policy.json
Network-Level Controls
# Create a VPC endpoint policy to restrict access
aws ec2 create-vpc-endpoint-policy --endpoint-id vpce-1234567890abcdef0 \
--policy-document '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "dynamodb:*",
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/*"
}
]
}'
# Configure security groups to block outbound SSRF attempts
aws ec2 authorize-security-group-ingress --group-id sg-0123456789abcdef0 \
--protocol tcp --port 443 --cidr 0.0.0.0/0
Application Architecture Controls
# Use AWS SDK's built-in validation
import boto3
from botocore.client import Config
# Create client with strict validation
client = boto3.client(
'dynamodb',
config=Config(
retries={'max_attempts': 3},
connect_timeout=5,
read_timeout=30,
validate_checksums=True
)
)
# Safe DynamoDB wrapper class
class SecureDynamoDB:
def __init__(self, table_name):
self.table_name = table_name
self.client = boto3.client('dynamodb')
def validate_request(self, params):
# Check for SSRF indicators in parameters
if 'endpoint_url' in params:
raise ValueError('Endpoint URL parameter not allowed')
# Validate table name format
if not re.match(r'^[a-zA-Z0-9_.-]+$', self.table_name):
raise ValueError('Invalid table name format')
def get_item(self, key):
self.validate_request({'TableName': self.table_name})
return self.client.get_item(
TableName=self.table_name,
Key=key
)