Análisis de vulnerabilidades de ataque DoS en contratos inteligentes Rust y soluciones

Ataque de denegación de servicio en contratos inteligentes Rust

El ataque de denegación de servicio ( DoS ) puede causar que los contratos inteligentes no funcionen correctamente durante un período de tiempo o incluso de forma permanente. Las principales razones incluyen:

  1. La lógica del contrato tiene defectos, como la complejidad de cálculo de ciertas funciones que provoca que el consumo de Gas exceda el límite.

  2. En la llamada entre contratos, la ejecución del contrato depende del estado del contrato externo y puede ser bloqueada por el contrato externo.

  3. Factores humanos, como la pérdida de la clave privada por parte del propietario del contrato, que impide la llamada a funciones privilegiadas.

A continuación, analizamos las vulnerabilidades de ataque de denegación de servicio en contratos inteligentes a través de ejemplos concretos.

1. Recorrido de estructuras de datos grandes que pueden ser modificadas externamente

A continuación se presenta un contrato simple para distribuir dividendos a los usuarios registrados:

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

impl Contract { pub fn register_account(&mut self) { if self.accounts.insert(&env::predecessor_account_id(), &0).is_some() { env::panic("La cuenta ya está registrada".to_string().as_bytes()); } else { self.registered.push(env::predecessor_account_id()); } log!("registrar cuenta {}", env::predecessor_account_id()); }

pub fn distribute_token(&mut self, amount: u128) {
    assert_eq!(env::predecessor_account_id(), DISTRIBUTOR, "No tiene permiso para operar");
    for account in self.registered.iter() {
        let balance = self.accounts.get(\u0026account).expect("获取失败");
        self.accounts.insert(\u0026account, \u0026balance.checked_add(amount).expect("desbordamiento de suma")); 
        log!("Intentando distribuir a la cuenta {}", &cuenta);
        ext_ft_token::ft_transfer(
            account.clone(),
            cantidad,
            &FTTOKEN,
            0,
            GAS_FOR_SINGLE_CALL
        );
    }
}

}

El problema del contrato es que el tamaño del array registered no tiene límites, lo que puede ser manipulado por usuarios malintencionados para volverse demasiado grande, lo que resulta en un consumo de Gas excesivo en la función distribute_token.

Recomendaciones de solución:

Reestructurar el contrato adoptando el modo de retiro. Permitir que los usuarios llamen activamente a la función de retiro para obtener recompensas; el contrato solo necesita registrar la cantidad de recompensas que el usuario puede retirar.

2. La dependencia del estado entre contratos cruzados provoca bloqueos

Considera un contrato de licitación:

óxido #[near_bindgen] #[derive(BorshDeserialize, BorshSerialize)] pub struct Contract { pub registered: Vec, pub bid_price: UnorderedMap\u003caccountid,balance\u003e, pub current_leader: AccountId, pub highest_bid: u128, pub refund: bool }

impl Contract { PromiseOrValue { assert!(cantidad > self.highest_bid); if 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, cantidad, &env::current_account_id((, 0, GAS_FOR_SINGLE_CALL * 3, (); } log!) "El actual mayor postor: {} Mayor oferta: {}", self.current_leader, self.highest_bid ); PromiseOrValue::Value(0) }

#(
pub fn account_resolve)&mut self, sender_id: AccountId, amount: u128[private] {
    coincidir env::resultado_promesa(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)(,
                cantidad,
                &FTTOKEN,
                0,
                GAS_FOR_SINGLE_CALL * 2,
            (;
            log!)"devolver la oferta actual");
        }
    };
}

}

El problema del contrato es que: debe devolver con éxito los tokens del anterior postor para poder actualizar la oferta más alta. Si el anterior postor cancela su cuenta, el contrato no podrá completar el reembolso y se bloqueará.

Solución:

Considerar la posibilidad de que las llamadas a contratos externos puedan fallar, implementando un manejo de errores razonable. Se pueden almacenar temporalmente tokens no reembolsables en el contrato, permitiendo posteriormente a los usuarios retirarlos de manera activa.

3. Pérdida de la clave privada del propietario del contrato

Algunas funciones del contrato están configuradas para ser ejecutadas solo por el propietario, utilizadas para cambiar variables clave del sistema. Si se pierde la clave privada del propietario, estas funciones no podrán ser llamadas, lo que puede llevar a que el contrato no funcione correctamente.

Solución:

Configurar múltiples propietarios de contratos para la gobernanza conjunta, o utilizar un mecanismo de firma múltiple para reemplazar el control de permisos de un solo propietario, logrando así una gobernanza descentralizada.

<accountid,balance><accountid,>

Ver originales
Esta página puede contener contenido de terceros, que se proporciona únicamente con fines informativos (sin garantías ni declaraciones) y no debe considerarse como un respaldo por parte de Gate a las opiniones expresadas ni como asesoramiento financiero o profesional. Consulte el Descargo de responsabilidad para obtener más detalles.
  • Recompensa
  • 8
  • Compartir
Comentar
0/400
WhaleWatchervip
· 07-20 17:14
Un contrato solo será atacado si es un tamiz.
Ver originalesResponder0
CryptoSourGrapevip
· 07-20 17:08
Si hubiera sabido de esta vulnerabilidad antes, no tendría que haber caído en la situación de estar lamentándome todos los días.
Ver originalesResponder0
PancakeFlippavip
· 07-18 18:19
Los contratos también tienen un umbral, ¿quién te mandó a tener mala técnica?
Ver originalesResponder0
LazyDevMinervip
· 07-17 19:29
Hablaremos de escribir código en la próxima vida 8
Ver originalesResponder0
NftPhilanthropistvip
· 07-17 19:28
en realidad... *bebe té* otro contrato ineficiente en gas que podría optimizarse para el impacto social. ¿cuándo aprenderán los desarrolladores sobre prácticas de codificación consciente? smh
Ver originalesResponder0
just_another_walletvip
· 07-17 19:20
¡Los problemas de seguridad deben ser tomados en serio, amigos!
Ver originalesResponder0
NFTragedyvip
· 07-17 19:16
Este problema, eh, el código ni siquiera está terminado...
Ver originalesResponder0
HalfBuddhaMoneyvip
· 07-17 19:01
Vaya, tengo que volver a llenar el hueco, contrato basura.
Ver originalesResponder0
  • Anclado
Opere con criptomonedas en cualquier momento y lugar
qrCode
Escanee para descargar la aplicación Gate
Comunidad
Español
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)