IP-Adresse aus einem Header vertraut
CWE-290CWE-348OWASP A01:2021Aktualisiert 4. September 20265 Min. Lesezeit
Hinter einem Proxy steht die echte IP-Adresse des Besuchers in einem Header wie X-Forwarded-For. Dieser Header wird ebenso angenommen, wenn ein Client ihn selbst mitsendet. Vertraut Ihre Anwendung ihm, ohne zu wissen, wer ihn gesetzt hat, bestimmt der Angreifer seine eigene IP-Adresse und umgeht damit Limits, Sperren und Zugriffsregeln.
Nahezu jede Anwendung läuft heute hinter einem Lastverteiler, einem Reverse Proxy oder einem CDN. Dadurch sieht die Anwendung nicht mehr die Adresse des Besuchers, sondern die des Proxys, und die echte Adresse wird in einem Header mitgesendet. Diese Lösung funktioniert, bis jemand diesen Header selbst ausfüllt. Die Kunst besteht darin zu unterscheiden, wer ihn gesetzt hat.
Warum ist der Header nicht vertrauenswürdig?
Leitet ein Proxy eine Anfrage weiter, fügt er die Adresse des ursprünglichen Besuchers einem Header hinzu, meist X-Forwarded-For. Die Anwendung liest diesen Wert und weiß so, von wem die Anfrage kam. So ist es gedacht.
Der Punkt ist, dass ein Header Bestandteil der Anfrage ist. Ein Client kann ihn selbst mitsenden, und ein Proxy, der einen vorhandenen Wert antrifft, hängt meist seine eigenen Angaben an, statt ihn zu ersetzen. Der Header ist also eine Liste, deren Anfang der Client bestimmt hat und deren Ende Ihre eigene Infrastruktur.
Von einer aus einem Header vertrauten IP-Adresse spricht man, wenn eine Anwendung den ersten Wert dieser Liste nimmt oder den gesamten Wert unbesehen übernimmt, ohne zu wissen, welcher Teil von ihrem eigenen Proxy stammt. Vergleichen Sie es mit einem Paket, auf dem mehrere Absender gestempelt sind: dem des Verteilzentrums können Sie vertrauen, dem, den der Versender selbst daraufgeschrieben hat, nicht. Wer den obersten liest, liest das, was der Versender ihn lesen lassen wollte.
Wie missbraucht ein Angreifer X-Forwarded-For?
Verwundbar:
function ipVon(req) {
// Der erste Wert: genau der, den der Client selbst bestimmen kann
const kette = req.headers['x-forwarded-for'];
return kette ? kette.split(',')[0].trim() : req.socket.remoteAddress;
}
app.post('/anmelden', async (req, res) => {
const ip = ipVon(req);
if (await zuVieleVersuche(ip)) return res.status(429).send('Zu viele Versuche');
// ...
});
// Und eine Zugriffsregel auf Grundlage derselben Adresse
app.use('/verwaltung', (req, res, next) => {
if (ipVon(req).startsWith('10.0.')) return next(); // "intern"
res.sendStatus(403);
});
Zwei Maßnahmen, die beide auf derselben unzuverlässigen Quelle ruhen. Der Angreifer sendet schlicht selbst einen Header mit:
POST /anmelden HTTP/1.1
X-Forwarded-For: 203.0.113.7
Bei jedem Versuch eine andere Adresse, und die Ratenbegrenzung zählt nie über eins hinaus. Ein Passwortangriff, der nach fünf Versuchen hätte enden sollen, läuft ungehindert weiter. Und die Zugriffsregel für die Verwaltungsoberfläche ist noch unmittelbarer umgangen:
GET /verwaltung/nutzer HTTP/1.1
X-Forwarded-For: 10.0.4.12
HTTP/1.1 200 OK
Der Angreifer hat sich selbst zum internen System erklärt, und die Anwendung glaubt ihm.
Sicher:
// Die Zahl der Proxys vor der Anwendung ist bekannt und fest
app.set('trust proxy', 2); // etwa: CDN plus eigener Lastverteiler
app.post('/anmelden', async (req, res) => {
const ip = req.ip; // zählt vom Ende der Liste zurück
if (await zuVieleVersuche(ip)) return res.status(429).send('Zu viele Versuche');
// ...
});
# Und der Proxy überschreibt, was der Client mitgesendet hat
location / {
proxy_set_header X-Forwarded-For $remote_addr; # ersetzen, nicht anhängen
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://anwendung;
}
Die Anwendung zählt nun vom Ende der Liste die bekannte Zahl vertrauenswürdiger Proxys zurück und nimmt damit genau den Wert, den ihre eigene Infrastruktur hinzugefügt hat. Und der Proxy ersetzt den Header, statt ihn zu ergänzen, sodass das, was der Client mitgesendet hat, vollständig verschwindet.
Für die Zugriffsregel an der Verwaltungsoberfläche gilt zudem: Eine IP-Adresse ist ein Hinweis, kein Identitätsnachweis. Verwenden Sie sie allenfalls als ergänzende Bedingung zusätzlich zu echter Authentifizierung und Autorisierung.
Welche Auswirkungen hat ein vertrauter IP-Header?
Der Schweregrad reicht von mittel bis hoch, abhängig davon, wofür die Adresse verwendet wird. Dient sie nur der Statistik, bleibt der Schaden bei verfälschten Zahlen. Sobald Sicherheitsentscheidungen darauf ruhen, wird es ernst.
Die häufigsten Folgen sind das Umgehen von Ratenbegrenzungen und Sperren. Ein Angreifer, der seine Adresse je Anfrage wechselt, kann unbegrenzt Passwörter ausprobieren, Codes erraten oder Daten abrufen, ohne je an ein Limit zu stoßen. Die Maßnahme besteht, zählt aber nie durch.
Schwerwiegender ist das Umgehen von Zugriffsregeln. Systeme, die eine Verwaltungsoberfläche, eine Überwachungsseite oder eine interne API anhand eines IP-Bereichs abschirmen, geben diesen Zugang an jeden weiter, der den passenden Header mitsendet. Das ist ein unmittelbarer Weg zu Funktionen, die als abgeschirmt galten.
Schließlich gibt es die Protokollseite. Wird die Adresse aus einem unzuverlässigen Header festgehalten, kann ein Angreifer seine Spuren auf eine beliebige andere Adresse zeigen lassen. Bei einer Untersuchung eines Vorfalls führt das zur falschen Schlussfolgerung und mitunter zu einem unbeteiligten Dritten.
Wie spürt man einen vertrauten IP-Header auf?
Ein Tester sendet Anfragen mit einem selbst gewählten X-Forwarded-For und beobachtet, ob sich die Anwendung anders verhält: Wird die Ratenbegrenzung neu gezählt, ändert sich die Adresse in einer Rückmeldung oder Protokollzeile, oder wird eine abgeschirmte Route plötzlich zugänglich?
Zusätzlich werden die Varianten ausprobiert. Neben X-Forwarded-For gibt es X-Real-IP, X-Client-IP, X-Originating-IP, Forwarded und True-Client-IP; Anwendungen sehen häufig auf mehrere davon und vertrauen mitunter einem, den der Proxy überhaupt nicht setzt. Ebenso wird geprüft, was bei mehreren Werten in der Liste und bei einem erfundenen Wert an vorderster Stelle geschieht. Ferner wird betrachtet, ob der Proxy den Header ersetzt oder ergänzt und ob die Anwendung die richtige Zahl von Proxys verwendet. AssistSec widmet Zugriffsregeln, die auf einem IP-Bereich ruhen, besondere Aufmerksamkeit, denn dort liegt der Unterschied zwischen einem umgangenen Limit und einer umgangenen Autorisierung.
Wie verhindert man einen vertrauten IP-Header?
- Konfigurieren Sie Ihre Anwendung mit der genauen Zahl vertrauenswürdiger Proxys, die davorstehen.
- Lassen Sie Ihren eigenen Proxy den Weiterleitungsheader ersetzen, statt ihn zu ergänzen.
- Nehmen Sie nie den ersten Wert der Liste; zählen Sie vom Ende zurück.
- Ignorieren Sie den Header vollständig, wenn Ihre Anwendung unmittelbar am Internet hängt.
- Verwenden Sie eine IP-Adresse nie als alleinige Grundlage für Zugriff; sie ist ein Hinweis, keine Identität.
- Begrenzen Sie den Zugang zu internen Funktionen mit Netzwerksegmentierung, einem VPN oder gegenseitiger Authentifizierung.
- Achten Sie auf die alternativen Header, die Ihr Framework möglicherweise berücksichtigt.
- Stützen Sie Ratenbegrenzungen nach Möglichkeit auf das Konto und auf die IP-Adresse nur bei anonymen Anfragen.
- Halten Sie in Ihren Protokolldateien fest, welcher Wert verwendet wurde und woher er stammte.
Quellen
Häufige Fragen
Wie bestimme ich die echte IP-Adresse dann?
Indem Sie wissen, wie viele vertrauenswürdige Proxys vor Ihrer Anwendung stehen, und vom Ende der Liste aus diese Anzahl zurückzählen. Die Werte, die Ihr eigener Proxy hinzugefügt hat, sind verlässlich; alles, was der Client selbst mitgesendet hat, steht vorn und ist es nicht.
Warum ist das schlimmer als nur ein umgangenes Limit?
Weil die IP-Adresse in vielen Systemen auch für Zugriffsregeln, für das Erkennen vertrauenswürdiger Standorte und in Protokolldateien verwendet wird. Ein Angreifer, der seine Adresse bestimmt, kann sich als internes System ausgeben und seine Spuren auf eine andere Adresse zeigen lassen.
Darf ich den Header ganz ignorieren?
Läuft Ihre Anwendung unmittelbar am Internet, ist das die richtige Wahl: Verwenden Sie die Adresse der Verbindung. Steht ein Proxy davor, benötigen Sie den Header, jedoch nur den Teil, den Ihr eigener Proxy hinzugefügt hat.
Was, wenn es mehrere Proxys gibt?
Dann kommt es auf die Anzahl an. Konfigurieren Sie Ihr Framework mit der genauen Zahl vertrauenswürdiger Proxys, damit es exakt so viele Positionen zurückzählt. Eine Einstellung, die allen Proxys vertraut, läuft darauf hinaus, dem Client zu vertrauen.
Verwandte Artikel
- SchwachstellenCWE-284A01:2021Broken Access ControlBroken Access Control erklärt: horizontale und vertikale Rechteausweitung, Forced Browsing und warum Deny by Default serverseitig gehört.
- SchwachstellenCWE-307A07:2021Brute Force und Credential StuffingAngreifer raten Passwörter oder spielen geleakte Anmeldedaten erneut ein. Lesen Sie, welche Grenzen und welcher zweite Faktor beides stoppen.
- SchwachstellenCWE-644A03:2021Host Header InjectionBaut Ihre Anwendung Links aus dem Host-Header, bestimmt der Angreifer, wohin diese zeigen. Lesen Sie, wie das eine Passwortwiederherstellung kapert.
- SchwachstellenCWE-770A04:2021Keine Ratenbegrenzung auf der APIOhne Ratenbegrenzung lässt sich eine API endlos abfragen. Lesen Sie, wie das zu Datendiebstahl, Kostenmissbrauch und Ausfällen führt.
- SchwachstellenCWE-16A05:2021Security MisconfigurationSecurity Misconfiguration erklärt: wie Standardpasswörter, Debug-Modi und offene Cloud-Buckets Angreifern Zugang geben, und wie Sie sich schützen.