HIGH ssrfflaskdynamodb

Ssrf in Flask with Dynamodb

Ssrf in Flask with Dynamodb — how this specific combination creates or exposes the vulnerability

Server-Side Request Forgery (SSRF) in a Flask application that interacts with Amazon DynamoDB typically arises when the application constructs HTTP requests to external services using data supplied by the caller. An attacker can supply a malicious URL or metadata service endpoint that the server-side code uses to build a request, causing the backend to perform unintended network actions. Because DynamoDB access patterns often involve SDK calls that may rely on HTTP clients, SSRF can indirectly affect DynamoDB operations if the attacker influences endpoint resolution, credential retrieval, or metadata queries.

Flask applications may expose SSRRF when they accept user input such as a table name, key condition expression, or a URL for importing external data and pass it to DynamoDB utilities without strict validation. For example, if the application fetches an external schema or mapping from a user-provided URL and uses that to shape DynamoDB requests, an attacker can point the request to the instance metadata service (169.254.169.254) to obtain sensitive IAM credentials or to probe internal services. Similarly, a misconfigured HTTP client used by the DynamoDB wrapper can be redirected to internal endpoints due to hostname confusion or lack of URL validation.

The risk is compounded when the application uses the AWS SDK for JavaScript (v3) or boto3 with custom HTTP agents or proxy configurations that do not enforce strict endpoint whitelisting. An SSRF vector may not directly mutate DynamoDB data, but it can reveal sensitive information about the runtime environment used to access DynamoDB, such as IAM role credentials attached to the host. This can lead to privilege escalation if the compromised credentials have broad DynamoDB permissions. Therefore, validating and sanitizing any user-influenced inputs that affect network destinations is crucial in Flask-DynamoDB integrations.

Dynamodb-Specific Remediation in Flask — concrete code fixes

To mitigate SSRF in a Flask application working with DynamoDB, enforce strict allowlisting of endpoints and avoid using user input to construct network destinations. When using the AWS SDK for JavaScript (v3), configure the DynamoDB client with a custom HTTPS agent that restricts resolved hostnames. For boto3, avoid passing user-controlled host headers and use resource endpoints that are hardcoded or selected from a safe set.

Example: Safe DynamoDB client configuration in Flask (AWS SDK v3)

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { fromNodeProviderChain } from "@aws-sdk/credential-providers";
import https from "https";

const agent = new https.Agent({
  rejectUnauthorized: true,
});

const client = new DynamoDBClient({
  region: "us-east-1",
  requestHandler: {
    httpsAgent: agent,
  },
  credentials: fromNodeProviderChain(),
});

export default client;

Example: Safe DynamoDB access in Flask routes

from flask import Flask, request, jsonify
import boto3
from botocore.exceptions import ClientError

app = Flask(__name__)
dynamodb = boto3.resource('dynamodb', region_name='us-east-1')

@app.route('/tables//items', methods=['GET'])
def get_items(table_name):
    # Strict allowlist for table names
    allowed_tables = {'users', 'products', 'orders'}
    if table_name not in allowed_tables:
        return jsonify({'error': 'invalid table'}), 400

    table = dynamodb.Table(table_name)
    try:
        response = table.scan()
        return jsonify(response.get('Items', []))
    except ClientError as e:
        return jsonify({'error': str(e)}), 500

Example: Validating external URLs when used with DynamoDB workflows

from flask import Flask, request, jsonify
from urllib.parse import urlparse
import requests

app = Flask(__name__)

def is_safe_url(url):
    parsed = urlparse(url)
    return parsed.scheme in ('https',) and parsed.hostname in ('example.com', 'api.example.com')

@app.route('/import', methods=['POST'])
def import_metadata():
    data = request.get_json()
    external_url = data.get('url')
    if not is_safe_url(external_url):
        return jsonify({'error': 'invalid url'}), 400
    resp = requests.get(external_url, timeout=5)
    resp.raise_for_status()
    # Use resp.json() to shape DynamoDB put_item calls safely
    return jsonify({'status': 'ok'})

Additional SSRF mitigations

  • Disable redirect following or validate each redirect target against an allowlist.
  • Run the Flask application with minimal IAM permissions so that even if SSRF occurs, the attacker cannot perform destructive DynamoDB operations.
  • Use VPC endpoints for DynamoDB to keep traffic within the AWS network and reduce exposure to external SSRF-induced data leaks.

Related CWEs: ssrf

CWE IDNameSeverity
CWE-918Server-Side Request Forgery (SSRF) CRITICAL
CWE-441Unintended Proxy or Intermediary (Confused Deputy) HIGH

Frequently Asked Questions

How can I validate DynamoDB table names safely in Flask?
Use a strict allowlist of table names and avoid interpolating user input into resource identifiers. For example, check if table_name in {'users', 'products', 'orders'}: before accessing dynamodb.Table(table_name).
Does middleBrick detect SSRF in Flask-DynamoDB integrations?
middleBrick scans unauthenticated attack surfaces and tests input validation and data exposure checks; it can surface SSRF-related findings where user-influenced endpoints can affect backend behavior, including integrations that involve DynamoDB.