HIGH container escapedjango

Container Escape in Django

How Container Escape Manifests in Django

Container escape in Django applications typically occurs when attackers exploit the application's ability to interact with the underlying host system. Django's design as a full-stack web framework provides multiple attack surfaces that can lead to container escape if not properly secured.

The most common Django-specific container escape vectors include:

  • Unsafe file operations: Django's file handling utilities can inadvertently expose the host filesystem. For example, using FileSystemStorage with user-controlled paths or open() with .. path traversal.
  • Command injection via Django management commands: Custom management commands that execute shell commands with user input can break out of the container.
  • Subprocess execution: Django views or background tasks using subprocess with user input can escape containers.
  • Database file access: SQLite databases with paths constructed from user input can access files outside the intended directory.
  • Django Debug Toolbar exposure: When left enabled in production, it can expose sensitive system information and file access.

A concrete example of container escape in Django might look like this vulnerable view:

from django.http import JsonResponse
import subprocess

def escape_attempt(request):
    cmd = request.GET.get('cmd', 'ls')
    # Vulnerable: no input validation, allows container escape
    result = subprocess.run(cmd, shell=True, capture_output=True)
    return JsonResponse({'output': result.stdout.decode()})

An attacker could exploit this by sending ?cmd=cat /etc/shadow or ?cmd=ls / to traverse the host filesystem. In a containerized environment, this could reveal sensitive host files or even allow mounting host volumes.

Another Django-specific pattern involves file uploads. Consider this vulnerable code:

from django.core.files.storage import FileSystemStorage

def upload_file(request):
    if request.method == 'POST':
        uploaded_file = request.FILES['file']
        # Vulnerable: no path validation
        fs = FileSystemStorage(location='/var/www/uploads')
        filename = fs.save(uploaded_file.name, uploaded_file)
        return JsonResponse({'filename': filename})

An attacker could upload a file with a path like ../../etc/passwd, causing the file to be written outside the intended directory, potentially exposing or modifying host system files.

Django-Specific Detection

Detecting container escape vulnerabilities in Django applications requires both static code analysis and dynamic runtime scanning. middleBrick provides comprehensive detection capabilities specifically designed for Django applications.

middleBrick's Django-specific detection includes:

  • Static analysis of Django views: Scanning for dangerous patterns like subprocess.run(), os.system(), and unsafe file operations in view functions.
  • Management command analysis: Identifying custom management commands that execute shell commands or access the filesystem unsafely.
  • Template injection detection: Finding templates that might allow code execution or filesystem access.
  • Model field validation: Checking for FileField and ImageField configurations that might allow path traversal.
  • Middleware inspection: Analyzing custom middleware for unsafe operations.

middleBrick's scanning process for Django applications includes:

# Using middleBrick CLI to scan a Django API
middlebrick scan https://your-django-app.com/api/

The scanner tests for container escape by attempting controlled path traversal, command injection, and file access patterns specific to Django's architecture. It checks for:

  • Path traversal attempts: Testing ../ sequences in file-related endpoints.
  • Command injection probes: Sending payloads like ; cat /etc/passwd to detect unsafe subprocess usage.
  • SSRF detection: Checking if the Django app can make outbound requests that might access internal services.
  • Debug mode detection: Identifying if Django Debug Toolbar or DEBUG=True is enabled in production.

middleBrick also analyzes your Django application's OpenAPI/Swagger spec to understand the API surface and correlate findings with the documented endpoints. This helps identify discrepancies between intended and actual behavior.

For CI/CD integration, you can add middleBrick to your Django deployment pipeline:

# GitHub Action for Django API security
- name: Run middleBrick Security Scan
  uses: middlebrick/middlebrick-action@v1
  with:
    url: https://staging.yourdjangoapp.com/api/
    fail-on-severity: high

This ensures container escape vulnerabilities are caught before deployment to production environments.

Django-Specific Remediation

Remediating container escape vulnerabilities in Django requires a defense-in-depth approach using Django's built-in security features and Python best practices.

1. Input Validation and Sanitization

Always validate and sanitize user input before using it in file operations or system commands:

import re
from django.http import JsonResponse
from django.core.exceptions import ValidationError

def validate_safe_filename(filename):
    # Only allow alphanumeric, hyphens, underscores, and dots
    if not re.match(r'^[\w,\-,\.]+$', filename):
        raise ValidationError('Invalid filename')
    return filename

def safe_file_operation(request):
    filename = request.GET.get('filename', 'default.txt')
    try:
        safe_name = validate_safe_filename(filename)
    except ValidationError:
        return JsonResponse({'error': 'Invalid filename'}, status=400)
    
    # Safe: validated filename
    with open(f'/safe/directory/{safe_name}', 'r') as f:
        content = f.read()
    return JsonResponse({'content': content})

2. Safe File Handling with Django Storage

Use Django's storage backends with proper configuration:

from django.core.files.storage import FileSystemStorage
from django.conf import settings

def secure_upload(request):
    if request.method == 'POST':
        uploaded_file = request.FILES['file']
        
        # Use a dedicated, non-writable directory
        fs = FileSystemStorage(location=settings.MEDIA_ROOT)
        
        # Generate safe filename
        safe_name = re.sub(r'[^\w\.\-]', '_', uploaded_file.name)
        
        # Save with safe name
        filename = fs.save(safe_name, uploaded_file)
        
        return JsonResponse({'filename': filename})

3. Secure Management Commands

Always validate arguments in custom management commands:

from django.core.management.base import BaseCommand
import subprocess

class Command(BaseCommand):
    help = 'Safe file listing command'
    
    def add_arguments(self, parser):
        parser.add_argument('directory', type=str, help='Directory to list')
    
    def handle(self, *args, **options):
        directory = options['directory']
        
        # Validate directory is within allowed paths
        allowed_base = '/var/www/myapp'
        if not directory.startswith(allowed_base):
            self.stderr.write('Directory not allowed')
            return
        
        try:
            # Use safe method instead of shell=True
            result = subprocess.run(['ls', '-la', directory], 
                                   capture_output=True, text=True)
            self.stdout.write(result.stdout)
        except Exception as e:
            self.stderr.write(f'Error: {e}')

4. Django Security Middleware

Implement security middleware to prevent path traversal:

from django.http import HttpResponseForbidden
import os

class PathTraversalMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response
    
    def __call__(self, request):
        # Check for path traversal in GET parameters
        for key, value in request.GET.items():
            if '..' in str(value) or '/' in str(value):
                return HttpResponseForbidden('Path traversal detected')
        
        response = self.get_response(request)
        return response

5. Container Runtime Security

While middleBrick detects vulnerabilities, you should also implement runtime protections:

# docker-compose.yml with security context
django:
  image: yourdjangoapp:latest
  security_opt:
    - no-new-privileges:true
  read_only: true
  tmpfs:
    - /tmp
  volumes:
    - ./media:/var/www/media:ro  # read-only where possible
  user: "1000:1000"  # non-root user

6. Django Settings Security

Configure Django settings to minimize attack surface:

# settings.py
import os

# Disable debug in production
DEBUG = os.getenv('DJANGO_DEBUG', 'False') == 'True'

# Set allowed hosts
ALLOWED_HOSTS = os.getenv('DJANGO_ALLOWED_HOSTS', 'localhost,127.0.0.1').split(',')

# Secure file uploads
MEDIA_ROOT = '/var/www/media'
MEDIA_URL = '/media/'

# Disable debug toolbar in production
if not DEBUG:
    MIDDLEWARE = [m for m in MIDDLEWARE if 'debug_toolbar' not in m]
    INSTALLED_APPS = [app for app in INSTALLED_APPS if app != 'debug_toolbar']

By combining these Django-specific remediation techniques with middleBrick's detection capabilities, you can effectively prevent container escape vulnerabilities in your Django applications.

Frequently Asked Questions

How does middleBrick detect container escape vulnerabilities in Django applications?
middleBrick uses a combination of static code analysis and dynamic runtime scanning. It analyzes your Django views, management commands, and middleware for dangerous patterns like subprocess usage, unsafe file operations, and path traversal. The scanner then performs active testing by sending controlled payloads to detect if the application is vulnerable to container escape. It also analyzes your OpenAPI spec to understand the API surface and correlate findings with documented endpoints.
Can middleBrick scan Django applications that use Docker containers?
Yes, middleBrick can scan Django applications running in Docker containers. The scanner works by accessing the API endpoints exposed by your Django application, regardless of whether it's running in a container, on a VM, or on bare metal. For containerized deployments, middleBrick can scan the API endpoints exposed by your Django container. The scanner tests the unauthenticated attack surface and provides a security risk score with findings specific to your Django application's configuration.