Verlass auf IP-Adresse für Authentifizierung
Beschreibung
Verlass auf IP-Adresse für Authentifizierung ist eine Schwachstelle, die auftritt, wenn ein Produkt eine IP-Adresse als einziges Mittel der Authentifizierung verwendet. IP-Adressen können leicht gespooft werden - Angreifer können Quell-IP-Adressen in Paketen fälschen, die sie senden. Während Antwortpakete an die gefälschte Adresse zurückkehren (was bidirektionale Kommunikation einschränkt), können sich Angreifer positionieren, um den Verkehr zwischen dem Opfer und der gespooften IP-Adresse abzufangen. Obwohl Source-Routing-Mechanismen Subnetz-Positionierungsanforderungen umgehen könnten, sind sie im Internet weitgehend deaktiviert. Das grundlegende Problem ist, dass IP-Adressen nie als Authentifizierungsanmeldedaten konzipiert wurden und keinen kryptografischen Identitätsnachweis bieten.
Risiko
Die Verwendung von IP-Adressen für Authentifizierung bietet im Wesentlichen keine echte Sicherheit gegen motivierte Angreifer. In lokalen Netzwerken ermöglicht ARP-Spoofing Angreifern, Verkehr umzuleiten und jede IP-Adresse zu imitieren. In weiteren Netzwerken kann blindes IP-Spoofing für verbindungslose Protokolle wie UDP effektiv sein, bei denen Angreifer keine Antworten empfangen müssen. Selbst für TCP können Angreifer im selben Netzwerksegment andere Hosts vollständig imitieren. Das Risiko ist besonders schwerwiegend für administrative Schnittstellen, Datenbankzugriff und API-Endpunkte, die sich ausschließlich auf IP-Allowlists verlassen. Angreifer, die ein beliebiges System in einem vertrauenswürdigen Netzwerksegment kompromittieren, erlangen sofort Zugang zu allen IP-authentifizierten Ressourcen. Cloud-Umgebungen und containerisierte Bereitstellungen verkomplizieren IP-basiertes Vertrauen weiter, da IP-Adressen kurzlebig sind und neu zugewiesen werden können.
Lösung
Verwenden Sie IP-Adressverifikation als ergänzende Sicherheitsschicht, aber nie als einzelnen Authentifizierungsfaktor. Implementieren Sie ordnungsgemäße Authentifizierungsmechanismen, die nicht gespooft werden können: Benutzername/Passwort-Kombinationen mit sicherer Übertragung (TLS), digitale Zertifikate mit ordnungsgemäßer Validierung, API-Schlüssel mit kryptografischen Signaturen oder Multi-Faktor-Authentifizierung. Für interne Dienste verwenden Sie gegenseitiges TLS (mTLS), bei dem sowohl Client als auch Server Zertifikate präsentieren. Wenn IP-Beschränkungen für Compliance oder Defense-in-Depth erforderlich sind, kombinieren Sie sie mit stärker Authentifizierung. Erwägen Sie Netzwerksegmentierung und Zero-Trust-Architekturen, bei denen alle Anfragen unabhängig vom Quellnetzwerk Authentifizierung erfordern. Für sensible Operationen implementieren Sie zusätzliche Verifikation über Netzwerkebenenkontrollen hinaus.
Häufige Auswirkungen
| Auswirkung | Details |
|---|---|
| Zugriffskontrolle, Non-Repudiation | Bereich: Zugriffskontrolle, Non-Repudiation Böswillige Benutzer können Authentifizierungsinformationen fälschen, indem sie IP-Adressen spoofen und jeden Host imitieren. Dies ermöglicht unbefugten Zugang zu geschützten Ressourcen und unterbricht Audit-Trails, da Aktionen der gespooften Adresse zugeschrieben werden anstatt dem Angreifer. |
Beispielcode
Anfälliger Code (C)
Die folgenden Beispiele demonstrieren den Verlass auf IP-Adresse für Authentifizierung:
// Anfällig: Nur-IP-Authentifizierung für Dienstzugang
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#define TRUSTED_IP "192.168.1.100"
int vulnerable_check_auth(int client_socket) {
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
getpeername(client_socket, (struct sockaddr *)&client_addr, &addr_len);
// Anfällig: Authentifizierung basiert ausschließlich auf IP
char *client_ip = inet_ntoa(client_addr.sin_addr);
if (strcmp(client_ip, TRUSTED_IP) == 0) {
return 1; // Authentifiziert!
// Angreifer spooft IP um Zugang zu erlangen
}
return 0;
}
void vulnerable_service(int server_socket) {
while (1) {
int client = accept(server_socket, NULL, NULL);
if (vulnerable_check_auth(client)) {
// Gewährt vollen Zugang basierend nur auf IP
handle_privileged_request(client);
} else {
close(client);
}
}
}
// Anfällig: Java-Dienst mit IP-basierter Authentifizierung
import java.net.*;
public class VulnerableIPAuth {
private static final String[] TRUSTED_IPS = {
"10.0.0.1", "10.0.0.2", "192.168.1.100"
};
public boolean authenticate(Socket connection) {
// Anfällig: Prüft nur IP-Adresse
String clientIP = connection.getInetAddress().getHostAddress();
for (String trusted : TRUSTED_IPS) {
if (trusted.equals(clientIP)) {
return true; // Spoofbar!
}
}
return false;
}
public void handleConnection(Socket conn) {
if (authenticate(conn)) {
// Voller privilegierter Zugang basierend auf IP
processAdminRequest(conn);
}
}
}
# Anfällig: Web-API mit nur IP-Allowlist
from flask import Flask, request
app = Flask(__name__)
ALLOWED_IPS = ['10.0.0.1', '192.168.1.100', '172.16.0.5']
@app.route('/admin/api')
def vulnerable_admin_api():
# Anfällig: Nur-IP-Authentifizierung
client_ip = request.remote_addr
if client_ip in ALLOWED_IPS:
return perform_admin_action()
# Angreifer im selben Netzwerksegment kann IP spoofen
return "Zugriff verweigert", 403
Korrigierter Code (C)
// Korrigiert: Ordnungsgemäße Authentifizierung mit IP als ergänzende Prüfung
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
#include <openssl/ssl.h>
typedef struct {
char *api_key;
char *signature;
long timestamp;
} AuthCredentials;
int verify_credentials(AuthCredentials *creds) {
// Verifizieren, dass API-Schlüssel existiert und gültig ist
if (!is_valid_api_key(creds->api_key)) {
return 0;
}
// Signatur verifizieren
if (!verify_hmac_signature(creds->api_key, creds->signature, creds->timestamp)) {
return 0;
}
// Zeitstempel prüfen um Replay zu verhindern
if (abs(time(NULL) - creds->timestamp) > MAX_TIMESTAMP_SKEW) {
return 0;
}
return 1;
}
int secure_check_auth(SSL *ssl, int client_socket) {
// Korrigiert: Ordnungsgemäße Anmeldedaten erfordern
AuthCredentials creds;
if (!receive_credentials(ssl, &creds)) {
return 0;
}
if (!verify_credentials(&creds)) {
return 0;
}
// IP-Prüfung als zusätzliche Schicht (Defense in Depth)
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
getpeername(client_socket, (struct sockaddr *)&client_addr, &addr_len);
char *client_ip = inet_ntoa(client_addr.sin_addr);
if (!is_ip_in_allowed_range(client_ip)) {
log_warning("Gültige Anmeldedaten von unerwarteter IP: %s", client_ip);
// Könnte zusätzliche Verifikation erfordern, aber Anmeldedaten sind primär
}
return 1;
}
// Korrigiert: Java-Dienst mit ordnungsgemäßer Authentifizierung
import javax.net.ssl.*;
import java.security.*;
public class SecureAuth {
private final TokenValidator tokenValidator;
public AuthResult authenticate(SSLSocket connection) {
// Korrigiert: Client-Zertifikat verifizieren (gegenseitiges TLS)
try {
SSLSession session = connection.getSession();
Certificate[] certs = session.getPeerCertificates();
if (certs == null || certs.length == 0) {
return AuthResult.failure("Kein Client-Zertifikat");
}
X509Certificate clientCert = (X509Certificate) certs[0];
// Verifizieren, dass Zertifikat gültig und vertrauenswürdig ist
if (!verifyCertificate(clientCert)) {
return AuthResult.failure("Ungültiges Zertifikat");
}
// Identität aus Zertifikat extrahieren
String clientId = extractClientId(clientCert);
// IP kann für Auditing protokolliert werden
String clientIP = connection.getInetAddress().getHostAddress();
auditLog.record("auth_success", clientId, clientIP);
return AuthResult.success(clientId);
} catch (SSLPeerUnverifiedException e) {
return AuthResult.failure("Zertifikatsverifikation fehlgeschlagen");
}
}
// Alternative: Token-basierte Authentifizierung
public AuthResult authenticateByToken(String authHeader) {
if (authHeader == null || !authHeader.startsWith("Bearer ")) {
return AuthResult.failure("Autorisierung fehlt");
}
String token = authHeader.substring(7);
if (!tokenValidator.isValid(token)) {
return AuthResult.failure("Ungültiges Token");
}
return AuthResult.success(tokenValidator.getIdentity(token));
}
}
# Korrigiert: Web-API mit ordnungsgemäßer Authentifizierung
from flask import Flask, request, abort
from functools import wraps
import jwt
import hmac
import hashlib
import time
app = Flask(__name__)
def require_auth(f):
"""Korrigiert: Ordnungsgemäße token-basierte Authentifizierung"""
@wraps(f)
def decorated(*args, **kwargs):
auth_header = request.headers.get('Authorization')
if not auth_header or not auth_header.startswith('Bearer '):
abort(401, 'Autorisierung fehlt')
token = auth_header.split(' ')[1]
try:
# JWT-Token verifizieren
payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256'])
# Ablauf prüfen
if payload.get('exp', 0) < time.time():
abort(401, 'Token abgelaufen')
request.user = payload
except jwt.InvalidTokenError:
abort(401, 'Ungültiges Token')
return f(*args, **kwargs)
return decorated
def verify_api_signature(f):
"""Alternative: HMAC-Signaturverifikation"""
@wraps(f)
def decorated(*args, **kwargs):
api_key = request.headers.get('X-API-Key')
signature = request.headers.get('X-Signature')
timestamp = request.headers.get('X-Timestamp')
if not all([api_key, signature, timestamp]):
abort(401, 'Authentifizierungs-Header fehlen')
# Zeitstempel-Aktualität verifizieren
if abs(time.time() - int(timestamp)) > 300:
abort(401, 'Anfrage abgelaufen')
# Signatur verifizieren
secret = get_secret_for_api_key(api_key)
if not secret:
abort(401, 'Ungültiger API-Schlüssel')
expected = hmac.new(
secret.encode(),
f"{timestamp}{request.path}".encode(),
hashlib.sha256
).hexdigest()
if not hmac.compare_digest(signature, expected):
abort(401, 'Ungültige Signatur')
return f(*args, **kwargs)
return decorated
@app.route('/admin/api')
@require_auth
def secure_admin_api():
# IP protokolliert für Auditing, nicht für Auth verwendet
client_ip = request.remote_addr
app.logger.info(f"Admin-API-Zugriff durch {request.user['id']} von {client_ip}")
return perform_admin_action()
Die Korrektur ersetzt IP-basierte Authentifizierung durch ordnungsgemäße Anmeldedatenverifikation (Token, Zertifikate, signierte Anfragen) und behält IP-Prüfungen nur als ergänzende Audit- oder Defense-in-Depth-Maßnahme bei.
Ausgenutzt in der Praxis
Hausautomations-IP-Allowlist-Umgehung (IoT, 2022)
CVE-2022-30319 dokumentierte die S-Bus-Funktionalität eines Hausautomationsprodukts, die IP-Allowlisting für Zugriffskontrolle verwendete. Angreifer umgingen dies durch IP-Adress-Spoofing und erlangten unbefugte Kontrolle über Hausautomationssysteme.
Datenbankzugriff via IP-Spoofing (Unternehmenssysteme, Fortlaufend)
Datenbanksysteme, die mit IP-basierten Zugriffskontrollen konfiguriert waren, wurden kompromittiert, als Angreifer Zugang zu vertrauenswürdigen Netzwerksegmenten erlangten und autorisierte IP-Adressen spooften, um auf sensible Daten zuzugreifen.
Interne API-Ausnutzung (Cloud-Umgebungen, Fortlaufend)
Cloud-Dienste, die IP-Allowlists für interne APIs verwenden, wurden ausgenutzt, als Angreifer eine beliebige Instanz im vertrauenswürdigen IP-Bereich kompromittierten und Zugang zu allen IP-authentifizierten Diensten erlangten.
Tools zum Testen/Ausnutzen
-
hping3 — Netzwerktool, das Pakete mit gespooften Quelladressen senden kann.
-
Scapy — Python-Paketmanipulationsbibliothek für IP-Spoofing-Tests.
-
arpspoof — ARP-Spoofing-Tool für lokale Netzwerkangriffe.
CVE-Beispiele
- CVE-2022-30319 — S-Bus-Funktionalität eines Hausautomationsprodukts verwendete IP-Allowlisting, das Angreifer durch IP-Adressfälschung umgingen.
Referenzen
-
MITRE Corporation. "CWE-291: Reliance on IP Address for Authentication." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/291.html
-
OWASP Foundation. "Authentication Cheat Sheet." https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
-
NIST. "Zero Trust Architecture." SP 800-207. https://csrc.nist.gov/publications/detail/sp/800-207/final