Pesquisadores da empresa de segurança cibernética GRIMM publicaram recentemente um interessante trio de bugs que encontraram no kernel do Linux ...

… Em um código que passou despercebido por cerca de 15 anos.

Felizmente, parecia que ninguém mais havia olhado para o código por tanto tempo, pelo menos não diligentemente o suficiente para detectar os bugs, então eles agora foram corrigidos e os três CVEs que encontraram foram corrigidos:

  • CVE-2021-27365. Estouro de buffer de pilha explorável devido ao uso de sprintf ().
  • CVE-2021-27363. Perda do endereço do kernel devido ao ponteiro usado como ID exclusivo.
  • CVE-2021-27364. Overread do buffer levando ao vazamento de dados ou negação de serviço (kernel panic).

Os bugs foram encontrados no código do kernel que implementa iSCSI, um componente que implementa a venerável interface de dados SCSI na rede, para que você possa conversar com dispositivos SCSI como fitas e unidades de disco que não estão diretamente conectadas ao seu computador.

Claro, se você não usa mais SCSI ou iSCSI em qualquer lugar da sua rede, você provavelmente está dando de ombros agora e pensando, 'Não se preocupe comigo, eu não tenho nenhum dos drivers do kernel iSCSI carregados porque' não estou usando. "

Afinal, o código do kernel com erros não pode ser explorado se estiver apenas no disco; ele deve ser carregado na memória e usado ativamente antes que possa causar quaisquer problemas.

Exceto, é claro, que a maioria (ou pelo menos muitos) sistemas Linux não vêm apenas com centenas ou mesmo milhares de módulos do kernel na árvore de diretórios / lib / modules, prontos para usar caso sejam necessários. configurado para permitir aplicativos devidamente autorizados. para ativar o carregamento automático de módulos sob demanda.

Observação. Até onde sabemos, esses bugs foram corrigidos nos seguintes kernels Linux mantidos oficialmente, todos datados de 2021-03-07: 5.11.4, 5.10.21, 5.4.103, 4.19.179, 4.1.4.224, 4.9 .260, 4.4.260. Se você tiver um kernel modificado pelo fornecedor ou um kernel serial não oficial que não esteja nesta lista, verifique com o fabricante da distribuição. Para verificar a versão do kernel, execute uname -em um prompt de comando.

Por exemplo, meu próprio sistema Linux vem com quase 4500 módulos de kernel para o caso de você precisar deles:

root @ slack: /lib/modules/5.10.23# search. -name '* .ko'
./kernel/arch/x86/crypto/aegis128-aesni.ko
./kernel/arch/x86/crypto/blake2s-x86_64.ko
./kernel/arch/x86/crypto/blowfish-x86_64 .ko
[... 4472 linhas excluídas ...]
./kernel/sound/usb/usx2y/snd-usb-usx2y.ko
./kernel/sound/x86/snd-hdmi-lpe-audio.ko
./kernel /virt/lib/irqbypass.ko
#

Suponho que um dia eu possa precisar do módulo de criptografia Blowfish, mas como não tenho nenhum software que espero usar, provavelmente poderia passar sem o driver blowfish-x86_64.ko.

E embora eu realmente não me importasse de ter uma das ótimas placas de som Ux2y da Tascam (por exemplo, US122, US224, US428), eu realmente não preciso de espaço para uma, então duvido que algum dia precise do snd-usb-usx2y. kocontrolador. qualquer.

No entanto, lá estão eles e, por acidente ou propositalmente, qualquer um desses drivers pode acabar carregando automaticamente, dependendo do software que você está usando, mesmo que eu não esteja executando como root no momento.

Vale a pena dar uma segunda olhada

O risco potencial representado por motoristas não amados, não utilizados e, na maioria das vezes, esquecidos é o que fez o GRIMM procurar duas vezes os erros mencionados acima.

Os pesquisadores conseguiram encontrar um software que um invasor sem privilégios poderia executar para ativar o código do driver defeituoso que encontraram e produziram exploits funcionais que poderiam de várias maneiras:

  • Execute o escalonamento de privilégios para promover um usuário regular a superpoderes no nível do kernel.
  • Extraia os endereços da memória do kernel para facilitar outros ataques que precisam saber onde o código do kernel está carregado na memória.
  • Ele bloqueia o kernel e, portanto, todo o sistema.
  • Leia pedaços de dados da memória do kernel que deveriam estar fora dos limites.

Tão incerto e limitado em escopo quanto a última exploração soa, parece que os dados que um usuário sem privilégios pode ver podem incluir pedaços de dados que são transferidos durante acessos a dispositivos iSCSI genuínos.

Nesse caso, isso significa teoricamente que um criminoso com uma conta sem privilégios em um servidor onde o iSCSI foi usado poderia executar um programa de aparência inocente para ficar em segundo plano, farejando uma seleção aleatória de dados privilegiados da memória. .

Mesmo um fluxo fragmentado e não estruturado de dados confidenciais retirados intermitentemente de um processo privilegiado (lembra do infame bug Heartbleed?) Pode permitir que segredos perigosos escapem.

Não se esqueça de como é fácil para o software de computador reconhecer e "raspar" padrões de dados à medida que voam pela RAM, como números de cartão de crédito e endereços de e-mail.

Erros revisitados

Acima, mencionamos que o primeiro erro neste conjunto foi devido ao "uso de sprintf ()".

Essa é uma função C, abreviação de imprimir formatado em uma string e é uma maneira de imprimir uma mensagem de texto em um bloco de memória para que você possa usá-la mais tarde.

Por exemplo, este código ...

char buf [64]; / * Reserve um bloco de bytes de 64 bytes * /
char * str = "42"; / * Na verdade, tem 3 bytes, portanto: '4' '2' NUL * /
/ * Zero à direita adicionado automaticamente: 0x34 0x32 0x00 * /
sprintf (buf, "A resposta é% s", str)
... Deixaria o bloco de memória que buf contém os 12 caracteres "A resposta é 42", seguido por um terminador de zero byte (ASCII NUL), seguido por 51 bytes intocados no final do buffer de 64 bytes.

No entanto, sprintf () é sempre perigoso e nunca deve ser usado, pois não verifica se há espaço suficiente no bloco de memória final para caber os dados impressos.

Acima, se a string armazenada na variável strt tiver mais de 54 bytes, incluindo o byte zero à direita, buf não corresponderá com o texto extra "A resposta é".

Pior ainda, se os dados de texto strno tiverem um byte zero no final, que é como C indica quando parar de copiar uma string, você pode copiar acidentalmente milhares ou mesmo milhões de bytes que continuam rodando pela memória até que você chegue a um byte zero , ponto no qual o kernel quase certamente travou.

O código moderno não deve usar funções C que podem fazer cópias de memória de comprimento ilimitado - eu uso snprintf (), que significa formatar e imprimir no máximo N bytes em uma string, e seus amigos ao invés.

Não dê seu endereço

O segundo erro acima surgiu do uso de endereços de memória como identificadores únicos.

Parece uma boa ideia: se você precisar indicar um objeto de dados em seu código de kernel com um número de identificação que não colidirá com nenhum outro objeto em seu código, você pode usar os números 1, 2, 3 e assim por diante . , adicionando um de cada vez e resolvendo o problema.

Mas se você quiser um identificador único que não entre em conflito com nenhum outro objeto numerado no kernel, você pode pensar: “Por que não usar o endereço de memória onde meu objeto está armazenado, porque obviamente ele é único, uma vez que dois objetos não podem estar no mesmo lugar na RAM do kernel ao mesmo tempo? ”(Não, a menos que já haja uma crise de uso de memória).

O problema é que se o seu ID de objeto estiver sempre visível fora do kernel, por exemplo para que programas não confiáveis ​​na área do usuário possam se referir a ele, você apenas forneceu informações sobre o layout da memória interna do kernel, e isso não deveria acontecer .

Kernels modernos usam o que é chamado KASLR, abreviação de randomização do layout do espaço de endereço do kernel, especificamente para evitar que usuários sem privilégios descubram o layout interno exato do kernel.

Se você já abriu bloqueios (é um hobby popular e surpreendentemente relaxante entre hackers e pesquisadores de segurança cibernética - você pode até comprar bloqueios transparentes para diversão educacional), você saberá que é muito mais fácil se você já souber como o bloqueio funciona. O mecanismo é apresentado internamente.

Da mesma forma, saber exatamente o que foi carregado dentro do kernel quase sempre torna outros erros, como estouros de buffer, muito mais fáceis de explorar.

O que fazer?

  • Atualize seu kernel. Se você confia no fabricante da sua distribuição para os novos kernels, certifique-se de obter a atualização mais recente. Veja acima os números das versões onde esses bugs foram corrigidos.
  • Não use funções de programação C que são conhecidas por serem problemáticas. Evite qualquer recurso de acesso à memória que não controle a quantidade máxima de dados a ser usada. Mantenha um registro das “funções seguras da string C” oficialmente documentadas para o sistema operacional ou ambiente de programação de sua escolha e use-as sempre que puder. Isso dá a você uma chance melhor de evitar a sobrecarga de memória.
  • Não use endereços de memória como identificadores ou identificadores "exclusivos". Se você não puder usar um contador que aumenta apenas em 1 por vez, use um número aleatório de pelo menos 128 bits. Às vezes, eles são conhecidos como UUIDs, para identificadores exclusivos universais. Use uma fonte aleatória de alta qualidade, como / dev / urandomen no Linux e macOS ou BCryptGenRandom () no Windows.
  • Considere bloquear o carregamento do módulo do kernel para evitar surpresas. Se você definir a variável do sistema Linux a kernel.modules_disable = 1 depois que seu servidor for iniciado e estiver funcionando corretamente, nenhum outro módulo poderá ser carregado, seja por acidente ou por projeto, e essa configuração só pode ser desabilitada reinicializando. Use sysctl -w kernel.modules_disable = 1st echo 1> / proc / sys / kernel / modules_disable.
  • Considere identificar e manter apenas os módulos do kernel de que você precisa. Você pode construir um kernel estático com apenas os módulos necessários compilados ou criar um pacote de kernel para seus servidores com todos os módulos desnecessários removidos. Com um kernel estático, você pode desabilitar totalmente o carregamento do módulo, se desejar.

fonte: Ligação

fechar

VAMOS MANTER CONTATO!

Adoraríamos mantê-lo atualizado com nossas últimas notícias e ofertas 😎

Não fazemos spam! Leia nosso política de privacidade para mais informações.

Sobre o autor: Eduardo Kando Gerente WiseGroup
Estou aqui para ajudar e orientar todos os visitantes do site WisePlant. Será um prazer responder suas perguntas, conhecer suas preocupações e receber suas recomendações para melhorar nossos serviços.