Skip to main content

Como detectar e mitigar ataques Trojan Source em bases de código JavaScript com o ESLint

Escrito por

10 de novembro de 2021

0 minutos de leitura

Em 1º de novembro de 2021, a divulgação pública de um artigo intitulado Trojan Source: vulnerabilidades invisíveis descreveu como agentes mal-intencionados podem usar caracteres de controle bidirecional baseados em Unicode para inserir código-fonte malicioso em uma base de código aparentemente inofensiva. Esse ataque depende de confundir revisores, fazendo com que código-fonte malicioso ofuscado pareça um comentário.

O que é um ataque Trojan Source?

Editores de código tradicionais e práticas de revisão de código não detectam caracteres bidirecionais presentes no código-fonte. Isso permite que invasores insiram código malicioso que parece inofensivo. Essa vulnerabilidade foi divulgada publicamente em 1º de novembro de 2021 e recebeu o identificador CVE-2021-42574.

Veja o trecho a seguir, exibido no VS Code, de um ataque Trojan Source em código-fonte JavaScript:

// running internal logic for privileged users:
var accessLevel = "user";
if (accessLevel != "user‮ ⁦// Check if admin⁩ ⁦") {
    console.log("You are an admin.");
}

E agora, com esta captura de tela:

Trecho de código JavaScript que verifica se accessLevel é diferente de "user" e registra uma mensagem de administrador

Você percebeu o problema no código-fonte acima? Se não, examine o trecho com um pouco mais de atenção.

O que está acontecendo aqui é um ataque do tipo Stretched String. O código na linha 3 dá a impressão de que a expressão condicional verifica se a variável accessLevel é igual ao valor user. Há um comentário no fim da linha sobre verificações de lógica, que pode parecer inofensivo, mas a verdade é bem diferente.

Na verdade, o uso de caracteres bidirecionais Unicode na linha 3 oculta o valor real da string verificada pela variável accessLevel. Veja a linha 3 como o compilador realmente a executaria:

If (accessLevel != "user // Check if admin") {

O artigo descreve várias formas de abusar de caracteres de controle bidirecional para injetar código malicioso no código-fonte: Commenting-Out, Stretched String, Invisible Functions e Homoglyph Function. Os pesquisadores forneceram exemplos em JavaScript de todos esses ataques neste repositório trojan-source no GitHub.

Embora o uso de caracteres de controle bidirecional seja uma abordagem nova, esse tipo de ataque não é novidade e já foi mencionado em listas de discussão e fóruns. Alguns exemplos são esta issue do Golang, de 2017, sobre a proibição de caracteres RTL/LTR e esta entrada do Bugzilla, de 2011, intitulada [BiDi] Exibição enganosa de strings bidirecionais quando RLO, LRO ou PDF são usados (observe o uso do Google Cache para acessá-la).

Como corrigir ataques Trojan Source?

Os autores do artigo acadêmico sugerem que o problema está nos editores de código e nas IDEs, que devem ser corrigidos para exibir esses caracteres Unicode, além dos compiladores, que devem alertar os usuários sobre eles.

Como detectar ataques Trojan Source no código-fonte

Suas ferramentas e processos de edição e revisão de código talvez usem plataformas que não destacam esses perigosos caracteres bidirecionais Unicode. Isso significa que eles podem já estar presentes na sua base de código.

Como descobrir se seu código-fonte contém caracteres bidirecionais Unicode? Para ajudar, criei um pacote npm chamado anti-trojan-source que verifica um diretório ou recebe dados da entrada padrão (STDIN) e procura esses caracteres Unicode no texto.

Você pode usar o npx para verificar arquivos da seguinte forma:

npx anti-trojan-source --files='src/**/*.js'

Ou, se quiser usá-lo como biblioteca em um projeto JavaScript:

import { hasTrojanSource } from 'anti-trojan-source'
const isDangerous = hasTrojanSource({
  sourceText: 'if (accessLevel != "user) {' // Check if admin
})

Como prevenir ataques Trojan Source em JavaScript com o ESLint

Nota do editor: Desde a publicação original deste post, regras contra Trojan Source foram adicionadas ao Snyk Code. Saiba mais no nosso post sobre como prevenir ataques Trojan Source com o Snyk Code.

Mas, melhor do que apenas encontrar problemas existentes, é proteger sua base de código proativamente para garantir que nenhum ataque Trojan Source chegue ao seu código-fonte. Na comunidade JavaScript, costumamos recorrer ao ESLint e aos seus vários plugins para aplicar padrões de qualidade e estilo de código.

Com o eslint-plugin-anti-trojan-source, você também pode incluir um plugin do ESLint para garantir que nenhum desenvolvedor, sistema de integração contínua ou processo de build faça, por engano, o merge de código potencialmente malicioso por causa de caracteres bidirecionais Unicode.

Veja um exemplo de configuração do ESLint para um projeto JavaScript:

"eslintConfig": {
    "plugins": [
        "anti-trojan-source"
    ],
    "rules": {
        "anti-trojan-source/no-bidi": "error"
    }
}

E aqui está um exemplo da saída para um trecho de código vulnerável que entrou na base de código:

$ npm run lint

/Users/lirantal/projects/repos/@gigsboat/cli/index.js
  1:1  error  Detected potential trojan source attack with unicode bidi introduced in this comment: ' begin admins only '  anti-trojan-source/no-bidi if (isAdmin) {
  1:1  error  Detected potential trojan source attack with unicode bidi introduced in this comment: ' end admin only    anti-trojan-source/no-bidi }

/Users/lirantal/projects/repos/@gigsboat/cli/lib/helper.js
  2:1  error  Detected potential trojan source attack with unicode bidi introduced in this code: '"user" // Check if admin

Como o ecossistema está mitigando os ataques Trojan Source?

IDEs como o VS Code lançaram versões que destacam esses caracteres Unicode, para que os programadores percebam sua presença e tenham o contexto adequado ao revisar e editar código. Da mesma forma, o GitHub publicou avisos para que as bases de código exibidas passem a destacar o uso desses caracteres Trojan potencialmente perigosos no GitHub:

Visualização de código no GitHub com um aviso de que o arquivo JavaScript contém texto Unicode bidirecional e uma condição que verifica se o usuário é administrador.
Fonte: https://github.com/nickboucher/trojan-source/blob/main/JavaScript/stretched-string.js

No entanto, observe que o GitHub não destaca todos os tipos de ataques de malware Trojan. Por exemplo, veja o caso a seguir, apresentado no artigo e chamado de Invisible Functions:

Editor de código mostrando duas funções isAdmin com nomes semelhantes, retornando false e true, seguidas por uma condição de acesso de administrador.

Como você pode ver no trecho de código JavaScript acima, não há avisos do GitHub ao revisar esse código. O que está acontecendo de fato?

A declaração da função na linha 7 usa um caractere de controle Unicode de espaço de largura zero, identificado como U200B. Isso faz com que ela pareça visualmente uma função legítima function isAdmin().

Podemos confirmar isso exibindo o código com uma ferramenta como o bat, um clone da ferramenta cat do UNIX com realce de sintaxe aprimorado e integração com o Git:

Código JavaScript que mostra nomes de funções visualmente semelhantes usando caracteres Unicode invisíveis, sendo que uma retorna false e a outra, true.

Compiladores e ambientes de execução devem mitigar ataques Trojan Source?

E quanto aos compiladores e ambientes de execução de linguagens? A maioria das linguagens, incluindo o Node.js, decidiu não atualizar seus compiladores para rejeitar caracteres Unicode. Na prática, isso transfere o risco para os editores de código e para as pessoas, que precisam ter mais cuidado ao ler o código e fazer revisões de código.

Dito isso, alguns ambientes de execução de linguagem, como o Zig, já consideraram usar um erro de compilação ao detectar o uso de caracteres bidirecionais Unicode no código-fonte, permitindo contornar esses erros com um comentário explícito.

Recursos sobre ataques Trojan Source

Espero que este post tenha ajudado você a entender os ataques Trojan Source e como eles podem aparecer no ecossistema JavaScript. Para saber mais sobre esses ataques, recomendo conferir os seguintes recursos:

  1. Post Como prevenir ataques Trojan Source com o Snyk Code

  2. Site oficial do Trojan Source: https://www.trojansource.codes

  3. Repositório oficial do Trojan Source com exemplos de código e provas de conceito: https://github.com/nickboucher/trojan-source

  4. Artigo oficial de anúncio do Trojan Source:  https://www.lightbluetouchpaper.org/2021/11/01/trojan-source-invisible-vulnerabilities

Proteja seu código com inteligência de ponta

Conheça toda a gama de recursos de análise estática (SAST) do Snyk Code em apenas 30 minutos.