Externally-Generated Error Message Containing Sensitive Information
Description
Externally-Generated Error Message Containing Sensitive Information is a vulnerability that occurs when a product performs an operation that triggers diagnostic or error messages from external components not directly controlled by the application. These external sources include programming language interpreters, database engines, web servers, operating systems, and third-party libraries. Unlike self-generated errors, these messages originate from underlying infrastructure and often contain detailed system information that developers may not anticipate being exposed. Common examples include PHP interpreter errors revealing file paths, SQL database errors exposing query structure, and web server errors disclosing software versions and configurations.
Risk
Externally-generated error messages pose significant security risks because they often contain more detailed system information than developers expect. Database errors may reveal table names, column structures, and query logic that aids SQL injection attacks. Interpreter errors expose full file system paths, code structure, and configuration details. Web server errors can disclose software versions, module configurations, and internal network information. These messages are particularly dangerous because they bypass application-level error handling and may expose information that the application code explicitly tries to protect. Attackers systematically trigger these errors through malformed inputs, invalid parameters, and edge-case requests to map application internals before launching targeted attacks.
Solution
Configure all external components to suppress detailed error output in production environments. For PHP, set display_errors = Off and log_errors = On in php.ini. For databases, configure connections to not expose detailed error messages to clients. Implement application-level exception handling that catches errors from external components before they reach users. Configure web servers to return custom error pages instead of default error messages. Use error handling middleware that intercepts all responses and strips sensitive information. Regularly test applications to ensure external component errors don't leak through error handling boundaries. Maintain consistent error handling across all deployment environments and automate security configuration verification.
Common Consequences
| Impact | Details |
|---|---|
| Confidentiality | Scope: Confidentiality External error messages often expose sensitive application data including file paths, database structure, configuration details, and software versions. This information aids attackers in planning and executing targeted attacks against the specific implementation. |
Example Code
Vulnerable Code (PHP)
The following code allows external component error messages to reach users:
<?php
// php.ini setting: display_errors = On (VULNERABLE)
// Database connection with exposed errors
function getUserData($userId) {
try {
$conn = new PDO(
"mysql:host=localhost;dbname=production_db",
"app_user",
"SecretPassword123"
);
// No error mode set - PDO will expose errors
} catch (PDOException $e) {
// Vulnerable: Exposes database error with credentials
die("Database error: " . $e->getMessage());
}
// Vulnerable: SQL error messages exposed
$stmt = $conn->query("SELECT * FROM users WHERE id = $userId");
return $stmt->fetchAll();
}
// File inclusion with exposed paths
function loadTemplate($template) {
// Vulnerable: PHP interpreter error exposes full path
include("/var/www/app/templates/" . $template . ".php");
}
// Direct include request exposes paths
// Attacker visits: /app/includes/database.php
// PHP Error: "Failed opening '/var/www/app/includes/database.php'"
// Invalid SQL triggers detailed error
// Attacker sends: userId = "1 OR 1=1"
// MySQL Error: "You have an error in your SQL syntax near 'OR 1=1'..."
External components (PHP interpreter, MySQL database) generate error messages containing file paths, SQL syntax, and database details.
Fixed Code (PHP)
<?php
// php.ini settings (production):
// display_errors = Off
// log_errors = On
// error_log = /var/log/php/errors.log
// Custom error handler for all external errors
set_error_handler(function($severity, $message, $file, $line) {
// Log detailed error internally
error_log("[$severity] $message in $file on line $line");
// Throw exception for handling
throw new ErrorException($message, 0, $severity, $file, $line);
});
// Generic error display function
function displayGenericError($errorId) {
http_response_code(500);
echo json_encode([
'error' => 'An error occurred. Please try again.',
'reference' => $errorId
]);
exit;
}
function getUserData($userId) {
$errorId = uniqid('err_');
try {
$conn = new PDO(
"mysql:host=localhost;dbname=production_db",
"app_user",
getenv('DB_PASSWORD') // Password from environment
);
// Prevent PDO from exposing errors
$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
// Parameterized query prevents SQL injection
$stmt = $conn->prepare("SELECT id, name, email FROM users WHERE id = ?");
$stmt->execute([$userId]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// Log detailed error internally
error_log(
"[$errorId] Database error: " . $e->getMessage() .
" | User ID: " . $userId .
" | File: " . $e->getFile() .
" | Line: " . $e->getLine()
);
// Generic error to user
displayGenericError($errorId);
}
}
function loadTemplate($template) {
$errorId = uniqid('err_');
// Validate template name (whitelist approach)
$allowedTemplates = ['home', 'profile', 'settings', 'about'];
if (!in_array($template, $allowedTemplates)) {
error_log("[$errorId] Invalid template requested: $template");
displayGenericError($errorId);
}
$templatePath = "/var/www/app/templates/" . $template . ".php";
if (!file_exists($templatePath)) {
error_log("[$errorId] Template not found: $templatePath");
displayGenericError($errorId);
}
try {
include($templatePath);
} catch (Exception $e) {
error_log("[$errorId] Template include error: " . $e->getMessage());
displayGenericError($errorId);
}
}
// Global exception handler for uncaught exceptions
set_exception_handler(function($e) {
$errorId = uniqid('err_');
error_log("[$errorId] Uncaught exception: " . $e->getMessage());
displayGenericError($errorId);
});
The fix configures PHP to log errors instead of displaying them, implements global error and exception handlers, uses parameterized queries, and ensures all external component errors are caught before reaching users.
Exploited in the Wild
PHP display_errors Reconnaissance (Widespread, Ongoing)
Attackers routinely trigger PHP interpreter errors to gather reconnaissance on web applications. By requesting non-existent files, submitting malformed input, or exploiting type juggling, attackers trigger PHP notices and warnings that reveal document root paths, included file locations, and function names. This information is used to plan directory traversal attacks, identify vulnerable file upload locations, and map application structure.
SQL Error-Based Injection (Multiple Organizations, Ongoing)
Error-based SQL injection attacks deliberately trigger database errors to extract data through error messages. When applications expose MySQL, PostgreSQL, or SQL Server error messages, attackers craft queries that embed extracted data in error text. This technique has been used in countless breaches to exfiltrate entire databases through verbose error messages without requiring direct query results.
Django Debug Mode Information Disclosure (Multiple Organizations, 2019)
Security researchers discovered thousands of Django applications running with DEBUG=True in production, causing the framework's external error handler to generate detailed debug pages. These pages exposed environment variables, installed packages, database queries, and local file contents. The exposure included API keys, database credentials, and cloud provider secrets.
Tools to Test/Exploit
-
SQLMap — Automatic SQL injection tool that uses error-based techniques to extract data through database error messages.
-
Burp Suite Scanner — Automated scanner that tests for information disclosure in error responses from external components.
-
WFuzz — Fuzzing tool for triggering error conditions to identify information leakage.
CVE Examples
-
CVE-2004-1581 — Direct include file request triggered PHP interpreter error that disclosed full file path.
-
CVE-2004-1579 — Invalid SQL query caused database error message to reveal complete file path.
-
CVE-2005-0459 — Direct library file request caused path disclosure through interpreter error.
-
CVE-2005-0433 — Verbose external errors exposed class instantiation attempts and file access failures.
References
-
MITRE Corporation. "CWE-211: Externally-Generated Error Message Containing Sensitive Information." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/211.html
-
OWASP Foundation. "Error Handling." OWASP Testing Guide. https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/08-Testing_for_Error_Handling/
-
PHP Documentation. "Error Handling and Logging Configuration." https://www.php.net/manual/en/errorfunc.configuration.php