Como corrigir uma vulnerabilidade de execução remota de código no EJS
Tim Kadlec
30 de novembro de 2016
0 minutos de leituraNesta semana, adicionamos ao nosso banco de dados de vulnerabilidades uma vulnerabilidade de execução remota de código no pacote EJS.
EJS (Embedded JavaScript Templates) é um mecanismo de templates para JavaScript rápido, simples e muito popular. O EJS oferece algumas opções diferentes para renderizar um template. Duas delas, render e renderFile, são bastante parecidas. A única diferença é que render espera receber uma string como template, enquanto renderFile espera receber o caminho de um arquivo de template. Ambos os métodos também aceitam argumentos para os dados e um conjunto opcional de opções de configuração. O método renderFile também aceita uma função de callback.
Ambos os métodos também permitem combinar os dados e as opções em um único objeto.
A vulnerabilidade
Usar o método abreviado pode parecer mais fácil, mas misturar dados e opções pode causar erros com o tempo. Se isso não for motivo suficiente para você deixar de usá-lo, aqui vai outro: o método abreviado pode expor sua aplicação a uma vulnerabilidade de execução remota de código.
Os templates EJS compilados podem incluir outros arquivos usando uma diretiva include.
Por padrão, esses includes usam o template como referência. Se o template estiver na pasta templates, o EJS procurará o arquivo a ser incluído em templates/path/to/include.
Uma das opções de configuração disponíveis é root, que permite alterar o local padrão de onde esses includes são carregados.
Isso não é um problema quando as opções são passadas como um argumento separado, mas passa a ser quando você combina as opções e os dados em um único objeto. Se o método repassar uma lista de dados fornecidos pelo usuário, um invasor poderá interceptá-los e injetar também uma opção root .
Ao repassar a diretiva root na linha acima, todos os includes passarão a ser carregados de /bad/root, em vez do caminho esperado, possibilitando a execução remota de código.
A possibilidade de configurar a raiz pode ser útil para desenvolvedores que usam o mecanismo EJS, mas permitir essa configuração em um objeto junto com dados do usuário representa um sério risco à segurança. O desenvolvedor poderia tomar algumas medidas para limpar as entradas, mas o mecanismo seria inseguro por padrão.
Nossa equipe de segurança encontrou o problema e o divulgou em 27 de novembro. O responsável pelo projeto, Matthew Eernisse, preparou uma correção simples que bloqueia a opção root, impedindo que ela seja incluída junto com dados do usuário.
Muitas vezes, as vulnerabilidades continuam sem correção muito tempo depois de serem divulgadas. Na verdade, se você se lembra da vulnerabilidade de XSS no Marked, levou mais de um ano para que ela fosse corrigida. Felizmente, não foi o que aconteceu neste caso. Graças a uma versão lançada muito rapidamente por Matthew, a vulnerabilidade foi corrigida apenas um dia após a divulgação. A versão 2.5.3 do EJS, lançada em 28 de novembro, inclui a correção.
Como corrigir
Se você pediu à Snyk para monitorar seu projeto e ele usa EJS, provavelmente já recebeu um alerta sobre o problema. Você pode corrigir a vulnerabilidade usando a integração com o GitHub para gerar uma solicitação de pull no seu painel ou executando snyk wizard pela interface de linha de comando. Nos dois casos, a Snyk identificará o problema e solicitará que você atualize o pacote EJS para a versão mais recente.
Se você não usa a Snyk — tudo bem, continuamos gostando de você — pode corrigir o problema atualizando manualmente o EJS para a versão mais recente. Não se esqueça de verificar também todas as suas dependências. Se alguma delas incluir o pacote EJS, ele não aparecerá no seu arquivo package.json, e o processo de atualização poderá ser bem mais complexo.
Comece a participar de desafios de Capture the Flag
Aprenda a resolver desafios de Capture the Flag assistindo sob demanda ao nosso workshop virtual introdutório.