Translated ['src/pentesting-web/hacking-with-cookies/README.md'] to sr

This commit is contained in:
Translator 2025-05-18 03:05:21 +00:00
parent 7b345c93e6
commit 4b2ace2b72
2 changed files with 173 additions and 151 deletions

View File

@ -1,4 +1,4 @@
# Hacking sa Kolačićima
# Hacking Kolačića
{{#include ../../banners/hacktricks-training.md}}
@ -8,26 +8,26 @@ Kolačići dolaze sa nekoliko atributa koji kontrolišu njihovo ponašanje u kor
### Expires i Max-Age
Datum isteka kolačića određuje atribut `Expires`. Nasuprot tome, atribut `Max-age` definiše vreme u sekundama do brisanja kolačića. **Izaberite `Max-age` jer odražava modernije prakse.**
Datum isteka kolačića određuje atribut `Expires`. Nasuprot tome, atribut `Max-age` definiše vreme u sekundama do brisanja kolačića. **Odaberite `Max-age` jer odražava savremenije prakse.**
### Domen
Domaćini koji primaju kolačić su određeni atributom `Domain`. Po defaultu, ovo je postavljeno na domaćina koji je izdao kolačić, ne uključujući njegove poddomene. Međutim, kada je atribut `Domain` eksplicitno postavljen, obuhvata i poddomene. Ovo čini specifikaciju atributa `Domain` manje restriktivnom opcijom, korisnom za scenarije gde je deljenje kolačića preko poddomena neophodno. Na primer, postavljanje `Domain=mozilla.org` čini kolačiće dostupnim na njegovim poddomenama kao što je `developer.mozilla.org`.
Domaćini koji primaju kolačić određeni su atributom `Domain`. Podrazumevano, ovo je postavljeno na domaćina koji je izdao kolačić, ne uključujući njegove poddomenke. Međutim, kada je atribut `Domain` eksplicitno postavljen, obuhvata i poddomenke. Ovo čini specifikaciju atributa `Domain` manje restriktivnom opcijom, korisnom za scenarije gde je deljenje kolačića preko poddomenki neophodno. Na primer, postavljanje `Domain=mozilla.org` čini kolačiće dostupnim na njegovim poddomenkama kao što je `developer.mozilla.org`.
### Putanja
Specifična URL putanja koja mora biti prisutna u traženom URL-u da bi se `Cookie` zaglavlje poslalo označena je atributom `Path`. Ovaj atribut smatra karakter `/` kao separator direktorijuma, omogućavajući podudaranja u poddirektorijumima.
Specifična URL putanja koja mora biti prisutna u zahtevu URL-a da bi se `Cookie` zaglavlje poslalo označena je atributom `Path`. Ovaj atribut smatra karakter `/` kao separator direktorijuma, omogućavajući podudaranja u poddirektorijumima.
### Pravila Redosleda
Kada dva kolačića imaju isto ime, onaj koji se bira za slanje zasniva se na:
- Kolačiću koji se podudara sa najdužom putanjom u traženom URL-u.
- Kolačiću koji se podudara sa najdužom putanjom u zahtevu URL-a.
- Najnovije postavljenom kolačiću ako su putanje identične.
### SameSite
- Atribut `SameSite` određuje da li se kolačići šalju na zahteve koji potiču sa trećih strana. Nudi tri podešavanja:
- Atribut `SameSite` određuje da li se kolačići šalju na zahteve koji potiču sa domena trećih strana. Nudi tri podešavanja:
- **Strict**: Ograničava kolačić da se ne šalje na zahteve trećih strana.
- **Lax**: Omogućava kolačiću da se šalje sa GET zahtevima koje pokreću veb sajtovi trećih strana.
- **None**: Dozvoljava kolačiću da se šalje sa bilo kog domena treće strane.
@ -35,34 +35,34 @@ Kada dva kolačića imaju isto ime, onaj koji se bira za slanje zasniva se na:
Zapamtite, dok konfigurišete kolačiće, razumevanje ovih atributa može pomoći da se osigura da se ponašaju kako se očekuje u različitim scenarijima.
| **Tip Zahteva** | **Primer Koda** | **Kolačići Se Šalju Kada** |
| ---------------- | ---------------------------------- | --------------------- |
| Link | \<a href="...">\</a> | NotSet\*, Lax, None |
| Prerender | \<link rel="prerender" href=".."/> | NotSet\*, Lax, None |
| Form GET | \<form method="GET" action="..."> | NotSet\*, Lax, None |
| Form POST | \<form method="POST" action="..."> | NotSet\*, None |
| iframe | \<iframe src="...">\</iframe> | NotSet\*, None |
| AJAX | $.get("...") | NotSet\*, None |
| Slika | \<img src="..."> | NetSet\*, None |
| ---------------- | ---------------------------------- | --------------------------- |
| Link | \<a href="...">\</a> | NotSet\*, Lax, None |
| Prerender | \<link rel="prerender" href=".."/> | NotSet\*, Lax, None |
| Form GET | \<form method="GET" action="..."> | NotSet\*, Lax, None |
| Form POST | \<form method="POST" action="..."> | NotSet\*, None |
| iframe | \<iframe src="...">\</iframe> | NotSet\*, None |
| AJAX | $.get("...") | NotSet\*, None |
| Slika | \<img src="..."> | NetSet\*, None |
Tabela iz [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) i malo izmenjena.\
Kolačić sa _**SameSite**_ atributom će **ublažiti CSRF napade** gde je potrebna prijavljena sesija.
**\*Napomena da od Chrome80 (feb/2019) podrazumevano ponašanje kolačića bez samesite** **atributa će biti lax** ([https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/](https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/)).\
Napomena da će privremeno, nakon primene ove promene, **kolačići bez SameSite** **politike** u Chrome-u biti **tretirani kao None** tokom **prvih 2 minuta, a zatim kao Lax za POST zahteve na vrhunskim stranicama.**
Napomena da će privremeno, nakon primene ove promene, **kolačići bez SameSite** **politike** u Chrome-u biti **tretirani kao None** tokom **prvih 2 minuta, a zatim kao Lax za POST zahtev na vrhunskom nivou između sajtova.**
## Zastavice Kolačića
### HttpOnly
Ovo sprečava **klijenta** da pristupi kolačiću (putem **Javascript-a**, na primer: `document.cookie`)
Ovo sprečava **klijenta** da pristupi kolačiću (putem **JavaScript-a**, na primer: `document.cookie`)
#### **Obilaženja**
- Ako stranica **šalje kolačiće kao odgovor** na zahteve (na primer na **PHPinfo** stranici), moguće je zloupotrebiti XSS da se pošalje zahtev ovoj stranici i **ukrade kolačiće** iz odgovora (proverite primer u [https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/)).
- Ako stranica **šalje kolačiće kao odgovor** na zahteve (na primer, na **PHPinfo** stranici), moguće je zloupotrebiti XSS da se pošalje zahtev na ovu stranicu i **ukrade kolačiće** iz odgovora (proverite primer u [https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/](https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/)).
- Ovo se može zaobići sa **TRACE** **HTTP** zahtevima jer će odgovor servera (ako je ova HTTP metoda dostupna) odražavati poslate kolačiće. Ova tehnika se naziva **Cross-Site Tracking**.
- Ova tehnika se izbegava od strane **modernih pretraživača ne dozvoljavajući slanje TRACE** zahteva iz JS-a. Međutim, neka obilaženja su pronađena u specifičnom softveru kao što je slanje `\r\nTRACE` umesto `TRACE` u IE6.0 SP2.
- Ova tehnika se izbegava od strane **modernih pretraživača koji ne dozvoljavaju slanje TRACE** zahteva iz JS-a. Međutim, neka obilaženja su pronađena u specifičnom softveru kao što je slanje `\r\nTRACE` umesto `TRACE` u IE6.0 SP2.
- Drugi način je iskorišćavanje zero/day ranjivosti pretraživača.
- Moguće je **prepisati HttpOnly kolačiće** izvođenjem napada Cookie Jar overflow:
- Moguće je **prepisati HttpOnly kolačiće** izvođenjem napada na Cookie Jar overflow:
{{#ref}}
cookie-jar-overflow.md
@ -89,7 +89,7 @@ Važno je napomenuti da kolačići sa prefiksom `__Host-` ne smeju biti poslati
### Prepisivanje kolačića
Dakle, jedna od zaštita kolačića sa prefiksom `__Host-` je sprečavanje da budu prepisani iz poddomena. Sprečavanje, na primer, [**Cookie Tossing napada**](cookie-tossing.md). U predavanju [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**rad**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) je predstavljeno da je bilo moguće postaviti kolačiće sa prefiksom \_\_HOST- iz poddomena, prevarom parsera, na primer, dodavanjem "=" na početak ili na kraj...:
Dakle, jedna od zaštita kolačića sa prefiksom `__Host-` je sprečavanje da budu prepisani iz poddomena. Sprečavanje, na primer, [**Cookie Tossing napada**](cookie-tossing.md). U predavanju [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**rad**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) predstavljeno je da je bilo moguće postaviti kolačiće sa prefiksom \_\_HOST- iz poddomena, varajući parser, na primer, dodavanjem "=" na početak ili na kraj...:
<figure><img src="../../images/image (6) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
@ -103,15 +103,15 @@ Ako prilagođeni kolačić sadrži osetljive podatke, proverite ga (posebno ako
### Dekodiranje i Manipulacija Kolačićima
Osjetljivi podaci ugrađeni u kolačiće uvek treba da budu pažljivo ispitani. Kolačići kodirani u Base64 ili sličnim formatima često se mogu dekodirati. Ova ranjivost omogućava napadačima da izmene sadržaj kolačića i da se predstavljaju kao drugi korisnici kodiranjem svojih izmenjenih podataka nazad u kolačić.
Osjetljivi podaci ugrađeni u kolačiće uvek treba da budu pažljivo ispitani. Kolačići kodirani u Base64 ili sličnim formatima često se mogu dekodirati. Ova ranjivost omogućava napadačima da izmene sadržaj kolačića i da se predstavljaju kao drugi korisnici tako što će ponovo kodirati svoje izmenjene podatke u kolačić.
### Otimanje Sesije
Ovaj napad uključuje krađu korisnikovog kolačića kako bi se dobio neovlašćen pristup njihovom nalogu unutar aplikacije. Korišćenjem ukradenog kolačića, napadač može da se predstavi kao legitimni korisnik.
Ovaj napad uključuje krađu korisničkog kolačića kako bi se dobio neovlašćen pristup njihovom nalogu unutar aplikacije. Korišćenjem ukradenog kolačića, napadač može da se predstavi kao legitimni korisnik.
### Fiksacija Sesije
U ovom scenariju, napadač prevari žrtvu da koristi određeni kolačić za prijavu. Ako aplikacija ne dodeljuje novi kolačić prilikom prijave, napadač, posedujući originalni kolačić, može se predstaviti kao žrtva. Ova tehnika se oslanja na to da žrtva prijavi sa kolačićem koji je obezbedio napadač.
U ovom scenariju, napadač prevari žrtvu da koristi određeni kolačić za prijavu. Ako aplikacija ne dodeli novi kolačić prilikom prijave, napadač, koji poseduje originalni kolačić, može se predstaviti kao žrtva. Ova tehnika se oslanja na to da se žrtva prijavi sa kolačićem koji je obezbedio napadač.
Ako ste pronašli **XSS u poddomeni** ili **kontrolišete poddomenu**, pročitajte:
@ -121,7 +121,7 @@ cookie-tossing.md
### Donacija Sesije
Ovde, napadač ubeđuje žrtvu da koristi napadačev kolačić sesije. Žrtva, verujući da je prijavljena na svoj nalog, nenamerno će izvršiti radnje u kontekstu napadačevog naloga.
Ovde, napadač uverava žrtvu da koristi napadačev kolačić sesije. Žrtva, verujući da je prijavljena na svoj nalog, nenamerno će izvršiti radnje u kontekstu napadačevog naloga.
Ako ste pronašli **XSS u poddomeni** ili **kontrolišete poddomenu**, pročitajte:
@ -131,13 +131,13 @@ cookie-tossing.md
### [JWT Kolačići](../hacking-jwt-json-web-tokens.md)
Kliknite na prethodni link da biste pristupili stranici koja objašnjava moguće slabosti u JWT.
Kliknite na prethodni link da biste pristupili stranici koja objašnjava moguće nedostatke u JWT-u.
JSON Web Tokens (JWT) korišćeni u kolačićima takođe mogu predstavljati ranjivosti. Za detaljne informacije o potencijalnim slabostima i kako ih iskoristiti, preporučuje se pristup povezanom dokumentu o hakovanju JWT.
JSON Web Tokens (JWT) korišćeni u kolačićima takođe mogu predstavljati ranjivosti. Za detaljne informacije o potencijalnim nedostacima i kako ih iskoristiti, preporučuje se pristup povezanom dokumentu o hakovanju JWT-a.
### Cross-Site Request Forgery (CSRF)
Ovaj napad prisiljava prijavljenog korisnika da izvrši neželjene radnje na veb aplikaciji u kojoj su trenutno autentifikovani. Napadači mogu iskoristiti kolačiće koji se automatski šalju sa svakim zahtevom na ranjivu stranicu.
Ovaj napad prisiljava prijavljenog korisnika da izvrši neželjene radnje na veb aplikaciji u kojoj su trenutno autentifikovani. Napadači mogu iskoristiti kolačiće koji se automatski šalju sa svakim zahtevom na ranjivi sajt.
### Prazni Kolačići
@ -147,7 +147,7 @@ document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"
```
Rezultat u poslatom cookie header-u je `a=v1; test value; b=v2;`. Zanimljivo je da ovo omogućava manipulaciju kolačićima ako je postavljen kolačić sa praznim imenom, potencijalno kontrolišući druge kolačiće postavljanjem praznog kolačića na specifičnu vrednost:
Rezultat u poslatom cookie header-u je `a=v1; test value; b=v2;`. Zanimljivo, ovo omogućava manipulaciju kolačićima ako je postavljen kolačić sa praznim imenom, potencijalno kontrolišući druge kolačiće postavljanjem praznog kolačića na specifičnu vrednost:
```js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
@ -157,29 +157,29 @@ setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value
```
To dovodi do toga da pregledač šalje zaglavlje kolačića koje svaki veb server interpretira kao kolačić nazvan `a` sa vrednošću `b`.
#### Chrome greška: Problem sa Unicode zamenskim kodnim tačkama
#### Chrome Bug: Unicode Surrogate Codepoint Issue
U Chrome-u, ako je Unicode zamenska kodna tačka deo postavljenog kolačića, `document.cookie` postaje oštećen, vraćajući prazan string kasnije:
U Chrome-u, ako je Unicode surrogate codepoint deo postavljenog kolačića, `document.cookie` postaje oštećen, vraćajući prazan string kasnije:
```js
document.cookie = "\ud800=meep"
```
Ovo rezultira time da `document.cookie` vraća prazan string, što ukazuje na trajnu korupciju.
Ovo rezultira time da `document.cookie` ispisuje prazan string, što ukazuje na trajnu korupciju.
#### Krađa kolačića zbog problema sa parsiranjem
#### Prevara sa kolačićima zbog problema sa parsiranjem
(Pogledajte dalje detalje u[originalnom istraživanju](https://blog.ankursundara.com/cookie-bugs/)) Nekoliko web servera, uključujući one iz Jave (Jetty, TomCat, Undertow) i Pythona (Zope, cherrypy, web.py, aiohttp, bottle, webob), pogrešno obrađuju stringove kolačića zbog zastarele podrške za RFC2965. Čitaju vrednost kolačića u dvostrukim navodnicima kao jednu vrednost čak i ako uključuje tačke-zareze, koje bi obično trebale da razdvajaju parove ključ-vrednost:
(Pogledajte dalje detalje u[originalnom istraživanju](https://blog.ankursundara.com/cookie-bugs/)) Nekoliko veb servera, uključujući one iz Jave (Jetty, TomCat, Undertow) i Pythona (Zope, cherrypy, web.py, aiohttp, bottle, webob), pogrešno obrađuju stringove kolačića zbog zastarele podrške za RFC2965. Oni čitaju vrednost kolačića u dvostrukim navodnicima kao jednu vrednost čak i ako uključuje tačke-zareze, koje bi obično trebale da razdvajaju parove ključ-vrednost:
```
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
```
#### Cookie Injection Vulnerabilities
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Neispravno parsiranje kolačića od strane servera, posebno Undertow, Zope, i onih koji koriste Pythonov `http.cookie.SimpleCookie` i `http.cookie.BaseCookie`, stvara prilike za napade putem injekcije kolačića. Ovi serveri ne uspevaju pravilno da odrede početak novih kolačića, omogućavajući napadačima da lažiraju kolačiće:
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) Neispravno parsiranje kolačića od strane servera, posebno Undertow, Zope, i onih koji koriste Pythonov `http.cookie.SimpleCookie` i `http.cookie.BaseCookie`, stvara prilike za napade putem injekcije kolačića. Ovi serveri ne uspevaju da pravilno odvoje početak novih kolačića, omogućavajući napadačima da lažiraju kolačiće:
- Undertow očekuje novi kolačić odmah nakon citirane vrednosti bez tačke-zareza.
- Zope traži zarez da započne parsiranje sledećeg kolačića.
- Pythonove klase kolačića započinju parsiranje na razmaku.
Ova ranjivost je posebno opasna u web aplikacijama koje se oslanjaju na CSRF zaštitu zasnovanu na kolačićima, jer omogućava napadačima da injektiraju lažirane CSRF-token kolačiće, potencijalno zaobilazeći bezbednosne mere. Problem se dodatno pogoršava načinom na koji Python obrađuje duple nazive kolačića, gde poslednja pojava preuzima prethodne. Takođe, postavlja zabrinutosti za `__Secure-` i `__Host-` kolačiće u nesigurnim kontekstima i može dovesti do zaobilaženja autorizacije kada se kolačići proslede back-end serverima koji su podložni lažiranju.
Ova ranjivost je posebno opasna u web aplikacijama koje se oslanjaju na CSRF zaštitu zasnovanu na kolačićima, jer omogućava napadačima da ubace lažirane CSRF-token kolačiće, potencijalno zaobilazeći bezbednosne mere. Problem se dodatno pogoršava načinom na koji Python obrađuje duple nazive kolačića, gde poslednja pojava preuzima prethodne. Takođe, postavlja zabrinutosti za `__Secure-` i `__Host-` kolačiće u nesigurnim kontekstima i može dovesti do zaobilaženja autorizacije kada se kolačići proslede back-end serverima koji su podložni lažiranju.
### Cookies $version
@ -192,7 +192,7 @@ Prema [**ovom blogu**](https://portswigger.net/research/bypassing-wafs-with-the-
Prema [**ovom blogu**](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique), moguće je koristiti tehniku kolačić sendviča za krađu HttpOnly kolačića. Ovo su zahtevi i koraci:
- Pronađite mesto gde se očigledno beskoristan **kolačić odražava u odgovoru**
- **Kreirajte kolačić pod nazivom `$Version`** sa vrednošću `1` (to možete uraditi u XSS napadu iz JS) sa specifičnijim putem kako bi dobio početnu poziciju (neki okviri poput Pythona ne zahtevaju ovaj korak)
- **Kreirajte kolačić nazvan `$Version`** sa vrednošću `1` (možete to uraditi u XSS napadu iz JS) sa specifičnijim putem kako bi dobio početnu poziciju (neki okviri poput Pythona ne zahtevaju ovaj korak)
- **Kreirajte kolačić koji se odražava** sa vrednošću koja ostavlja **otvorene dvostruke navodnike** i sa specifičnim putem kako bi bio pozicioniran u bazi kolačića nakon prethodnog (`$Version`)
- Tada će legitiman kolačić ići sledeći u redu
- **Kreirajte lažni kolačić koji zatvara dvostruke navodnike** unutar svoje vrednosti
@ -212,14 +212,14 @@ Proverite prethodnu sekciju.
#### Bypassing value analysis with quoted-string encoding
Ova analiza ukazuje na to da se neizbežene vrednosti unutar kolačića pretvaraju, tako da "\a" postaje "a". Ovo može biti korisno za zaobilaženje WAFS-a kao:
Ova analiza ukazuje na to da se neizbežene vrednosti unutar kolačića moraju osloboditi, tako da "\a" postaje "a". Ovo može biti korisno za zaobilaženje WAFS-a kao:
- `eval('test') => forbidden`
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
#### Bypassing cookie-name blocklists
U RFC2109 je naznačeno da se **zarez može koristiti kao razdvojnik između vrednosti kolačića**. Takođe, moguće je dodati **prostore i tabove pre i posle znaka jednakosti**. Stoga kolačić poput `$Version=1; foo=bar, abc = qux` ne generiše kolačić `"foo":"bar, admin = qux"` već kolačiće `foo":"bar"` i `"admin":"qux"`. Obratite pažnju na to kako su generisana 2 kolačića i kako je adminu uklonjen prostor pre i posle znaka jednakosti.
U RFC2109 je naznačeno da se **zarez može koristiti kao razdvojnik između vrednosti kolačića**. Takođe je moguće dodati **razmake i tabove pre i posle znaka jednakosti**. Stoga kolačić poput `$Version=1; foo=bar, abc = qux` ne generiše kolačić `"foo":"bar, admin = qux"` već kolačiće `foo":"bar"` i `"admin":"qux"`. Obratite pažnju na to kako su generisana 2 kolačića i kako je adminu uklonjen razmak pre i posle znaka jednakosti.
#### Bypassing value analysis with cookie splitting
@ -244,7 +244,7 @@ Resulting cookie: name=eval('test//, comment') => allowed
- **kolačić** je **isti** svaki put kada se **prijavite**.
- Odjavite se i pokušajte da koristite isti kolačić.
- Pokušajte da se prijavite sa 2 uređaja (ili pregledača) na isti nalog koristeći isti kolačić.
- Proverite da li kolačić sadrži bilo kakve informacije i pokušajte da ga izmenite.
- Proverite da li kolačić sadrži neku informaciju i pokušajte da je izmenite.
- Pokušajte da kreirate nekoliko naloga sa gotovo istim korisničkim imenom i proverite da li možete primetiti sličnosti.
- Proverite opciju "**zapamti me**" ako postoji da vidite kako funkcioniše. Ako postoji i može biti ranjiva, uvek koristite kolačić **zapamti me** bez bilo kog drugog kolačića.
- Proverite da li prethodni kolačić funkcioniše čak i nakon što promenite lozinku.
@ -254,7 +254,7 @@ Resulting cookie: name=eval('test//, comment') => allowed
Ako kolačić ostaje isti (ili gotovo isti) kada se prijavite, to verovatno znači da je kolačić povezan sa nekim poljem vašeg naloga (verovatno korisničkim imenom). Tada možete:
- Pokušajte da kreirate mnogo **naloga** sa korisničkim imenima vrlo **sličnim** i pokušajte da **pogodite** kako algoritam funkcioniše.
- Pokušajte da **bruteforce-ujete korisničko ime**. Ako se kolačić čuva samo kao metoda autentifikacije za vaše korisničko ime, tada možete kreirati nalog sa korisničkim imenom "**Bmin**" i **bruteforce-ovati** svaki pojedinačni **bit** vašeg kolačića jer će jedan od kolačića koje ćete pokušati biti onaj koji pripada "**admin**".
- Pokušajte da **bruteforce-ujete korisničko ime**. Ako kolačić služi samo kao metoda autentifikacije za vaše korisničko ime, onda možete kreirati nalog sa korisničkim imenom "**Bmin**" i **bruteforce**-ovati svaki pojedinačni **bit** vašeg kolačića jer će jedan od kolačića koje ćete pokušati biti onaj koji pripada "**admin**".
- Pokušajte **Padding** **Oracle** (možete dekriptovati sadržaj kolačića). Koristite **padbuster**.
**Padding Oracle - Padbuster primeri**
@ -267,11 +267,11 @@ padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies a
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2
```
Padbuster će napraviti nekoliko pokušaja i pitaće vas koja je greška (uslov koji nije validan).
Padbuster će napraviti nekoliko pokušaja i pitaće vas koja je uslov greške (onaj koji nije validan).
Zatim će početi da dekriptuje kolačić (može potrajati nekoliko minuta).
Ako je napad uspešno izveden, možete pokušati da enkriptujete string po vašem izboru. Na primer, ako želite da **enkriptujete** **user=administrator**
Ako je napad uspešno izveden, onda možete pokušati da enkriptujete string po vašem izboru. Na primer, ako želite da **encrypt** **user=administrator**
```
padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator
```
@ -296,11 +296,11 @@ Kada se prijavite, kolačić koji dobijate mora uvek biti isti.
Kreirajte 2 korisnika sa gotovo istim podacima (korisničko ime, lozinka, email, itd.) i pokušajte da otkrijete neki obrazac unutar datog kolačića.
Kreirajte korisnika nazvanog, na primer, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" i proverite da li postoji neki obrazac u kolačiću (pošto ECB enkriptuje sa istim ključem svaki blok, isti enkriptovani bajtovi mogu se pojaviti ako je korisničko ime enkriptovano).
Kreirajte korisnika pod imenom "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" i proverite da li postoji neki obrazac u kolačiću (pošto ECB enkriptuje sa istim ključem svaki blok, isti enkriptovani bajtovi mogu se pojaviti ako je korisničko ime enkriptovano).
Trebalo bi da postoji obrazac (sa veličinom korišćenog bloka). Tako, znajući kako je gomila "a" enkriptovana, možete kreirati korisničko ime: "a"\*(veličina bloka)+"admin". Tada biste mogli da obrišete enkriptovani obrazac jednog bloka "a" iz kolačića. I imaćete kolačić korisničkog imena "admin".
## References
## Reference
- [https://blog.ankursundara.com/cookie-bugs/](https://blog.ankursundara.com/cookie-bugs/)
- [https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd](https://www.linkedin.com/posts/rickey-martin-24533653_100daysofhacking-penetrationtester-ethicalhacking-activity-7016286424526180352-bwDd)

View File

@ -1,27 +1,28 @@
/**
* HackTricks AI Chat Widget v1.15 Markdown rendering + sanitised
* ------------------------------------------------------------------------
* Replaces the static placeholder with a three-dot **bouncing** loader
* Renders assistant replies as Markdown while purging any unsafe HTML
* (XSS-safe via DOMPurify)
* ------------------------------------------------------------------------
* HackTricks AI Chat Widget v1.16 resizable sidebar
* ---------------------------------------------------
* Markdown rendering + sanitised (same as before)
* NEW: dragtoresize panel, width persists via localStorage
*/
(function () {
const LOG = "[HackTricks-AI]";
/* ---------------- User-tunable constants ---------------- */
const MAX_CONTEXT = 3000; // highlighted-text char limit
const MAX_QUESTION = 500; // question char limit
const LOG = "[HackTricksAI]";
/* ---------------- Usertunable constants ---------------- */
const MAX_CONTEXT = 3000; // highlightedtext char limit
const MAX_QUESTION = 500; // question char limit
const MIN_W = 250; // ← resize limits →
const MAX_W = 600;
const DEF_W = 350; // default width (if nothing saved)
const TOOLTIP_TEXT =
"💡 Highlight any text on the page,\nthen click to ask HackTricks AI about it";
"💡 Highlight any text on the page,\nthen click to ask HackTricks AI about it";
const API_BASE = "https://www.hacktricks.ai/api/assistants/threads";
const BRAND_RED = "#b31328"; // HackTricks brand
const BRAND_RED = "#b31328";
/* ------------------------------ State ------------------------------ */
let threadId = null;
let isRunning = false;
/* ---------- helpers ---------- */
const $ = (sel, ctx = document) => ctx.querySelector(sel);
if (document.getElementById("ht-ai-btn")) {
console.warn(`${LOG} Widget already injected.`);
@ -31,44 +32,37 @@
? document.addEventListener("DOMContentLoaded", init)
: init());
/* ==================================================================== */
/* 🔗 1. 3rd-party libs → Markdown & sanitiser */
/* ==================================================================== */
/* =================================================================== */
/* 🔗 1. 3rdparty libs → Markdown & sanitiser */
/* =================================================================== */
function loadScript(src) {
return new Promise((resolve, reject) => {
return new Promise((res, rej) => {
const s = document.createElement("script");
s.src = src;
s.onload = resolve;
s.onerror = () => reject(new Error(`Failed to load ${src}`));
s.onload = res;
s.onerror = () => rej(new Error(`Failed to load ${src}`));
document.head.appendChild(s);
});
}
async function ensureDeps() {
const deps = [];
if (typeof marked === "undefined") {
if (typeof marked === "undefined")
deps.push(loadScript("https://cdn.jsdelivr.net/npm/marked/marked.min.js"));
}
if (typeof DOMPurify === "undefined") {
if (typeof DOMPurify === "undefined")
deps.push(
loadScript(
"https://cdnjs.cloudflare.com/ajax/libs/dompurify/3.2.5/purify.min.js"
)
);
}
if (deps.length) await Promise.all(deps);
}
const mdToSafeHTML = (md) =>
DOMPurify.sanitize(marked.parse(md, { mangle: false, headerIds: false }), {
USE_PROFILES: { html: true }
});
function mdToSafeHTML(md) {
// 1⃣ Markdown → raw HTML
const raw = marked.parse(md, { mangle: false, headerIds: false });
// 2⃣ Purify
return DOMPurify.sanitize(raw, { USE_PROFILES: { html: true } });
}
/* ==================================================================== */
/* =================================================================== */
async function init() {
/* ----- make sure marked & DOMPurify are ready before anything else */
try {
await ensureDeps();
} catch (e) {
@ -76,14 +70,14 @@
return;
}
console.log(`${LOG} Injecting widget… v1.15`);
console.log(`${LOG} Injecting widget… v1.16`);
await ensureThreadId();
injectStyles();
const btn = createFloatingButton();
createTooltip(btn);
const panel = createSidebar();
const panel = createSidebar(); // ← panel with resizer
const chatLog = $("#ht-ai-chat");
const sendBtn = $("#ht-ai-send");
const inputBox = $("#ht-ai-question");
@ -100,15 +94,8 @@
function addMsg(text, cls) {
const b = document.createElement("div");
b.className = `ht-msg ${cls}`;
// ✨ assistant replies rendered as Markdown + sanitised
if (cls === "ht-ai") {
b.innerHTML = mdToSafeHTML(text);
} else {
// user / context bubbles stay plain-text
b.textContent = text;
}
b[cls === "ht-ai" ? "innerHTML" : "textContent"] =
cls === "ht-ai" ? mdToSafeHTML(text) : text;
chatLog.appendChild(b);
chatLog.scrollTop = chatLog.scrollHeight;
return b;
@ -116,30 +103,28 @@
const LOADER_HTML =
'<span class="ht-loading"><span></span><span></span><span></span></span>';
function setInputDisabled(d) {
const setInputDisabled = (d) => {
inputBox.disabled = d;
sendBtn.disabled = d;
}
function clearThreadCookie() {
};
const clearThreadCookie = () => {
document.cookie = "threadId=; Path=/; Max-Age=0";
threadId = null;
}
function resetConversation() {
threadId = null;
};
const resetConversation = () => {
chatLog.innerHTML = "";
clearThreadCookie();
panel.classList.remove("open");
}
};
/* ------------------- Panel open / close ------------------- */
btn.addEventListener("click", () => {
if (!savedSelection) {
alert("Please highlight some text first to then ask HackTricks AI about it.");
alert("Please highlight some text first.");
return;
}
if (savedSelection.length > MAX_CONTEXT) {
alert(
`Highlighted text is too long (${savedSelection.length} chars). Max allowed: ${MAX_CONTEXT}.`
);
alert(`Highlighted text is too long. Max ${MAX_CONTEXT} chars.`);
return;
}
chatLog.innerHTML = "";
@ -157,11 +142,10 @@
addMsg("Please wait until the current operation completes.", "ht-ai");
return;
}
isRunning = true;
setInputDisabled(true);
const loadingBubble = addMsg("", "ht-ai");
loadingBubble.innerHTML = LOADER_HTML;
const loading = addMsg("", "ht-ai");
loading.innerHTML = LOADER_HTML;
const content = context
? `### Context:\n${context}\n\n### Question to answer:\n${question}`
@ -178,43 +162,39 @@
try {
const e = await res.json();
if (e.error) err = `Error: ${e.error}`;
else if (res.status === 429)
err = "Rate limit exceeded. Please try again later.";
else if (res.status === 429) err = "Rate limit exceeded.";
} catch (_) {}
loadingBubble.textContent = err;
loading.textContent = err;
return;
}
const data = await res.json();
loadingBubble.remove();
loading.remove();
if (Array.isArray(data.response))
data.response.forEach((p) => {
data.response.forEach((p) =>
addMsg(
p.type === "text" && p.text && p.text.value
? p.text.value
: JSON.stringify(p),
"ht-ai"
);
});
)
);
else if (typeof data.response === "string")
addMsg(data.response, "ht-ai");
else addMsg(JSON.stringify(data, null, 2), "ht-ai");
} catch (e) {
console.error("Error sending message:", e);
loadingBubble.textContent = "An unexpected error occurred.";
loading.textContent = "An unexpected error occurred.";
} finally {
isRunning = false;
setInputDisabled(false);
chatLog.scrollTop = chatLog.scrollHeight;
}
}
async function handleSend() {
const q = inputBox.value.trim();
if (!q) return;
if (q.length > MAX_QUESTION) {
alert(
`Your question is too long (${q.length} chars). Max allowed: ${MAX_QUESTION}.`
);
alert(`Question too long (${q.length}). Max ${MAX_QUESTION}.`);
return;
}
inputBox.value = "";
@ -228,9 +208,9 @@
handleSend();
}
});
}
} /* end init */
/* ==================================================================== */
/* =================================================================== */
async function ensureThreadId() {
const m = document.cookie.match(/threadId=([^;]+)/);
if (m && m[1]) {
@ -241,62 +221,67 @@
const r = await fetch(API_BASE, { method: "POST", credentials: "include" });
const d = await r.json();
if (!r.ok || !d.threadId) throw new Error(`${r.status} ${r.statusText}`);
threadId = d.threadId;
threadId = d.threadId;
document.cookie =
`threadId=${threadId}; Path=/; Secure; SameSite=Strict; Max-Age=7200`;
} catch (e) {
console.error("Error creating threadId:", e);
alert("Failed to initialise the conversation. Please refresh and try again.");
alert("Failed to initialise the conversation. Please refresh.");
throw e;
}
}
/* ==================================================================== */
/* =================================================================== */
function injectStyles() {
const css = `
#ht-ai-btn{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);width:60px;height:60px;border-radius:50%;background:#1e1e1e;color:#fff;font-size:28px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:99999;box-shadow:0 2px 8px rgba(0,0,0,.4);transition:opacity .2s}
#ht-ai-btn:hover{opacity:.85}
@media(max-width:768px){#ht-ai-btn{display:none}}
#ht-ai-tooltip{position:fixed;padding:6px 8px;background:#111;color:#fff;border-radius:4px;font-size:13px;white-space:pre-wrap;pointer-events:none;opacity:0;transform:translate(-50%,-8px);transition:opacity .15s ease,transform .15s ease;z-index:100000}
#ht-ai-tooltip.show{opacity:1;transform:translate(-50%,-12px)}
#ht-ai-panel{position:fixed;top:0;right:0;height:100%;width:350px;max-width:90vw;background:#000;color:#fff;display:flex;flex-direction:column;transform:translateX(100%);transition:transform .3s ease;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial,sans-serif}
#ht-ai-panel.open{transform:translateX(0)}
@media(max-width:768px){#ht-ai-panel{display:none}}
#ht-ai-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #333}
#ht-ai-header .ht-actions{display:flex;gap:8px;align-items:center}
#ht-ai-close,#ht-ai-reset{cursor:pointer;font-size:18px;background:none;border:none;color:#fff;padding:0}
#ht-ai-close:hover,#ht-ai-reset:hover{opacity:.7}
#ht-ai-chat{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;font-size:14px}
.ht-msg{max-width:90%;line-height:1.4;padding:10px 12px;border-radius:8px;white-space:pre-wrap;word-wrap:break-word}
.ht-user{align-self:flex-end;background:${BRAND_RED}}
.ht-ai{align-self:flex-start;background:#222}
.ht-context{align-self:flex-start;background:#444;font-style:italic;font-size:13px}
#ht-ai-input{display:flex;gap:8px;padding:12px 16px;border-top:1px solid #333}
#ht-ai-question{flex:1;min-height:40px;max-height:120px;resize:vertical;padding:8px;border-radius:6px;border:none;font-size:14px}
#ht-ai-send{padding:0 18px;border:none;border-radius:6px;background:${BRAND_RED};color:#fff;font-size:14px;cursor:pointer}
#ht-ai-send:disabled{opacity:.5;cursor:not-allowed}
/* Loader animation */
.ht-loading{display:inline-flex;align-items:center;gap:4px}
.ht-loading span{width:6px;height:6px;border-radius:50%;background:#888;animation:ht-bounce 1.2s infinite ease-in-out}
.ht-loading span:nth-child(2){animation-delay:0.2s}
.ht-loading span:nth-child(3){animation-delay:0.4s}
@keyframes ht-bounce{0%,80%,100%{transform:scale(0);}40%{transform:scale(1);} }
::selection{background:#ffeb3b;color:#000}
::-moz-selection{background:#ffeb3b;color:#000}`;
#ht-ai-btn{position:fixed;bottom:20px;left:50%;transform:translateX(-50%);min-width:60px;height:60px;border-radius:30px;background:linear-gradient(45deg, #b31328, #d42d3f, #2d5db4, #3470e4);background-size:300% 300%;animation:gradientShift 8s ease infinite;color:#fff;font-size:18px;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:99999;box-shadow:0 2px 8px rgba(0,0,0,.4);transition:opacity .2s;padding:0 20px}
#ht-ai-btn span{margin-left:8px;font-weight:bold}
@keyframes gradientShift{0%{background-position:0% 50%}50%{background-position:100% 50%}100%{background-position:0% 50%}}
#ht-ai-btn:hover{opacity:.85}
@media(max-width:768px){#ht-ai-btn{display:none}}
#ht-ai-tooltip{position:fixed;padding:6px 8px;background:#111;color:#fff;border-radius:4px;font-size:13px;white-space:pre-wrap;pointer-events:none;opacity:0;transform:translate(-50%,-8px);transition:opacity .15s ease,transform .15s ease;z-index:100000}
#ht-ai-tooltip.show{opacity:1;transform:translate(-50%,-12px)}
#ht-ai-panel{position:fixed;top:0;right:0;height:100%;max-width:90vw;background:#000;color:#fff;display:flex;flex-direction:column;transform:translateX(100%);transition:transform .3s ease;z-index:100000;font-family:system-ui,-apple-system,Segoe UI,Roboto,"Helvetica Neue",Arial,sans-serif}
#ht-ai-panel.open{transform:translateX(0)}
@media(max-width:768px){#ht-ai-panel{display:none}}
#ht-ai-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #333}
#ht-ai-header .ht-actions{display:flex;gap:8px;align-items:center}
#ht-ai-close,#ht-ai-reset{cursor:pointer;font-size:18px;background:none;border:none;color:#fff;padding:0}
#ht-ai-close:hover,#ht-ai-reset:hover{opacity:.7}
#ht-ai-chat{flex:1;overflow-y:auto;padding:16px;display:flex;flex-direction:column;gap:12px;font-size:14px}
.ht-msg{max-width:90%;line-height:1.4;padding:10px 12px;border-radius:8px;white-space:pre-wrap;word-wrap:break-word}
.ht-user{align-self:flex-end;background:${BRAND_RED}}
.ht-ai{align-self:flex-start;background:#222}
.ht-context{align-self:flex-start;background:#444;font-style:italic;font-size:13px}
#ht-ai-input{display:flex;gap:8px;padding:12px 16px;border-top:1px solid #333}
#ht-ai-question{flex:1;min-height:40px;max-height:120px;resize:vertical;padding:8px;border-radius:6px;border:none;font-size:14px}
#ht-ai-send{padding:0 18px;border:none;border-radius:6px;background:${BRAND_RED};color:#fff;font-size:14px;cursor:pointer}
#ht-ai-send:disabled{opacity:.5;cursor:not-allowed}
/* Loader */
.ht-loading{display:inline-flex;align-items:center;gap:4px}
.ht-loading span{width:6px;height:6px;border-radius:50%;background:#888;animation:ht-bounce 1.2s infinite ease-in-out}
.ht-loading span:nth-child(2){animation-delay:0.2s}
.ht-loading span:nth-child(3){animation-delay:0.4s}
@keyframes ht-bounce{0%,80%,100%{transform:scale(0);}40%{transform:scale(1);} }
::selection{background:#ffeb3b;color:#000}
::-moz-selection{background:#ffeb3b;color:#000}
/* NEW: resizer handle */
#ht-ai-resizer{position:absolute;left:0;top:0;width:6px;height:100%;cursor:ew-resize;background:transparent}
#ht-ai-resizer:hover{background:rgba(255,255,255,.05)}`;
const s = document.createElement("style");
s.id = "ht-ai-style";
s.textContent = css;
document.head.appendChild(s);
}
/* =================================================================== */
function createFloatingButton() {
const d = document.createElement("div");
d.id = "ht-ai-btn";
d.textContent = "🤖";
d.innerHTML = "🤖<span>HackTricksAI</span>";
document.body.appendChild(d);
return d;
}
function createTooltip(btn) {
const t = document.createElement("div");
t.id = "ht-ai-tooltip";
@ -311,11 +296,16 @@
btn.addEventListener("mouseleave", () => t.classList.remove("show"));
}
/* =================================================================== */
function createSidebar() {
const saved = parseInt(localStorage.getItem("htAiWidth") || DEF_W, 10);
const width = Math.min(Math.max(saved, MIN_W), MAX_W);
const p = document.createElement("div");
p.id = "ht-ai-panel";
p.style.width = width + "px"; // ← applied width
p.innerHTML = `
<div id="ht-ai-header"><strong>HackTricks AI Chat</strong>
<div id="ht-ai-header"><strong>HackTricks AI Chat</strong>
<div class="ht-actions">
<button id="ht-ai-reset" title="Reset"></button>
<span id="ht-ai-close" title="Close"></span>
@ -326,7 +316,39 @@
<textarea id="ht-ai-question" placeholder="Type your question…"></textarea>
<button id="ht-ai-send">Send</button>
</div>`;
/* NEW: resizer strip */
const resizer = document.createElement("div");
resizer.id = "ht-ai-resizer";
p.appendChild(resizer);
document.body.appendChild(p);
addResizeLogic(resizer, p);
return p;
}
/* ---------------- resize behaviour ---------------- */
function addResizeLogic(handle, panel) {
let startX, startW, dragging = false;
const onMove = (e) => {
if (!dragging) return;
const dx = startX - e.clientX; // dragging leftwards ⇒ +dx
let newW = startW + dx;
newW = Math.min(Math.max(newW, MIN_W), MAX_W);
panel.style.width = newW + "px";
};
const onUp = () => {
if (!dragging) return;
dragging = false;
localStorage.setItem("htAiWidth", parseInt(panel.style.width, 10));
document.removeEventListener("mousemove", onMove);
document.removeEventListener("mouseup", onUp);
};
handle.addEventListener("mousedown", (e) => {
dragging = true;
startX = e.clientX;
startW = parseInt(window.getComputedStyle(panel).width, 10);
document.addEventListener("mousemove", onMove);
document.addEventListener("mouseup", onUp);
});
}
})();