Autor: Chengdu Lian’an
Original: “Research on Cross-Chain Bridge Security (3)” | Polygon Warrior Diálise Segura, Como Evitar a Abertura da “Caixa de Pandora”?
Bem-vindo à série de artigos sobre “Cross-chain Bridge Security Research” produzida pela Chengdu Chain Security, no artigo anterior (Cross-Chain Bridge Security Research (2) | O que nos traz o primeiro roubo descentralizado da ponte Nomad?), realizamos uma análise técnica profissional do protocolo da ponte Nomad em detalhes.
Hoje, a Equipe de Pesquisa de Segurança da Cadeia de Chengdu realizará uma diálise segura do Polígono, um guerreiro polígono, então continue lendo.
Quem é 1_Polygon?
Polygon é a solução de escalonamento de camada 2 do Ethereum, com uma visão para construir a internet blockchain do Ethereum. O Polygon fornece uma estrutura comum que permite aos desenvolvedores aproveitar a segurança do Ethereum para criar cadeias personalizadas e focadas em aplicativos e fornecer uma rede interoperável que combina uma variedade de diferentes esquemas de escala, tais como: zk-rollup, PoS, etc. Entre eles, o Polygon PoS é atualmente a solução de escalonamento mais madura e conhecida no Polygon. Ele usa a cadeia lateral para processamento de transações para alcançar o objetivo de melhorar a velocidade de transação e economizar o consumo de gás, e a estrutura da rede inclui principalmente as seguintes três camadas:
Camada Ethereum:
Uma série de contratos na rede principal Ethereum, incluindo, principalmente: contratos Staking, Checkpoint e Reward, são responsáveis pelas funções de gerenciamento de staking relacionadas às apostas PoS, incluindo: fornecer a função de staking do token nativo MATIC, para que qualquer pessoa que estaque o token possa se juntar ao sistema como um validador, verificar a conversão da rede Polygon para obter recompensas de stake, punir validadores por assinaturas duplas, tempo de inatividade do validador e outros comportamentos ilegais e salvar pontos de verificação.
Camada de Heimdall:
A camada de validação de prova de participação, que consiste em um conjunto de nós PoS Heimdall, é responsável por enviar os pontos de verificação da rede Polygon para a rede principal Ethereum enquanto ouve um conjunto de contratos de staking implantados no Ethereum. O processo principal é o seguinte: primeiro, selecione um subconjunto de validadores ativos no pool de validadores como produtores de blocos, que serão responsáveis por criar blocos na camada Bor e transmiti-los, em seguida, validar o hash raiz Merkle e anexar assinaturas com base nos pontos de verificação enviados por Bor e, finalmente, o proponente será responsável por coletar todas as assinaturas do validador para o ponto de verificação especificado, e se o número de assinaturas atingir mais de 2/3, o ponto de verificação será enviado no Ethereum.
Bor Camada:
A camada de produtor de bloco, que consiste em um grupo de produtores de blocos regularmente selecionados por um comitê de validadores na camada de Heimdall, é um subconjunto de validadores responsáveis por agregar transações na cadeia lateral do Polígono e gerar blocos. Esta camada publica periodicamente pontos de verificação para a camada de Heimdall, onde o ponto de verificação representa um instantâneo da cadeia de Bor, como mostrado na imagem abaixo.
2_Polygon Interoperabilidade
2.1 Ponto de verificação
O mecanismo de ponto de verificação é um mecanismo para sincronizar os dados da camada Bor com o Ethereum, onde os dados sincronizados são um ponto de verificação, ou seja, um instantâneo dos dados de bloco da camada Bor contidos em um intervalo de ponto de verificação, o código-fonte é o seguinte:
Proponente: O proponente, que também é selecionado pelos validadores, os produtores de blocos e os proponentes são um subconjunto de validadores, e suas responsabilidades são determinadas por sua participação no pool geral
RootHash: é um hash Merkle gerado a partir do bloco Bor entre StartBlock e EndBlock
A seguir está um pseudo-código para o bloco Bor numerado de 1 a n para gerar o valor RootHash:
Em resumo, esse valor é o valor de hash raiz da árvore Merkel, que é composto pelo número do bloco no cabeçalho do bloco Bor, o carimbo de data/hora do bloco, o valor de hash da raiz da árvore de transações tx hash e o valor de hash keccak256 calculado a partir do hash raiz da árvore de recebimento.
AccountRootHash: Um hash Merkle das informações da conta relacionadas ao validador que precisa ser enviado para cada ponto de verificação no Ethereum e o valor de hash das informações da conta individual é calculado da seguinte forma:
O AccountRootHash é gerado a partir do hash raiz da árvore Merkle da conta da mesma forma que o valor RootHash.
2.2 StateSync
StateSync refere-se à sincronização de dados Ethereum com a cadeia Polygon Matic, que é dividida principalmente nas seguintes etapas:
Primeiro, o contrato no Ethereum acionará a função syncState() em StateSender.sol para sincronização de estado
A função syncState() emitirá um evento da seguinte forma:
Todos os validadores na camada de Heimdall receberão o evento, e um dos validadores empacotará a transação no bloco heimdall e a adicionará à lista de sincronização de estado pendente;
O nó da camada bor obterá a lista acima para ser sincronizada através da API, e entregá-la ao contrato da camada bor para processamento posterior da lógica de negócios.
2.3 Ponte Polygon
O Polygon Bridge permite um canal de cadeia cruzada bidirecional entre o Polygon e o Ethereum, tornando mais fácil para os usuários transferir tokens entre duas plataformas de cadeia diferentes sem ameaças de terceiros e restrições de liquidez do mercado. Existem dois tipos de Polygon Bridge, PoS e Plasma, e ambos têm as seguintes semelhanças na transferência de ativos entre Polygon e Ethereum:
Primeiro você precisa mapear o token no Ethereum para o Polygon, como mostrado na imagem abaixo:
A tecnologia de ancoragem bidirecional (Two-way Peg) também é usada, ou seja,
a: Todos os ativos de token transferidos do Ethereum serão bloqueados no Ethereum primeiro, e o mesmo número de tokens mapeados será cunhado no Polygon;
b: Para retirar ativos de token para o Ethereum, você primeiro precisa queimar esses tokens mapeados no Polygon e, em seguida, desbloquear os ativos bloqueados no Ethereum;
A figura a seguir mostra a comparação entre PoS Bridge e Plasma Bridge:
Como pode ser visto na figura acima, em termos de segurança, o PoS Bridge depende da segurança do conjunto de validadores externos, enquanto o Plasma depende da segurança da cadeia principal do Ethereum. Ao mesmo tempo, quando os usuários fazem transferências de ativos entre cadeias (como a transferência de tokens do Polygon para o Ethereum), o PoS requer apenas um intervalo de ponto de verificação, cerca de 20 minutos a 3 horas, enquanto o Plasma requer um período de desafio de disputa de 7 dias. Ao mesmo tempo, o PoS suporta mais tokens padrão, enquanto o Plasma suporta apenas três tipos, incluindo: ETH, ERC20, ERC721.
3_Cross mensagens em cadeia—PoS Bridge
A PoS Bridge consiste principalmente em duas funções: Depósito refere-se à transferência de ativos dos usuários no Ethereum para o Polygon, e Retiradas refere-se à retirada de ativos do Polygon para o Ethereum.
Depósito
A seguir está um exemplo da usuária Alice usando PoS Bridge para enviar ativos de token de sua conta Ethereum para sua conta Polygon:
Se os ativos de token que você deseja transferir são ERC20, ERC721 ou ERC1155, você precisa autorizar o token que deseja transferir através da função approtect. Como mostrado abaixo, o número correspondente de tokens é autorizado para o contrato erc20Prefer chamando o método approtect no contrato de token no Ethereum.
A função approtect tem dois parâmetros:
Spender: O endereço de destino onde o usuário autoriza o gasto de tokens
montante: o número de tokens que podem ser gastos
Depois que a transação de autorização acima é confirmada, o usuário bloqueia o token no contrato erc20Preliminary no Ethereum chamando o método depositFor() do contrato RootChainManager. Aqui, se o tipo de ativo a ser transferido for ETH, depositEtherFor() é chamado. Os detalhes são os seguintes:
A função depositFor tem três parâmetros:
usuário: O endereço do usuário que recebeu os tokens de depósito no Polygon
rootToken: O endereço do token na cadeia principal do Ethereum
depositData: O número de tokens codificados pela ABI
A seguir está o código específico da função depositFor no contrato RootChainManager:
Analisando o código-fonte, pode-se ver que a função primeiro obtém o endereço do contrato de predicado correspondente ao token e, em seguida, chama sua função lockTokens() para bloquear o token no contrato. Finalmente, syncState() será chamado para sincronização de estado por _stateSender, que só pode ser chamado pelo remetente de estado definido por admin.
A função syncState() em StateSender.sol enviará o evento StateSynced, especificamente:
O primeiro parâmetro é o índice de número de sequência do log, o segundo parâmetro é usado para verificar se o chamador é um endereço de contrato legítimo registrado e o terceiro parâmetro são os dados que precisam ser sincronizados com o estado. A transação é adicionada ao bloco Heimdall e adicionada à lista de sincronização de estado pendente.
Então, depois que o nó bor na cadeia Polygon Matic obtém o evento StateSynced na lista de sincronização de estado através da API, o contrato ChildChainManager na cadeia chamará a função onStateReceive(), que é usada para receber os dados de sincronização carregados do Ethereum, e prosseguirá para a próxima etapa de acordo com o tipo de lógica de negócios da sincronização de estado:
data: bytes32 syncType e bytes syncData. Quando syncType está mapeando, syncData é o endereço rootToken codificado, o endereço childToken e bytes32 tokenType e, quando syncType é depósito, syncData é o endereço de usuário codificado. O endereço rootToken e depositData do tipo bytes. depositData é a quantidade em REC20 e tokenId em ERC721.
Uma vez que este é um negócio de depósito, a função _syncDeposit() será chamada. Esta função irá primeiro descodificar o syncData no formato correspondente para obter o rootToken, endereço de utilizador e depositData correspondentes. Em seguida, verifique se o rootToken tem um token de mapeamento correspondente no polígono e chame a função deposit() do childToken se houver.
Aqui tomamos o contrato de token ERC20 como um exemplo para introduzir como depositar o contrato de token de mapeamento. Esta função transfere o número correspondente de tokens para a conta do usuário.
A função tem dois parâmetros:
usuário: O endereço do usuário que está fazendo um depósito
depositData: O valor codificado em ABI
Levantamentos
O seguinte é um exemplo da usuária Alice usando PoS Bridge para retirar os fundos depositados em sua conta Polygon para sua conta Ethereum:
Quando o usuário se retira, ele precisa gravar o número correspondente de tokens mapeados chamando a função withdraw() do contrato de token de mapeamento na cadeia Polygon.
Retirar contém apenas um parâmetro: o número de tokens que serão queimados. A função withdraw() no contrato token correspondente é a seguinte:
As transações acima serão incluídas no ponto de verificação após cerca de 20 minutos a 3 horas, e o validador enviará para o Ethereum.
Uma vez que a transação é adicionada ao ponto de verificação e enviada ao Ethereum, a função exit() do contrato RootChainManager no Ethereum será chamada, o que confirmará a validade da transação de retirada no Polygon verificando o conteúdo do ponto de verificação enviado e acionará o contrato de Predicado correspondente para desbloquear os tokens depositados do usuário.
O Proof inputData passado para a função inclui os seguintes dados:
headerNumber: Contém o cabeçalho do bloco de pontos de verificação para a transação de retirada
blockProof: Prove que o cabeçalho do bloco na cadeia filho é o nó da folha da raiz merkle que cometeu
blockNumber: O número de bloco na cadeia filho que contém a transação de retirada
blockTime: O carimbo de data/hora do bloco da transação de retirada
txRoot: O valor raiz da árvore de transações de bloco
receiptRoot: O valor raiz da árvore de recebimento de bloco
Recibo: Um recibo para uma transação de retirada
receiptProof: Comprovativo Merck do recibo da transação de levantamento
branchMask: O caminho para o recibo representado pelos 32 bits na árvore de recibos
receiptLogIndex: O índice de log que é lido a partir da árvore de recibos
A seguir está a lógica central da função, que inclui principalmente três partes: a primeira parte é verificar a validade do recibo de transação de retirada, a segunda parte é verificar se o ponto de verificação contém o bloco de transação e a terceira parte é chamar a função exitTokens() no contrato de predicado para enviar os tokens bloqueados para o usuário.
Tomemos o contrato ERC20Predicate como exemplo, ou seja, depois de decodificar o recetor, o remetente e o número de tokens enviados do log, um determinado número de tokens será enviado ao usuário.
De acordo com a análise do código-fonte do processo de mensagens de cadeia cruzada PoS Bridge, as chamadas de função de todo o processo só podem ser chamadas pela função especificada pelo validador, portanto, a segurança da cadeia cruzada só é garantida pelo PoS (notário).
4_Cross mensagens em cadeia — Ponte de Plasma
Ponte de Plasma também inclui duas funções: Depósito e Levantamentos, como mostrado na figura a seguir:
O Polygon Plasma é ligeiramente diferente da implementação do Bitcoin Plasma MVP introduzida no primeiro artigo da nossa série de pontes de cadeia cruzada, que usa principalmente o modelo Plasma MoreVP baseado em conta. Em comparação com o Plasma, o algoritmo foi parcialmente melhorado na parte de retirada.
Uma vez que a transferência de token de ERC20 e ERC721 é realizada através de um log de eventos semelhante a um Bitcoin UTXO, vamos primeiro apresentar o evento:
input1: O saldo da conta do remetente antes da transferência
input2: saldo da conta do beneficiário antes da transferência
output1: O saldo da conta do remetente após a transferência
output2: Saldo da conta do beneficiário após a transferência
Em segundo lugar, como o MVP de plasma original é gerado por um único operador ou um pequeno número de produtores de blocos, há dois cenários de ataque no Polygon:
Operador Evil:
Artigo anterior (Investigação sobre segurança de pontes entre cadeias (2) | Nomad cross-chain bridge) menciona que quando a transação de um usuário é empacotada em um bloco de Plasma pelo Operador, há uma indisponibilidade de dados off-chain. Portanto, quando um usuário faz uma transação de saída, se ele começar a desistir de uma transação mais antiga, o Operador pode desafiá-la com uma de suas transações mais recentes, e o desafio será bem-sucedido. Ao mesmo tempo, devido ao mecanismo de verificação PoS usado no Plasma, se o Operador conluio com validadores para fazer o mal, eles podem até mesmo forjar algumas transições de estado e submetê-las ao Ethereum.
Mal do usuário:
Os usuários continuam a gastar tokens no Polygon depois de iniciar uma transação de saída, semelhante a um gasto duplo entre cadeias.
Em resumo, o algoritmo Plasma MoreVp da Polygon usa outro algoritmo para calcular a prioridade de saída, que é sair da transação mais recente. Como esse método usa um evento LogTransfer semelhante ao UTXO, desde que a transação legítima do usuário use a entrada correta1 e a entrada2, mesmo que algumas transações maliciosas sejam empacotadas antes da transação do usuário, a transação do usuário pode ser tratada corretamente porque a transação do usuário vem apenas de uma entrada válida. O pseudocódigo relevante é o seguinte:
Depósito
Vamos pegar o exemplo da usuária Alice usando o Plasma Bridge para enviar ativos de token de sua conta Ethereum para sua conta Polygon:
Em primeiro lugar, os usuários também precisam autorizar os ativos de token que precisam transferir para o depositManager do contrato Polygon na cadeia principal (Ethereum) através da função approtect.
Depois que a transação autorizada é confirmada, o usuário chama a função erc20token.deposit() para acionar a função depositERC20ForUser() do contrato depositManager e depositar os ativos do token ERC20 do usuário.
Quando a rede principal Ethereum confirmar a transação de depósito, criará um bloco contendo apenas essa transação e enviá-lo-á para o contrato childChain na rede Polygon usando o mecanismo de sincronização de estado, cunhará a mesma quantidade de moedas mapeadas e as depositará na conta do usuário no Polygon.
Nota: De acordo com a análise do código fonte do contrato childChain, o Plasma suporta apenas três tipos, incluindo: ETH, ERC20 e ERC721.
Retirar
Quando um usuário quiser usar a ponte Plasma para retirar ativos do Polygon para o Ethereum, ele passará pelas seguintes etapas:
O usuário grava os ativos de token mapeados na cadeia Polygon chamando a função withdraw() da moeda mapeada no Polygon:
Você também pode chamar a implementação da interface withdrawStart() do Plasma Client no Polygon.
O usuário pode chamar a função startExitWithBurntTokens() no contrato ERC20Predicate, que primeiro chamará WithdrawManager.verifyInclusion() para verificar se o ponto de verificação contém a transação de retirada e o recibo correspondente, o código é o seguinte:
Depois que a verificação for aprovada, WithdrawManager.addExitToQueue() será chamado para inseri-lo na fila de mensagens em ordem de prioridade:
Finalmente, addExitToQueue() chama _addExitToQueue() para cunhar um NFT como um voucher de reembolso:
O usuário aguarda um período de desafio de 7 dias
Depois que o período de desafio for concluído, você pode chamar a função WithdrawManager.processExits() para enviar tokens para o usuário.
A função é dividida em duas etapas: primeiro, confirme se a transação de retirada na fila de mensagens passou o período de desafio de 7 dias e, se o período de desafio já passou, remova a transação da fila:
Em seguida, determine se o voucher de reembolso NFT foi excluído durante o período de desafio e, se não for, o NFT será destruído e os ativos correspondentes serão devolvidos ao usuário:
5_Polygon Vulnerabilidade de gasto duplo da Ponte de Plasma
Em 5 de outubro de 2021, o White Hat Gerhard Wagner apresentou uma vulnerabilidade Polygon que poderia levar a um ataque de gastos duplos envolvendo US$ 850 milhões, pelo qual o White Hat recebeu uma recompensa oficial de US$ 2.000.000 da Polygon.
Na introdução do Plasma Bridge acima, sabemos que o processo completo de transação de retirada é o seguinte:
- O usuário inicia uma transação Retirar no Polygon, que queima os tokens do usuário no Polygon;
- Após um intervalo de checkpoint (aproximadamente 30 minutos), aguarde até que a transação de levantamento seja incluída no checkpoint;
- Mais de 2/3 dos validadores assinam e enviam para o Ethereum, momento em que o usuário chama startExitWithBurntTokens() no contrato ERC20PredicateBurnOnly para verificar se o ponto de verificação contém transações de gravação;
- Se a verificação for aprovada, um voucher de reembolso NFT será cunhado e enviado ao usuário
- Os usuários esperam por um período de desafio de 7 dias
- Chame WithdrawManager.processExits() para destruir o NFT e reembolsar o usuário
Nota: Para evitar a repetição de transações (ataques de gasto duplo), a Polygon usa NFTs como prova de reembolso para identificar exclusivamente uma transação de retirada. No entanto, devido ao defeito da geração de NFT ID, os atacantes podem construir parâmetros para gerar vários NFTs com IDs diferentes usando a mesma transação válida de retirada e, em seguida, usar esses NFTs para transações de reembolso, alcançando assim um “ataque de gasto duplo”.
Aqui está um olhar mais atento sobre como gerar NFTs:
A partir da análise do código-fonte acima, pode-se ver que addExitToQueue() chamará _addExitToQueue() para cunhar um NFT:
De acordo com a análise de parâmetros, exitid = prioridade, então o ID do NFT é gerado pelo deslocamento à esquerda da prioridade de idade na Ponte de Plasma.
Como pode ser visto na análise do código-fonte acima, idade é o valor de retorno da função WithdrawManager.verifyInclusion(), que primeiro verificará a validade da transação de retirada e, em seguida, gerará a idade correspondente se a verificação for aprovada. Na lógica de validação, o valor decodificado pelos dados do parâmetro controlável é branchMaskBytes:
Este valor também é usado ao gerar idade:
Rastreie a função MerklePatriciaProof.verify() chamada na lógica de verificação de transação e descubra que a função chama _getNibbleArray() para transcodificar branchMaskBytes:
Continue a rastrear a função de decodificação, que descarta parte do valor ao transcodificar branchMaskBytes, e essa maneira de perder o valor fará com que valores diferentes sejam transcodificados para obter o mesmo valor decodificado. Especificamente, se o primeiro bit hexadecimal (meio byte) do valor codificado hp de entrada b for 1 ou 3, o segundo bit hexadecimal será analisado. Caso contrário, o primeiro byte é simplesmente ignorado.
Se um invasor construir um parâmetro branchMaskBytes para que o primeiro bit hexadecimal não seja igual a 1 e 3, há 14*16 = 224 maneiras de obter o mesmo valor transcodificado.
O processo de ataque específico é o seguinte:
- Deposite uma grande quantidade de ETH/tokens na Polygon via Polygon Plasma
- Inicie uma negociação de retirada no Polygon e aguarde um período de desafio de 7 dias
- Modifique o primeiro byte do parâmetro branchMaskBytes na transação de retirada (a mesma transação válida pode ser reenviada até 223 vezes) e inicie a transação de retirada repetidamente
Em resumo, esta vulnerabilidade deve-se principalmente a um problema no design do algoritmo de ID do NFT que gera o voucher de reembolso para evitar a repetição, resultando na mesma transação de reembolso pode gerar NFTs diferentes, resultando em um ataque de gasto duplo. Acontece que o primeiro byte da máscara de ramificação codificada deve ser sempre 0x00. A correção é verificar se o primeiro byte da máscara de ramificação codificada está 0x00 e não tratá-lo como uma máscara incorreta.
Bem, o compartilhamento de hoje acabou, na próxima edição, a Equipe de Pesquisa de Segurança da Cadeia de Chengdu apresentará a pesquisa de segurança de outro projeto de cadeia cruzada, aguarde ansiosamente.
Ver original
Esta página pode conter conteúdos de terceiros, que são fornecidos apenas para fins informativos (sem representações/garantias) e não devem ser considerados como uma aprovação dos seus pontos de vista pela Gate, nem como aconselhamento financeiro ou profissional. Consulte a Declaração de exoneração de responsabilidade para obter mais informações.
Polygon Warrior Polygon Security Dialysis: Como garantir a segurança e estabilidade entre cadeias?
Autor: Chengdu Lian’an
Original: “Research on Cross-Chain Bridge Security (3)” | Polygon Warrior Diálise Segura, Como Evitar a Abertura da “Caixa de Pandora”?
Bem-vindo à série de artigos sobre “Cross-chain Bridge Security Research” produzida pela Chengdu Chain Security, no artigo anterior (Cross-Chain Bridge Security Research (2) | O que nos traz o primeiro roubo descentralizado da ponte Nomad?), realizamos uma análise técnica profissional do protocolo da ponte Nomad em detalhes.
Hoje, a Equipe de Pesquisa de Segurança da Cadeia de Chengdu realizará uma diálise segura do Polígono, um guerreiro polígono, então continue lendo.
Quem é 1_Polygon?
Polygon é a solução de escalonamento de camada 2 do Ethereum, com uma visão para construir a internet blockchain do Ethereum. O Polygon fornece uma estrutura comum que permite aos desenvolvedores aproveitar a segurança do Ethereum para criar cadeias personalizadas e focadas em aplicativos e fornecer uma rede interoperável que combina uma variedade de diferentes esquemas de escala, tais como: zk-rollup, PoS, etc. Entre eles, o Polygon PoS é atualmente a solução de escalonamento mais madura e conhecida no Polygon. Ele usa a cadeia lateral para processamento de transações para alcançar o objetivo de melhorar a velocidade de transação e economizar o consumo de gás, e a estrutura da rede inclui principalmente as seguintes três camadas:
Camada Ethereum:
Uma série de contratos na rede principal Ethereum, incluindo, principalmente: contratos Staking, Checkpoint e Reward, são responsáveis pelas funções de gerenciamento de staking relacionadas às apostas PoS, incluindo: fornecer a função de staking do token nativo MATIC, para que qualquer pessoa que estaque o token possa se juntar ao sistema como um validador, verificar a conversão da rede Polygon para obter recompensas de stake, punir validadores por assinaturas duplas, tempo de inatividade do validador e outros comportamentos ilegais e salvar pontos de verificação.
Camada de Heimdall:
A camada de validação de prova de participação, que consiste em um conjunto de nós PoS Heimdall, é responsável por enviar os pontos de verificação da rede Polygon para a rede principal Ethereum enquanto ouve um conjunto de contratos de staking implantados no Ethereum. O processo principal é o seguinte: primeiro, selecione um subconjunto de validadores ativos no pool de validadores como produtores de blocos, que serão responsáveis por criar blocos na camada Bor e transmiti-los, em seguida, validar o hash raiz Merkle e anexar assinaturas com base nos pontos de verificação enviados por Bor e, finalmente, o proponente será responsável por coletar todas as assinaturas do validador para o ponto de verificação especificado, e se o número de assinaturas atingir mais de 2/3, o ponto de verificação será enviado no Ethereum.
Bor Camada:
A camada de produtor de bloco, que consiste em um grupo de produtores de blocos regularmente selecionados por um comitê de validadores na camada de Heimdall, é um subconjunto de validadores responsáveis por agregar transações na cadeia lateral do Polígono e gerar blocos. Esta camada publica periodicamente pontos de verificação para a camada de Heimdall, onde o ponto de verificação representa um instantâneo da cadeia de Bor, como mostrado na imagem abaixo.
2_Polygon Interoperabilidade
2.1 Ponto de verificação
O mecanismo de ponto de verificação é um mecanismo para sincronizar os dados da camada Bor com o Ethereum, onde os dados sincronizados são um ponto de verificação, ou seja, um instantâneo dos dados de bloco da camada Bor contidos em um intervalo de ponto de verificação, o código-fonte é o seguinte:
Proponente: O proponente, que também é selecionado pelos validadores, os produtores de blocos e os proponentes são um subconjunto de validadores, e suas responsabilidades são determinadas por sua participação no pool geral
RootHash: é um hash Merkle gerado a partir do bloco Bor entre StartBlock e EndBlock
A seguir está um pseudo-código para o bloco Bor numerado de 1 a n para gerar o valor RootHash:
Em resumo, esse valor é o valor de hash raiz da árvore Merkel, que é composto pelo número do bloco no cabeçalho do bloco Bor, o carimbo de data/hora do bloco, o valor de hash da raiz da árvore de transações tx hash e o valor de hash keccak256 calculado a partir do hash raiz da árvore de recebimento.
AccountRootHash: Um hash Merkle das informações da conta relacionadas ao validador que precisa ser enviado para cada ponto de verificação no Ethereum e o valor de hash das informações da conta individual é calculado da seguinte forma:
O AccountRootHash é gerado a partir do hash raiz da árvore Merkle da conta da mesma forma que o valor RootHash.
2.2 StateSync
StateSync refere-se à sincronização de dados Ethereum com a cadeia Polygon Matic, que é dividida principalmente nas seguintes etapas:
Primeiro, o contrato no Ethereum acionará a função syncState() em StateSender.sol para sincronização de estado
A função syncState() emitirá um evento da seguinte forma:
Todos os validadores na camada de Heimdall receberão o evento, e um dos validadores empacotará a transação no bloco heimdall e a adicionará à lista de sincronização de estado pendente;
O nó da camada bor obterá a lista acima para ser sincronizada através da API, e entregá-la ao contrato da camada bor para processamento posterior da lógica de negócios.
2.3 Ponte Polygon
O Polygon Bridge permite um canal de cadeia cruzada bidirecional entre o Polygon e o Ethereum, tornando mais fácil para os usuários transferir tokens entre duas plataformas de cadeia diferentes sem ameaças de terceiros e restrições de liquidez do mercado. Existem dois tipos de Polygon Bridge, PoS e Plasma, e ambos têm as seguintes semelhanças na transferência de ativos entre Polygon e Ethereum:
a: Todos os ativos de token transferidos do Ethereum serão bloqueados no Ethereum primeiro, e o mesmo número de tokens mapeados será cunhado no Polygon;
b: Para retirar ativos de token para o Ethereum, você primeiro precisa queimar esses tokens mapeados no Polygon e, em seguida, desbloquear os ativos bloqueados no Ethereum;
A figura a seguir mostra a comparação entre PoS Bridge e Plasma Bridge:
Como pode ser visto na figura acima, em termos de segurança, o PoS Bridge depende da segurança do conjunto de validadores externos, enquanto o Plasma depende da segurança da cadeia principal do Ethereum. Ao mesmo tempo, quando os usuários fazem transferências de ativos entre cadeias (como a transferência de tokens do Polygon para o Ethereum), o PoS requer apenas um intervalo de ponto de verificação, cerca de 20 minutos a 3 horas, enquanto o Plasma requer um período de desafio de disputa de 7 dias. Ao mesmo tempo, o PoS suporta mais tokens padrão, enquanto o Plasma suporta apenas três tipos, incluindo: ETH, ERC20, ERC721.
3_Cross mensagens em cadeia—PoS Bridge
A PoS Bridge consiste principalmente em duas funções: Depósito refere-se à transferência de ativos dos usuários no Ethereum para o Polygon, e Retiradas refere-se à retirada de ativos do Polygon para o Ethereum.
Depósito
A seguir está um exemplo da usuária Alice usando PoS Bridge para enviar ativos de token de sua conta Ethereum para sua conta Polygon:
A função approtect tem dois parâmetros:
Spender: O endereço de destino onde o usuário autoriza o gasto de tokens
montante: o número de tokens que podem ser gastos
A função depositFor tem três parâmetros:
usuário: O endereço do usuário que recebeu os tokens de depósito no Polygon
rootToken: O endereço do token na cadeia principal do Ethereum
depositData: O número de tokens codificados pela ABI
A seguir está o código específico da função depositFor no contrato RootChainManager:
Analisando o código-fonte, pode-se ver que a função primeiro obtém o endereço do contrato de predicado correspondente ao token e, em seguida, chama sua função lockTokens() para bloquear o token no contrato. Finalmente, syncState() será chamado para sincronização de estado por _stateSender, que só pode ser chamado pelo remetente de estado definido por admin.
O primeiro parâmetro é o índice de número de sequência do log, o segundo parâmetro é usado para verificar se o chamador é um endereço de contrato legítimo registrado e o terceiro parâmetro são os dados que precisam ser sincronizados com o estado. A transação é adicionada ao bloco Heimdall e adicionada à lista de sincronização de estado pendente.
data: bytes32 syncType e bytes syncData. Quando syncType está mapeando, syncData é o endereço rootToken codificado, o endereço childToken e bytes32 tokenType e, quando syncType é depósito, syncData é o endereço de usuário codificado. O endereço rootToken e depositData do tipo bytes. depositData é a quantidade em REC20 e tokenId em ERC721.
A função tem dois parâmetros:
usuário: O endereço do usuário que está fazendo um depósito
depositData: O valor codificado em ABI
Levantamentos
O seguinte é um exemplo da usuária Alice usando PoS Bridge para retirar os fundos depositados em sua conta Polygon para sua conta Ethereum:
Retirar contém apenas um parâmetro: o número de tokens que serão queimados. A função withdraw() no contrato token correspondente é a seguinte:
As transações acima serão incluídas no ponto de verificação após cerca de 20 minutos a 3 horas, e o validador enviará para o Ethereum.
Uma vez que a transação é adicionada ao ponto de verificação e enviada ao Ethereum, a função exit() do contrato RootChainManager no Ethereum será chamada, o que confirmará a validade da transação de retirada no Polygon verificando o conteúdo do ponto de verificação enviado e acionará o contrato de Predicado correspondente para desbloquear os tokens depositados do usuário.
O Proof inputData passado para a função inclui os seguintes dados:
headerNumber: Contém o cabeçalho do bloco de pontos de verificação para a transação de retirada
blockProof: Prove que o cabeçalho do bloco na cadeia filho é o nó da folha da raiz merkle que cometeu
blockNumber: O número de bloco na cadeia filho que contém a transação de retirada
blockTime: O carimbo de data/hora do bloco da transação de retirada
txRoot: O valor raiz da árvore de transações de bloco
receiptRoot: O valor raiz da árvore de recebimento de bloco
Recibo: Um recibo para uma transação de retirada
receiptProof: Comprovativo Merck do recibo da transação de levantamento
branchMask: O caminho para o recibo representado pelos 32 bits na árvore de recibos
A seguir está a lógica central da função, que inclui principalmente três partes: a primeira parte é verificar a validade do recibo de transação de retirada, a segunda parte é verificar se o ponto de verificação contém o bloco de transação e a terceira parte é chamar a função exitTokens() no contrato de predicado para enviar os tokens bloqueados para o usuário.
De acordo com a análise do código-fonte do processo de mensagens de cadeia cruzada PoS Bridge, as chamadas de função de todo o processo só podem ser chamadas pela função especificada pelo validador, portanto, a segurança da cadeia cruzada só é garantida pelo PoS (notário).
4_Cross mensagens em cadeia — Ponte de Plasma
Ponte de Plasma também inclui duas funções: Depósito e Levantamentos, como mostrado na figura a seguir:
O Polygon Plasma é ligeiramente diferente da implementação do Bitcoin Plasma MVP introduzida no primeiro artigo da nossa série de pontes de cadeia cruzada, que usa principalmente o modelo Plasma MoreVP baseado em conta. Em comparação com o Plasma, o algoritmo foi parcialmente melhorado na parte de retirada.
Uma vez que a transferência de token de ERC20 e ERC721 é realizada através de um log de eventos semelhante a um Bitcoin UTXO, vamos primeiro apresentar o evento:
input1: O saldo da conta do remetente antes da transferência
input2: saldo da conta do beneficiário antes da transferência
output1: O saldo da conta do remetente após a transferência
output2: Saldo da conta do beneficiário após a transferência
Em segundo lugar, como o MVP de plasma original é gerado por um único operador ou um pequeno número de produtores de blocos, há dois cenários de ataque no Polygon:
Operador Evil:
Artigo anterior (Investigação sobre segurança de pontes entre cadeias (2) | Nomad cross-chain bridge) menciona que quando a transação de um usuário é empacotada em um bloco de Plasma pelo Operador, há uma indisponibilidade de dados off-chain. Portanto, quando um usuário faz uma transação de saída, se ele começar a desistir de uma transação mais antiga, o Operador pode desafiá-la com uma de suas transações mais recentes, e o desafio será bem-sucedido. Ao mesmo tempo, devido ao mecanismo de verificação PoS usado no Plasma, se o Operador conluio com validadores para fazer o mal, eles podem até mesmo forjar algumas transições de estado e submetê-las ao Ethereum.
Mal do usuário:
Os usuários continuam a gastar tokens no Polygon depois de iniciar uma transação de saída, semelhante a um gasto duplo entre cadeias.
Em resumo, o algoritmo Plasma MoreVp da Polygon usa outro algoritmo para calcular a prioridade de saída, que é sair da transação mais recente. Como esse método usa um evento LogTransfer semelhante ao UTXO, desde que a transação legítima do usuário use a entrada correta1 e a entrada2, mesmo que algumas transações maliciosas sejam empacotadas antes da transação do usuário, a transação do usuário pode ser tratada corretamente porque a transação do usuário vem apenas de uma entrada válida. O pseudocódigo relevante é o seguinte:
Depósito
Vamos pegar o exemplo da usuária Alice usando o Plasma Bridge para enviar ativos de token de sua conta Ethereum para sua conta Polygon:
Em primeiro lugar, os usuários também precisam autorizar os ativos de token que precisam transferir para o depositManager do contrato Polygon na cadeia principal (Ethereum) através da função approtect.
Depois que a transação autorizada é confirmada, o usuário chama a função erc20token.deposit() para acionar a função depositERC20ForUser() do contrato depositManager e depositar os ativos do token ERC20 do usuário.
Nota: De acordo com a análise do código fonte do contrato childChain, o Plasma suporta apenas três tipos, incluindo: ETH, ERC20 e ERC721.
Retirar
Quando um usuário quiser usar a ponte Plasma para retirar ativos do Polygon para o Ethereum, ele passará pelas seguintes etapas:
Você também pode chamar a implementação da interface withdrawStart() do Plasma Client no Polygon.
Depois que a verificação for aprovada, WithdrawManager.addExitToQueue() será chamado para inseri-lo na fila de mensagens em ordem de prioridade:
Finalmente, addExitToQueue() chama _addExitToQueue() para cunhar um NFT como um voucher de reembolso:
O usuário aguarda um período de desafio de 7 dias
Depois que o período de desafio for concluído, você pode chamar a função WithdrawManager.processExits() para enviar tokens para o usuário.
A função é dividida em duas etapas: primeiro, confirme se a transação de retirada na fila de mensagens passou o período de desafio de 7 dias e, se o período de desafio já passou, remova a transação da fila:
Em seguida, determine se o voucher de reembolso NFT foi excluído durante o período de desafio e, se não for, o NFT será destruído e os ativos correspondentes serão devolvidos ao usuário:
5_Polygon Vulnerabilidade de gasto duplo da Ponte de Plasma
Em 5 de outubro de 2021, o White Hat Gerhard Wagner apresentou uma vulnerabilidade Polygon que poderia levar a um ataque de gastos duplos envolvendo US$ 850 milhões, pelo qual o White Hat recebeu uma recompensa oficial de US$ 2.000.000 da Polygon.
Na introdução do Plasma Bridge acima, sabemos que o processo completo de transação de retirada é o seguinte:
- O usuário inicia uma transação Retirar no Polygon, que queima os tokens do usuário no Polygon;
- Após um intervalo de checkpoint (aproximadamente 30 minutos), aguarde até que a transação de levantamento seja incluída no checkpoint;
- Mais de 2/3 dos validadores assinam e enviam para o Ethereum, momento em que o usuário chama startExitWithBurntTokens() no contrato ERC20PredicateBurnOnly para verificar se o ponto de verificação contém transações de gravação;
- Se a verificação for aprovada, um voucher de reembolso NFT será cunhado e enviado ao usuário
- Os usuários esperam por um período de desafio de 7 dias
- Chame WithdrawManager.processExits() para destruir o NFT e reembolsar o usuário
Nota: Para evitar a repetição de transações (ataques de gasto duplo), a Polygon usa NFTs como prova de reembolso para identificar exclusivamente uma transação de retirada. No entanto, devido ao defeito da geração de NFT ID, os atacantes podem construir parâmetros para gerar vários NFTs com IDs diferentes usando a mesma transação válida de retirada e, em seguida, usar esses NFTs para transações de reembolso, alcançando assim um “ataque de gasto duplo”.
Aqui está um olhar mais atento sobre como gerar NFTs:
De acordo com a análise de parâmetros, exitid = prioridade, então o ID do NFT é gerado pelo deslocamento à esquerda da prioridade de idade na Ponte de Plasma.
Este valor também é usado ao gerar idade:
Se um invasor construir um parâmetro branchMaskBytes para que o primeiro bit hexadecimal não seja igual a 1 e 3, há 14*16 = 224 maneiras de obter o mesmo valor transcodificado.
O processo de ataque específico é o seguinte:
- Deposite uma grande quantidade de ETH/tokens na Polygon via Polygon Plasma
- Inicie uma negociação de retirada no Polygon e aguarde um período de desafio de 7 dias
- Modifique o primeiro byte do parâmetro branchMaskBytes na transação de retirada (a mesma transação válida pode ser reenviada até 223 vezes) e inicie a transação de retirada repetidamente
Em resumo, esta vulnerabilidade deve-se principalmente a um problema no design do algoritmo de ID do NFT que gera o voucher de reembolso para evitar a repetição, resultando na mesma transação de reembolso pode gerar NFTs diferentes, resultando em um ataque de gasto duplo. Acontece que o primeiro byte da máscara de ramificação codificada deve ser sempre 0x00. A correção é verificar se o primeiro byte da máscara de ramificação codificada está 0x00 e não tratá-lo como uma máscara incorreta.
Bem, o compartilhamento de hoje acabou, na próxima edição, a Equipe de Pesquisa de Segurança da Cadeia de Chengdu apresentará a pesquisa de segurança de outro projeto de cadeia cruzada, aguarde ansiosamente.