External Control of System or Configuration Setting
This weakness occurs when user-supplied input is allowed to directly control or modify system or application configuration settings without proper validation…
This weakness occurs when user-supplied input is allowed to directly control or modify system or application configuration settings without proper validation or restriction. An attacker can exploit this to change critical settings—such as debug modes, file paths, database credentials, or security policies—to compromise the application's security or functionality. Even seemingly harmless configuration options can become dangerous if an attacker can manipulate them.
02How It Happens
Applications often read configuration from multiple sources: environment variables, query parameters, form fields, configuration files, or HTTP headers. When the code treats user input as a trusted configuration value without validation, an attacker can inject or override settings. This typically happens when developers assume that configuration comes only from trusted sources (like a config file) but later add the ability to override it from user input without implementing proper access controls or allowlisting. The vulnerability is especially common in development or "convenience" features that are left enabled in production.
03Real-World Impact
An attacker exploiting this weakness can disable security features (such as CSRF protection or input validation), redirect the application to use a malicious database or external service, enable debug output that leaks sensitive information, change file upload directories to web-accessible locations, or modify authentication settings to bypass login requirements. The impact ranges from information disclosure to complete application compromise, depending on which settings are exposed to user control.
04Vulnerable & Fixed Patterns
Vulnerable pattern
import os
from flask import Flask, request
app = Flask(__name__)
@app.route('/config', methods=['GET'])
def update_config():
setting_name = request.args.get('setting')
setting_value = request.args.get('value')
# Directly set environment variable from user input
os.environ[setting_name] = setting_value
return f"Config updated: {setting_name} = {setting_value}"
Why it's vulnerable: The code allows any query parameter to directly set environment variables. An attacker could set DEBUG=True, DATABASE_URL=attacker.com, or other critical settings.
Fixed pattern
import os
from flask import Flask, request
app = Flask(__name__)
# Allowlist of safe, non-sensitive settings that users may modify
ALLOWED_SETTINGS = {'theme', 'language', 'items_per_page'}
@app.route('/config', methods=['POST'])
def update_config():
setting_name = request.form.get('setting')
setting_value = request.form.get('value')
# Only allow whitelisted settings
if setting_name not in ALLOWED_SETTINGS:
return "Invalid setting", 403
# Validate the value (e.g., items_per_page must be an integer 1-100)
if setting_name == 'items_per_page':
try:
val = int(setting_value)
if not (1 <= val <= 100):
return "Value out of range", 400
setting_value = val
except ValueError:
return "Invalid value type", 400
# Store in user session or database, not in environment
request.session[setting_name] = setting_value
return "Config updated"
Vulnerable pattern
<?php
// Directly use user input to set configuration
$setting = $_GET['setting'];
$value = $_GET['value'];
// Dangerous: allows any setting to be modified
ini_set($setting, $value);
// Or write to a config file
$config_content = "$setting = $value;\n";
file_put_contents('/var/www/config.php', $config_content, FILE_APPEND);
echo "Setting updated";
?>
Why it's vulnerable: The code allows any GET parameter to modify PHP configuration or write to the config file. An attacker could set display_errors=1 to leak information, or modify database connection strings.
Fixed pattern
<?php
// Allowlist of safe, user-modifiable settings
$allowed_settings = array('theme', 'language', 'timezone');
$setting = isset($_POST['setting']) ? sanitize_text_field($_POST['setting']) : '';
$value = isset($_POST['value']) ? sanitize_text_field($_POST['value']) : '';
// Only allow whitelisted settings
if (!in_array($setting, $allowed_settings, true)) {
wp_die('Invalid setting', 403);
}
// Validate specific values
if ($setting === 'timezone') {
$valid_timezones = timezone_identifiers_list();
if (!in_array($value, $valid_timezones, true)) {
wp_die('Invalid timezone', 400);
}
}
// Store in user meta or options table, not in PHP config
update_user_meta(get_current_user_id(), "user_$setting", $value);
echo "Setting updated";
?>
05Prevention Checklist
Maintain an allowlist of configurable settings. Only permit users to modify settings that are explicitly safe and non-security-critical. Never allow modification of database credentials, debug flags, file paths, or authentication settings.
Validate and type-check all configuration values. Ensure values match expected types (integer, boolean, enum) and fall within safe ranges before applying them.
Separate user preferences from system configuration. Store user-modifiable settings in a user profile or session, not in global environment variables or system config files.
Restrict configuration endpoints to authenticated users. Require authentication and authorization checks before allowing any configuration change, and log all modifications.
Never read sensitive configuration from user input. Load critical settings (database URLs, API keys, security flags) only from protected files or environment variables set by administrators, never from request parameters.
Disable or remove debug/development configuration options in production. Ensure features like DEBUG=True, verbose logging, or test credentials are not accessible or modifiable in live environments.
06Signs You May Already Be Affected
Check your application logs for unusual configuration changes, unexpected modifications to settings files, or requests to configuration endpoints with suspicious parameter names. Review your codebase for any code that reads from $_GET, $_POST, environment variables, or query strings and directly applies those values to ini_set(), putenv(), or configuration file writes without validation. If you find such patterns, audit which settings are exposed and whether an attacker could have exploited them.