NodeJS - __proto__ & prototype Pollution
Objetos em JavaScript
Objetos em JavaScript são essencialmente coleções de pares chave-valor, conhecidos como propriedades. Um objeto pode ser criado usando Object.create
com null
como argumento para produzir um objeto vazio. Este método permite a criação de um objeto sem nenhuma propriedade herdada.
Um objeto vazio é semelhante a um dicionário vazio, representado como {}
.
Funções e Classes em JavaScript
Em JavaScript, classes e funções estão intimamente ligadas, com funções frequentemente servindo como construtores para classes. Apesar da falta de suporte nativo a classes no JavaScript, construtores podem emular o comportamento de classes.
Prototypes em JavaScript
JavaScript permite a modificação, adição ou exclusão de atributos de protótipo em tempo de execução. Essa flexibilidade possibilita a extensão dinâmica das funcionalidades de classes.
Funções como toString
e valueOf
podem ser alteradas para mudar seu comportamento, demonstrando a natureza adaptável do sistema de protótipos do JavaScript.
Herança
Na programação baseada em protótipos, propriedades/métodos são herdados por objetos de classes. Essas classes são criadas adicionando propriedades/métodos a uma instância de outra classe ou a um objeto vazio.
Deve-se notar que, quando uma propriedade é adicionada a um objeto que serve como protótipo para outros objetos (como myPersonObj
), os objetos que herdam ganham acesso a essa nova propriedade. No entanto, essa propriedade não é exibida automaticamente, a menos que seja invocada explicitamente.
__proto__ pollution
Explorando a Poluição de Protótipos em JavaScript
Objetos JavaScript são definidos por pares de chave-valor e herdam do protótipo do Objeto JavaScript. Isso significa que alterar o protótipo do Objeto pode influenciar todos os objetos no ambiente.
Vamos usar um exemplo diferente para ilustrar:
O acesso ao protótipo do Object é possível através de:
Ao adicionar propriedades ao protótipo do Object, todo objeto JavaScript herdará essas novas propriedades:
poluição de protótipo
Para um cenário onde o uso de __proto__
é restrito, modificar o protótipo de uma função é uma alternativa:
Isso afeta apenas objetos criados a partir do construtor Vehicle
, dando a eles as propriedades beep
, hasWheels
, honk
e isElectric
.
Duas maneiras de afetar globalmente objetos JavaScript através da poluição de protótipos incluem:
Poluir o
Object.prototype
diretamente:
Poluindo o protótipo de um construtor para uma estrutura comumente usada:
Após essas operações, cada objeto JavaScript pode executar os métodos goodbye
e greet
.
Poluindo outros objetos
De uma classe para Object.prototype
Em um cenário onde você pode poluir um objeto específico e precisa chegar ao Object.prototype
, você pode procurá-lo com algo como o seguinte código:
Poluição de elementos de array
Note que, assim como você pode poluir atributos de objetos em JS, se você tiver acesso para poluir um array, você também pode poluir valores do array acessíveis por índices (note que você não pode sobrescrever valores, então você precisa poluir índices que são de alguma forma utilizados, mas não escritos).
Poluição de elementos Html
Ao gerar um elemento HTML via JS, é possível sobrescrever o atributo innerHTML
para fazer com que ele escreva código HTML arbitrário. Ideia e exemplo deste artigo.
Exemplos
Exemplo Básico
Uma poluição de protótipo ocorre devido a uma falha na aplicação que permite sobrescrever propriedades em Object.prototype
. Isso significa que, uma vez que a maioria dos objetos deriva suas propriedades de Object.prototype
O exemplo mais simples é adicionar um valor a um atributo indefinido de um objeto que será verificado, como:
Se o atributo admin
está indefinido, é possível abusar de um PP e defini-lo como True com algo como:
O mecanismo por trás disso envolve manipular propriedades de forma que, se um atacante tiver controle sobre certas entradas, ele pode modificar o protótipo de todos os objetos na aplicação. Essa manipulação geralmente envolve definir a propriedade __proto__
, que, em JavaScript, é sinônimo de modificar diretamente o protótipo de um objeto.
As condições sob as quais esse ataque pode ser executado com sucesso, conforme descrito em um estudo específico, incluem:
Realizar uma mesclagem recursiva.
Definir propriedades com base em um caminho.
Clonar objetos.
Função de substituição
Poluição de Proto para RCE
Prototype Pollution to RCEOutros payloads:
Poluição de protótipo do lado do cliente para XSS
Client Side Prototype PollutionCVE-2019–11358: Ataque de poluição de protótipo através do jQuery $ .extend
Para mais detalhes, consulte este artigo No jQuery, a função $ .extend
pode levar à poluição de protótipo se o recurso de cópia profunda for utilizado de forma inadequada. Esta função é comumente usada para clonar objetos ou mesclar propriedades de um objeto padrão. No entanto, quando mal configurada, propriedades destinadas a um novo objeto podem ser atribuídas ao protótipo em vez disso. Por exemplo:
Esta vulnerabilidade, identificada como CVE-2019–11358, ilustra como uma cópia profunda pode inadvertidamente modificar o protótipo, levando a potenciais riscos de segurança, como acesso não autorizado de administrador se propriedades como isAdmin
forem verificadas sem a devida verificação de existência.
CVE-2018–3721, CVE-2019–10744: Ataque de poluição de protótipo através do lodash
Para mais detalhes, consulte este artigo
Lodash encontrou vulnerabilidades semelhantes de poluição de protótipo (CVE-2018–3721, CVE-2019–10744). Esses problemas foram resolvidos na versão 4.17.11.
Outro tutorial com CVEs
Ferramentas para detectar Poluição de Protótipo
Server-Side-Prototype-Pollution-Gadgets-Scanner: Extensão do Burp Suite projetada para detectar e analisar vulnerabilidades de poluição de protótipo do lado do servidor em aplicações web. Esta ferramenta automatiza o processo de escaneamento de requisições para identificar potenciais problemas de poluição de protótipo. Ela explora gadgets conhecidos - métodos de aproveitar a poluição de protótipo para executar ações prejudiciais - focando particularmente em bibliotecas Node.js.
server-side-prototype-pollution: Esta extensão identifica vulnerabilidades de poluição de protótipo do lado do servidor. Ela utiliza técnicas descritas na poluição de protótipo do lado do servidor.
Poluição de Protótipo AST no NodeJS
NodeJS utiliza extensivamente Árvores de Sintaxe Abstrata (AST) em JavaScript para funcionalidades como motores de template e TypeScript. Esta seção explora as vulnerabilidades relacionadas à poluição de protótipo em motores de template, especificamente Handlebars e Pug.
Análise de Vulnerabilidade do Handlebars
O motor de template Handlebars é suscetível a um ataque de poluição de protótipo. Esta vulnerabilidade surge de funções específicas dentro do arquivo javascript-compiler.js
. A função appendContent
, por exemplo, concatena pendingContent
se estiver presente, enquanto a função pushSource
redefine pendingContent
para undefined
após adicionar a fonte.
Processo de Exploração
A exploração aproveita o AST (Árvore de Sintaxe Abstrata) produzido pelo Handlebars, seguindo estas etapas:
Manipulação do Parser: Inicialmente, o parser, através do nó
NumberLiteral
, impõe que os valores sejam numéricos. A poluição de protótipo pode contornar isso, permitindo a inserção de strings não numéricas.Tratamento pelo Compilador: O compilador pode processar um Objeto AST ou um template de string. Se
input.type
for igual aProgram
, a entrada é tratada como pré-analisada, o que pode ser explorado.Injeção de Código: Através da manipulação de
Object.prototype
, pode-se injetar código arbitrário na função de template, o que pode levar à execução remota de código.
Um exemplo demonstrando a exploração da vulnerabilidade do Handlebars:
Este código demonstra como um atacante poderia injetar código arbitrário em um template Handlebars.
Referência Externa: Um problema relacionado à poluição de protótipos foi encontrado na biblioteca 'flat', conforme detalhado aqui: Problema no GitHub.
Referência Externa: Problema relacionado à poluição de protótipos na biblioteca 'flat'
Exemplo de exploração de poluição de protótipos em Python:
Vulnerabilidade do Pug
Pug, outro mecanismo de template, enfrenta um risco semelhante de poluição de protótipo. Informações detalhadas estão disponíveis na discussão sobre Injeção de AST no Pug.
Exemplo de poluição de protótipo no Pug:
Medidas Preventivas
Para reduzir o risco de poluição de protótipos, as estratégias listadas abaixo podem ser empregadas:
Imutabilidade de Objetos: O
Object.prototype
pode ser tornado imutável aplicandoObject.freeze
.Validação de Entrada: As entradas JSON devem ser rigorosamente validadas em relação ao esquema da aplicação.
Funções de Mesclagem Seguras: O uso inseguro de funções de mesclagem recursivas deve ser evitado.
Objetos Sem Protótipo: Objetos sem propriedades de protótipo podem ser criados usando
Object.create(null)
.Uso de Map: Em vez de
Object
,Map
deve ser usado para armazenar pares chave-valor.Atualizações de Biblioteca: Correções de segurança podem ser incorporadas atualizando bibliotecas regularmente.
Ferramentas de Linter e Análise Estática: Use ferramentas como ESLint com plugins apropriados para detectar e prevenir vulnerabilidades de poluição de protótipos.
Revisões de Código: Implemente revisões de código minuciosas para identificar e remediar riscos potenciais relacionados à poluição de protótipos.
Treinamento em Segurança: Eduque os desenvolvedores sobre os riscos da poluição de protótipos e as melhores práticas para escrever código seguro.
Uso Cauteloso de Bibliotecas: Tenha cautela ao usar bibliotecas de terceiros. Avalie sua postura de segurança e revise seu código, especialmente aquelas que manipulam objetos.
Proteção em Tempo de Execução: Empregue mecanismos de proteção em tempo de execução, como o uso de pacotes npm focados em segurança que podem detectar e prevenir ataques de poluição de protótipos.
Referências
Last updated