HIGH format stringdjangodynamodb

Format String in Django with Dynamodb

Format String in Django with Dynamodb — how this specific combination creates or exposes the vulnerability

A format string vulnerability occurs when user-controlled input is passed directly into string formatting operations without validation or sanitization. In Django applications that interact with DynamoDB, this typically arises when constructing query parameters, table names, or conditional expressions using Python string formatting methods such as % formatting, str.format(), or f-strings, and then using the resulting string in DynamoDB API calls.

Consider a Django view that retrieves an item from a DynamoDB table using a user-supplied key:

import boto3
from django.http import HttpResponseBadRequest

def get_item(request, table_name):
    # Unsafe: table_name comes directly from the user
    dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
    table = dynamodb.Table(table_name)
    key = request.GET.get('id')
    response = table.get_item(Key={'id': key})
    return HttpResponse(json.dumps(response.get('Item', {})))

If the application further uses string formatting to build a condition or a filter expression based on user input, the risk increases. For example:

filter_expression = "attribute_exists(%s)" % user_input
response = table.scan(FilterExpression=filter_expression)

Here, user_input is injected directly into the format string. An attacker could supply ${AWS_ACCESS_KEY_ID} or other sensitive environment variables if the application also evaluates the formatted string in a broader context, or craft input that alters the logical structure of the expression. While DynamoDB itself does not evaluate format strings, the surrounding Python code may evaluate the resulting string in unintended ways, such as passing it to boto3 methods that interpret dynamic expressions. This can lead to unauthorized data access or unexpected query behavior.

In the context of middleBrick’s checks, this pattern would be flagged under Input Validation and Property Authorization. The scanner recognizes that user-controlled data is being used to influence API request construction without proper sanitization or parameterization, increasing the risk of injection-style logic manipulation even though DynamoDB queries are typically parameterized.

Additionally, if the formatted string is used to construct table or index names dynamically, an attacker might attempt directory traversal or namespace manipulation. For instance:

table_name = "users_{}".format(user_supplied_region)

If user_supplied_region contains special characters or is derived from an untrusted source, it may lead to interactions with unintended tables or configurations. middleBrick’s Inventory Management and Property Authorization checks are designed to detect such unsafe dynamic resource referencing patterns.

Dynamodb-Specific Remediation in Django — concrete code fixes

To mitigate format string risks in Django applications using DynamoDB, always prefer parameterized inputs and strict validation. Avoid inserting user data directly into string expressions that influence API calls. Instead, use DynamoDB’s built-in expression parameterization features and enforce allowlists for identifiers such as table names.

Safe table name access with validation:

import boto3
from django.core.exceptions import ValidationError
import re

def is_valid_table_name(name):
    return re.match(r'^[a-zA-Z0-9_-]+$', name) is not None

def get_item_safe(request):
    table_name = request.GET.get('table', 'default_table')
    if not is_valid_table_name(table_name):
        raise ValidationError('Invalid table name')
    dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
    table = dynamodb.Table(table_name)
    key = request.GET.get('id')
    response = table.get_item(Key={'id': key})
    return HttpResponse(json.dumps(response.get('Item', {})))

Using DynamoDB ExpressionAttributeNames and ExpressionAttributeValues:

import boto3

def get_item_with_expression(request):
    table_name = 'users'
    dynamodb = boto3.resource('dynamodb', region_name='us-east-1')
    table = dynamodb.Table(table_name)
    user_id = request.GET.get('id')
    
    response = table.get_item(
        Key={
            'id': user_id
        }
    )
    return HttpResponse(json.dumps(response.get('Item', {})))

Safe filtering with ExpressionAttributeValues:

def scan_with_filter(request):
    table = boto3.resource('dynamodb', region_name='us-east-1').Table('items')
    user_status = request.GET.get('status', 'active')
    
    response = table.scan(
        FilterExpression='#status = :val',
        ExpressionAttributeNames={'#status': 'status'},
        ExpressionAttributeValues={':val': user_status}
    )
    return HttpResponse(json.dumps(response.get('Items', [])))

These patterns ensure that user input is never interpreted as code or format directives. The use of ExpressionAttributeNames and ExpressionAttributeValues keeps query construction safe and predictable. middleBrick’s checks for Input Validation and BFLA/Privilege Escalation will confirm that such parameterization practices are in place and that no raw string interpolation affects API request construction.

Frequently Asked Questions

How does middleBrick detect format string risks in Django-Dynamodb integrations?
middleBrick runs 12 parallel security checks including Input Validation and Property Authorization. It analyzes your OpenAPI/Swagger specification and runtime behavior to identify places where user-controlled data influences request construction, such as formatted strings used in DynamoDB interactions.
Can middleBrick fix format string vulnerabilities automatically?
middleBrick detects and reports findings with severity, category, and remediation guidance. It does not automatically patch or block code. Developers should apply parameterized expressions and input allowlists as outlined in the remediation examples.