Anteriormente, a equipe da CertiK descobriu uma série de vulnerabilidades de negação de serviço na blockchain Sui. Dentre essas vulnerabilidades, destaca-se uma nova vulnerabilidade de alto impacto. Essa vulnerabilidade pode fazer com que os nós da rede Sui sejam incapazes de processar novas transações e o efeito é equivalente a um desligamento completo de toda a rede.
Na segunda-feira passada, a CertiK recebeu uma recompensa de bug de $ 500.000 da SUI por descobrir essa grande vulnerabilidade de segurança. A CoinDesk, uma mídia autorizada na indústria dos EUA, informou sobre o evento e, em seguida, a grande mídia também divulgou notícias relacionadas após seu relatório.
Essa vulnerabilidade de segurança é claramente chamada de "Hamster Wheel": seu método de ataque exclusivo é diferente dos ataques conhecidos atualmente. O invasor só precisa enviar uma carga útil de cerca de 100 bytes para acionar um loop infinito no nó de verificação Sui. , tornando-o insensível a novas transações.
Além disso, os danos causados pelo ataque podem continuar após a reinicialização da rede, podendo ser propagados automaticamente na rede Sui, tornando todos os nós incapazes de processar novas transações como hamsters rodando sem parar na roda. Portanto, nos referimos a esse tipo único de ataque como um ataque de "roda de hamster".
Depois de descobrir o bug, a CertiK o relatou a Sui por meio do programa de recompensas de bugs de Sui. Sui também respondeu de forma eficaz na primeira vez, confirmou a gravidade da vulnerabilidade e ativamente tomou as medidas correspondentes para reparar o problema antes do lançamento da rede principal. Além de corrigir essa vulnerabilidade específica, a Sui também implementou mitigações preventivas para reduzir o dano potencial que essa vulnerabilidade poderia causar.
Para agradecer à equipe da CertiK por sua divulgação responsável, Sui concedeu à equipe da CertiK uma recompensa de US$ 500.000.
Os detalhes desta vulnerabilidade crítica serão divulgados no nível técnico abaixo, e a causa raiz e o impacto potencial da vulnerabilidade serão esclarecidos.
Explicação da vulnerabilidade
O papel principal dos validadores no Sui
Para cadeias de blocos baseadas na linguagem Move, como Sui e Aptos, o mecanismo de proteção para evitar ataques de carga maliciosa é principalmente a tecnologia de verificação estática. Por meio da tecnologia de verificação estática, o Sui pode verificar a validade da carga enviada pelo usuário antes que o contrato seja emitido ou atualizado. O validador disponibiliza uma série de verificadores para garantir a exatidão da estrutura e semântica, somente após passar na verificação do cheque, o contrato entrará na máquina virtual Move para ser executado.
Ameaças maliciosas de carga útil na cadeia de movimento
A cadeia Sui fornece um novo conjunto de modelos de armazenamento e interfaces sobre a máquina virtual Move original, portanto, a Sui tem uma versão personalizada da máquina virtual Move. A fim de oferecer suporte a novas primitivas de armazenamento, a Sui apresenta ainda uma série de métodos de inspeção adicionais e personalizados para verificação de segurança de cargas úteis não confiáveis, como segurança de objetos e funções de acesso de armazenamento global. Essas verificações personalizadas se encaixam nos recursos exclusivos do Sui, por isso chamamos essas verificações personalizadas de validadores Sui.
Ordem de Sui de checagem de cargas
Conforme mostrado na figura acima, a maioria das verificações no verificador executa a verificação de segurança estrutural no CompiledModule (representando a execução da carga útil do contrato fornecida pelo usuário). Por exemplo, use o "Duplicate Checker" para garantir que não haja entradas duplicadas na carga de tempo de execução; use o "Limit Checker" para garantir que o comprimento de cada campo na carga de tempo de execução esteja dentro do limite de entrada máximo permitido.
Além das verificações estruturais, as verificações estáticas do verificador ainda requerem métodos de análise mais complexos para garantir a robustez de payloads não confiáveis no nível semântico.
Aprenda sobre o interpretador abstrato do Move:
Análise Linear e Iterativa
O interpretador abstrato fornecido pelo Move é uma estrutura especialmente projetada para realizar análises de segurança complexas em bytecode por meio de interpretação abstrata. Esse mecanismo torna o processo de verificação mais granular e preciso, e cada validador pode definir seu estado abstrato exclusivo para análise.
Na inicialização, o interpretador abstrato constrói um gráfico de fluxo de controle (CFG) a partir de módulos compilados. Cada bloco básico nesses CFGs mantém um conjunto de estados, um "estado de pré-encomenda" e um "estado de pós-encomenda". O "estado de pré-ordem" fornece um instantâneo do estado do programa antes da execução do bloco básico, enquanto o "estado pós-ordem" fornece uma descrição do estado do programa após a execução do bloco básico.
Quando o interpretador abstrato não encontra um salto (ou loop) no gráfico de fluxo de controle, ele segue um princípio de execução linear simples: cada bloco básico é analisado por sua vez e a instrução anterior é calculada de acordo com a semântica de cada instrução no bloco.Estado sequencial e estado pós-sequencial. O resultado é um instantâneo preciso do estado de cada bloco básico durante a execução de um programa, ajudando a verificar as propriedades de segurança do programa.
Fluxo de trabalho do interpretador abstrato Move
No entanto, o processo se torna mais complicado quando há loops no fluxo de controle. A aparência de um ciclo significa que o gráfico de fluxo de controle contém uma borda de salto para trás. A origem da borda de salto para trás corresponde ao estado subsequente do bloco básico atual e o bloco básico de destino (cabeça do loop) back edge é previamente analisado Portanto, o interpretador abstrato precisa mesclar cuidadosamente os estados dos dois blocos básicos relacionados ao jumpback.
Se o estado mesclado for diferente do estado de pré-encomenda existente do bloco básico de cabeçalho de loop, o interpretador abstrato atualiza o estado do bloco básico de cabeçalho de loop e reinicia a análise a partir desse bloco básico. Este processo de análise iterativa continuará até que o pré-estado do loop se estabilize. Em outras palavras, esse processo é repetido até que o estado de pré-encomenda do bloco básico de cabeça de loop não mude mais entre as iterações. Atingir um ponto fixo indica que a análise do ciclo está completa.
Sui IDLeak Validator:
Análise de interpretação abstrata personalizada
Ao contrário do design original do Move, a plataforma blockchain de Sui apresenta um modelo de armazenamento global centrado em "objetivos" exclusivo. Uma característica notável deste modelo é: qualquer estrutura de dados com um atributo chave (armazenado na cadeia como um índice) deve ter o tipo de ID como o primeiro campo da estrutura. O campo ID é imutável e não pode ser transferido para outros objetos, pois cada objeto deve ter um ID único globalmente. Para garantir essas propriedades, Sui construiu um conjunto de lógica de análise personalizada sobre o interpretador abstrato.
O verificador IDLeak, também conhecido como id_leak_verifier, funciona em conjunto com o interpretador abstrato para análise. Ele tem seu próprio AbstractDomain exclusivo, chamado AbstractState. Cada AbstractState consiste em AbstractValue correspondente a múltiplas variáveis locais. O estado de cada variável local é monitorado por AbstractValue para rastrear se uma variável de ID é totalmente nova.
No processo de empacotamento da estrutura, o validador IDLeak só permite empacotar um novo ID em uma estrutura. Ao abstrair a análise de interpretação, os validadores IDLeak podem rastrear exaustivamente o estado do fluxo de dados local para garantir que nenhum ID existente seja transferido para outros objetos struct.
Problema de inconsistência de manutenção do estado do validador Sui IDLeak
O validador IDLeak é integrado ao interpretador abstrato Move implementando a função AbstractState::join. Essa função desempenha um papel integral no gerenciamento de estado, especialmente na fusão e atualização de valores de estado.
Examine essas funções em detalhes para entender sua operação:
Em AbstractState::join, a função recebe outro AbstractState como entrada e tenta mesclar seu estado local com o estado local do objeto atual. Para cada variável local no estado de entrada, ele compara o valor dessa variável com seu valor atual no estado local (o padrão é AbstractValue::Other se não for encontrado). Se os dois valores não forem iguais, ele definirá um sinalizador "alterado" como base para saber se o resultado da mesclagem de estado final foi alterado e atualizará o valor da variável local no estado local chamando AbstractValue::join.
Em AbstractValue::join, a função compara seu valor com outro AbstractValue. Se forem iguais, retornará o valor passado. Se não for igual, retorna AbstractValue::Other.
No entanto, essa lógica de manutenção de estado contém um problema de inconsistência oculto. Embora AbstractState::join retorne um resultado indicando que o estado mesclado foi alterado (JoinResult::Changed) com base na diferença entre os valores novos e antigos, o valor do estado atualizado mesclado ainda pode permanecer inalterado.
Esse problema de inconsistência é causado pela ordem das operações: a decisão de mudar o estado em AbstractState::join ocorre antes da atualização do estado (AbstractValue::join), e essa decisão não reflete o resultado real da atualização do estado.
Além disso, em AbstractValue::join, AbstractValue::Other desempenha um papel decisivo no resultado da mesclagem. Por exemplo, se o valor antigo for AbstractValue::Other e o novo valor for AbstractValue::Fresh, o valor do estado atualizado ainda será AbstractValue::Other, mesmo que os valores antigo e novo sejam diferentes, o próprio estado permanece inalterado após a atualização.
Exemplo: incoerência de conexões com estado
Isso introduz uma inconsistência: o resultado da mesclagem do estado de um bloco básico é considerado "alterado", mas o próprio valor do estado mesclado não mudou. No processo de análise de interpretação abstrata, tais inconsistências podem ter sérias consequências. Revisamos o comportamento de um interpretador abstrato quando ocorre um ciclo em um gráfico de fluxo de controle (CFG):
Quando um loop é encontrado, o interpretador abstrato emprega um método de análise iterativa para mesclar o estado do bloco básico alvo de salto para trás e o bloco básico atual. Se o estado mesclado mudar, o interpretador abstrato irá reanalisar a partir do alvo do salto.
No entanto, se a operação de fusão da análise de interpretação abstrata erroneamente marcar o resultado da fusão de estado como "mudança", quando na verdade o valor da variável interna do estado não mudou, isso levará a uma reanálise sem fim, resultando em uma Loop infinito.
Exploração adicional de inconsistências
** Aciona loop infinito no validador Sui IDLeak **
Explorando essa inconsistência, um invasor pode construir um gráfico de fluxo de controle malicioso que engana os validadores do IDLeak em um loop infinito. Este gráfico de fluxo de controle cuidadosamente construído consiste em três blocos básicos: BB1 e BB2, BB3. Vale a pena notar que introduzimos intencionalmente uma borda de salto para trás de BB3 para BB2 para construir um loop.
Status CFG+ malicioso pode levar a um loop infinito interno no validador IDLeak
O processo começa com BB2, onde o AbstractValue de uma determinada variável local é definido como ::Other. Depois de executar BB2, o fluxo é transferido para BB3 onde a mesma variável é definida como ::Fresh. No final de BB3, há uma borda de salto para trás, saltando para BB2.
As inconsistências acima mencionadas desempenham um papel fundamental na interpretação abstrata deste exemplo. Quando a borda de salto para trás é processada, o interpretador abstrato tenta conectar o estado de pós-ordem de BB3 (com a variável "::Fresh") com o estado de pré-ordem de BB2 (com a variável "::Outro"). A função AbstractState::join percebe a diferença entre os valores antigos e novos e define o sinalizador "change" para indicar que o BB2 precisa ser reanalisado.
No entanto, o comportamento dominante de "::Other" em AbstractValue::join significa que, após o AbstractValue ser mesclado, o valor real da variável de estado BB2 ainda é "::Other" e o resultado da mesclagem de estado não foi alterado .
Então, uma vez que este processo cíclico começa, ou seja, enquanto os validadores continuam a reanalisar BB2 e todos os seus nós de blocos básicos sucessores (BB3 neste caso), ele continua indefinidamente. O loop infinito consome todos os ciclos de CPU disponíveis, tornando-o incapaz de processar e responder a novas transações, que persistem nas reinicializações do validador.
Ao explorar essa vulnerabilidade, os nós de validação são executados indefinidamente como hamsters em uma roda em um loop infinito, incapazes de processar novas transações. Portanto, nos referimos a esse tipo único de ataque como um ataque de "roda de hamster".
O ataque de “roda de hamster” pode efetivamente paralisar os validadores Sui, o que, por sua vez, pode derrubar toda a rede Sui.
Depois de entender a causa da vulnerabilidade e o processo de acionamento, construímos um exemplo concreto usando a seguinte simulação de bytecode Move e acionamos com sucesso a vulnerabilidade na simulação no ambiente real:
Este exemplo mostra como acionar a vulnerabilidade em um ambiente real por meio de bytecode cuidadosamente construído. Especificamente, um invasor pode acionar um loop infinito no validador IDLeak, consumindo todos os ciclos de CPU de um nó Sui com uma carga útil de apenas cerca de 100 bytes, impedindo efetivamente o processamento de novas transações e causando uma negação de serviço na rede Sui.
O ataque "Hamster Wheel" continua prejudicando a rede Sui
O programa de recompensas de bugs de Sui possui regulamentos rígidos sobre a avaliação dos níveis de vulnerabilidade, principalmente com base no grau de dano a toda a rede. As vulnerabilidades que atendem à classificação "crítica" devem desligar toda a rede e impedir efetivamente novas confirmações de transação e exigir um hard fork para corrigir o problema; (médio)" ou vulnerabilidades de "alto risco (alto)".
A vulnerabilidade "roda do hamster" descoberta pela equipe CertiK Skyfall pode desligar toda a rede Sui e requer o lançamento oficial de uma nova versão para atualização e reparo. Sui finalmente classificou a vulnerabilidade como "Crítica" com base em sua criticidade. Para entender melhor o grave impacto causado pelo ataque "hamster wheel", é necessário entendermos a complexa arquitetura do sistema de back-end do Sui, especialmente todo o processo de publicação ou atualização de transações na cadeia.
Visão geral das interações para envio de transações no Sui
Inicialmente, as transações do usuário são enviadas via RPC de front-end e passadas para serviços de back-end após a verificação básica. O serviço de back-end Sui é responsável por validar ainda mais as cargas de transações recebidas. Depois de verificar com sucesso a assinatura do usuário, a transação é convertida em um certificado de transação (contendo as informações da transação e a assinatura de Sui).
Esses certificados de transação são parte fundamental do funcionamento da rede Sui e podem ser disseminados entre os diversos nós de verificação da rede. Para transações de criação/atualização de contrato, antes que possam ser carregados na cadeia, o nó de verificação chamará o verificador Sui para verificar e verificar a validade da estrutura/semântica do contrato desses certificados. É durante esse estágio crítico de verificação que a vulnerabilidade de "loop infinito" pode ser acionada e explorada.
Quando a vulnerabilidade foi acionada, ela fez com que o processo de verificação fosse interrompido indefinidamente, impedindo efetivamente a capacidade do sistema de processar novas transações e fazendo com que a rede fosse totalmente desligada. Para adicionar insulto à lesão, a situação persistiu após o reinício do nó, o que significava que as atenuações tradicionais estavam longe de serem adequadas. Assim que a vulnerabilidade for ativada, haverá "danos contínuos" e deixará um impacto duradouro em toda a rede Sui.
Solução da Sui
Após o feedback da CertiK, Sui confirmou a vulnerabilidade em tempo hábil e lançou uma correção para corrigir a falha crítica. A correção garante a consistência entre as alterações de estado e os sinalizadores pós-alteração, removendo o efeito crítico do ataque de "roda de hamster".
Para remover a inconsistência acima mencionada, a correção de Sui inclui um ajuste pequeno, mas crítico, na função AbstractState::join. Este patch remove a lógica de determinar o resultado da mesclagem de estado antes de executar AbstractValue::join. Em vez disso, execute primeiro a função AbstractValue::join para mesclagem de estado e defina a mesclagem comparando o resultado final da atualização com o valor do estado original (antigo _value) Um sinalizador para alterações.
Dessa forma, o resultado da fusão de estados será consistente com o resultado da atualização real e não ocorrerá um loop infinito durante o processo de análise.
Além de corrigir essa vulnerabilidade específica, a Sui também implantou mitigações para reduzir o impacto de futuras vulnerabilidades do validador. De acordo com a resposta de Sui no relatório de bug, a mitigação envolve um recurso chamado Denylist.
"No entanto, os validadores têm um arquivo de configuração de nó que lhes permite rejeitar temporariamente certas classes de transações. Essa configuração pode ser usada para desativar temporariamente o processamento de lançamentos e atualizações de pacotes. Devido a esse bug, execute o Sui antes de assinar um lançamento ou atualização de pacote tx validadores, enquanto a lista de bloqueio impedirá a execução do validador e eliminará o tx malicioso, negar temporariamente esses tipos de tx é uma mitigação 100% eficaz (embora interrompa temporariamente o serviço para pessoas que tentam liberar ou atualizar o código).
A propósito, temos esse arquivo de configuração de lista de negação de TX há algum tempo, mas também adicionamos um mecanismo semelhante para certificados como uma mitigação de acompanhamento para sua vulnerabilidade de "loop do validador" relatada anteriormente. Com esse mecanismo, teremos mais flexibilidade contra esse ataque: usaremos a configuração da lista de negação de certificado para fazer com que os validadores esqueçam os certificados ruins (quebrando o loop infinito) e a configuração da lista de negação TX para proibir publicações/upgrades, evitando assim a criação de novas transações de ataque malicioso. Obrigado por nos fazer pensar sobre isso!
Um validador tem um número limitado de "ticks" (diferente do gas) para verificação do bytecode antes de assinar uma transação, e se todo o bytecode emitido em uma transação não puder ser verificado nestes muitos ticks, o validador se recusará a assinar a transação, impedindo de executar na rede. Anteriormente, a medição aplicava-se apenas a um conjunto selecionado de passagens complexas do validador. Para combater isso, estendemos a medição para cada validador para garantir uma restrição no trabalho que um validador realiza durante o processo de validação de cada tick. Também corrigimos um possível bug de loop infinito no validador de vazamento de ID. "
--Explicação dos desenvolvedores Sui sobre correções de bugs
Em suma, o Denylist permite que os validadores evitem temporariamente a exploração de vulnerabilidades nos validadores e evitem efetivamente possíveis danos causados por algumas transações maliciosas, desativando o processo de lançamento ou atualização. Quando as medidas de mitigação do Denylist entram em vigor, os nós garantem que podem continuar trabalhando sacrificando suas próprias funções de contrato de publicação/atualização.
Resumir
Neste artigo, compartilhamos os detalhes técnicos do ataque "Hamster Wheel" descoberto pela equipe CertiK Skyfall, explicando como esse novo tipo de ataque explora as principais vulnerabilidades para causar o desligamento completo da rede Sui. Além disso, também estudamos cuidadosamente a resposta oportuna de Sui para corrigir esse problema crítico e compartilhamos a correção de vulnerabilidade e os métodos de mitigação subsequentes para vulnerabilidades semelhantes.
Ver original
O conteúdo é apenas para referência, não uma solicitação ou oferta. Nenhum aconselhamento fiscal, de investimento ou jurídico é fornecido. Consulte a isenção de responsabilidade para obter mais informações sobre riscos.
Detalhes técnicos da "roda do hamster" mais recente vulnerabilidade de Sui e análise aprofundada
Anteriormente, a equipe da CertiK descobriu uma série de vulnerabilidades de negação de serviço na blockchain Sui. Dentre essas vulnerabilidades, destaca-se uma nova vulnerabilidade de alto impacto. Essa vulnerabilidade pode fazer com que os nós da rede Sui sejam incapazes de processar novas transações e o efeito é equivalente a um desligamento completo de toda a rede.
Na segunda-feira passada, a CertiK recebeu uma recompensa de bug de $ 500.000 da SUI por descobrir essa grande vulnerabilidade de segurança. A CoinDesk, uma mídia autorizada na indústria dos EUA, informou sobre o evento e, em seguida, a grande mídia também divulgou notícias relacionadas após seu relatório.
Essa vulnerabilidade de segurança é claramente chamada de "Hamster Wheel": seu método de ataque exclusivo é diferente dos ataques conhecidos atualmente. O invasor só precisa enviar uma carga útil de cerca de 100 bytes para acionar um loop infinito no nó de verificação Sui. , tornando-o insensível a novas transações.
Além disso, os danos causados pelo ataque podem continuar após a reinicialização da rede, podendo ser propagados automaticamente na rede Sui, tornando todos os nós incapazes de processar novas transações como hamsters rodando sem parar na roda. Portanto, nos referimos a esse tipo único de ataque como um ataque de "roda de hamster".
Depois de descobrir o bug, a CertiK o relatou a Sui por meio do programa de recompensas de bugs de Sui. Sui também respondeu de forma eficaz na primeira vez, confirmou a gravidade da vulnerabilidade e ativamente tomou as medidas correspondentes para reparar o problema antes do lançamento da rede principal. Além de corrigir essa vulnerabilidade específica, a Sui também implementou mitigações preventivas para reduzir o dano potencial que essa vulnerabilidade poderia causar.
Para agradecer à equipe da CertiK por sua divulgação responsável, Sui concedeu à equipe da CertiK uma recompensa de US$ 500.000.
Os detalhes desta vulnerabilidade crítica serão divulgados no nível técnico abaixo, e a causa raiz e o impacto potencial da vulnerabilidade serão esclarecidos.
Explicação da vulnerabilidade
O papel principal dos validadores no Sui
Para cadeias de blocos baseadas na linguagem Move, como Sui e Aptos, o mecanismo de proteção para evitar ataques de carga maliciosa é principalmente a tecnologia de verificação estática. Por meio da tecnologia de verificação estática, o Sui pode verificar a validade da carga enviada pelo usuário antes que o contrato seja emitido ou atualizado. O validador disponibiliza uma série de verificadores para garantir a exatidão da estrutura e semântica, somente após passar na verificação do cheque, o contrato entrará na máquina virtual Move para ser executado.
Ameaças maliciosas de carga útil na cadeia de movimento
A cadeia Sui fornece um novo conjunto de modelos de armazenamento e interfaces sobre a máquina virtual Move original, portanto, a Sui tem uma versão personalizada da máquina virtual Move. A fim de oferecer suporte a novas primitivas de armazenamento, a Sui apresenta ainda uma série de métodos de inspeção adicionais e personalizados para verificação de segurança de cargas úteis não confiáveis, como segurança de objetos e funções de acesso de armazenamento global. Essas verificações personalizadas se encaixam nos recursos exclusivos do Sui, por isso chamamos essas verificações personalizadas de validadores Sui.
Ordem de Sui de checagem de cargas
Conforme mostrado na figura acima, a maioria das verificações no verificador executa a verificação de segurança estrutural no CompiledModule (representando a execução da carga útil do contrato fornecida pelo usuário). Por exemplo, use o "Duplicate Checker" para garantir que não haja entradas duplicadas na carga de tempo de execução; use o "Limit Checker" para garantir que o comprimento de cada campo na carga de tempo de execução esteja dentro do limite de entrada máximo permitido.
Além das verificações estruturais, as verificações estáticas do verificador ainda requerem métodos de análise mais complexos para garantir a robustez de payloads não confiáveis no nível semântico.
Aprenda sobre o interpretador abstrato do Move:
Análise Linear e Iterativa
O interpretador abstrato fornecido pelo Move é uma estrutura especialmente projetada para realizar análises de segurança complexas em bytecode por meio de interpretação abstrata. Esse mecanismo torna o processo de verificação mais granular e preciso, e cada validador pode definir seu estado abstrato exclusivo para análise.
Na inicialização, o interpretador abstrato constrói um gráfico de fluxo de controle (CFG) a partir de módulos compilados. Cada bloco básico nesses CFGs mantém um conjunto de estados, um "estado de pré-encomenda" e um "estado de pós-encomenda". O "estado de pré-ordem" fornece um instantâneo do estado do programa antes da execução do bloco básico, enquanto o "estado pós-ordem" fornece uma descrição do estado do programa após a execução do bloco básico.
Quando o interpretador abstrato não encontra um salto (ou loop) no gráfico de fluxo de controle, ele segue um princípio de execução linear simples: cada bloco básico é analisado por sua vez e a instrução anterior é calculada de acordo com a semântica de cada instrução no bloco.Estado sequencial e estado pós-sequencial. O resultado é um instantâneo preciso do estado de cada bloco básico durante a execução de um programa, ajudando a verificar as propriedades de segurança do programa.
Fluxo de trabalho do interpretador abstrato Move
No entanto, o processo se torna mais complicado quando há loops no fluxo de controle. A aparência de um ciclo significa que o gráfico de fluxo de controle contém uma borda de salto para trás. A origem da borda de salto para trás corresponde ao estado subsequente do bloco básico atual e o bloco básico de destino (cabeça do loop) back edge é previamente analisado Portanto, o interpretador abstrato precisa mesclar cuidadosamente os estados dos dois blocos básicos relacionados ao jumpback.
Se o estado mesclado for diferente do estado de pré-encomenda existente do bloco básico de cabeçalho de loop, o interpretador abstrato atualiza o estado do bloco básico de cabeçalho de loop e reinicia a análise a partir desse bloco básico. Este processo de análise iterativa continuará até que o pré-estado do loop se estabilize. Em outras palavras, esse processo é repetido até que o estado de pré-encomenda do bloco básico de cabeça de loop não mude mais entre as iterações. Atingir um ponto fixo indica que a análise do ciclo está completa.
Sui IDLeak Validator:
Análise de interpretação abstrata personalizada
Ao contrário do design original do Move, a plataforma blockchain de Sui apresenta um modelo de armazenamento global centrado em "objetivos" exclusivo. Uma característica notável deste modelo é: qualquer estrutura de dados com um atributo chave (armazenado na cadeia como um índice) deve ter o tipo de ID como o primeiro campo da estrutura. O campo ID é imutável e não pode ser transferido para outros objetos, pois cada objeto deve ter um ID único globalmente. Para garantir essas propriedades, Sui construiu um conjunto de lógica de análise personalizada sobre o interpretador abstrato.
O verificador IDLeak, também conhecido como id_leak_verifier, funciona em conjunto com o interpretador abstrato para análise. Ele tem seu próprio AbstractDomain exclusivo, chamado AbstractState. Cada AbstractState consiste em AbstractValue correspondente a múltiplas variáveis locais. O estado de cada variável local é monitorado por AbstractValue para rastrear se uma variável de ID é totalmente nova.
No processo de empacotamento da estrutura, o validador IDLeak só permite empacotar um novo ID em uma estrutura. Ao abstrair a análise de interpretação, os validadores IDLeak podem rastrear exaustivamente o estado do fluxo de dados local para garantir que nenhum ID existente seja transferido para outros objetos struct.
Problema de inconsistência de manutenção do estado do validador Sui IDLeak
O validador IDLeak é integrado ao interpretador abstrato Move implementando a função AbstractState::join. Essa função desempenha um papel integral no gerenciamento de estado, especialmente na fusão e atualização de valores de estado.
Examine essas funções em detalhes para entender sua operação:
Em AbstractState::join, a função recebe outro AbstractState como entrada e tenta mesclar seu estado local com o estado local do objeto atual. Para cada variável local no estado de entrada, ele compara o valor dessa variável com seu valor atual no estado local (o padrão é AbstractValue::Other se não for encontrado). Se os dois valores não forem iguais, ele definirá um sinalizador "alterado" como base para saber se o resultado da mesclagem de estado final foi alterado e atualizará o valor da variável local no estado local chamando AbstractValue::join.
Em AbstractValue::join, a função compara seu valor com outro AbstractValue. Se forem iguais, retornará o valor passado. Se não for igual, retorna AbstractValue::Other.
No entanto, essa lógica de manutenção de estado contém um problema de inconsistência oculto. Embora AbstractState::join retorne um resultado indicando que o estado mesclado foi alterado (JoinResult::Changed) com base na diferença entre os valores novos e antigos, o valor do estado atualizado mesclado ainda pode permanecer inalterado.
Esse problema de inconsistência é causado pela ordem das operações: a decisão de mudar o estado em AbstractState::join ocorre antes da atualização do estado (AbstractValue::join), e essa decisão não reflete o resultado real da atualização do estado.
Além disso, em AbstractValue::join, AbstractValue::Other desempenha um papel decisivo no resultado da mesclagem. Por exemplo, se o valor antigo for AbstractValue::Other e o novo valor for AbstractValue::Fresh, o valor do estado atualizado ainda será AbstractValue::Other, mesmo que os valores antigo e novo sejam diferentes, o próprio estado permanece inalterado após a atualização.
Exemplo: incoerência de conexões com estado
Isso introduz uma inconsistência: o resultado da mesclagem do estado de um bloco básico é considerado "alterado", mas o próprio valor do estado mesclado não mudou. No processo de análise de interpretação abstrata, tais inconsistências podem ter sérias consequências. Revisamos o comportamento de um interpretador abstrato quando ocorre um ciclo em um gráfico de fluxo de controle (CFG):
Quando um loop é encontrado, o interpretador abstrato emprega um método de análise iterativa para mesclar o estado do bloco básico alvo de salto para trás e o bloco básico atual. Se o estado mesclado mudar, o interpretador abstrato irá reanalisar a partir do alvo do salto.
No entanto, se a operação de fusão da análise de interpretação abstrata erroneamente marcar o resultado da fusão de estado como "mudança", quando na verdade o valor da variável interna do estado não mudou, isso levará a uma reanálise sem fim, resultando em uma Loop infinito.
Exploração adicional de inconsistências
** Aciona loop infinito no validador Sui IDLeak **
Explorando essa inconsistência, um invasor pode construir um gráfico de fluxo de controle malicioso que engana os validadores do IDLeak em um loop infinito. Este gráfico de fluxo de controle cuidadosamente construído consiste em três blocos básicos: BB1 e BB2, BB3. Vale a pena notar que introduzimos intencionalmente uma borda de salto para trás de BB3 para BB2 para construir um loop.
Status CFG+ malicioso pode levar a um loop infinito interno no validador IDLeak
O processo começa com BB2, onde o AbstractValue de uma determinada variável local é definido como ::Other. Depois de executar BB2, o fluxo é transferido para BB3 onde a mesma variável é definida como ::Fresh. No final de BB3, há uma borda de salto para trás, saltando para BB2.
As inconsistências acima mencionadas desempenham um papel fundamental na interpretação abstrata deste exemplo. Quando a borda de salto para trás é processada, o interpretador abstrato tenta conectar o estado de pós-ordem de BB3 (com a variável "::Fresh") com o estado de pré-ordem de BB2 (com a variável "::Outro"). A função AbstractState::join percebe a diferença entre os valores antigos e novos e define o sinalizador "change" para indicar que o BB2 precisa ser reanalisado.
No entanto, o comportamento dominante de "::Other" em AbstractValue::join significa que, após o AbstractValue ser mesclado, o valor real da variável de estado BB2 ainda é "::Other" e o resultado da mesclagem de estado não foi alterado .
Então, uma vez que este processo cíclico começa, ou seja, enquanto os validadores continuam a reanalisar BB2 e todos os seus nós de blocos básicos sucessores (BB3 neste caso), ele continua indefinidamente. O loop infinito consome todos os ciclos de CPU disponíveis, tornando-o incapaz de processar e responder a novas transações, que persistem nas reinicializações do validador.
Ao explorar essa vulnerabilidade, os nós de validação são executados indefinidamente como hamsters em uma roda em um loop infinito, incapazes de processar novas transações. Portanto, nos referimos a esse tipo único de ataque como um ataque de "roda de hamster".
O ataque de “roda de hamster” pode efetivamente paralisar os validadores Sui, o que, por sua vez, pode derrubar toda a rede Sui.
Depois de entender a causa da vulnerabilidade e o processo de acionamento, construímos um exemplo concreto usando a seguinte simulação de bytecode Move e acionamos com sucesso a vulnerabilidade na simulação no ambiente real:
Este exemplo mostra como acionar a vulnerabilidade em um ambiente real por meio de bytecode cuidadosamente construído. Especificamente, um invasor pode acionar um loop infinito no validador IDLeak, consumindo todos os ciclos de CPU de um nó Sui com uma carga útil de apenas cerca de 100 bytes, impedindo efetivamente o processamento de novas transações e causando uma negação de serviço na rede Sui.
O ataque "Hamster Wheel" continua prejudicando a rede Sui
O programa de recompensas de bugs de Sui possui regulamentos rígidos sobre a avaliação dos níveis de vulnerabilidade, principalmente com base no grau de dano a toda a rede. As vulnerabilidades que atendem à classificação "crítica" devem desligar toda a rede e impedir efetivamente novas confirmações de transação e exigir um hard fork para corrigir o problema; (médio)" ou vulnerabilidades de "alto risco (alto)".
A vulnerabilidade "roda do hamster" descoberta pela equipe CertiK Skyfall pode desligar toda a rede Sui e requer o lançamento oficial de uma nova versão para atualização e reparo. Sui finalmente classificou a vulnerabilidade como "Crítica" com base em sua criticidade. Para entender melhor o grave impacto causado pelo ataque "hamster wheel", é necessário entendermos a complexa arquitetura do sistema de back-end do Sui, especialmente todo o processo de publicação ou atualização de transações na cadeia.
Visão geral das interações para envio de transações no Sui
Inicialmente, as transações do usuário são enviadas via RPC de front-end e passadas para serviços de back-end após a verificação básica. O serviço de back-end Sui é responsável por validar ainda mais as cargas de transações recebidas. Depois de verificar com sucesso a assinatura do usuário, a transação é convertida em um certificado de transação (contendo as informações da transação e a assinatura de Sui).
Esses certificados de transação são parte fundamental do funcionamento da rede Sui e podem ser disseminados entre os diversos nós de verificação da rede. Para transações de criação/atualização de contrato, antes que possam ser carregados na cadeia, o nó de verificação chamará o verificador Sui para verificar e verificar a validade da estrutura/semântica do contrato desses certificados. É durante esse estágio crítico de verificação que a vulnerabilidade de "loop infinito" pode ser acionada e explorada.
Quando a vulnerabilidade foi acionada, ela fez com que o processo de verificação fosse interrompido indefinidamente, impedindo efetivamente a capacidade do sistema de processar novas transações e fazendo com que a rede fosse totalmente desligada. Para adicionar insulto à lesão, a situação persistiu após o reinício do nó, o que significava que as atenuações tradicionais estavam longe de serem adequadas. Assim que a vulnerabilidade for ativada, haverá "danos contínuos" e deixará um impacto duradouro em toda a rede Sui.
Solução da Sui
Após o feedback da CertiK, Sui confirmou a vulnerabilidade em tempo hábil e lançou uma correção para corrigir a falha crítica. A correção garante a consistência entre as alterações de estado e os sinalizadores pós-alteração, removendo o efeito crítico do ataque de "roda de hamster".
Para remover a inconsistência acima mencionada, a correção de Sui inclui um ajuste pequeno, mas crítico, na função AbstractState::join. Este patch remove a lógica de determinar o resultado da mesclagem de estado antes de executar AbstractValue::join. Em vez disso, execute primeiro a função AbstractValue::join para mesclagem de estado e defina a mesclagem comparando o resultado final da atualização com o valor do estado original (antigo _value) Um sinalizador para alterações.
Dessa forma, o resultado da fusão de estados será consistente com o resultado da atualização real e não ocorrerá um loop infinito durante o processo de análise.
Além de corrigir essa vulnerabilidade específica, a Sui também implantou mitigações para reduzir o impacto de futuras vulnerabilidades do validador. De acordo com a resposta de Sui no relatório de bug, a mitigação envolve um recurso chamado Denylist.
"No entanto, os validadores têm um arquivo de configuração de nó que lhes permite rejeitar temporariamente certas classes de transações. Essa configuração pode ser usada para desativar temporariamente o processamento de lançamentos e atualizações de pacotes. Devido a esse bug, execute o Sui antes de assinar um lançamento ou atualização de pacote tx validadores, enquanto a lista de bloqueio impedirá a execução do validador e eliminará o tx malicioso, negar temporariamente esses tipos de tx é uma mitigação 100% eficaz (embora interrompa temporariamente o serviço para pessoas que tentam liberar ou atualizar o código).
A propósito, temos esse arquivo de configuração de lista de negação de TX há algum tempo, mas também adicionamos um mecanismo semelhante para certificados como uma mitigação de acompanhamento para sua vulnerabilidade de "loop do validador" relatada anteriormente. Com esse mecanismo, teremos mais flexibilidade contra esse ataque: usaremos a configuração da lista de negação de certificado para fazer com que os validadores esqueçam os certificados ruins (quebrando o loop infinito) e a configuração da lista de negação TX para proibir publicações/upgrades, evitando assim a criação de novas transações de ataque malicioso. Obrigado por nos fazer pensar sobre isso!
Um validador tem um número limitado de "ticks" (diferente do gas) para verificação do bytecode antes de assinar uma transação, e se todo o bytecode emitido em uma transação não puder ser verificado nestes muitos ticks, o validador se recusará a assinar a transação, impedindo de executar na rede. Anteriormente, a medição aplicava-se apenas a um conjunto selecionado de passagens complexas do validador. Para combater isso, estendemos a medição para cada validador para garantir uma restrição no trabalho que um validador realiza durante o processo de validação de cada tick. Também corrigimos um possível bug de loop infinito no validador de vazamento de ID. "
--Explicação dos desenvolvedores Sui sobre correções de bugs
Em suma, o Denylist permite que os validadores evitem temporariamente a exploração de vulnerabilidades nos validadores e evitem efetivamente possíveis danos causados por algumas transações maliciosas, desativando o processo de lançamento ou atualização. Quando as medidas de mitigação do Denylist entram em vigor, os nós garantem que podem continuar trabalhando sacrificando suas próprias funções de contrato de publicação/atualização.
Resumir
Neste artigo, compartilhamos os detalhes técnicos do ataque "Hamster Wheel" descoberto pela equipe CertiK Skyfall, explicando como esse novo tipo de ataque explora as principais vulnerabilidades para causar o desligamento completo da rede Sui. Além disso, também estudamos cuidadosamente a resposta oportuna de Sui para corrigir esse problema crítico e compartilhamos a correção de vulnerabilidade e os métodos de mitigação subsequentes para vulnerabilidades semelhantes.