Unsaubere Programmierung und Cross Site Scripting ermöglichen Manipulationen, vor denen auch prominente Webseiten nicht gefeit sind .
Planmäßig fliegt eine Boeing 747-400, aber die Thai Airways setzt auch mal kurzfristig eine 777 auf der Langstrecke von München nach Bangkok ein. Dann sind alle Platzreservierungen hinfällig und der Passagier landet trotz gebuchten Fensterplatzes auch mal in der Mitte der Fünfer-Reihe. Nicht nur deshalb lohnt es sich, am Vorabend vor dem Abflug noch schnell online die Flugdaten zu prüfen. Aber wer die Seite im Browser als Bookmark ablegt, zum Beispiel, um sich am nächsten Morgen zu versichern, dass sich keine Verspätungen ergeben haben, der kann beim Flughafen München eine böse Überraschung erleben (Abbildung 1).

Abbildung 1: Die Informationsseite des Flughafens München für einen Flug nach Bangkok. Alle gezeigten Details wie Flugnummer, Typ des Flugzeugs und Uhrzeit sind manipulierbar, weil die Webanwendung sie ungeprüft via URL übergibt.
Zunächst freut er sich aber: Alles bleibt beim Alten, die 747-400 soll pünktlich abheben. Doch beim Check-in heißt es dann plötzlich, die Platzreservierung sei geändert, es fliegt eine 777. Wieso zeigt die Webseite diese Information nicht an? Denn dieselbe Maschine hatte zuvor einen 12-stündigen Flug nach München und dort zwei Stunden Aufenthalt vor dem geplanten Take-off. Dem Onlinesystem blieben mindestens 14 Stunden Zeit, um die Änderungen zu verarbeiten.
Ein genauerer Blick auf die Webseite des Flughafens München weist den Weg zur Lösung des Rätsels. Die URL der Auskunftseite ist verdächtig lang:
http://www.munich-airport.de/de/consumer/fluginfo/flugdetail/index.jsp?lsk=S&fnr=TG++925&lvg=Thai+Airways+International&ha1=BKK&ha2=&ha3=&haf=Bangkok&hafen=Bangkok&stt=2008-11-13+21%3A50%3A00.0&ett=&lde=Thailand&len=Thailand&ter=2&ber=3&typ=B744&ver=+++&saa=88&gat=H28&zurueck=../abflug/g2000_de_S.jsp
Tatsächlich enthält der Link als Parameter alle Informationen, von der Flugnummer, der verwendeten Maschine bis hin zur geplanten Landezeit. Durch simples Probieren können neugierige Besucher die Inhalte der angezeigten Webseite ändern (Abbildung 2). Damit erklärt sich auch das Erlebnis eingangs, bei dem Reloads immer dieselben veralteten Informationen über den Flugzeugtyp ausgeben.
Der Server holt die Seite nicht aus einer Datenbank, sondern setzt sie nur anhand der in der URL übergebenen Parameter zusammen. Wie viele ahnungslose Fluggäste sind wohl schon auf diesen Fehler hereingefallen?
Usability und Sicherheit
Aber die mangelnde Benutzerfreundlichkeit ist das kleinere Problem. Es drohen Falschinformationen rund um Terminänderungen, Verspätungen oder abgesagte Flüge. Findige Angreifer könnten zudem gezielte Cross-Site-Scripting-Attacken fahren (Kasten “Cross Site Scripting”).
|
Cross Site Scripting |
|---|
|
Cross Site Scripting (XSS, manchmal auch CSS) sind Angriffe, die den Inhalt einer Webseite verändern, in der Regel, indem sie eine Client-seitige Skriptsprache ausführen. So lässt sich zum Beispiel der Action-Parameter eines Formulars, das Passwortdaten abfragt, per Javascript verändern. Die Eingaben landen im schlimmsten Fall auf einem anderen Server, statt des erwarteten Login-Skripts verarbeitet sie vielleicht ein Mailer. Im Beispiel des Flughafens München steht der Javascript-Code gut lesbar in der URL, der sich zwar mit den üblichen Mitteln tarnen lässt. Mit »tinyurl.com« verkürzt sind die Details des Links selbst relativ unsichtbar. Dies so genannte reflektive Cross Site Scripting ist den meisten Angreifern jedoch nicht genug, für sie praktischer ist das persistente XSS. Dabei landet in einem Gästebuch oder Forum ein Eintrag mit Javascript-Code, den der Browser bei jedem Laden der Seite ausführt. So lassen sich potenziell deutlich mehr Opfer in eine vorgefertigte Falle locken. Besonders pikant sind XSS-Angriffe, wenn sie auf einer Seite glücken, die der Browser für sicher hält, zum Beispiel einer lokalen Webseite. Denn dann überwachen die meisten Browser die Aktionen von Javascript (oder Active-X-Komponenten) weniger kritisch und ein Angreifer kann mehr Schaden anrichten [1]. |
Abbildung 2 zeigt ein (offensichtliches) Beispiel für eine Falschinformation. Die Seite traut den per URL übergebenen Parametern fast bedingungslos. Sie akzeptiert eine frei gewählte Ankunftszeit genauso wie eine offensichtlich ungültige Flugnummer, den noch nicht einmal geplanten Bereich I im Terminal 2 oder ein fiktives Datum. Übergibt der Besucher im Parameter »stt=« einen Wert wie den 13.13.2009, rechnet wahrscheinlich eine JSP-Library das brav um und zeigt den 13. Januar 2010. Solange der Angreifer Tag und Monat zweistellig angibt, ist sogar ein Termin in der Vergangenheit möglich, ein Plausibilitätstest findet offensichtlich nicht statt.

Abbildung 2: Dass der Transporthubschrauber CH-53 nonstop ins australische Outback nach Coober Pedy fliegt, überrascht. Selbst die Bundeswehr transportiert ihn per Flugzeug. Linux Magazin Airways macht’s möglich.
Immerhin wird das Kürzel der Fluggesellschaft in der Flugnummer auf maximal drei Zeichen beschränkt, sodass ein Angriff mit einem modifizierten URL-Pfad an dieser Stelle nicht funktioniert oder zumindest nur einen wertlosen Link erzeugt. In der Abbildung 3 ist das Ergebnis zu sehen, wenn der Benutzer in dem Feld »fnr=« den String »/etc/passwd++925« sendet. Immerhin setzt der Flughafen München anscheinend einen filternden Proxy ein: Eine manipulierte URL, die mehr als ein »../« enthält, verursacht eine Fehlermeldung.

Abbildung 3: Die Statuszeile zeigt: Übergibt ein Angreifer in der URL Zeichenketten wie »/etc/password«, dann erscheinen Teile davon in der Flugnummer.
|
Fehlerbericht |
|---|
|
Die Redaktion meldete vorab die im Artikel beschriebenen Manipulationsmöglichkeiten an die Flughafen München GmbH. Ein Sprecher der Gesellschaft bestätigte die Fehler und versicherte, dass die Lücken bei Erscheinen dieser Ausgabe geschlossen seien. |
Directory Traversal
Dieses Vorgehen ist Experten unter dem Begriff Directory-Traversal-Angriff bekannt. Dafür ist allerdings immer ein Fehler des Entwicklers notwendig, ein typischer Fall wäre folgender PHP-Code:
<?php
include('./'.$_REQUEST["filename"]);
?>
Hier hat der Entwickler übersehen, dass ein Verzeichniswechsel auch mit der relativen Pfadangabe »../« möglich ist. Ruft ein Angreifer das Skript zum Beispiel mit
http://test.local/listing1.php?filename=../../../../../../../../../../etc/passwd
auf, bekommt er sehr wahrscheinlich mehr zu sehen, als erwünscht ist. Eine verbreitete Gegenmaßnahme ist es, einfach führende »../« zu entfernen. Allerdings haben Angreifer mit URLs wie
http://test.local/listing1.php?filename=listing1.php/../../../../etc/passwd
immer noch Erfolg. Darüber hinaus gibt es noch den Umweg über alternatives Kodieren (siehe Kasten “URL-Encoding”), wo »..%2f« eine äquivalente Darstellung von »../« ist, »..%bg%qf« entspricht der Unicode-Repräsentation. Kommt dann noch mit
<?
include('./'.urldecode($_REQUEST["filename"]));
?>
ein typischer Denkfehler des Programmierers dazu, findet sich ein weiterer schöner Angriffsweg durch doppeltes URL-Encoding wie in »filename=..%252F«. Das Zeichen »%25« entschlüsselt der Webserver schon vor dem Aufruf von PHP zu einem »%«. Damit hat »filename« wieder den Wert »..%2F«. Ein zusätzlicher Aufruf von »urldecode« übersetzt diese Zeichenkombination zu »../«.
Eine andere Möglichkeit, in einem solchen Fall gefährliche Inhalte an einfachen Filtern vorbeizuschleusen, wäre »%%32F«, wobei der Server das innere »%32« zunächst zur Ziffer 2 übersetzt. Somit entsteht das gewünschte »%2F«.
|
URL-Encoding |
|---|
|
RFC 1738 definiert, wie eine URL aussehen soll. Dabei beschränkt sie sich auf eine Untermenge von Zeichen des 7-Bit-US-Ascii-Zeichensatzes, eine URL darf dementsprechend nur aus »[a-zA-Z0-9]« und »$-_.+!*\’,()« bestehen. Andere Zeichen sind nicht zulässig. Sie können aber trotzdem in einer URL auftauchen, in einem »GET«-Parameter oder weil ein User ein Dokument mit einem Leerzeichen im Dateinamen auf dem Server abgelegt hat. Außerdem haben einige Zeichen eine besondere Bedeutung: »#« als Verweis auf einen Anchor, »?« als Einleitung der Parameter und »#« als Trenner verschiedener »GET«-Parameter. Zu diesen Zeichen gehören auch »$+,:;/@%=«. Sollte nun ein Parameter oder ein Dateiname ein solches Zeichen enthalten, muss es geeignet verschlüsselt sein. Dazu ersetzt man das Sonderzeichen durch seinen hexadezimalen Ascii-Code und stellt ein Prozentsymbol voran. Das Leerzeichen wird so zu »%20«. Übervorsorgliche Programmierer trauen unter Umständen ihrem verwendeten Framework nicht zu, dieses Encoding wieder rückgängig zu machen, und rufen selbst zum Beispiel »urldecode()« in PHP auf. Dadurch lassen sich Angriffe an Filtern vorbeischleusen, indem sie Zeichen doppelt encodieren. Ein Angreifer könnte so »%20« zum Beispiel durch »%2520« ersetzen. |
Besser geschützt
Beim Flughafen München lässt sich mit diesen Techniken allerdings nicht viel ausrichten: Entweder schlägt der vorgeschaltete Contentfilter zu und eine Fehlermeldung erscheint oder der Webserver berechnet die Seite bei doppeltem Encoding nicht vollständig, sondern bricht nach der Hälfte des Inhalts ab, nach der Titelleiste mit dem Flughafenlogo. Gefährlich jedoch ist, dass der Server solche URL-Tricks potenziell weiterreicht: Die Flugnummer »../ 1234« trennt das Skript am Leerzeichen und extrahiert »../« als Fluggesellschaft. Diese Information nimmt es in den Link unter dem Flugzeugtyp auf. Hier gräbt der Flughafen normalerweise aus seiner Bilderdatenbank ein korrekt beschriftetes Beispielflugzeug aus. Dazu ermittelt es wiederum den Dateinamen des Bildes aus dem Flugzeugtyp (A320-200) und der Fluggesellschaft (LH) nach einem festen Muster, zum Beispiel »A320_200_LH.jpeg«.
Durch die Längenbeschränkung auf drei Zeichen und weil das Skript, das die Informationsseite zum Flugzeug erzeugt, prüft, ob das Bild existiert, entsteht jedoch kein Schaden (Abbildung 4). Genauso taucht die verunglückte Flugnummer auch im Link unter dem Namen der Fluggesellschaft wieder auf und könnte da zu bösen Überraschungen führen. Auch hier scheint nur die Längenbeschränkung Schlimmeres zu verhindern.

Abbildung 4: In der URL stehen auch das Fluggerät und die Fluggesellschaft. Die Angaben setzt der Server später zu einem Link zusammen.
Umleitung
Gefährlicher ist die Möglichkeit, den Zurück-Link beliebig zu setzen. Am Ende der URL lässt sich zum Beispiel durch ein »&zurueck=https://www.linux-magazin.de« ohne Probleme auf Linux-Magazin Online verlinken. Die Statuszeile in Abbildung 2 zeigt, dass das Skript den »zurueck«-Link ohne größere Bedenken oder Plausibilitätstests direkt aus der URL übernimmt. Dabei stört sich der vorgeschaltete Contentfilter noch nicht mal an dem dreist eingefügten »http://«.
Im einfachsten Fall kann ein Angreifer dies dazu verwenden, einen Kunden auf eine Seite umzuleiten, die der des Münchner Flughafens täuschend ähnlich sieht. Dort kann er dem Nutzer Flugbuchungen anbieten oder ihm E-Mail-Adressen, Handy- und Kreditkartennummern entlocken. Vielleicht initiiert der Link aber auch einfach einen Drive-by-Download, der Schadprogamme wie Trojaner auf dem meist verwendeten Windows-PC installiert.
Da der komplette »Zurück zur Übersicht«-Link aus dem »GET«-Parameter »zurueck« kommt, funktioniert hier auch Javascript. So zeigt etwa »zurueck=javascript:alert (document.location.href)« die manipulierte URL an (Abbildung 5). Allerdings greift hier wiederum der Contentfilter-Proxy ein: Er entfernt Gänsefüßchen und Hochkommata, aber nicht die beliebten Unix-Back- und Forward-Ticks.

Abbildung 5: Auch Javascript ist möglich: Hier zeigt eingeschleuster Code die manipulierte URL der Flughafen-Webseite selbst an.
Vorbeigemogelt
Das bietet ein großes Betätigungsfeld für verspielte Angreifer: Lässt sich Javascript ausführen, dann ist es auch möglich, durch ein Skript Texte zu erzeugen. Vielleicht tarnt sogar simples URL-Encoding die benötigten Gänsefüßchen. Der einfachste Ansatz ist: »zurueck=javascript:alert(%26quot;Test%26quot;);«. Der Code »%26« ersetzt das Ampersand (»&«), denn es trennt in einer »GET«-URL die Parameter. Und tatsächlich, schon erscheint beliebiger Text in einem Popup (Abbildung 6). Da hilft auch ein besserer Filter nicht weiter: Mit Javascript lassen sich Zeichenketten erzeugen, etwa mit der Funktion »fromCharCode()« des Objekts »String«. Die Statuszeile und das Popup in Abbildung 7 zeigen eine mögliche Variante.

Abbildung 6: Mit HTML-Entities lässt sich auch der Sicherheitsfilter des Flughafens umgehen. Über Javascript zeigt die Webseite beliebige Texte an.

Abbildung 7: Mit Javascript und der »CharCode«-Funktion kann die Flughafen-Webseite beliebige Zeichenketten wie »Linux Magazin« erzeugen.
Der Fehler ist offensichtlich und simpel: Niemals darf ein Skript eine URL als Parameter übergeben. Passiert dies trotzdem, sind Angriffen Tür und Tor geöffnet. Selbst die Suche nach der Zeichenkette »javascript« schützt dabei nicht, denn auch die kann gut getarnt sein. Viele Browser lassen sich zum Beispiel durch einen eingefügten Tabulator in Javascript nicht irritieren. So blockiert zwar der Firefox den Befehl »zurueck=java%26%23x0A;script:alert(document.location.href);«, doch Microsofts Internet Explorer, KDEs Konqueror und Apples Safari führen ihn anstandslos aus.
Wie die URL verrät, ist die Flughafenseite mit Java Server Pages (JSP) geschrieben. Es liegt nahe, dass dabei für Ausgaben »printf()« zum Einsatz kommt. Aus Bequemlichkeit benutzen viele Programmierer »printf(variable);« statt des korrekten »printf(“%s”, variable);«.
Dabei ist »variable« vom Anwender gesetzt, im vorliegendem Fall über einen Get-Parameter. Der erste Parameter bei einem Format-String gibt vor, wie die Ausgabe auszusehen hat, und enthält damit auch Informationen über die Gesamtzahl der Parameter. Lässt sich in der URL bei einem beliebigen Parameter »%s« einschleusen, dann kann ein Angreifer Stack-Inhalte auslesen. Damit »%s« korrekt ankommt, muss es allerdings als »%25s« kodiert sein.
Auch die Webseite des Flughafens München kann zu fehlerhaftem Verhalten gebracht werden: Der Server bricht das Berechnen der Seite einfach ab. Wahrscheinlich sorgt ein Speicherfehler dafür, denn jede andere, extra aufgesetzte Sicherheitsmaßnahme außer der korrekten Verwendung von »printf(“%s”, variable)« scheint reichlich unsinnig.
Fazit
Das Beispiel des Münchner Flughafens zeigt, dass unsichere Programmierpraktiken trotz aufgesetzter Sicherheitstools Risiken darstellen. Besser ist es, von vornherein sicherheitskritische Programmierfehler zu vermeiden. Dazu ist es unabdingbar, Entwickler zu schulen und ihnen die notwendigen Hackertools zur Verfügung zu stellen. Doch deren Besitz ist in Deutschland strafbar. (mfe)
|
Infos |
|---|
|
[1] Cross Site Scripting: [http://www.cgisecurity.com/articles/xss-faq.shtml] [2] Dafydd Stuttard, Marcus Pinto, “The Web Application Hacker s Handbook: Discovering and Exploiting Security Flaws”: Wiley, 2007 |
|
Die Autoren |
|---|
|
Professor Dr. Jörg Keller lehrt und forscht an der Fernuniversität in Hagen unter anderem über IT-Sicherheit, parallele Algorithmen und Kryptographie. Dr. Tobias Eggendorfer ist freiberuflicher IT-Berater [http://www.eggendorfer.info], lehrt IT-Sicherheit an der Fernuniversität Hagen und forscht an der Universität der Bundeswehr. |





