HTML5 Security - postMessage() sicher nutzen
Wie bereits erwähnt lehnt sich diese kleine Serie zur Sicherheit von
HTML5 an meinen
Vortrag
auf der WebTech Conference 2012 an. Womit auch schon das aktuelle Thema
vorgegeben ist: Die mit HTML5 eingeführte Methode
postMessage()
.
postMessage()
Die Methode
postMessage()
dient dem Austausch von Daten zwischen Skripten aus verschiedenen Origins.
postMessage()
wird mit den zu übertragenden Daten und der
Origin des Ziels aufgerufen und überträgt die Daten zwischen den
betroffenen Fenstern beziehungsweise Frames, sofern die Origin des Ziels
mit der angegebenen Origin übereinstimmt:
zielfenster.postMessage("Nachricht", "Ziel-Origin");
Das ist zum Beispiel sehr nützlich, wenn eine Seite mit eingebundenen
Widgets kommunizieren soll oder muss. Bisher hatten Sie beim Einbinden von
Widgets nur die Wahl zwischen zwei Möglichkeiten mit mehr oder weniger
großen Nachteilen: Entweder Sie sperrten das Widget in einen iframe
und konnten von Ihrer eigenen Seite aus nur schwer damit interagieren, oder
Sie luden es über ein script
-Tag ins DOM Ihrer Seite und
öffneten damit möglicherweise enthaltenem Schadcode Tür und
Tor.
postMessage()
kombiniert diese beiden Möglichkeiten: Sie
haben die Sicherheit des iframes (ggf. ergänzt durch den
zusätzlichen Schutz durch das sandbox
-Attribut von
HTML5), verbunden mit den Kommunikationsmöglichkeiten der direkten
DOM-Einbindung.
Passen Sie auf, mit wem Sie reden!
Wie üblich, müssen Sie auch beim Einsatz von
postMessage()
auf die Sicherheit achten (sonst würde ich
die Methode hier gar nicht erwähnen). Und zwar müssen Sie darauf
achten, mit wem Sie kommunizieren.
Der Browser liefert die Daten nur aus, wenn die Origin des Ziels mit der
angegebenen Origin übereinstimmt, es kann also nicht zu einem
unerwünschten Datenleck kommen. Jedenfalls nicht, wenn Sie die Origin
genau angeben. Die Kommunikation funktioniert auch, wenn Sie den Wildcard
'*'
als Zielorigin eingeben. Aber dann liefert der Browser
die Nachricht an den Code im angegebenen zielfenster
aus, egal
von welcher Origin der darin laufende Code geladen wurde.
Ob die empfangenen Daten von der erwarteten Origin stammen und nicht zum
Beispiel von einem bösartigen Skript von einer anderen Origin gesendet
werden, müssen Sie selbst überprüfen. Dazu können Sie
das vom Browser gesetzte origin
-Attribut verwenden.
Ausnahmsweise dürfen Sie dieser Information vertrauen, da das Attribut
vom Browser gesetzt wird und vom JavaScript-Code nicht manipuliert werden
kann (wie üblich mit der Einschränkung, dass es keine
entsprechende Schwachstelle im Browser gibt).
Die Prüfung könnte zum Beispiel so aussehen:
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
if (event.origin == "http://erwartete-origin.example") {
// alles OK
} else {
// Nachricht von falscher Origin
}
}
Vorsicht vor XSS!
Ein Problem lässt sich mit der Prüfung des
origin
-Attributs und der genauen Angabe der Ziel-Origin im
postMessage()
-Aufruf nicht lösen: Wurde in eine der
beteiligten Seiten über XSS Schadcode eingefügt, kann der von der
jeweils anderen Seite nicht erkannt werden.
Nehmen wir als Beispiel eine Website A, die ein Widget W
von einer anderen Website in einen iframe einbindet und über
postMessage()
-Aufrufe mit ihm kommuniziert. Dann gibt es vier
Möglichkeiten:
- Weder A noch W enthalten XSS-Schwachstellen, alles funktioniert so, wie es soll.
- Sowohl A als auch W enthalten XSS-Schwachstellen, und in beide Seiten wurde JavaScript-Schadcode eingeschleust. Das ist im Grunde der Worst Case. Natürlich müssen sämtliche XSS-Schwachstellen korrigiert werden. Aber der Gedanke, dass da zwei Cyberkriminelle sich gegenseitig falsche Daten unter schieben ist doch etwas erheiternd. Jedenfalls solange dabei nicht zum Beispiel im Rahmen einer Drive-by-Infektion Schadcode auf dem Rechner des Benutzers installiert oder anderweitig Schaden angerichtet wird.
- Die Website A enthält eine XSS Schwachstelle. Der darüber eingeschleuste Schadcode kann dann das Vertrauen des Widgets in die Website ausnutzen und Daten ausspähen oder einschleusen.
- Das Widget W enthält eine XSS Schwachstelle. Der darüber eingeschleuste Schadcode kann dann das Vertrauen der Website in das Widget ausnutzen und Daten ausspähen oder einschleusen.
Eine theoretische Lösung des Problems wäre das Signieren der Daten. Das müsste dann aber auf dem Server erfolgen, da beim Signieren durch den JavaScript-Code auf dem Client der dafür benötigte Schlüssel vom eingeschleusten Schadcode ausgespäht bzw. die Signatur-Funktion von ihm missbraucht werden könnte.
Da man aber sowieso keine XSS-Schwachstellen auf seinen Seiten haben möchte, kann man auf diesen Ansatz i.A. verzichten.
Weihnachtspause!
Sofern nichts außergewöhnliches mehr passiert, ist dies der letzte Grundlagen-Artikel für dieses Jahr. Im nächsten Jahr geht es dann mit Angriffen auf bzw. über HTML5 weiter.
Ich wünsche Ihnen ein frohes Fest, einen guten Rutsch ins neue Jahr und ein erfolgreiches 2013!
Übersicht über alle Artikel zum Thema
- HTML5 Security - Eine Einführung
- HTML5 Security - SVG und Resident XSS
- HTML5 Security - Formulare auf Abwegen
- HTML5 Security - Gift für den Application Cache
- HTML5 Security - Der Local Storage
- HTML5 Security - Die SQL-Datenbank
- HTML5 Security - Cross Origin Requests
- HTML5 Security - Gefährliche WebSockets
- HTML5 Security - postMessage() sicher nutzen
Trackbacks