Back to Blog

Protegendo o Ecossistema Solana (4) — Validação de Contas

1 de abril de 2022
6 min read

0. Revisão

1. Visão Geral

No artigo anterior, discutimos como atualizar um programa. Nesta publicação, apresentaremos os problemas relacionados ao controle de acesso, que é um dos tópicos de segurança mais comuns e fundamentais na área de DeFi.

2. Instruções

No Solana, cada programa exporta um único entrypoint, que é definido com entrypoint!. Diferente do Ethereum, os clientes só podem invocar uma única função definida como o entrypoint, que normalmente é chamada de process_instruction. A função entrypoint recebe três parâmetros: o ID do programa do contrato inteligente, as contas nas quais o programa irá operar e os dados de instrução. Os dados de instrução especificam qual instrução será invocada. A figura abaixo mostra um exemplo. Ao desempacotar os dados de instrução, diferentes instruções (por exemplo, Lock, Unlock) são selecionadas. Assim, as instruções acessíveis a partir do entrypoint são públicas para todos e podem ser executadas com dados de instrução especificados.

3. Validação de Conta

Conforme mencionado, o programa recebe as contas que precisa ler ou gravar. Esse design levanta duas questões. Para as contas a serem lidas, como garantir que os dados armazenados nelas são confiáveis. Para as contas a serem gravadas, como garantir que apenas usuários privilegiados possam invocar as instruções para gravar nessas contas. A seguir, ilustramos o problema de controle de acesso. Todos os códigos de teste podem ser encontrados aqui.

3.1 Revisão de Código (PrivilegeOwner)

Primeiro definimos duas structs: Door e Config. Apenas a conta chave (linha 17) especificada na struct door pode abrir a door criada. No entanto, a porta não pode ser aberta quando o estado do sistema está bloqueado, conforme especificado na estrutura Config (linha 81).

Conforme mencionado, a conta Config especifica se a porta pode ser aberta. Nesse caso, deve haver apenas uma conta Config no programa. Para isso, usamos PDA para armazenar os dados da Config. Após inicializar a conta Config, definimos o atributo is_initialized como true para que ela não possa ser inicializada novamente por atacantes (linha 108 - linha 110).

A instrução Open() é usada para abrir as portas. A instrução recebe várias contas, incluindo a conta da porta a ser aberta, a conta config e a conta owner que pretende abrir a door. Para garantir que a porta pertence ao programa e que a configuração é válida, verificamos o proprietário da conta door e da conta config (linha 204 - linha 205). Isso impede que usuários maliciosos forneçam contas falsas. Isso responde à nossa primeira pergunta: para garantir que a conta a ser lida seja confiável, precisamos verificar o proprietário da conta! Observe que apenas o proprietário da conta door pode abrir a porta. Nesse caso, verificamos se a conta owner é o verdadeiro owner da door e, mais importante, se a instrução está autorizada pelo proprietário (linha 217 - linha 219).

Na função validate_owner(), primeiro verificamos se as chaves públicas das duas contas são iguais e, em seguida, verificamos a assinatura do proprietário. Isso responde à segunda pergunta: para garantir que apenas usuários privilegiados possam invocar a instrução open, precisamos verificar o proprietário e o assinante da conta. A instrução close é semelhante à open e os detalhes podem ser encontrados no código.

Implantamos o programa na testnet e ele pode ser encontrado no seguinte link.

https://explorer.solana.com/address/2Q7FFMWCthBvc6ubLQRx9TRswvaimmd66VaCAfHwsYuC?cluster=testnet

Todas as transações de teste estão listadas abaixo. O processo completo desta transação é AllocatePDA()-> InitializeDoor()-> InitializeConfig()-> Unlock() -> Open() -> Close().

https://explorer.solana.com/tx/2X9CyMrHTNEvbzXTE95gem2j8spnvsQsabFeSpV8hiNpYjiQPPzLRqt5KN86ZYRjnQvydvs7y5eUjJK7no8knDhk?cluster=testnet
https://explorer.solana.com/tx/2XfVWiXeQeHbpqAEYm3AH2RU6hunnqtr155EC4EAM5Bq9VVZNP6QocAav9cPjEQdJFcQrbsSSxiKadr4HPMov8pz?cluster=testnet
https://explorer.solana.com/tx/5Em41sg7yFXeNpnEJnhUQJanfLWKwjMqiBeNAqEEzFrSN9P8zKKafcv5F7RKT2pseB171qeoa8Uz4fKgazzayCnW?cluster=testnet
https://explorer.solana.com/tx/2PMtzpSgjnKDLGmRWBdUSFBPimWnudCPekUYbWzPzokENFYa4N4ab4HCtynfGrzswFPTgGYKHU8PccUMHv3mXHkR?cluster=testnet
https://explorer.solana.com/tx/3kviP9MqkWGMV4yA7k7yPQ5BGfXmcYLcctmY1u2D7n56eT1nx8jMtDumkUNJy8yA3KkmzrmfQLjqpigc8ehGZzBN?cluster=testnet
https://explorer.solana.com/tx/38iEaJBzuGMLbfcszdVB8pkniezH8JrA3XGq7JdADZTQ4hNQC82GSTUA2bmcypdVy3t7htWnUzkZ4F8EakmNvqz8?cluster=testnet

3.2 Transação de Ataque

Para demonstrar a importância da verificação de proprietário e da verificação de assinante, usamos dois cenários de ataque como exemplos.

Primeiro Cenário

O primeiro é que o proprietário da 'door' tenta abrir a porta quando a config está bloqueada. Para isso, criamos uma conta config falsa em outro programa e atribuímos ao atributo is_lock o valor false. O código do programa personalizado é mostrado abaixo.

Enviamos a transação para criar a conta config falsa; a chave pública da conta config falsa é: 2MtSrbWp24VjPZQcSUkiWrvNro7qqKemVCsh3Yxc8LTy.

https://explorer.solana.com/tx/2qSyrL5gdQXmgGCFzmzMm1StFQRkDgWpss9A9jV11q2fgDGM5C1XRuXvbX1N5Dt3q2pRqnmyXHVtXGF5dqadAzpJ?cluster=testnet

Uma vez criada a conta config falsa, a inserimos no programa (linha 423).

O resultado é mostrado abaixo; o log imprime incorrect program id for instruction, o que significa que o proprietário da conta config deve ser o programa. Portanto, o atacante não consegue contornar essa verificação.

Segundo Cenário

O segundo cenário é que um usuário malicioso tenta abrir a porta quando ela está desbloqueada.

Nesse caso, inserimos a conta do proprietário real no programa (linha 419) e enviamos a transação. O resultado é mostrado abaixo.

É impresso Signature verification failed, o que significa que o proprietário real deve assinar a transação para abrir a porta, portanto nosso segundo ataque também falha.

4. Resumo

No Solana, as instruções implementam lógicas específicas com base em diferentes contas, que são fornecidas por clientes ou por outros programas. Portanto, a verificação adequada das contas é extremamente importante.

Neste artigo, apresentamos como verificar corretamente as contas e usamos dois cenários de ataque para ilustrar a importância dessas verificações. Continue acompanhando e mais artigos serão compartilhados.

Leia outros artigos desta série:


Sobre a BlockSec

A BlockSec é uma empresa pioneira em segurança blockchain, fundada em 2021 por um grupo de especialistas em segurança de renome mundial. A empresa está comprometida em aprimorar a segurança e a usabilidade para o emergente mundo Web3, a fim de facilitar sua adoção em massa. Para isso, a BlockSec oferece serviços de auditoria de segurança de contratos inteligentes e chains EVM, a plataforma Phalcon para desenvolvimento seguro e bloqueio proativo de ameaças, a plataforma MetaSleuth para rastreamento e investigação de fundos, e a extensão MetaSuites para construtores web3 que navegam com eficiência no mundo cripto.

Até o momento, a empresa atendeu mais de 300 clientes de prestígio, como MetaMask, Uniswap Foundation, Compound, Forta e PancakeSwap, e recebeu dezenas de milhões de dólares americanos em duas rodadas de financiamento de investidores proeminentes, incluindo Matrix Partners, Vitalbridge Capital e Fenbushi Capital.

Site oficial: https://blocksec.com/

Conta oficial no Twitter: https://twitter.com/BlockSecTeam

Sign up for the latest updates
Como a solução de segurança de pagamentos da BlockSec ajuda instituições a se manterem seguras na era da IA
Security Services

Como a solução de segurança de pagamentos da BlockSec ajuda instituições a se manterem seguras na era da IA

Descubra como a BlockSec ajuda instituições de pagamento a proteger recursos financeiros e dados, além de fortalecer sua resiliência por meio de avaliações de segurança, testes e monitoramento contínuo.

Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec
Security Insights

Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec

Este relatório semanal aborda dois incidentes de segurança na Ethereum e na BNB Chain no período de 19/10/2026–25/10/2026. Ele examina uma tomada de controle da governança do X100 Freezer financiada por um empréstimo-relâmpago e uma falha na liquidação de impostos que afetou um pool de liquidez de um token NEM na BNB Chain. As perdas estimadas no escopo do relatório totalizam aproximadamente 5,57 milhões USD: cerca de 4,75 milhões USD da transação representativa do X100 e cerca de 820 mil USD do incidente no pool do NEM. O total exclui as extrações subsequentes do X100 relatadas separadamente.

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec
Security Insights

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec

Este relatório semanal aborda 3 incidentes de segurança no período de 12/10/2026–18/10/2026, com perdas totais estimadas em aproximadamente 3,87 milhões USD. A Autheo Network sofreu um comprometimento de chave privada com perdas de cerca de 1,76 milhões USD, a Qubic Wallet perdeu cerca de 1,30 milhões USD devido à geração de seeds fracas, e os contratos Smart Token Vesting V2 da UNCX Network sofreram um erro contábil de cerca de 807 mil USD nas redes Ethereum, BNB Chain, Base e Robinhood Chain. A análise em destaque da UNCX explica como um cálculo incorreto do total de cotas misturou parcelas de vesting criadas com diferentes proporções entre tokens e cotas, permitindo saques acima do devido de pools compartilhados.

Protegendo o Ecossistema Solana (4) — Validação de Contas