Unsachgemäße Eingabevalidierung
Beschreibung
Unsachgemäße Eingabevalidierung ist eine Software-Schwachstelle, bei der ein Produkt Eingaben oder Daten empfängt, diese aber nicht oder nur unzureichend darauf überprüft, ob sie die erforderlichen Eigenschaften für eine sichere und korrekte Verarbeitung besitzen. Diese Schwachstelle tritt auf, wenn Anwendungen vom Benutzer bereitgestellte Daten akzeptieren, ohne zu überprüfen, ob sie erwarteten Formaten, Längen, Typen oder Wertebereichen entsprechen. Angreifer können diese Schwachstelle ausnutzen, indem sie bösartige, fehlerhafte oder unerwartete Eingaben bereitstellen, um das Programmverhalten zu ändern, unbefugten Zugriff zu erlangen, beliebigen Code auszuführen oder einen Denial-of-Service zu verursachen. Fehler bei der Eingabevalidierung sind die Grundursache vieler kritischer Schwachstellen, darunter SQL-Injection, Cross-Site-Scripting (XSS), Command-Injection, Buffer-Overflows und Path-Traversal-Angriffe.
Risiko
Anwendungen, die Eingaben nicht ordnungsgemäß validieren, setzen sich einer Vielzahl von Angriffen aus, die Vertraulichkeit, Integrität und Verfügbarkeit gefährden können. Angreifer können bösartige Eingaben erstellen, um Sicherheitskontrollen zu umgehen, unbefugte Befehle auszuführen, auf sensible Daten zuzugreifen oder Systeme zum Absturz zu bringen. Die Auswirkungen reichen von der Offenlegung von Informationen bis hin zur vollständigen Systemkompromittierung, was häufig zu erheblichen finanziellen Verlusten, behördlichen Strafen und Reputationsschäden führt. Da Fehler bei der Eingabevalidierung zahlreiche andere Schwachstellenklassen ermöglichen, stellen sie eine der grundlegendsten und gefährlichsten Sicherheitsschwächen in der Softwareentwicklung dar.
Lösung
Implementieren Sie eine umfassende serverseitige Eingabevalidierung mit einem Allowlist-Ansatz, der akzeptable Eingabeformate, Längen, Typen und Zeichensätze strikt definiert. Verlassen Sie sich niemals ausschließlich auf clientseitige Validierung, da diese leicht umgangen werden kann. Validieren Sie alle Eingaben an Vertrauensgrenzen, einschließlich Formularfelder, URL-Parameter, HTTP-Header, Cookies, Datei-Uploads und API-Anfragen. Verwenden Sie nach Möglichkeit stark typisierte Daten, setzen Sie parametrisierte Abfragen für Datenbankinteraktionen ein und wenden Sie kontextgerechte Ausgabecodierung an. Implementieren Sie Defense-in-Depth, indem Sie Eingabevalidierung mit anderen Sicherheitskontrollen wie Web Application Firewalls, Least-Privilege-Prinzipien und Sicherheitsüberwachung kombinieren.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Verfügbarkeit | Bereich: Verfügbarkeit Ein Angreifer könnte unerwartete Werte bereitstellen, die die Anwendung zum Absturz bringen oder übermäßige Ressourcen verbrauchen, was zu einem Denial-of-Service führt. |
| Vertraulichkeit | Bereich: Vertraulichkeit Ein Angreifer könnte sensible Daten lesen, wenn eine unsachgemäße Validierung unbefugte Datenbankabfragen oder Dateizugriffe durch Injection-Angriffe ermöglicht. |
| Integrität | Bereich: Integrität Ein Angreifer könnte kritische Daten modifizieren, das Anwendungsverhalten ändern oder bösartige Inhalte einschleusen, indem er Schwachstellen in der Eingabevalidierung ausnutzt. |
| Zugriffskontrolle | Bereich: Zugriffskontrolle Ein Angreifer könnte Authentifizierungs- oder Autorisierungsmechanismen umgehen, indem er Eingabeparameter manipuliert, die Zugriffsentscheidungen steuern. |
Beispielcode + Lösungscode
Das folgende Beispiel zeigt eine anfällige Python-Webanwendung, die Benutzereingaben ohne ordnungsgemäße Validierung akzeptiert und so eine potenzielle Command-Injection ermöglicht:
Anfälliger Code
import os
from flask import Flask, request
app = Flask(__name__)
@app.route('/lookup')
def dns_lookup():
# ANFÄLLIG: Benutzereingabe wird direkt an Systembefehl übergeben
hostname = request.args.get('host')
result = os.popen(f'nslookup {hostname}').read()
return f'<pre>{result}</pre>'
@app.route('/user')
def get_user():
# ANFÄLLIG: Benutzer-ID wird vor Datenbankabfrage nicht validiert
user_id = request.args.get('id')
query = f"SELECT * FROM users WHERE id = {user_id}"
# Abfrage ohne Parametrisierung ausführen...
return query
Der anfällige Code akzeptiert den hostname-Parameter direkt in einem Systembefehl ohne jegliche Validierung, wodurch ein Angreifer zusätzliche Befehle einschleusen kann (z.B. google.com; cat /etc/passwd). Ebenso wird die Benutzer-ID direkt in eine SQL-Abfrage eingefügt, was SQL-Injection-Angriffe ermöglicht.
Korrigierter Code
import subprocess
import re
from flask import Flask, request, abort
import sqlite3
app = Flask(__name__)
# Allowlist-Muster für gültige Hostnamen
HOSTNAME_PATTERN = re.compile(r'^[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])?)*$')
@app.route('/lookup')
def dns_lookup():
hostname = request.args.get('host', '')
# Eingabevalidierung mit Allowlist-Muster
if not hostname or len(hostname) > 253:
abort(400, 'Ungültige Hostnamelänge')
if not HOSTNAME_PATTERN.match(hostname):
abort(400, 'Ungültiges Hostnameformat')
# subprocess mit Argumentliste verwenden (keine Shell-Injection möglich)
try:
result = subprocess.run(
['nslookup', hostname],
capture_output=True,
text=True,
timeout=10
)
return f'<pre>{result.stdout}</pre>'
except subprocess.TimeoutExpired:
abort(504, 'Lookup-Timeout')
@app.route('/user')
def get_user():
user_id = request.args.get('id', '')
# Benutzer-ID muss eine positive Ganzzahl sein
if not user_id.isdigit() or int(user_id) <= 0:
abort(400, 'Ungültige Benutzer-ID')
# Parametrisierte Abfrage zur Verhinderung von SQL-Injection
conn = sqlite3.connect('users.db')
cursor = conn.cursor()
cursor.execute("SELECT * FROM users WHERE id = ?", (int(user_id),))
user = cursor.fetchone()
conn.close()
if not user:
abort(404, 'Benutzer nicht gefunden')
return str(user)
Der korrigierte Code implementiert mehrere Ebenen der Eingabevalidierung: Regex-Musterabgleich für Hostnamen mit einem Allowlist-Ansatz, Längenvalidierung, Typprüfung für numerische IDs und parametrisierte Abfragen für Datenbankzugriffe. Die Verwendung von subprocess.run() mit einer Argumentliste anstelle von Shell-Ausführung verhindert Command-Injection, selbst wenn die Validierung umgangen wird.
Ausgenutzt in der Praxis
Equifax-Datenpanne (Equifax, 2017)
Angreifer nutzten CVE-2017-5638 aus, eine kritische Schwachstelle in Apache Struts, bei der der Jakarta-Multipart-Parser den Content-Type-HTTP-Header nicht ordnungsgemäß validierte. Dieser Fehler in der Eingabevalidierung ermöglichte Remote-Code-Ausführung, wodurch Angreifer die Systeme von Equifax kompromittieren und persönliche Daten von 147,9 Millionen Amerikanern exfiltrieren könnten, darunter Sozialversicherungsnummern, Geburtsdaten und Adressen. Der Angriff blieb 76 Tage lang unentdeckt und führte zu Gesamtkosten von über 1,4 Milliarden Dollar.
BitGrail-Kryptowährungsbörsen-Hack (BitGrail, 2018)
Die italienische Kryptowährungsbörse BitGrail verlor etwa 170 Millionen Dollar in Nano (XRB)-Kryptowährung aufgrund unsachgemäßer Eingabevalidierung. Die Börse führte die Guthabenvalidierung in clientseitigem JavaScript statt serverseitig durch, was es Angreifern ermöglichte, diese Prüfungen zu umgehen und mehr Geld abzuheben, als ihr Kontostand erlaubte. Eine zweite Schwachstelle ermöglichte es Benutzern, Auszahlungen auf ihr Wallet anzufordern, während sie das Guthaben eines anderen Kontos nutzten. Der Börsengründer wurde später von italienischen Gerichten angewiesen, Vermögenswerte an Kunden zurückzugeben.
Heartland Payment Systems-Datenpanne (Heartland, 2008)
SQL-Injection-Angriffe, die auf Fehler in der Eingabevalidierung zurückzuführen waren, führten zur Kompromittierung von 134 Millionen Kreditkarten bei Heartland Payment Systems, damals der fünftgrößte Kreditkartenprozessor in den USA. Angreifer nutzten eine anfällige Web-Login-Seite aus, die acht Jahre zuvor ohne ordnungsgemäße Eingabevalidierung bereitgestellt worden war. Nach dem ersten Zugriff verbrachten sie acht Monate damit, Sniffer-Malware zu installieren, die Zahlungskartendaten während der Verarbeitung abfing, was zu Entschädigungszahlungen in Höhe von 145 Millionen Dollar führte.
Tools zum Testen/Ausnutzen
-
Burp Suite — umfassende Plattform für Sicherheitstests von Webanwendungen mit integrierten Tools zum Testen von Schwachstellen in der Eingabevalidierung, einschließlich Parametermanipulation, Fuzzing und automatisiertem Scanning.
-
OWASP ZAP — Open-Source-Sicherheitsscanner für Webanwendungen, der Probleme bei der Eingabevalidierung durch aktives und passives Scanning identifiziert, mit Unterstützung für automatisiertes Fuzzing von Eingabefeldern.
-
SQLMap — automatisiertes Tool zur Erkennung und Ausnutzung von SQL-Injection, das auf Fehler in der Eingabevalidierung bei Datenbankabfragen über mehrere Datenbankplattformen hinweg testet.
CVE-Beispiele
-
CVE-2017-5638 — Apache Struts Jakarta-Multipart-Parser unsachgemäße Eingabevalidierung ermöglicht Remote-Code-Ausführung über manipulierten Content-Type-Header (Equifax-Datenpanne).
-
CVE-2024-3400 — Palo Alto Networks PAN-OS GlobalProtect-Funktion Command-Injection aufgrund unsachgemäßer Eingabevalidierung ermöglicht unauthentifizierte Remote-Code-Ausführung.
-
CVE-2021-44228 — Apache Log4j2 JNDI-Injection-Schwachstelle (Log4Shell) verursacht durch unsachgemäße Validierung von benutzergesteuerten Eingaben in Log-Nachrichten.
-
CVE-2019-11510 — Pulse Secure VPN willkürliches Lesen von Dateien aufgrund unsachgemäßer Eingabevalidierung, die Path-Traversal-Angriffe ermöglicht.
Referenzen
-
MITRE. "CWE-20: Improper Input Validation." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/20.html
-
OWASP. "Input Validation Cheat Sheet." OWASP Cheat Sheet Series. https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html
-
OWASP. "Web Security Testing Guide - Input Validation Testing." https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/
-
Invicti. "Input validation errors: The root of all evil in web application security." https://www.invicti.com/blog/web-security/input-validation-errors-root-of-all-evil/