2 pontos por GN⁺ 2024-10-08 | 2 comentários | Compartilhar no WhatsApp
  • Um experimento de escalonamento local de privilégios conseguiu induzir falhas eletromagnéticas no barramento de memória DDR3 de um notebook usando apenas um isqueiro de cigarro piezoelétrico, chegando de um usuário Linux sem privilégios até um shell root
  • No notebook Samsung S3520, foi soldado um resistor de 15Ω e um fio atuando como antena nos pinos de dados do SODIMM, e ao acionar o isqueiro por perto foram criados erros de memória que invertiam bits específicos
  • No experimento com CPython, uma falha na linha DQ7 inverteu o bit 7 de um ponteiro de objeto, fazendo-o referenciar uma estrutura falsa de bytearray dentro de bytes, o que permitiu montar primitivas de leitura/escrita arbitrárias de memória
  • A escalada de privilégios no Linux funciona ao pulverizar tabelas de páginas em grande quantidade na memória física e, durante a leitura de uma PTE, induzir uma falha no bit 29 para que um mapeamento acessível ao usuário passe a apontar para uma tabela de páginas
  • Após o sucesso, a primeira página de /usr/bin/su foi localizada na memória física e substituída por um pequeno ELF setuid root, contaminando o page cache; no ambiente de teste, a confiabilidade percebida foi de cerca de 50% via SSH e cerca de 20% no shell gráfico

Ponto de partida do experimento de EMFI com isqueiro

  • Mesmo sem bugs de software, é possível criar comportamentos excepcionais por meio de injeção de falhas (fault injection)
    • Métodos de injeção de falhas incluem corrupção de dados de controle por software, glitches de alimentação, glitches de clock, pulsos eletromagnéticos e laser
  • A injeção de falhas em hardware normalmente exige precisão de tempo e localização para inserir a falha, o que requer equipamento especializado e custo elevado
  • O ponto de partida foi uma abordagem que acopla um acendedor piezoelétrico de churrasqueira a um indutor para usá-lo como ferramenta barata de injeção eletromagnética de falhas (EMFI)
    • Antes disso, já havia sido possível atacar uma implementação de AES em software rodando em Arduino com DFA
  • No contexto da proximidade do anúncio do Nintendo Switch 2, e prevendo software de sistema semelhante ao do Switch 1 com escassez de bugs de software, os experimentos de EMFI de baixo custo foram retomados

Alvo do teste e falhas no barramento DDR

  • O alvo do teste foi um notebook Samsung S3520 fabricado em 2011, com CPU Intel i3-2310M e 1GB de RAM DDR3
    • Ele foi escolhido por conseguir rodar Arch, uma distribuição Linux de desktop leve, e por ser um equipamento cujo dano seria aceitável
  • O objetivo era escrever um exploit de escalonamento local de privilégios baseado em falhas de hardware induzidas
  • Como ponto fisicamente mais vulnerável, foi escolhido o barramento DDR que conecta a memória DRAM ao sistema
    • O SODIMM possui 64 pinos DQ, de DQ0 a DQ63, que transportam os bits de dados de leitura/escrita
  • O dispositivo experimental consistia em soldar um resistor de 15Ω e um fio em um pino estimado como DQ26
    • O fio recebe interferência eletromagnética ao redor como uma antena e a transmite ao barramento de dados
    • O resistor serve para limitar a intensidade da interferência para não atrapalhar continuamente o funcionamento normal da memória, embora talvez não seja realmente necessário
  • Só de acionar um isqueiro piezoelétrico comum perto do fio-antena, erros de memória apareciam de forma estável no memtest
    • Todos os erros exibidos eram inversões do bit 29
    • O pino soldado era estimado como DQ26, mas a razão para a inversão do bit 29 pode ser contagem incorreta dos pinos ou remapeamento das linhas de dados pela placa-mãe
  • Como o controle de tempo da injeção de falhas depende da velocidade de reação dos dedos, ele não é preciso
    • Quando a falha acontece, há grande chance de o mesmo bit ser invertido em uma leitura ou escrita específica de 64 bits

Explorando bit flips no CPython

  • O primeiro experimento foi criar um exploit em forma de escape de sandbox no CPython
    • Como o próprio CPython não é uma sandbox, isso não representa uma evasão real de fronteira de segurança, mas uma etapa preparatória usando estruturas internas familiares
  • Nesse experimento, em vez do DQ26 da foto anterior, foi usado um fio soldado ao DQ7
  • Objetos do CPython ficam no heap do garbage collector, e o cabeçalho do objeto contém o refcount e um ponteiro para o objeto de tipo, seguidos pelos campos específicos do tipo
    • Um objeto bytes armazena os próprios dados na mesma alocação de heap após o campo de tamanho
    • Um objeto bytearray tem, após o campo de tamanho, um ponteiro para o buffer onde os dados reais são armazenados
  • A estratégia principal é colocar uma estrutura falsa de bytearray como dados dentro de um objeto bytes
    • Se for possível enganar o CPython para que ele entregue uma referência a esse objeto falso, o atacante consegue leitura/escrita arbitrária de memória usando os campos de tamanho e ponteiro do bytearray escolhido
  • Uma falha que inverte o bit 7 em uma word de 64 bits tem o efeito de somar ou subtrair 128 de um ponteiro
    • Ao posicionar o bytearray falso a um deslocamento de +128 bytes dentro do objeto bytes, o ponteiro do objeto bytes pode, por falha, virar um ponteiro para o bytearray falso
    • Essa conversão ocorre na direção desejada com probabilidade de 50%
  • O importante é que a falha afeta a operação de leitura/escrita no barramento de memória, e não o conteúdo armazenado em si
    • Diferente do Rowhammer, não é o dado persistido que muda, mas o acesso em andamento no barramento que é corrompido
  • Para que o acesso ao ponteiro desejado dominasse a maior parte da atividade no barramento, a mesma referência de objeto foi preenchida em uma tupla grande
    • Como o cache da CPU reduz acessos à DRAM, foi usada uma estrutura maior que o cache de 3MiB, acessada sequencialmente, para forçar leituras da DRAM a cada vez
    • O operador is do Python funciona como comparação de ponteiros e foi usado para verificar se o ponteiro havia mudado
  • O código-fonte completo do exploit para CPython está em ddr3_dq7.py
    • A variável TESTING permite simular o bit flip em software sem hardware

Estruturas de memória necessárias para a escalada de privilégios no Linux

  • Na escalada local de privilégios no Linux, as estruturas centrais são cache, memória virtual e tabelas de páginas, e a TLB
  • Como a DRAM é relativamente lenta, a CPU usa caches L1, L2 e L3
    • O cache L3 do notebook do experimento é de 3MiB
    • Com cache hit, não há acesso à DRAM; leituras da DRAM só acontecem quando ocorre cache miss
  • A unidade mínima do ponto de vista do cache é a cache line, que nesse notebook tem 64 bytes
    • Mesmo lendo um único byte, se os dados não estiverem em cache ocorre uma leitura de 64 bytes na DRAM
    • Como o barramento de dados DDR tem largura de 64 bits, essa leitura é processada em 8 acessos burst sequenciais
  • A memória virtual em x86-64 é implementada com páginas de 4KiB e tabelas de páginas em formato de árvore
    • Nessa plataforma há 4 níveis de tabelas de páginas
    • Cada tabela de páginas ocupa uma página de 4KiB e contém 512 PTEs de 64 bits
    • As PTEs dos níveis superiores apontam para o endereço físico da tabela do nível seguinte, e as PTEs de nível 0 apontam para a página física de destino
    • O endereço físico da tabela de páginas raiz fica armazenado no registrador de CPU CR3
  • Na PTE, a parte necessária é o campo de endereço físico
    • Ao mascarar os bits de flags, sobra um endereço de memória física alinhado à página
  • A TLB é um hardware interno da CPU que faz cache dos mapeamentos de páginas entre endereços virtuais e físicos
    • O tamanho exato da TLB no notebook do experimento é desconhecido, mas parece ficar em torno de 1024 entradas

Trazendo tabelas de páginas para a memória do usuário

  • A estratégia do exploit Linux foi inspirada em elementos do exploit Rowhammer de Mark Seaborn
  • O objetivo é mapear as tabelas de páginas do próprio processo em memória acessível ao usuário
    • Feito isso, torna-se possível modificar PTEs para acessar memória física arbitrária
  • Em vez de controlar com precisão o layout da memória física, a ideia foi preencher exatamente 50% da memória física com tabelas de páginas de nível 0
  • Depois disso, acessam-se repetidamente os mapeamentos R/W para contornar a TLB
    • Como o número de mapeamentos excede o tamanho da TLB, cada acesso pode forçar um page walk
    • Durante esse page walk, o objetivo é provocar uma falha no bit 29 na leitura da PTE de nível 0
  • Quando o bit 29 é invertido, o endereço físico apontado pela PTE muda em um offset de 512MiB
    • Com sorte, o novo endereço passa a apontar para uma das tabelas de páginas de nível 0 previamente pulverizadas
    • Nesse caso, um mapeamento que deveria parecer uma página R/W comum passa a expor uma tabela de páginas como se fosse uma página R/W comum
  • Em teoria, qualquer bit flip do bit 29 ao bit 12 poderia funcionar
    • O bit 12 corresponde a um offset de 4KiB
    • O ponto essencial é que a PTE passe a apontar para “algum outro lugar” e que cerca de 50% da memória física esteja preenchida com tabelas de páginas exploráveis
  • Soldar o fio-antena talvez não seja estritamente necessário
    • Se for possível gerar interferência eletromagnética suficientemente forte, pode funcionar, mas com probabilidade muito maior de travar ou danificar o sistema

Método de pulverização de tabelas de páginas de nível 0

  • Primeiro, cria-se um arquivo em memória com memfd_create
    • Ele cumpre papel semelhante ao arquivo em /dev/shm/ do exploit de Mark Seaborn, mas sem tocar diretamente no sistema de arquivos
  • O mesmo buffer é então mapeado várias vezes com mmap
    • A opção MAP_FIXED força cada mapeamento a ficar alinhado a 2MiB no espaço de memória virtual
    • Esse alinhamento garante a criação de uma nova tabela de páginas de nível 0 a cada vez
  • O Linux impõe um limite de cerca de 2^16 mapeamentos por processo, isto é, VMAs
    • Cada mapeamento foi feito com 32MiB de comprimento, para que um único mapeamento gere 16 tabelas de páginas de nível 0
  • Cada mapeamento ocupa 32MiB no espaço de endereços virtuais, mas as PTEs apontam para a mesma página física
    • O custo em memória física são apenas as tabelas de páginas de nível 0
    • Assim, é possível pulverizar tabelas de páginas até a memória encher

Leitura/escrita de memória física e contaminação do page cache do su

  • Enquanto espera a falha, o exploit acessa repetidamente os mapeamentos R/W e detecta a falha quando um valor diferente do esperado é retornado
    • Se os dados retornados parecerem uma PTE, significa que foi obtido acesso R/W a uma tabela de páginas
  • O passo seguinte é descobrir a que endereço virtual essa tabela de páginas corresponde
    • Para isso, modifica-se a PTE para apontar para o endereço físico 0
    • Depois, escaneiam-se novamente os mapeamentos R/W para ver qual deles mudou
  • Mesmo após modificar uma PTE, a MMU não percebe isso imediatamente
    • Isso ocorre porque o mapeamento virtual-físico está em cache na TLB
    • Como não se conhecia uma forma de fazer flush da TLB diretamente do espaço do usuário, acessaram-se repetidamente milhares de mapeamentos R/W para preencher a TLB com novos valores e expulsar os antigos
  • A partir desse ponto, obtém-se acesso de leitura/escrita a toda a memória física
  • Em seguida, o arquivo executável /usr/bin/su é aberto em modo somente leitura e sua primeira página é mapeada com mmap
    • /usr/bin/su é um executável setuid root
    • Varre-se toda a memória física até encontrar a mesma página
    • Ao obter acesso de escrita nessa página física, ela é substituída por um ELF payload menor que 4KiB, que abre um shell root
  • Na próxima vez que su é executado, o Linux entende que a primeira página já está na memória e não a relê do disco
    • Ele reutiliza o page cache contaminado e executa o ELF injetado
    • O ELF injetado limpa o page cache com echo 1 > /proc/sys/vm/drop_caches, para que a execução seguinte de su volte ao comportamento normal
  • O código-fonte completo do exploit Linux está em linux_x86_64_lpe.c

Confiabilidade e restrições do ambiente

  • Na execução da demonstração, por sorte um bom glitch ocorreu com um único clique do isqueiro
    • Em várias tentativas anteriores, o sistema inteiro travou
  • A confiabilidade total do exploit não foi medida com rigor
    • Com a tela do notebook desligada e acesso via SSH, a percepção foi de cerca de 50%
    • No shell gráfico, ficou mais próxima de 20%
  • O sistema experimental usava gráficos integrados
    • É possível que os acessos de memória da GPU interfiram no exploit
  • Serviços em segundo plano ligados a pipewire, sshd, systemd e swap estavam ativos
    • Foi uma escolha para manter um ambiente Linux de desktop realista, mas desativá-los pode aumentar a confiabilidade
  • Se houvesse mais RAM instalada, seria possível preencher uma fração maior com tabelas de páginas, o que pode elevar a confiabilidade geral

Possíveis usos e questões em aberto

  • Se um escalonamento local de privilégios por EMFI confiável fosse possível no Windows, isso poderia impactar cenários em que anti-cheats baseados em TPM restringem o software permitido no sistema
  • Algo semelhante também pode valer para verificações do SafetyNet ou Play Integrity no Android, embora inserir um modchip de glitch em um celular seja bem mais difícil
  • Em otimização de desempenho de baixo nível, conhecimento sobre tabelas de páginas e TLB nem sempre é diretamente importante, mas neste exploit as estruturas que sustentam a ilusão de memória virtual tornam-se o alvo direto do ataque
  • Ainda há muito a confirmar sobre o alcance da técnica
    • se funciona em DDR4 e DDR5
    • se funciona em ARM
    • até que ponto vários tipos de ECC, em especial o Link-ECC do DDR5, mitigam isso
    • qual é a forma mais simples de acionar eletronicamente falhas semelhantes com dispositivos como RP2040
    • se isso pode ser usado para escape de hipervisor
    • se é possível transformá-lo em um exploit de WebKit ou em um exploit de kernel do Nintendo Switch

2 comentários

 
mammal 2024-10-08

Isso me lembra de tirar o ignitor do isqueiro para levantar as moedas das máquinas de fliperama.

 
GN⁺ 2024-10-08
Opiniões do Hacker News
  • A inspiração aqui era obter acesso root no Switch 2, e conseguir root no Linux foi uma prova de conceito.
    O objetivo não é tanto mostrar uma vulnerabilidade de segurança fundamental explorável na prática, mas sim algo mais próximo de recuperar a propriedade real do próprio hardware sem quebrar o TPM nem o anticheat com privilégios de kernel de jogos.

    • Entendo a intenção, mas não vejo muito o ponto. Isso fazia mais sentido 20 anos atrás, quando consoles eram computadores potentes vendidos com prejuízo ou margens baixas, mas hoje a Nintendo vende consoles com lucro, e é bem provável que o Switch 2 também seja assim.
      É impressionante, e fico feliz em ver trabalhos para defender a liberdade de software, mas eu preferiria apoiar alternativas. Por que dar a eles números que parecem base instalada e lucro? Compre um Steam Deck ou outro portátil em que acesso root já venha como recurso desde o início.
  • O texto é muito bem escrito e o desafio é enorme, mas minha cabeça reage pelo lado da sabedoria comum de hacking: “se há acesso físico, já acabou”.
    A primeira coisa que me veio à mente foi que, com acesso físico, dá para reflashear a BIOS, instalar um backdoor em driver e inicializar por um sistema operacional live para manipular /etc/{passwd,shadow,groups, etc}.
    Mas então lembrei que, se o disco estiver criptografado, a maioria dos ataques com acesso físico se torna impossível, e nesse caso um ataque desses parece extremamente atraente. A ideia da antena pode ser expandida para um hardware com dispositivo de interferência embutido, fazendo-o se comunicar com o exterior por meio sem fio para que o atacante possa causar interferência remotamente. Se somar a isso um site controlado pelo atacante que engane a vítima para acessá-lo, começa a ficar realista.

    • A motivação da introdução é fazer root/jailbreak em um console portátil de jogos. É uma situação bem plausível: há acesso físico, mas ainda se quer obter acesso “não autorizado”.
    • Do meu ponto de vista, reflashear a BIOS não renderia muita coisa. Antes de a execução começar, o hardware da CPU verifica se há uma assinatura correta de chave privada, então seria preciso assinar primeiro.
      Essa técnica de interferência eletromagnética engana a própria CPU, então não vejo muito bem como isso poderia ser corrigido, a menos que surja um novo algoritmo de paginação.
    • “Se o disco estiver criptografado, a maioria dos hacks com acesso físico é impossível” só é verdade quando o PC está desligado e ainda não descriptografou os dados para inicializar o sistema usando um arquivo de chave ou uma senha.
      Meu PC também usa criptografia de disco completo, mas, ao inicializar, o arquivo de chave usado para a descriptografia é utilizado, e a partir desse momento ele passa a ser um PC fisicamente acessível.
  • Gostei. O ponto é que ocorre uma inversão eletrostática de bits durante leitura ou escrita de memória e, com solda, dá para transformar de modo determinístico um ponteiro “seguro” em um ponteiro malicioso que eu escolher.
    Historicamente, a visão sobre acesso físico era “se o adversário põe as mãos no dispositivo, acabou o jogo”. TPM e ambientes de execução confiáveis mudaram essa visão para “mesmo que o usuário tenha acesso físico, certas operações dentro do enclave podem ser confiáveis”.
    O próximo passo é o mais interessante. Será que dá para obter resultados razoavelmente confiáveis sem soldar? Como já há muita complexidade envolvida em lidar com interferência elétrica, parece muito mais difícil, mas talvez seja possível. Se, a cada acionamento do isqueiro, um bit aleatório em uma leitura de 64 bits for invertido, e o exploit funcionar, por exemplo, com apenas uma entre 4 inversões de bit, o número médio de tentativas talvez não seja tão alto.

    • Se há acesso físico suficiente para soldar uma antena, dá para encaixar um DIMM personalizado programável “por trás” e atravessar TPM ou seja lá o que for.
      Como dá para mudar qualquer parte da memória para qualquer valor no momento desejado, não é preciso depender de inversões aleatórias de bit. Basta injetar o programa inteiro.
    • Sem a antena, acho que seria difícil limitar as inversões a um único bit. Pelo menos esse é o meu palpite.
  • Só pelo título, achei que fosse um texto sobre alguém obtendo acesso root em um isqueiro, e eu estava totalmente pronto para acreditar.
    Como o forno dos meus pais também recebe atualizações de software regularmente, nem sequer duvidei que um isqueiro pudesse ser “smart”.

    • Só pelo título, eu meio que esperava uma versão incendiária da criptoanálise por mangueira de borracha.
    • Fiquei pensando: e se existisse um isqueiro com um pequeno painel solar e bateria, que soltasse uma faísca como um pequeno taser quando um lidar detectasse um cigarro ou charuto por perto? Ele não reagiria a dedos nem a cachorros-quentes, não teria botão, e nunca precisaria repor fluido de isqueiro.
      Claro, também precisaria de um chip para rodar o lidar e, ao mesmo tempo, produzir um flash LED intenso com fade, impacto háptico e efeitos sonoros. Queria que alguém fizesse um demo. Seria legal se parecesse um revólver pequeno, mas acho que, para a segurança de dedos e cachorros-quentes, seria preciso reforçar o controlador de memória virtual.
    • O ferro de solda que eu mais uso também roda firmware modificável em um SoC RISC-V. (https://pine64.com/product/pinecil-smart-mini-portable-solde...)
      Quem diria que derreter solda poderia ser tão complicado. Por isso eu acreditaria tranquilamente num texto sobre rootear um isqueiro.
    • Achei que fosse calcular raízes quadradas pelo formato da chama.
  • Lembra um exploit que fazíamos nas máquinas de fliperama de Sydney nos anos 80 e 90. Os aquecedores a gás da escola tinham um isqueiro piezoelétrico que chamávamos de “clicker”, e dava para removê-lo do aquecedor
    Levávamos esse clicker ao fliperama do bairro e, ao clicar em um dos cantos do CRT, o sistema levava um choque e aumentava os créditos do jogo. Imagino que fosse porque o aterramento do CRT compartilhava fisicamente o mesmo fio de terra do dispositivo que verificava as moedas.
    Com o tempo, os donos perceberam e acrescentaram algo como um alarme, mas até então foram tempos realmente incríveis

    • Fizemos exatamente a mesma coisa no começo dos anos 80, mas usávamos o clicker de dentro de isqueiros descartáveis
      Fizemos isso por alguns anos, até que os donos perceberam e começaram a cobrir os gabinetes das máquinas com plástico transparente. Ao mesmo tempo, como os gabinetes ficaram vedados com plástico, eles fizeram furos na parte de trás para ventilação, e descobrimos que dava para apertar, com uma vareta de bambu, a alavanca que registrava a inserção de moeda.
      Então moveram as aberturas de ventilação para cima, em vez de deixá-las atrás, para impedir que a alavanca fosse alcançada; mas aí descobrimos que, ao empurrar uma moeda para cima pela saída de devolução, dava para tocar a alavanca de registro de moeda, e os jogos grátis continuaram. No fim, colocaram parafusos afiados dentro da caixa de devolução para cortar os dedos, e depois disso compramos um SEGA. Foi muito divertido
    • Lembra uma máquina em que, se um amigo entrasse atrás dela e desligasse e ligasse a energia, surgia um token grátis
      Não sei se ela foi projetada assim de propósito para que os funcionários pudessem testar de graça, mas meu amigo entrava rastejando por trás e continuava jogando de graça
    • Também funcionava nos EUA. Por volta dos anos 1990, a maioria dos fliperamas usava tokens próprios em vez de moedas em dinheiro, e também havia muitas máquinas de jogo de habilidade em que os tokens ficavam empilhados em fileiras, deslizando
      Na versão “Jungle Jive”, ao dar um pequeno choque com o acendedor elétrico de um isqueiro na entrada metálica, tokens saíam do outro lado da máquina. Se clicasse rápido demais e muitas vezes, ela entrava em modo de alerta. Dava para fazer sozinho, mas a configuração ideal era um trio: 1 pessoa vigiando os funcionários, 1 clicando e 1 recolhendo
    • Tenho uma lembrança vaga de ganhar um jogo grátis ao bater com precisão na lateral de uma máquina de pinball. Provavelmente era o mesmo princípio
    • Lembro de ter lido neste livro que o hacker Pengo era conhecido por adicionar créditos a máquinas de fliperama da mesma forma
      https://www.amazon.com/CYBERPUNK-Outlaws-Hackers-Computer-Fr...
  • Lido como australiano, a interpretação é diferente. Dependendo da sua habilidade de negociação, dá para conseguir root só com um isqueiro

  • Além de ser um exploit interessante, também é uma ótima miniintrodução explicando como o cache funciona em uma CPU
    Lembro de ter visto, há cerca de um ano, um texto que explicava como computadores funcionam e são construídos, começando pela menor parte, as portas lógicas. Alguém lembra qual era esse site?

  • “É só um resistor de 15 ohms e um fio soldados no DQ26. O fio funciona como uma antena, captando interferência eletromagnética próxima e injetando-a diretamente no barramento de dados”
    Hack realmente incrível. Criar interferência eletromagnética com um isqueiro, quem diria. Vou acender um perto de um barramento DDR e ver o que acontece

  • Claro, isso se primeiro for preciso soldar uma antena na memória :-)
    Ainda assim, é um texto excelente e minucioso sobre como explorar esse tipo de glitch na prática. O isqueiro também pode ser usado para ficar rondando a porta dos fundos de um data center, esperando o administrador sair para fumar

    • “Em teoria, se ocorrer uma inversão de bit em qualquer posição entre o bit 29 e o bit 12, isso funciona. Portanto, se for possível gerar interferência eletromagnética forte o bastante, talvez soldar o fio da antena não seja absolutamente indispensável”
    • Um uso na seção “uso prático” é burlar a proteção contra cópia de consoles
  • Pelo título, achei que seria uma história sobre hackear carros da Hyundai com um dispositivo de isqueiro USB-C