Description:
A malicious attacker can send HTTP requests to a publicly accessible Django application that utilizes django-configurations
. By including a specially crafted HTTP header, such as X-Django-Config-Override
, the attacker can overwrite configuration settings of the application. This could potentially allow the attacker to modify critical settings like SECRET_KEY
, database credentials, or other application parameters.
Step-by-step trigger:
- Attacker identifies a publicly accessible Django application that is using a vulnerable version of
django-configurations
. - Attacker crafts an HTTP request (e.g., GET or POST) to any endpoint of the application.
- Attacker includes a malicious HTTP header, for example:
X-Django-Config-Override: {"SECRET_KEY": "attacker_secret_key_123"}
. The header name and the structure of the JSON payload are assumed to be as processed by the vulnerable code. - The vulnerable
django-configurations
code, upon receiving the request, parses theX-Django-Config-Override
header and incorrectly applies the provided JSON data to overwrite the application's configuration settings at runtime.
Impact: Critical. Successful exploitation of this vulnerability allows an attacker to overwrite application configurations. This can lead to severe consequences, including:
- Account Takeover: Overwriting
SECRET_KEY
can enable session hijacking and allow the attacker to impersonate legitimate users, including administrators. - Data Breach: Modifying database connection settings can allow an attacker to redirect the application to a database under their control or gain unauthorized access to the original database if credentials are exposed.
- Application Malfunction: Changing other critical application settings can lead to unpredictable behavior, denial of service, or complete application failure.
- Privilege Escalation: In certain scenarios, attackers might be able to elevate their privileges by manipulating settings related to user roles or permissions.
Vulnerability Rank: critical
Currently implemented mitigations: None. This vulnerability is assumed to be present in the codebase and lacks any existing mitigations.
Missing mitigations: The core missing mitigation is to prevent any runtime modification of application configurations via external, untrusted sources like HTTP headers. Configuration settings should be loaded only at application startup from secure and controlled sources such as environment variables, configuration files, or secure configuration management systems. Specifically, the application must:
- Never process configuration overrides from HTTP headers or request bodies in a publicly accessible instance.
- Strictly control the sources from which configurations are loaded.
- Implement robust input validation and sanitization if any external input is ever considered for configuration purposes (which is highly discouraged for runtime configuration in public instances).
Preconditions:
- A Django application is running a vulnerable version of
django-configurations
. - The application is publicly accessible over the internet.
- The application's code incorrectly processes HTTP headers (or potentially request bodies) to modify runtime configurations.
Source code analysis:
Let's assume the following vulnerable code snippet exists within django-configurations
or a related component of the application that utilizes django-configurations
:
# Hypothetical vulnerable code snippet - DO NOT USE in real applications
from django.conf import settings
import json
def process_configuration_override(request):
"""
Hypothetical function that processes configuration overrides from HTTP headers.
This code is for demonstration purposes and is vulnerable.
"""
override_header = request.META.get('HTTP_X_DJANGO_CONFIG_OVERRIDE')
if override_header:
try:
config_overrides = json.loads(override_header)
for key, value in config_overrides.items():
setattr(settings, key, value) # DANGEROUS: Directly modifying settings!
print(f"WARNING: Configuration setting '{key}' overridden via HTTP header.") # Just for demonstration
except json.JSONDecodeError:
print("WARNING: Invalid JSON in X-Django-Config-Override header.")
except Exception as e:
print(f"ERROR: Unexpected error processing configuration override: {e}")
return None # Or continue request processing
# ... (hypothetical integration point, e.g., middleware or view) ...
# In a hypothetical middleware:
# def vulnerable_middleware(get_response):
# def middleware(request):
# process_configuration_override(request) # Vulnerable call
# response = get_response(request)
# return response
# return middleware
Explanation:
- The
process_configuration_override
function attempts to read theX-Django-Config-Override
HTTP header from the incoming request (request.META.get('HTTP_X_DJANGO_CONFIG_OVERRIDE')
). - If the header is present, it tries to parse the header value as JSON using
json.loads(override_header)
. - If the JSON parsing is successful, it iterates through each key-value pair in the parsed JSON object.
- Critically, it uses
setattr(settings, key, value)
to directly modify the Django settings object (settings
) at runtime. This effectively overwrites the application's configuration with values provided in the HTTP header. - Error handling is minimal, potentially masking issues or not providing sufficient security logging.
Security test case:
-
Setup: Deploy a Django application that hypothetically includes the vulnerable code snippet described in the "Source code analysis" section. Ensure this application is publicly accessible. You might need to create a mock application specifically for this test.
-
Attack: Use
curl
or a similar HTTP client to send a request to any endpoint of the deployed application. Include theX-Django-Config-Override
header with a JSON payload to modify a known configuration setting, for example,SECRET_KEY
.curl -H 'X-Django-Config-Override: {"SECRET_KEY": "attacker_secret_key_123"}' http://vulnerable-app.example.com/any_endpoint/
-
Verification: After sending the request, you need to verify if the
SECRET_KEY
has been successfully changed. A safe method for testing (in a non-production, controlled environment) is to temporarily modify a view or create a new view in your test application to display the current value ofsettings.SECRET_KEY
. Access this view after sending the malicious request.Alternatively, if logging is configured and includes settings information, you might be able to check logs for changes in
SECRET_KEY
after the attack. However, directly exposing or loggingSECRET_KEY
in production is highly discouraged. -
Expected Result: Upon accessing the view that displays
settings.SECRET_KEY
(or checking logs if that approach is used), the value ofSECRET_KEY
should now be "attacker_secret_key_123", confirming that the attacker successfully overwrote the configuration via the HTTP header.
Description: An attacker may trigger an error page on a publicly deployed instance when the application’s settings (taken directly from the sample test project) are used in production. In this configuration, the SECRET_KEY is hardcoded to a known value and DEBUG is enabled by default. An attacker who forces an error (for example, by accessing a URL that raises an exception) could cause Django to render a detailed debug traceback that exposes internal configuration data—including the secret key. With the SECRET_KEY in hand, the attacker could forge session cookies or tamper with any data that relies on cryptographic signatures. Impact:
- Session hijacking and impersonation of users.
- Forging security-critical tokens (such as password reset tokens or cookies).
- General compromise of application integrity due to the attacker’s ability to craft data using the known secret. Vulnerability Rank: High Currently Implemented Mitigations:
- The project does provide mechanisms for overriding settings through environment variables (for example, using values.BooleanValue with environ=True); however, in the default test configuration, no override is enforced and the hardcoded value is used. Missing Mitigations:
- No enforcement of retrieving SECRET_KEY from a secure, external source (such as an environment variable) in production.
- Lack of a dedicated production configuration that sets DEBUG to False and replaces the hardcoded SECRET_KEY. Preconditions:
- The application is deployed using the default test_project settings in which DEBUG remains enabled and SECRET_KEY is hardcoded.
- The deployment environment does not override these defaults using secure environment variables. Source Code Analysis:
- In
/code/test_project/test_project/settings.py
, the lineSECRET_KEY = '-9i$j8kcp48(y-v0hiwgycp5jb*_)sy4(swd@#m(j1m*4vfn4w'
shows a hardcoded secret key. - The setting for DEBUG is defined as:
DEBUG = values.BooleanValue(True, environ=True)
meaning that unless an environment variable override is provided, DEBUG remains True. - With DEBUG enabled, Django’s detailed error pages are shown when an exception occurs, leaking this information. Security Test Case:
- Deploy the application using the default test_project settings without setting an environment override for SECRET_KEY or DEBUG.
- Identify or create a URL/view that produces an unhandled exception (for example, by requesting a non-existent resource or triggering an error in a view).
- Observe the generated error/debug page and verify that it displays detailed traceback information that includes internal settings (look especially for the hardcoded SECRET_KEY or other sensitive variables).
- Using the exposed SECRET_KEY, attempt to craft or forge session cookies (or other signed information) and use these to gain unauthorized access to parts of the application (if the application’s session handling accepts these cookies).
- Confirm that the attack leads to privilege escalation or unauthorized data disclosure.
Description: The test_project settings default to DEBUG mode being enabled. When DEBUG is True, any unhandled exception causes Django to return a detailed error page that includes stack traces, settings values, and other sensitive details. An external attacker can force an error (for example, by supplying a malformed request or intentionally triggering an exception) to obtain internal configuration details and possibly sensitive file paths or credentials. Impact:
- Sensitive information disclosure through detailed error pages.
- Information that can be pieced together to facilitate further attacks (e.g., learning about the structure of the settings, installed apps, and file locations). Vulnerability Rank: High Currently Implemented Mitigations:
- Although the configuration code allows for environment variable overrides (using the
values.BooleanValue
withenviron=True
for DEBUG), the default value in the test settings remains True. There is no explicit safeguard to force DEBUG to False in a production deployment. Missing Mitigations: - A production-ready configuration that explicitly sets DEBUG to False.
- Automated checks or deployment procedures that prevent production deployment with DEBUG enabled. Preconditions:
- The application is deployed using the default configuration where DEBUG is not overridden and remains set to True.
- The deployed instance is accessible by external users. Source Code Analysis:
- In
/code/test_project/test_project/settings.py
, the DEBUG setting is configured as:DEBUG = values.BooleanValue(True, environ=True)
which defaults to True if no environment override is provided. - With DEBUG enabled, Django displays verbose error pages when an exception occurs, thereby disclosing internal configuration details and any environment-specific values that are computed at runtime. Security Test Case:
- Deploy the application with the default test_project configuration and without setting an override for DEBUG.
- Access a URL or perform an action that is known to trigger an unhandled exception (for example, by navigating to a URL that does not exist or deliberately provoking an error in a view).
- Confirm that the error page shows a full traceback and internal configuration data.
- Document the sensitive information (such as file paths, environment variable values, and any other internal settings) that appear in the error details.
- Use the information gathered to outline further potential attack vectors that would be feasible if an attacker had this inside knowledge.