Antes do Bitcoin Core v25.0, um invasor poderia travar remotamente os nós do Bitcoin Core acionando uma afirmação na lógica de tratamento de mensagens blocktxn.
Esta questão é considerada Alto gravidade.
Detalhes
Ao receber um anúncio de bloco através de uma mensagem cmpctblock, o Bitcoin Core tenta reconstruir o bloco anunciado usando as transações em seu próprio mempool, bem como outras transações disponíveis. Se a reconstrução falhar devido à falta de transações, ele irá solicitá-las ao par anunciador por meio de uma mensagem getblocktxn. Em resposta é esperada uma mensagem blocktxn, que deverá conter as transações solicitadas.
O protocolo de bloco compacto emprega identificadores de transação abreviados para reduzir a largura de banda. Esses short-ids têm 6 bytes de tamanho, resultando em uma pequena chance de colisões (ou seja, a transação A tem o mesmo short-id que a transação B) na reconstrução do bloco. As colisões serão detectadas porque a raiz merkle calculada a partir do conjunto reconstruído de transações não corresponderá à raiz merkle do anúncio do bloco. Os pares não devem ser punidos por colisões, pois elas podem acontecer de forma espúria, portanto, são tratadas recorrendo à solicitação do bloco completo.
Bitcoin Core criará uma instância de PartiallyDownloadedBlock
sempre que um novo bloco compacto é recebido. Se forem solicitadas transações ausentes, a instância persistirá até que a mensagem blocktxn correspondente seja processada. Ao receber a mensagem blocktxn,
PartiallyDownloadedBlock::FillBlock
é chamado, tentando reconstruir o bloco completo. No caso de colisão descrito acima, o bloqueio completo é solicitado, mas o PartiallyDownloadedBlock
instância, bem como o outro estado relacionado à solicitação de bloco subjacente, permanece intacto. Isso deixa espaço para uma segunda mensagem blocktxn para o mesmo bloco ser processado e acionado FillBlock
para ser chamado novamente. Isso viola a suposição (documentada como um assert
declaração) que
FillBlock
só pode ser chamado uma vez e faz com que o nó trave.
Um invasor não precisa ter sorte ao desencadear uma colisão, pois a lógica de tratamento de colisão pode ser facilmente acionada simplesmente incluindo transações na mensagem blocktxn que não estão comprometidas na raiz merkle do bloco.
Atribuição
O crédito vai para Niklas Gögge por descobrir e divulgar a vulnerabilidade, bem como por corrigir o problema em https://github.com/bitcoin/bitcoin/pull/26898.
Linha do tempo
- 05/10/2022 – Niklas Gögge relata o problema à lista de discussão de segurança do Bitcoin Core.
- 24/01/2023 – PR #26898 contendo a correção foi mesclado.
- 25/05/2023 – Bitcoin Core 25.0 é lançado com a correção.
- 09-10-2024 – Divulgação pública.