Ataques de hardware a microcontroladores usando ChipWhisperer e métodos de proteção contra eles


Os ataques de hardware representam uma grande ameaça para todos os dispositivos com microcontroladores (daqui em diante - MK), pois podem ignorar vários mecanismos de segurança. É difícil se defender contra esses ataques usando software ou hardware. Por exemplo, você pode ler um artigo da STMicroelectronics sobre vários tipos de ataques de hardware e métodos de proteção do MK.
Nós, a equipe de Raccoon Security, estamos interessados ​​neste tópico, uma vez que uma das áreas de atividade da nossa empresa é o desenvolvimento de dispositivos embarcados, incluindo aqueles que contêm mecanismos de proteção de informações. Na maior parte, estamos interessados ​​em ataques de falha, pois eles permitem que você ignore as instruções executáveis ​​do MK. Essa é uma séria ameaça às informações confidenciais contidas no MK, e a consequência mais perigosa de tais ataques é a leitura de firmware fechado, ignorando os mecanismos de segurança fornecidos pelos desenvolvedores do MK.


No Hardwear.io 2018, em Haia, e no EmbeddedWorld 2019, em Nuremberg, a NewAE demonstrou o dispositivo ChipWhisperer, que permite implementar a parte de ataques não invasivos de hardware que não exigem conhecimento aprofundado de nanoeletrônica e disponibilidade de equipamentos específicos. Usando esse dispositivo, estudamos a segurança dos dispositivos incorporados e descobrimos como minimizar o resultado desses ataques. Sob o corte - o que fizemos.


Chipwhisperer


O kit ChipWhisperer é um kit de ferramentas de código aberto para analisar a segurança dos MKs mais populares (STM, Xmega, Intel D2000, SAM, LPC, MSP, 78K e outros) e FPGAs. O projeto começou em 27 de fevereiro de 2015 no Kickstarter . No momento, existem versões diferentes do ChipWhisperer (todas as opções podem ser encontradas no catálogo ). Eles têm um conjunto diferente de ferramentas, mas geralmente são voltados para os seguintes tipos de ataques de hardware:


• ataques de canal lateral (SCA);


• ataques de falha.


Para uma análise mais aprofundada, escolhemos o ChipWhisperer-Pro (CW1200), que é o modelo mais antigo do ChipWhisperer no momento e possui ampla funcionalidade e um grande pacote:



Kit ChipWhisperer (CW1200)


A bordo, o CW1200 possui um osciloscópio, que consiste em um amplificador ajustável e um ADC com uma amostra de 105 MSPS. Este conjunto de ferramentas permite registrar o nível do sinal em centésimos de milivolt e obter uma boa base de tempo. Também no CW1200, existem portas para organizar CLK-glitch e Vcc-glitch, portas GPIO que podem ser atribuídas como gatilhos de entrada para rastrear a origem de um evento (solicitação de entrada de senha, status de download etc.). O CW1200 se conecta a um PC via USB e possui dois protocolos de comunicação com o MK: UART e SPI.


Para trabalhar com o ChipWhisperer, você precisa instalar drivers, baixar as bibliotecas Python e exemplos de trabalho do GitHub, ou baixar a imagem preparada de uma máquina virtual no Linux, na qual todas as bibliotecas e exemplos de trabalho estão pré-instalados. Essas bibliotecas abertas contêm:


• protocolo de comunicação com ChipWhisperer;


• algoritmos matemáticos para processar ataques a métodos populares de criptografia;


Protocolos para comunicação com gerenciadores de inicialização do popular MK;


• firmware preparado para treinamento nas placas com MK, incluído no kit.


Decidimos passar por todos os tutoriais no antigo site da NewAE. Agora, outro recurso está sendo desenvolvido, onde informações mais relevantes são apresentadas e há um fórum .


Neste artigo, apresentaremos apenas alguns exemplos de guias dos desenvolvedores do ChipWhisperer e os implementamos não nas placas com MK incluídas no pacote, mas no STM32F103RBT6:



Placa STM32F103RBT6


Também escrevemos código idêntico aos exemplos preparados, mas com bibliotecas HAL geradas a partir do CubeMX. Todas essas ações são necessárias para confirmar que os ataques com o ChipWhisperer podem ser implementados em qualquer dispositivo aleatório, e não apenas nas placas presentes no kit.


A seguir, fornecemos uma breve visão geral e exemplos de ataques SCA e ataques de falha.


Análise SCA


A base dos ataques da SCA é rastrear alterações nos fatores externos do estado do MC (consumo atual do MC, temperatura, campo eletromagnético) durante o desenvolvimento de várias instruções. O ChipWhisperer implementa canais para monitorar a energia usando um ADC e um campo eletromagnético usando uma antena.


A análise SCA é eficaz na detecção de senhas, chaves de criptografia, etc. O site da NewAE apresenta diversos
diretrizes úteis para encontrar chaves de criptografia e para ataques SCA , mas daremos apenas um exemplo de análise de SCA, uma vez que ataques de falha são de maior interesse para nós.


Exemplo de ataques SCA - análise de assinatura de energia


Este guia demonstra um tipo de ataque SCA - rastreando a entrada de senha caractere por caractere, monitorando as assinaturas no canal de energia. Repetindo assinaturas de energia, é possível identificar o desenvolvimento de várias instruções do programa dentro do MK. O exemplo acima demonstra o desenvolvimento da entrada MK da senha, rastreando a assinatura da operação de break .


Vamos começar a preparação. Primeiro de tudo, você precisa fazer as conexões de acordo com a figura:



Conexão MC para análise SCA


O diagrama mostra os componentes que não precisam ser conectados (ao contrário da conexão MK padrão). As setas indicam os pontos de conexão do ChipWhisperer e as assinaturas indicam seus pinos.


Prepare o firmware MK. A seguinte função está no loop principal while while(1) :


 028 void password_check() { 029 char passwd[32]; 030 char correct_passwd[] = "Vulkan"; 031 HAL_Delay(10); 032 uart_send("WARNING: UNAUTHORIZED ACCESS WILL BE PUNISHED\n"); 033 led_off(); 034 035 //Get password 036 uart_send("Please enter password to continue: "); 037 uart_receive(passwd, 32); 038 039 uint8_t passbad = 0; 040 041 led_on(); 042 043 for(uint8_t i = 0; i < sizeof(correct_passwd); i++) 044 { 045 if (correct_passwd[i] != passwd[i]) 046 { 047 passbad = 1; 048 break; 049 } 050 } 051 052 if (passbad) 053 { 054 //Stop them fancy timing attacks 055 int wait = rand() % 100000; 056 for(volatile int i = 0; i < wait; i++) 057 { 058 ; 059 } 060 HAL_Delay(4); 061 uart_send("PASSWORD FAIL\n"); 062 } 063 else 064 { 065 uart_send("Access granted, Welcome!\n"); 066 } 067 while(1) 068 { 069 ; 070 } 071 } 

A linha 030 define a senha para a entrada - Vulkan. Em seguida, o LED acende
led_on() e uma mensagem UART é enviada sobre a solicitação de senha. A função led_on() ativa o pino GPIO do PA12 MK e notifica um evento no qual o ChipWhisperer começará a acumular formas de onda. É neste pino que CW_TRIG deve estar conectado. Tudo isso é "sintetizado" por conveniência, mas em casos reais a diferença será insignificante, pois você pode inserir um atraso no número de ciclos do relógio CLOCK em relação a qualquer evento ao qual o CW_TRIG esteja conectado. Por exemplo, pode ser o início do download do MK, a recepção / transmissão de mensagens, a inclusão de um LED etc.


Além disso, o MK aguarda a inserção de uma senha, que verificará caractere por caractere. Se algum caractere da fila não corresponder, por exemplo, três caracteres estiverem corretos e o quarto não, será necessário sair do loop for com a instrução break e relatar a senha incorreta. Nas linhas 055-059, um gerador de atraso aleatório é implementado. Esse design costuma ser usado para complicar a conduta de ataques temporários (ou seja, rastrear alterações no tempo de resposta de todo o sistema). Esse design foi incluído para entender que não selecionamos uma senha usando o método de ataque temporário.


O código do tutorial do Jupyter Python está hospedado no recurso correspondente. A figura abaixo mostra um exemplo de digitação de uma senha com a saída da forma de onda da fonte de alimentação do MK com cada novo símbolo correto. Observe que, com a entrada de caracteres da senha correta (a senha que você digita é mostrada na parte superior da figura), a assinatura da operação de break é deslocada para a linha 046 (destacada em laranja na figura abaixo). Esta é a "fraqueza" da interrupção pela operação de interrupção ao verificar a senha por caractere da senha.



Oscilogramas de senha


Como resultado da familiarização com este guia, descobrimos como é fácil ignorar a proteção por senha com essa abordagem para verificá-la usando a análise SCA. Basta comentar a operação de break na linha 048 neste firmware e, em geral, a verificação da senha será bem-sucedida, mas o rastreamento do processamento da assinatura se tornará mais complicado. Portanto, para reduzir a eficácia de tais ataques, você deve evitar a operação de interrupção imediata dos ciclos de verificação.


A complexidade dessa análise está em encontrar as assinaturas necessárias. Portanto, conduzir esses ataques pode complicar significativamente a introdução de construções temporárias rand() no momento da verificação de senha, adicionando cálculos adicionais ou adicionando ruído a outros componentes.


Ataques de falha


Os ataques de falha são realizados por uma série de impulsos de curto prazo em um exato momento no tempo, de acordo com um determinado método de influência. Os métodos mais populares são: relógio (falha no CLK), potência (falha no Vcc) e campo eletromagnético. O campo eletromagnético é gerado por uma faísca de alta tensão perto do MC. Para isso, o NewAE usa o equipamento ChipSHOUTER . Como não o compramos, realizamos apenas os ataques CLK-glitch e Vcc-glitch.


Os ataques de falha são realizados adicionando um pulso de voltagem: para CLK-glitch - ao sinal CLOCK externo do MK (de um quartzo ou gerador externo), para Vcc-glitch - na energia.


Em geral, os ataques de falhas permitem ignorar qualquer instrução MK, por exemplo, digitar uma senha, solicitação de acesso, contrato de licença, etc. Os ataques de falha são mais complexos, meticulosos e demorados. Além disso, é necessário repetir repetidamente o ataque de falha, pois seu sucesso é de natureza probabilística e depende dos parâmetros do pulso. A seguir estão as opções de falha:


• scope.glitch.width - largura do pulso em porcentagem em relação ao CLOCK;


• scope.glitch.offset - deslocamento do impulso em porcentagem em relação ao CLOCK;


Scope.glitch.repeat - o número de repetições de pulsos de ataque;


Scope.glitch.ext_offset - o número de medidas perdidas após o acionamento do evento.


Os mapeamentos de falhas para CLK-glitch e Vcc-glitch são mostrados nos diagramas de tempo:



Diagrama de tempo para CLK-glitch



Diagrama de tempo para falha de Vcc


Todos os parâmetros do pulso de falha são selecionados para que o núcleo MK opere em um modo instável (devido ao qual as instruções são ignoradas).


De acordo com os resultados de ataques de falha, foi revelado que, se o valor do parâmetro scope.glitch.repeat for muito pequeno, o “escorregamento” das instruções não ocorrerá. Se você definir um valor grande, poderá pular não apenas as instruções necessárias, mas também todas as seguintes. Na maioria dos casos, basta procurar scope.glitch.repeat na região de 5 a 25. Com relação a outros parâmetros, tudo depende do tipo de ataque e das condições de conexão.


CLK-glitch


Os ataques de falha do CLK são realizados adicionando pulsos de menor duração ao sinal CLOCK MK. Portanto, o CLOCK deve ser desconectado do MK e alimentá-lo do ChipWhisperer já com um ataque de falha do CLK.


Primeiro você precisa conectar o ChipWhisperer ao MK:



Esquema de conexão para CLK-glitch


Todo o código Python e uma descrição detalhada do manual são apresentados no recurso . Em seguida, no STM32F103RBT6, “preencha” o firmware, onde a seguinte função é adicionada ao while(1) :


 075 void glitch_password(void) 076 { 077 char inp[16]; 078 char c = 'A'; 079 unsigned char cnt = 0; 080 uart_send("Password:"); 081 082 while((c != '\n') & (cnt < 16)) 083 { 084 c = getch(); 085 inp[cnt] = c; 086 cnt++; 087 } 088 089 char passwd[] = "Vulkan"; 090 char passok = 1; 091 092 led_on(); 093 led_off(); 094 095 //Simple test - doesn't check for too-long password! 096 for(cnt = 0; cnt < 5; cnt++) 097 { 098 if (inp[cnt] != passwd[cnt]) 099 { 100 passok = 0; 101 } 102 } 103 if (!passok){ 104 uart_send("Denied\n"); 105 } 106 else 107 { 108 uart_send("Wow! Vulkan win!\n"); 109 } 110 } 

Nosso objetivo é ignorar a if na linha 103 ao inserir a senha errada e entrar no caso else na linha 106. O mais importante nesse ataque é verificar a variável passok na linha 103. Para fazer isso, selecione o parâmetro scope.glitch.ext_offset. Isso é mais fácil, conectando o osciloscópio ao UART e configurando o glitch para o local da interferência, pois o glitch percorre todo o MK:



Localização da falha


O código e a metodologia de ataque são retirados deste manual (seção Loop de ataque, blocos 9 a 10). A única coisa que alteramos no código foi permitir a saída de todas print(response) mensagens de print(response) sem filtragem, pois eventos importantes são frequentemente ignorados devido a filtros configurados, como:


 if need_response not in response: pass else: print ("!") 

As figuras abaixo mostram exemplos de um log de saída de mensagens que aparece quando um ataque de falha do CLK está próximo do sucesso ou está longe de ser bem-sucedido. Ao se aproximar dos parâmetros de falha corretos, as instabilidades na operação do MK começam a aparecer (as mensagens são interrompidas, o MK é reiniciado). Isso pode ser uma dica ao pesquisar.



Saída de mensagem durante um ataque de falha com parâmetros longe do êxito (a) e próximos do sucesso (b)



O resultado de um ataque bem-sucedido de falha de CLK


Como resultado dos ataques, foi revelado que os parâmetros do pulso do glitch CLK podem "flutuar" dependendo da qualidade da conexão do ChipWhisperer ao CLOCK MK. Por exemplo, ao definir a sonda do osciloscópio no pino CLOCK, o parâmetro scope.glitch.offset se tornou diferente para um ataque bem-sucedido, pois a sonda possui seus próprios parâmetros capacitivamente indutivos que corrigem a falha de alta frequência. Portanto, conectar-se através de um cabo longo e não blindado pode trazer surpresas. Caso contrário, os ataques de falha do CLK podem ser chamados estáveis, como seus parâmetros mudaram ligeiramente para várias instruções (se, por, enquanto foram verificados).


O método de proteção contra esses ataques é usar o sinal interno do CLOCK MK, mas possui a pior estabilidade de temperatura e tempo. Além disso, um método eficaz pode ser a introdução de um atraso de tempo aleatório antes e depois de instruções importantes (verificação de senhas, dados pessoais, etc.), o que pode complicar o acerto exato do pulso da falha do CLK no momento certo.


Vcc-glitch


O Vcc-glitch, como o CLK-glitch, introduz interferência de alta frequência na operação do MK, apenas com um curto-circuito da fonte de alimentação do MK ao terra. Ao realizar ataques de falha de Vcc, deve-se levar em consideração que os parâmetros de um pulso bem-sucedido dependem de muitos fatores, como:


• recursos de design da placa de circuito impresso para MK e a presença de uma cinta diversificada;


• o comprimento do cabo coaxial para conectar o MK e a porta de falha do ChipWhisperer (quanto mais longo o cabo, menor a probabilidade de um ataque bem-sucedido, o comprimento ideal é de 10 a 15 cm);


• série MK;


• instruções a serem puladas;


• otimização de compilador MK;


• tipo de transistor MOSFET (devido à diferença nos componentes de alta frequência dos parâmetros S).


Portanto, ao realizar ataques, é necessário garantir que esses parâmetros não sejam alterados.


Primeiro você deve conectar o ChipWhisperer ao MK:



Esquema de conexão para ataques Vcc-glitch


A seguir, fazemos o "flash" do firmware no MK, onde no while(1) existe a seguinte função:


 115 void glitch_while() 116 { 117 volatile uint8_t infinity = 0; 118 uart_send(" Hello habr!"); 119 led_on(); 120 led_off(); 121 122 while(infinity != 2) 123 { 124 ; 125 } 126 uart_send("WOW!!! Vcc Glitch work!"); 127 while(1) 128 { 129 ; 130 } 131 } 

O MK após enviar a mensagem "Hello habr!" Entra em um loop sem fim na linha 122. Nossa tarefa é remover o MK desse loop usando a falha Vcc. Nesse loop, a variável volatile uint8_t infinity é usada como uma condição, que nunca será igual a dois quando o programa for volatile uint8_t infinity normalmente. Se colocarmos while(1) vez de while(infinity != 2) , o compilador ignorará o código abaixo, incluindo nossa mensagem anunciando a saída do loop infinito. Devido a uma variável do tipo volatile compilador não poderá fazer isso. O while(1) linha 127 é adicionado para que após o WOW !!! Vcc Glitch trabalho! nós não exibimos novamente Olá habr!


Usamos o código Python para controlar o ChipWhisperer neste guia . Aqui estão as mensagens do MK:



O resultado de um ataque bem-sucedido de falha de Vcc


Como pode ser visto na figura, o ataque Vcc-glitch foi bem-sucedido.


A dificuldade em conduzir um ataque de falha Vcc está na seleção dos parâmetros de pulso corretos. A implementação desse ataque levou mais tempo em comparação com os outros, pois a implementação bem-sucedida dos ataques de falha de Vcc depende dos fatores descritos acima.


O método de proteção contra esses ataques também pode ser a introdução de um atraso aleatório antes de instruções importantes e depois delas (verificação de senhas, dados pessoais etc.). Isso pode complicar o acerto exato do pulso da falha Vcc no momento certo. Um aumento no acoplamento capacitivo entre energia e terra durante a fiação da placa de circuito impresso também pode ajudar um pouco.


Conclusões


Ataques conduzidos permitem contornar as instruções no MK. Um exemplo de uma análise SCA mostrou que mesmo o tipo mais simples de um ataque desse tipo pode ameaçar a segurança de seus dados (senhas, chaves de criptografia). Garantimos que os ataques de falha contornem várias instruções e métodos de proteção de software previstos nos dispositivos. O método universal de proteção contra ataques nos manuais considerados pode ser a introdução de atrasos aleatórios ao executar instruções importantes no MC.


Nosso estudo de ataques de hardware não termina aí. No futuro, planejamos explorar a possibilidade de ignorar a verificação do byte de firmware do firmware MK usando ataques de falha de Vcc. O acesso ao firmware MK pode abrir grandes oportunidades para um invasor: da clonagem de um dispositivo para revenda ao acesso total a todas as informações proprietárias e controle sobre o MK.


Em nossos experimentos com falha de Vcc, tentamos ignorar a proteção do firmware e conseguimos. Garantimos que isso seja possível. Apresentaremos experimentos demonstrando a leitura do firmware MK oculto no próximo artigo.



A Raccoon Security é uma equipe especial de especialistas do Centro Técnico e Científico do Vulcão na área de segurança da informação prática, criptografia, circuitos, engenharia reversa e criação de software de baixo nível.

Source: https://habr.com/ru/post/pt480500/


All Articles