Análise e soluções para vulnerabilidades de DoS em contratos inteligentes Rust

Rust contratos inteligentes中的 ataque de negação de serviço

ataque de negação de serviço ( DoS ) pode levar a contratos inteligentes a não funcionarem corretamente por um período de tempo ou até mesmo de forma permanente. As principais razões incluem:

  1. A lógica do contrato apresenta falhas, como a complexidade de cálculo de certas funções sendo demasiado alta, levando ao consumo de Gas a ultrapassar o limite.

  2. Nas chamadas entre contratos, a execução do contrato depende do estado de contratos externos, podendo ser bloqueada por contratos externos.

  3. Fatores humanos, como a perda da chave privada pelo proprietário do contrato, levam à incapacidade de chamar funções privilegiadas.

Abaixo, analisamos as vulnerabilidades de ataque de negação de serviço (DoS) em contratos inteligentes através de exemplos concretos.

1. Percorrendo estruturas de dados grandes que podem ser modificadas externamente

Segue um contrato simples para distribuir dividendos a usuários registrados:

ferrugem #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec\u003caccountid\u003e, pub accounts: UnorderedMap\u003caccountid, balance=""\u003e, }

impl Contrato { pub fn register_account(&mut self) { se self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::panic("Conta já registrada".to_string().as_bytes()); } else { self.registered.push(env::predecessor_account_id()); } log!("registar conta {}", env::predecessor_account_id()); }

pub fn distribute_token(&mut self, amount: u128) {
    assert_eq!(env::predecessor_account_id(), DISTRIBUTOR, "sem permissão para operar");
    para conta em self.registered.iter() {
        let balance = self.accounts.get(\u0026account).expect("obtenção falhou");
        self.accounts.insert(\&account, \&balance.checked_add(amount).expect("adicionar overflow")); 
        log!("tentativa de distribuição para a conta {}", &account);
        ext_ft_token::ft_transfer(
            account.clone(),
            montante,
            &FTTOKEN,
            0,
            GAS_FOR_SINGLE_CALL
        );
    }
}

}

O problema do contrato é que o tamanho do array registered não tem limite, podendo ser manipulado por usuários mal-intencionados, tornando-se excessivamente grande, o que leva a um consumo de Gas muito alto na função distribute_token.

Recomendações de soluções:

Reestruturar o contrato utilizando o modo de retirada. Permitir que os usuários chamem ativamente a função de retirada para obter recompensas, o contrato só precisa registrar o montante de recompensas que os usuários podem retirar.

2. A dependência de estado entre contratos causa bloqueio

Considere um contrato de licitação:

ferrugem #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec, pub bid_price: UnorderedMap<accountid,balance>, pub current_leader: AccountId, pub highest_bid: u128, pub refund: bool }

impl Contrato { PromiseOrValue { assert!(amount > self.highest_bid); se self.current_leader == DEFAULT_ACCOUNT { self.current_leader = sender_id; self.highest_bid = amount; } else { ext_ft_token::account_exist( self.current_leader.clone)(, &FTTOKEN, 0, env::prepaid_gas() - GAS_FOR_SINGLE_CALL * 4, (.then)ext_self::account_resolve) sender_id, montante, &env::current_account_id((, 0, GAS_FOR_SINGLE_CALL * 3, (); } log!) "Lanceador mais alto atual: {} Lance mais alto: {}" self.current_leader, self.highest_bid ); PromiseOrValue::Value(0) }

#(
pub fn account_resolve)&mut self, sender_id: AccountId, amount: u128[private] {
    match env::promise_result(0) {
        PromiseResult::NotReady => unreachable!(),
        PromiseResult::Successful(_) => {
            ext_ft_token::ft_transfer(
                self.current_leader.clone)(,
                self.highest_bid,
                &FTTOKEN,
                0,
                GAS_FOR_SINGLE_CALL * 2,
            (;
            self.current_leader = sender_id;
            self.highest_bid = amount;
        }
        PromiseResult::Failed => {
            ext_ft_token::ft_transfer)
                sender_id.clone)(,
                quantidade,
                &FTTOKEN,
                0,
                GAS_FOR_SINGLE_CALL * 2,
            (;
            log!)"Retornar a oferta atual");
        }
    };
}

}

O problema do contrato é que: é necessário devolver com sucesso os tokens do licitante anterior para atualizar a oferta mais alta. Se o licitante anterior cancelar a conta, o contrato não conseguirá concluir o reembolso, bloqueando assim o processo.

Solução:

Considere a possibilidade de falhas nas chamadas de contratos externos e implemente um tratamento de erros adequado. Os tokens que não podem ser devolvidos podem ser temporariamente armazenados no contrato, permitindo que os usuários os retirem ativamente posteriormente.

3. Perda da chave privada do proprietário do contrato

Algumas funções do contrato são definidas para serem executadas apenas pelo proprietário, para alterar variáveis-chave do sistema. Se a chave privada do proprietário for perdida, essas funções não poderão ser chamadas, o que pode levar o contrato a não funcionar corretamente.

Solução:

Definir múltiplos proprietários de contratos para governança conjunta, ou adotar um mecanismo de múltiplas assinaturas para substituir o controle de permissões de um único proprietário, alcançando a governança descentralizada.

</accountid,balance></accountid,>

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.
  • Recompensa
  • 8
  • Partilhar
Comentar
0/400
WhaleWatchervip
· 19h atrás
O contrato só será atacado se for uma peneira, certo?
Ver originalResponder0
CryptoSourGrapevip
· 19h atrás
Se eu soubesse dessa falha mais cedo, não teria que me humilhar todos os dias agora.
Ver originalResponder0
PancakeFlippavip
· 07-18 18:19
Os contratos também têm um limite, quem manda ter habilidades fracas?
Ver originalResponder0
LazyDevMinervip
· 07-17 19:29
Falar sobre escrever código na próxima vida.
Ver originalResponder0
NftPhilanthropistvip
· 07-17 19:28
na verdade... *bebe chá* outro contrato ineficiente em termos de gás que poderia ser otimizado para impacto social. quando é que os desenvolvedores vão aprender sobre práticas de codificação conscientes smh
Ver originalResponder0
just_another_walletvip
· 07-17 19:20
Os problemas de segurança devem ser levados a sério, pessoal.
Ver originalResponder0
NFTragedyvip
· 07-17 19:16
Este problema, o código nem está completo...
Ver originalResponder0
HalfBuddhaMoneyvip
· 07-17 19:01
Eu caramba, tenho que tapar buracos novamente, contrato lixo.
Ver originalResponder0
Negocie cripto em qualquer lugar e a qualquer hora
qrCode
Digitalizar para transferir a aplicação Gate
Novidades
Português (Portugal)
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)