CRITICAL command injectiondjangobasic auth

Command Injection in Django with Basic Auth

Command Injection in Django with Basic Auth — how this specific combination creates or exposes the vulnerability

Command Injection occurs when an attacker can inject and execute arbitrary system commands on the host. In Django, this typically arises when user-controlled input is passed to subprocess or shell utilities without proper validation or escaping. Combining this with HTTP Basic Authentication creates a layered exposure: the authentication layer identifies a caller, but does not reduce the attack surface if an endpoint is vulnerable to injection. An authenticated (or unauthenticated) attacker who can influence a parameter used in a shell command may achieve remote code execution (RCE).

Consider a Django view that accepts a filename from a query parameter and uses that value in a shell command to inspect file metadata. If the input is concatenated into the command string, an attacker can escape the expected argument boundaries and execute arbitrary commands. Basic Authentication can give a false sense of security: it limits access to a credentialed user, but does not sanitize or validate the content of requests. Therefore, the presence of Basic Auth does not mitigate Command Injection; it only changes who can reach the vulnerable endpoint. Attack patterns such as OS command injection via subprocess, misuse of shell metacharacters, and unsafe use of Python’s os or subprocess modules remain relevant to OWASP API Top 10 and can appear in API inventory management and unsafe consumption checks.

Real-world examples include using subprocess.run or os.system with unsanitized user input. For instance, passing a filename like report.txt; cat /etc/passwd can lead to unintended command execution. The scanner’s checks—such as Input Validation, Property Authorization, and Unsafe Consumption—can surface these issues by correlating runtime behavior with OpenAPI specifications. Even when endpoints are protected by Basic Auth, findings may map to compliance frameworks like OWASP API Top 10, PCI-DSS, SOC2, and GDPR due to the risk of data exposure and RCE.

Basic Auth-Specific Remediation in Django — concrete code fixes

To mitigate Command Injection in Django while using HTTP Basic Authentication, always treat user input as untrusted and avoid constructing shell commands with dynamic content. Prefer built-in APIs that do not invoke a shell, and rigorously validate and sanitize any input that must be passed to system utilities.

Secure Django view example with Basic Auth and no shell usage

import os
import re
from django.http import JsonResponse
from django.views.decorators.http import require_http_methods
from django.contrib.auth.decorators import login_required
from django.contrib.auth import authenticate, login
from django.views.decorators.http import require_http_methods
import subprocess

def safe_is_filename(value: str) -> bool:
    # Allow alphanumeric, underscore, hyphen, and a single dot for extension
    return re.match(r'^[A-Za-z0-9_.\-]+$', value) is not None

@require_http_methods(["GET"])
def file_report(request):
    username = request.META.get('PHP_AUTH_USER')
    password = request.META.get('PHP_AUTH_PW')
    # Example Basic Auth verification (use Django’s built-in auth where possible)
    user = authenticate(request, username=username, password=password)
    if user is None:
        return JsonResponse({'error': 'Unauthorized'}, status=401)

    filename = request.GET.get('filename', '')
    if not safe_is_filename(filename):
        return JsonResponse({'error': 'Invalid filename'}, status=400)

    # Avoid shell=True; use a list of arguments and validate path
    base_dir = '/var/reports'
    safe_path = os.path.join(base_dir, filename)
    if not safe_path.startswith(os.path.abspath(base_dir)):
        return JsonResponse({'error': 'Invalid path'}, status=400)

    try:
        # Prefer non-shell subprocess calls
        result = subprocess.run(
            ['stat', '--format=%s', safe_path],
            capture_output=True,
            text=True,
            timeout=5
        )
        result.check_returncode()
        return JsonResponse({'size': result.stdout.strip()})
    except subprocess.CalledProcessError as e:
        return JsonResponse({'error': str(e)}, status=500)
    except Exception as e:
        return JsonResponse({'error': 'server error'}, status=500)

Insecure example to avoid

import subprocess
from django.http import JsonResponse

def insecure_report(request):
    filename = request.GET.get('filename', '')
    # Vulnerable: shell=True and unsanitized input
    cmd = f'ls -l /var/reports/{filename}'
    out = subprocess.run(cmd, shell=True, capture_output=True, text=True)
    return JsonResponse({'output': out.stdout})

Additional remediation practices

  • Do not use shell=True unless absolutely necessary; if required, sanitize input with strict allowlists and avoid any shell metacharacters.
  • Use Django’s authentication mechanisms (e.g., token or session auth) rather than raw Basic Auth where feasible; if using Basic Auth, validate credentials via Django’s authenticate and enforce HTTPS.
  • Apply principle of least privilege to the process executing commands, and restrict filesystem paths to prevent directory traversal.
  • Leverage the middleBrick CLI (middlebrick scan <url>) and GitHub Action to detect Command Injection and related findings in CI/CD pipelines, and use the Web Dashboard to track scores over time.

Related CWEs: inputValidation

CWE IDNameSeverity
CWE-20Improper Input Validation HIGH
CWE-22Path Traversal HIGH
CWE-74Injection CRITICAL
CWE-77Command Injection CRITICAL
CWE-78OS Command Injection CRITICAL
CWE-79Cross-site Scripting (XSS) HIGH
CWE-89SQL Injection CRITICAL
CWE-90LDAP Injection HIGH
CWE-91XML Injection HIGH
CWE-94Code Injection CRITICAL

Frequently Asked Questions

Does Basic Authentication prevent Command Injection in Django APIs?
No. Basic Authentication identifies callers but does not sanitize input. Command Injection depends on how user-controlled data is used in commands; authentication alone does not mitigate injection risks.
What are effective mitigations for Command Injection in Django when using system utilities?
Avoid shell=True, use allowlist validation on inputs, avoid string concatenation for commands, use subprocess with a list of arguments, enforce path safety, and leverage Django’s built-in authentication and HTTPS. Scanning with the middleBrick CLI and GitHub Action can help detect these issues early.