NodeJS - __proto__ & prototype Pollution
Last updated
Last updated
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
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 {}
.
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.
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.
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.
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:
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
.
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:
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).
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.
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.
Outros payloads:
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.
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.
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.
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.
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 a Program
, 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:
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:
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 aplicando Object.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.
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)