Skip to main content

Overview

This vulnerability occurs when an application reveals sensitive information through its error messages. This can include detailed stack traces, database error messages, internal file paths, framework versions, private IP addresses, or configuration details. Attackers deliberately trigger errors to gather this information, which helps them understand the application’s technology stack, structure, and potential weaknesses. 🕵️‍♂️📜

Business Impact

Exposing sensitive information via errors provides attackers with valuable reconnaissance data.
  • Technology Fingerprinting: Reveals specific software versions (e.g., “Apache/2.4.54”, “Python/3.9.1”), allowing attackers to look for known exploits.
  • Internal Structure Disclosure: Leaked file paths (/var/www/app/models/user.py) reveal the application’s directory structure.
  • Database Information: SQL error messages can leak table names, column names, or data types, aiding SQL Injection attacks.
  • Debugging Information: Stack traces expose function names, variable names, and code logic, helping attackers find other flaws.

Reference Details

CWE ID: CWE-209 OWASP Top 10 (2021): A04:2021 - Insecure Design Severity: Low to Medium (provides information, doesn’t directly cause compromise)

Framework-Specific Analysis and Remediation

This is primarily a configuration issue. Most modern web frameworks have a “debug” or “development” mode that intentionally shows detailed errors, and a “production” mode that shows generic error pages. The vulnerability is almost always caused by deploying to production without disabling debug mode. The fix involves:
  1. Disabling Debug Mode: Ensure the framework’s production setting is active.
  2. Custom Error Pages: Configure user-friendly, generic error pages (e.g., for 404 Not Found, 500 Internal Server Error) that do not reveal internal details.
  3. Logging: Log detailed errors server-side for developers, but do not display them to users.

  • Python
  • Java
  • .NET(C#)
  • PHP
  • Node.js
  • Ruby

Framework Context

Mainly controlled by the DEBUG setting in Django’s settings.py or FLASK_ENV / FLASK_DEBUG environment variables in Flask.

Vulnerable Scenario 1: Django Debug Mode in Production

# settings.py (Production Deployment)
# DANGEROUS: If True, Django shows detailed error pages with stack traces,
# settings, request details, etc.
DEBUG = True
ALLOWED_HOSTS = ['yourdomain.com'] # Even with allowed hosts, DEBUG=True is risky

Vulnerable Scenario 2: Flask Debug Mode in Production

Running Flask with debug mode enabled via environment variable or code.
# DANGEROUS: Running Flask in debug mode on production server
export FLASK_ENV=development
export FLASK_DEBUG=1
flask run --host=0.0.0.0
# app.py (Alternative dangerous way)
if __name__ == '__main__':
    # DANGEROUS: Never run with debug=True in production.
    app.run(debug=True, host='0.0.0.0')

Mitigation and Best Practices

  • Django: Set DEBUG = False in your production settings.py. Configure ADMINS and LOGGING to receive error details server-side. Create custom HTML templates for error views (e.g., templates/500.html, templates/404.html).
  • Flask: Ensure FLASK_ENV is set to production and FLASK_DEBUG is 0 (or unset) in production. Use Flask’s @app.errorhandler() decorator or app.register_error_handler() to define custom, generic error pages. Configure logging.

Secure Code Example

# settings.py (Django Production - Secure)
DEBUG = False # SECURE
ALLOWED_HOSTS = ['yourdomain.com', '[www.yourdomain.com](https://www.yourdomain.com)']

# Configure logging to capture details server-side
LOGGING = { ... }
ADMINS = [('Admin', 'admin@yourdomain.com')] # For error emails
# app.py (Flask Production - Secure)
from flask import Flask, render_template

app = Flask(__name__)
# Load production config where DEBUG=False
app.config.from_object('config.ProductionConfig')

@app.errorhandler(500)
def internal_server_error(e):
    # SECURE: Log the detailed error server-side
    app.logger.error(f'Server Error: {e}', exc_info=True)
    # SECURE: Show a generic error page to the user
    return render_template('500.html'), 500

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

# Run via WSGI server (like Gunicorn/uWSGI), not app.run() in production

Testing Strategy

Intentionally trigger errors in the deployed application (e.g., browse to non-existent pages for 404, cause exceptions for 500). Verify that generic, user-friendly error pages are shown, and no stack traces, configuration details, or internal paths are visible in the browser. Check server logs to ensure detailed errors are being recorded there.