Verwendung einer weniger vertrauenswürdigen Quelle

Beschreibung

Verwendung einer weniger vertrauenswürdigen Quelle ist eine Schwachstelle, die auftritt, wenn ein Produkt zwischen mehreren Datenquellen auswählt, aber diejenige wählt, die reduzierte Verifizierungsfähigkeit, verminderte Vertrauenswürdigkeit oder erhöhte Anfälligkeit für Kompromittierung bietet. Dies manifestiert sich häufig, wenn Anwendungen client-gelieferten Daten mehr vertrauen als server-verifizierten Informationen, wie z.B. dem X-Forwarded-For HTTP-Header anstelle der tatsächlichen Verbindungs-IP-Adresse zu vertrauen, oder client-bereitgestellter Benutzeridentität anstelle von serverseitigen Authentifizierungsdaten zu vertrauen. Die Schwachstelle entsteht durch Priorisierung von Bequemlichkeit oder Kompatibilität über Sicherheit, wenn mehrere Informationsquellen unterschiedlicher Vertrauenswürdigkeit verfügbar sind. Die gewählte weniger vertrauenswürdige Quelle kann von Angreifern manipuliert werden, um Sicherheitskontrollen zu umgehen, Identitäten zu fälschen oder bösartige Daten zu injizieren.

Risiko

Das Vertrauen in weniger zuverlässige Datenquellen erzeugt Sicherheits-Bypasses, die Angreifer ausnutzen können, um Authentifizierungs-, Autorisierungs- und Audit-Kontrollen zu umgehen. Wenn Anwendungen X-Forwarded-For-Headern für IP-basierte Zugriffskontrolle vertrauen, können Angreifer interne IP-Adressen fälschen, um Firewall-Beschränkungen zu umgehen und auf nur intern zugängliche Ressourcen zuzugreifen. Client-gelieferte Identitätsinformationen können für Session-Hijacking oder Privilegien-Eskalation manipuliert werden. Audit-Logs, die auf fälschbaren Daten basieren, werden für forensische Analyse und Incident Response unzuverlässig. IP-basiertes Rate-Limiting mit gefälschten Headern ermöglicht Angreifern, Missbrauchsschutz zu umgehen. Geografische Beschränkungen basierend auf gefälschten Standortdaten können umgangen werden. Das Risiko ist besonders schwerwiegend, wenn die weniger vertrauenswürdige Quelle für sicherheitskritische Entscheidungen wie Zugriffskontrolle, Authentifizierung oder Audit-Logging verwendet wird, da Angreifer sowohl bösartige Aktionen durchführen als auch ihre wahre Identität verbergen können.

Lösung

Bevorzugen Sie immer die vertrauenswürdigste Datenquelle, wenn mehrere Quellen verfügbar sind. Für IP-Adressen verwenden Sie die direkte Verbindungs-IP (REMOTE_ADDR) anstelle von Headern wie X-Forwarded-For, die gefälscht werden können. Wenn Proxy-Header verwendet werden müssen, vertrauen Sie ihnen nur von bekannten Proxy-Servern, indem Sie zuerst die direkte Verbindungs-IP validieren. Implementieren Sie eine Vertrauenskette, bei der jeder Hop in einer Proxy-Kette verifiziert wird. Für Benutzeridentität verwenden Sie immer serverseitige Session-Daten anstelle von client-gelieferten Werten. Dokumentieren Sie die Vertrauensstufe jeder Datenquelle und stellen Sie sicher, dass Sicherheitsentscheidungen angemessen vertrauenswürdige Quellen verwenden. Wenn Client-Daten verwendet werden müssen, validieren Sie sie gegen serverseitige Aufzeichnungen. Implementieren Sie Logging, das sowohl vertrauenswürdige als auch nicht vertrauenswürdige Werte erfasst, um forensische Analyse zu unterstützen.

Häufige Auswirkungen

AuswirkungDetails
ZugriffskontrolleUmfang: Zugriffskontrolle

Angreifer können IP-basierte Zugriffsbeschränkungen, Authentifizierungsprüfungen und Autorisierungskontrollen umgehen, indem sie gefälschte Werte über die weniger vertrauenswürdige Quelle liefern.
IntegritätUmfang: Integrität

Audit-Logs und Sicherheitsaufzeichnungen werden unzuverlässig, wenn sie angreifer-kontrollierte Daten aus weniger vertrauenswürdigen Quellen enthalten, was Incident Response und Forensik kompromittiert.
Nicht-AbstreitbarkeitUmfang: Nicht-Abstreitbarkeit

Angreifer können ihre wahre Identität verbergen, indem sie Daten in weniger vertrauenswürdigen Quellen fälschen, was es schwierig macht, bösartige Aktionen ihrer tatsächlichen Quelle zuzuordnen.

Beispielcode

Anfälliger Code (PHP/Python)

Die folgenden Beispiele demonstrieren die Verwendung weniger vertrauenswürdiger Quellen:

<?php
// Anfällig: Verwendung des weniger vertrauenswürdigen X-Forwarded-For Headers

// Anfällig: X-Forwarded-For für Zugriffskontrolle vertrauen
function vulnerable_check_internal_access() {
    // Anfällig: Bevorzugt X-Forwarded-For gegenüber REMOTE_ADDR
    if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
        $client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
    } else {
        $client_ip = $_SERVER['REMOTE_ADDR'];
    }

    // Anfällig: IP-basierte Zugriffskontrolle auf fälschbarem Header
    return strpos($client_ip, '10.') === 0 ||
           strpos($client_ip, '192.168.') === 0;
}

// Anfällig: Rate-Limiting mit fälschbarer IP
function vulnerable_rate_limit() {
    // Anfällig: Client-gelieferter IP vertrauen
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];

    $key = "rate_limit_" . $ip;
    $count = cache_get($key) ?? 0;

    if ($count > 100) {
        http_response_code(429);
        exit("Ratenlimit überschritten");
    }

    cache_set($key, $count + 1, 60);
}

// Anfällig: Logging mit fälschbaren Daten
function vulnerable_log_action($action) {
    // Anfällig: Angreifer-kontrollierte IP loggen
    $ip = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'];

    // Audit-Log für Forensik unzuverlässig
    log_to_file("Aktion: $action von IP: $ip");
}

// Anfällig: Client-gelieferter Benutzeridentität vertrauen
function vulnerable_get_user_id() {
    // Anfällig: Client-Cookie gegenüber Session vertrauen
    if (isset($_COOKIE['user_id'])) {
        return $_COOKIE['user_id'];
    }
    return $_SESSION['user_id'] ?? null;
}

// Anfällig: Geografische Beschränkung umgehbar
function vulnerable_geo_restriction() {
    // Anfällig: CF-IPCountry Header vertrauen
    $country = $_SERVER['HTTP_CF_IPCOUNTRY'] ?? 'XX';

    // Angreifer kann diesen Header fälschen
    if (in_array($country, ['US', 'CA', 'UK'])) {
        return true;
    }
    return false;
}
?>
# Anfällig: Verwendung weniger vertrauenswürdiger Quellen in Python
from flask import Flask, request

app = Flask(__name__)

# Anfällig: X-Forwarded-For für IP vertrauen
def vulnerable_get_client_ip():
    # Anfällig: Bevorzugt fälschbaren Header gegenüber tatsächlicher Verbindungs-IP
    forwarded_for = request.headers.get('X-Forwarded-For')
    if forwarded_for:
        # Anfällig: Erste IP aus Header nehmen (angreifer-kontrolliert)
        return forwarded_for.split(',')[0].strip()
    return request.remote_addr

# Anfällig: Zugriffskontrolle mit gefälschter IP
@app.route('/admin')
def vulnerable_admin_access():
    client_ip = vulnerable_get_client_ip()

    # Anfällig: IP-basierte Zugriffskontrolle auf nicht vertrauenswürdigen Daten
    if not client_ip.startswith('10.') and not client_ip.startswith('192.168.'):
        return "Zugriff verweigert", 403

    return render_admin_panel()

# Anfällig: Client-gelieferter Rolle vertrauen
@app.route('/api/action')
def vulnerable_role_check():
    # Anfällig: Rolle aus Request statt Session vertrauen
    user_role = request.headers.get('X-User-Role', 'user')

    if user_role == 'admin':
        return perform_admin_action()
    return perform_user_action()

# Anfällig: Authentifizierung mit weniger vertrauenswürdiger Quelle
@app.route('/api/data')
def vulnerable_auth():
    # Anfällig: JWT aus Cookie gegenüber Session vertrauen
    jwt_token = request.cookies.get('auth_token')
    session_user = session.get('user_id')

    # Anfällig: Bevorzugt client-kontrolliertes Cookie
    if jwt_token:
        user = decode_jwt_without_verification(jwt_token)
        return get_user_data(user['id'])
    elif session_user:
        return get_user_data(session_user)
    return "Nicht authentifiziert", 401

# Anfällig: Rate-Limiting mit gefälschter Identität
from functools import wraps

def vulnerable_rate_limit(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        # Anfällig: Fälschbaren Header für Rate-Limit-Schlüssel verwenden
        client_id = request.headers.get('X-Client-ID',
                                         vulnerable_get_client_ip())

        key = f"rate:{client_id}"
        count = redis.incr(key)
        if count == 1:
            redis.expire(key, 60)

        if count > 100:
            return "Ratenlimit überschritten", 429

        return f(*args, **kwargs)
    return decorated
// Anfällig: Verwendung weniger vertrauenswürdiger Quellen in Java
import javax.servlet.http.*;

public class VulnerableTrustSource extends HttpServlet {

    // Anfällig: IP aus Header statt Verbindung
    private String vulnerableGetClientIP(HttpServletRequest request) {
        // Anfällig: Bevorzugt fälschbaren Header
        String forwardedFor = request.getHeader("X-Forwarded-For");
        if (forwardedFor != null && !forwardedFor.isEmpty()) {
            return forwardedFor.split(",")[0].trim();
        }
        return request.getRemoteAddr();
    }

    // Anfällig: Zugriffskontrolle mit gefälschter IP
    @Override
    protected void doGet(HttpServletRequest request,
                         HttpServletResponse response) {
        String clientIP = vulnerableGetClientIP(request);

        // Anfällig: Sicherheitsentscheidung auf nicht vertrauenswürdigen Daten
        if (!clientIP.startsWith("10.") && !clientIP.startsWith("192.168.")) {
            response.setStatus(403);
            return;
        }

        serveAdminContent(response);
    }

    // Anfällig: Benutzeridentität aus Header
    private String vulnerableGetUserId(HttpServletRequest request) {
        // Anfällig: Client-geliefertem Header gegenüber Session vertrauen
        String headerUserId = request.getHeader("X-User-Id");
        if (headerUserId != null) {
            return headerUserId;  // Angreifer-kontrolliert!
        }

        HttpSession session = request.getSession(false);
        return session != null ? (String) session.getAttribute("userId") : null;
    }

    // Anfällig: Logging mit gefälschten Daten
    private void vulnerableAuditLog(HttpServletRequest request, String action) {
        String clientIP = vulnerableGetClientIP(request);
        String userId = vulnerableGetUserId(request);

        // Anfällig: Log enthält angreifer-kontrollierte Daten
        logger.info("Aktion: {} von Benutzer {} von IP {}", action, userId, clientIP);
    }

    // Anfällig: Geografische Beschränkung
    private boolean vulnerableCheckGeo(HttpServletRequest request) {
        // Anfällig: CloudFlare-Header ohne Verifizierung vertrauen
        String country = request.getHeader("CF-IPCountry");
        if (country == null) {
            country = "XX";
        }

        // Angreifer kann diesen Header hinzufügen
        return Arrays.asList("US", "CA", "UK").contains(country);
    }
}

Korrigierter Code (PHP/Python)

<?php
// Korrigiert: Verwendung vertrauenswürdiger Datenquellen

// Korrigiert: Nur Proxy-Headern von bekannten Proxies vertrauen
function secure_get_client_ip() {
    // Korrigiert: Liste vertrauenswürdiger Proxy-IPs
    $trusted_proxies = ['10.0.0.1', '10.0.0.2'];  // Load-Balancer-IPs

    // Korrigiert: Immer mit REMOTE_ADDR beginnen (nicht fälschbar)
    $remote_addr = $_SERVER['REMOTE_ADDR'];

    // Korrigiert: Nur X-Forwarded-For vertrauen wenn Request von vertrauenswürdigem Proxy
    if (in_array($remote_addr, $trusted_proxies) &&
        isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {

        // Korrigiert: Kette ordnungsgemäß parsen
        $chain = array_map('trim', explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']));

        // Korrigiert: Rechteste nicht vertrauenswürdige IP zurückgeben
        // (letzte IP vor unserer vertrauenswürdigen Proxy-Kette)
        return $chain[0];
    }

    // Korrigiert: Standard auf tatsächliche Verbindungs-IP
    return $remote_addr;
}

// Korrigiert: Zugriffskontrolle mit vertrauenswürdiger IP
function secure_check_internal_access() {
    $client_ip = secure_get_client_ip();

    // Korrigiert: Vertrauenswürdige IP-Quelle verwenden
    return strpos($client_ip, '10.') === 0 ||
           strpos($client_ip, '192.168.') === 0;
}

// Korrigiert: Rate-Limiting mit vertrauenswürdiger Identität
function secure_rate_limit() {
    // Korrigiert: Vertrauenswürdige IP-Quelle verwenden
    $ip = secure_get_client_ip();

    // Korrigiert: Zusätzlich authentifizierte Benutzer-ID verwenden falls verfügbar
    $user_id = $_SESSION['user_id'] ?? null;
    $key = $user_id ? "rate_limit_user_$user_id" : "rate_limit_ip_$ip";

    $count = cache_get($key) ?? 0;

    if ($count > 100) {
        http_response_code(429);
        exit("Ratenlimit überschritten");
    }

    cache_set($key, $count + 1, 60);
}

// Korrigiert: Logging mit vertrauenswürdigen und nicht vertrauenswürdigen Daten
function secure_log_action($action) {
    // Korrigiert: Vertrauenswürdige IP loggen
    $trusted_ip = secure_get_client_ip();

    // Korrigiert: Auch nicht vertrauenswürdig für Forensik loggen (klar markiert)
    $forwarded_for = $_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'keine';

    // Korrigiert: Klare Unterscheidung zwischen vertrauenswürdig und nicht vertrauenswürdig
    log_to_file(sprintf(
        "Aktion: %s | Vertrauenswürdige IP: %s | X-Forwarded-For (nicht vertrauenswürdig): %s",
        $action, $trusted_ip, $forwarded_for
    ));
}

// Korrigiert: Benutzeridentität nur aus Session
function secure_get_user_id() {
    // Korrigiert: Nur serverseitiger Session vertrauen
    if (!isset($_SESSION['user_id'])) {
        return null;
    }
    return $_SESSION['user_id'];
    // Korrigiert: Niemals client-gelieferter Benutzer-ID vertrauen
}

// Korrigiert: Geografische Beschränkung mit Verifizierung
function secure_geo_restriction() {
    // Korrigiert: Vertrauenswürdige Client-IP holen
    $client_ip = secure_get_client_ip();

    // Korrigiert: Serverseitige Geo-Abfrage durchführen
    $country = geoip_country_code($client_ip);  // Serverseitige Abfrage

    if (in_array($country, ['US', 'CA', 'UK'])) {
        return true;
    }
    return false;
}
?>
# Korrigiert: Verwendung vertrauenswürdiger Datenquellen in Python
from flask import Flask, request, session
import ipaddress

app = Flask(__name__)

# Korrigiert: Konfiguration für vertrauenswürdige Proxies
TRUSTED_PROXIES = {'10.0.0.1', '10.0.0.2'}  # Load-Balancer-IPs
INTERNAL_NETWORKS = [
    ipaddress.ip_network('10.0.0.0/8'),
    ipaddress.ip_network('192.168.0.0/16'),
    ipaddress.ip_network('172.16.0.0/12')
]

# Korrigiert: Vertrauenswürdige IP-Extraktion
def secure_get_client_ip():
    remote_addr = request.remote_addr

    # Korrigiert: Nur Proxy-Headern von bekannten Proxies vertrauen
    if remote_addr in TRUSTED_PROXIES:
        forwarded_for = request.headers.get('X-Forwarded-For')
        if forwarded_for:
            # Korrigiert: Erste (Client) IP aus Kette holen
            client_ip = forwarded_for.split(',')[0].strip()
            try:
                # Korrigiert: Validieren dass es eine gültige IP ist
                ipaddress.ip_address(client_ip)
                return client_ip
            except ValueError:
                pass  # Ungültige IP, auf remote_addr zurückfallen

    # Korrigiert: Standard auf direkte Verbindungs-IP
    return remote_addr

# Korrigiert: Zugriffskontrolle mit vertrauenswürdiger IP
@app.route('/admin')
def secure_admin_access():
    client_ip = secure_get_client_ip()

    try:
        ip_obj = ipaddress.ip_address(client_ip)
        # Korrigiert: Gegen interne Netzwerke mit vertrauenswürdiger IP prüfen
        is_internal = any(ip_obj in net for net in INTERNAL_NETWORKS)

        if not is_internal:
            return "Zugriff verweigert", 403

        return render_admin_panel()
    except ValueError:
        return "Ungültige Anfrage", 400

# Korrigiert: Rolle nur aus Session
@app.route('/api/action')
def secure_role_check():
    # Korrigiert: Nur Session-Daten für Rolle vertrauen
    if 'user' not in session:
        return "Nicht authentifiziert", 401

    user_role = session['user']['role']  # Aus serverseitiger Session

    if user_role == 'admin':
        return perform_admin_action()
    return perform_user_action()

# Korrigiert: Authentifizierung mit vertrauenswürdiger Quelle
@app.route('/api/data')
def secure_auth():
    # Korrigiert: Nur serverseitiger Session vertrauen
    if 'user_id' not in session:
        return "Nicht authentifiziert", 401

    user_id = session['user_id']  # Server-verifiziert
    return get_user_data(user_id)

# Korrigiert: Rate-Limiting mit vertrauenswürdiger Identität
from functools import wraps

def secure_rate_limit(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        # Korrigiert: Vertrauenswürdige Identität für Rate-Limiting verwenden
        if 'user_id' in session:
            # Authentifizierte Benutzer: Rate-Limit nach Benutzer-ID
            key = f"rate:user:{session['user_id']}"
        else:
            # Anonym: Rate-Limit nach vertrauenswürdiger IP
            key = f"rate:ip:{secure_get_client_ip()}"

        count = redis.incr(key)
        if count == 1:
            redis.expire(key, 60)

        if count > 100:
            return "Ratenlimit überschritten", 429

        return f(*args, **kwargs)
    return decorated

# Korrigiert: Logging mit Vertrauensstufen
import logging

def secure_audit_log(action):
    trusted_ip = secure_get_client_ip()
    user_id = session.get('user_id', 'anonym')

    # Korrigiert: Vertrauensstufe der Daten klar markieren
    untrusted_xff = request.headers.get('X-Forwarded-For', 'keine')

    logging.info(
        f"AUDIT | action={action} | "
        f"trusted_ip={trusted_ip} | "
        f"user_id={user_id} | "
        f"xff_untrusted={untrusted_xff}"
    )

Die Korrektur stellt sicher, dass Sicherheitsentscheidungen die vertrauenswürdigste verfügbare Datenquelle verwenden, mit ordnungsgemäßer Validierung von Proxy-Ketten.


Ausgenutzt in der Praxis

X-Forwarded-For Spoofing (CVE-2001-0860)

Anwendung verließ sich auf client-gelieferte IP anstelle von Paket-Headern, was Angreifern ermöglichte, IP-basierte Zugriffskontrollen zu umgehen.

PHP-Anwendung Header-Vertrauen (CVE-2006-1126)

PHP-Anwendung vertraute X-Forwarded-For anstelle von REMOTE_ADDR, was Zugriffskontroll-Bypass ermöglichte.


Tools zum Testen/Ausnutzen

  • Burp Suite — HTTP-Header modifizieren um X-Forwarded-For Spoofing zu testen.

  • curl — Anfragen mit benutzerdefinierten Headern zum Testen senden.

  • OWASP ZAP — Automatisiertes Scannen nach Header-Injection-Schwachstellen.


CVE-Beispiele

  • CVE-2001-0860 — Client-gelieferter IP gegenüber Paket-Headern vertraut.

  • CVE-2004-1950 — X-Forwarded-For gegenüber Server-Variablen priorisiert.

  • CVE-2006-1126 — PHP vertraute X-Forwarded-For für Zugriffskontrolle.


Referenzen

  1. MITRE Corporation. "CWE-348: Use of Less Trusted Source." Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/348.html

  2. OWASP Foundation. "HTTP Request Smuggling." https://owasp.org/www-community/attacks/HTTP_Request_Smuggling

  3. Mozilla Developer Network. "X-Forwarded-For." https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-For