Servergenerierte Fehlermeldung mit sensiblen Informationen

Beschreibung

Servergenerierte Fehlermeldung mit sensiblen Informationen ist eine Schwachstelle, bei der Fehlermeldungen, die von Webservern, Anwendungsservern oder Backend-Systemen erzeugt werden, sensible Daten für Benutzer oder Angreifer offenlegen. Während Fehlermeldungen einen legitimen Zweck erfüllen, werden sie zu Sicherheitsschwachstellen, wenn sie Informationen preisgeben, die Angreifer für Aufklärung oder Ausnutzung verwenden können. Dies umfasst Server-Versionen, interne Pfade, Datenbankdetails, Konfigurationseinstellungen, Stack-Traces und andere technische Informationen.

Risiko

Servergenerierte Fehlermeldungen bergen erhebliche Aufklärungsrisiken. HTTP-Fehlerseiten können Webserver-Software und Versionsnummern offenlegen, was gezielte Exploits ermöglicht. Datenbankfehler können Abfragestrukturen, Tabellennamen und Datenwerte preisgeben. Anwendungsfehler können vollständige Dateipfade anzeigen. Stack-Traces legen Klassennamen, Methodensignaturen und Zeilennummern offen. Angreifer lösen systematisch Fehler aus, um die Backend-Infrastruktur zu kartieren.

Lösung

Implementieren Sie konsistente Fehlerbehandlung, die legitimen Benutzern aussagekräftiges Feedback bietet, während angreifernutzbare Informationen eingeschränkt werden. Konfigurieren Sie Webserver für benutzerdefinierte Fehlerseiten. Fangen Sie alle Ausnahmen ab und geben Sie generische Fehlermeldungen zurück. Protokollieren Sie detaillierte Fehlerinformationen serverseitig. Deaktivieren Sie Debug-Modi in der Produktion.

Häufige Auswirkungen

AuswirkungDetails
VertraulichkeitBereich: Vertraulichkeit

Anwendungsdaten lesen - Angreifer können sensible Systeminformationen aus Fehlermeldungen extrahieren, einschließlich Server-Versionen, Pfade und Datenbankdetails.

Beispielcode

Verwundbarer Code

// Verwundbar: Rohe Ausnahme an Client
public class VerwundbaresServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            Connection conn = DriverManager.getConnection(
                "jdbc:mysql://db.internal:3306/app", "admin", "password");
        } catch (SQLException e) {
            // Verwundbar: Details werden exponiert
            response.sendError(500, "Datenbankfehler: " + e.getMessage());
            // Ausgabe enthält Hostnamen und Port!
        }
    }
}
<?php
// Verwundbar: display_errors aktiviert
// php.ini: display_errors = On

function getUserData($userId) {
    $conn = mysqli_connect("localhost", "root", "password", "users");
    $result = mysqli_query($conn, "SELECT * FROM users WHERE id = '$userId'");

    if (!$result) {
        // Verwundbar: SQL-Fehler mit Abfragedetails
        die("Datenbankfehler: " . mysqli_error($conn));
    }
}
?>
# Verwundbar: Flask mit Debug-Modus
from flask import Flask
import traceback

app = Flask(__name__)
app.debug = True  # Verwundbar!

@app.route('/api/user/<user_id>')
def get_user(user_id):
    try:
        user = database.get_user(user_id)
        return jsonify(user)
    except Exception as e:
        # Verwundbar: Vollständiger Traceback
        return f"Fehler: {traceback.format_exc()}", 500

Lösungscode

// Behoben: Sichere Fehlerbehandlung
public class SicheresServlet extends HttpServlet {
    private static final Logger logger = LoggerFactory.getLogger(SicheresServlet.class);

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        try {
            Connection conn = getConnection();
            // ...
        } catch (SQLException e) {
            String errorId = UUID.randomUUID().toString().substring(0, 8);
            // Behoben: Details nur im Log
            logger.error("Datenbankfehler [{}]: {}", errorId, e.getMessage(), e);
            // Behoben: Generische Nachricht an Client
            response.sendError(500, "Ein Fehler ist aufgetreten. Referenz: " + errorId);
        }
    }
}
<?php
// Behoben: Sichere Fehlerbehandlung
// php.ini: display_errors = Off, log_errors = On

set_exception_handler(function($e) {
    $errorId = bin2hex(random_bytes(4));
    error_log("Fehler [$errorId]: " . $e->getMessage());
    
    http_response_code(500);
    echo json_encode(['error' => 'Ein Fehler ist aufgetreten', 'reference' => $errorId]);
});

function getUserData($userId) {
    try {
        $conn = getSecureConnection();
        $stmt = $conn->prepare("SELECT * FROM users WHERE id = ?");
        $stmt->execute([$userId]);
        return $stmt->fetch();
    } catch (PDOException $e) {
        throw new RuntimeException("Benutzerdaten nicht abrufbar");
    }
}
?>
# Behoben: Flask ohne Debug-Modus
from flask import Flask, jsonify
import logging
import uuid

app = Flask(__name__)
app.debug = False  # Behoben

logging.basicConfig(filename='/var/log/app/error.log', level=logging.ERROR)
logger = logging.getLogger(__name__)

@app.route('/api/user/<user_id>')
def get_user(user_id):
    try:
        user = database.get_user(user_id)
        return jsonify(user)
    except Exception as e:
        error_id = str(uuid.uuid4())[:8]
        logger.error(f"Fehler [{error_id}]", exc_info=True)
        return jsonify({'error': 'Ein Fehler ist aufgetreten', 'reference': error_id}), 500

@app.errorhandler(Exception)
def handle_exception(e):
    error_id = str(uuid.uuid4())[:8]
    logger.error(f"Unbehandelt [{error_id}]", exc_info=True)
    return jsonify({'error': 'Interner Fehler', 'reference': error_id}), 500

CVE-Beispiele

Keine spezifischen CVEs, aber servergenerierte Fehler-Informationsoffenlegung ist häufig bei fehlkonfigurierten Webanwendungen und Entwicklungseinstellungen in der Produktion.


Referenzen

  1. MITRE Corporation. "CWE-550: Server-generated Error Message Containing Sensitive Information." https://cwe.mitre.org/data/definitions/550.html
  2. OWASP. "Error Handling Cheat Sheet."
  3. OWASP. "OWASP Top Ten 2021 - A05:2021 Security Misconfiguration."