
0. Revisión
- Asegurando el Ecosistema Solana (1) — Hola Solana
- Asegurando el Ecosistema Solana (2) — Llamadas entre Programas
- Asegurando el Ecosistema Solana (3) — Actualización de Programas
1. Descripción General
En el artículo anterior, discutimos cómo actualizar un programa. En esta publicación, presentaremos los problemas relacionados con el control de acceso, que es uno de los temas de seguridad más comunes y básicos en el área de DeFi.
2. Instrucciones
En Solana, cada programa exporta un único entrypoint, que se define con entrypoint!. A diferencia de Ethereum, los clientes solo pueden invocar una única función definida como el entrypoint, que generalmente se llama process_instruction. La función entrypoint recibe tres parámetros: el ID del programa del contrato inteligente, las cuentas sobre las que operará el programa y los datos de instrucción. Los datos de instrucción especifican qué instrucción será invocada. La figura a continuación muestra un ejemplo. Al desempaquetar los datos de instrucción, se eligen diferentes instrucciones (p. ej., Lock, Unlock). Por lo tanto, las instrucciones accesibles desde el entrypoint son públicas para todos y pueden ejecutarse con datos de instrucción específicos.

3. Validación de Cuentas
Como se mencionó, el programa recibe las cuentas que necesita leer o escribir. Este diseño plantea dos preguntas. Para las cuentas a leer, cómo garantizar que los datos almacenados en las cuentas son de confianza. Para las cuentas a escribir, cómo garantizar que solo los usuarios con privilegios puedan invocar las instrucciones para escribir en las cuentas. A continuación, ilustramos el problema de control de acceso. Todos los códigos de prueba se pueden encontrar aquí.
3.1 Revisión de Código (PrivilegeOwner)


Primero definimos dos estructuras: Door y Config. Solo la cuenta clave (línea 17) especificada en la estructura door puede abrir la door creada. Sin embargo, la puerta no puede abrirse cuando el estado del sistema está bloqueado, lo cual se especifica en la estructura Config (línea 81).

Como se mencionó, la cuenta Config especifica si la puerta puede abrirse. En este caso, solo debería haber una cuenta Config en el programa. Para lograrlo, usamos PDA para almacenar los datos de Config. Después de inicializar la cuenta Config, establecemos el atributo is_initialized en true para que no pueda ser inicializada nuevamente por atacantes (línea 108 - línea 110).

La instrucción Open() se usa para abrir las puertas. La instrucción recibe varias cuentas, incluida la cuenta de puerta a abrir, la cuenta config y la cuenta owner que intenta abrir la door. Para garantizar que la puerta pertenece al programa y que la configuración es válida, verificamos el propietario de la cuenta door y de la cuenta config (línea 204 - línea 205). Esto evita que usuarios maliciosos introduzcan cuentas falsas. Esto responde nuestra primera pregunta. Para garantizar que la cuenta a leer sea de confianza, ¡necesitamos verificar el propietario de la cuenta!. Nótese que solo el propietario de la cuenta door puede abrir la puerta. En este caso, verificamos si la cuenta owner es el owner real de la door y, más importante aún, si la instrucción está autorizada por el propietario (línea 217 - línea 219).

En la función validate_owner(), primero verificamos si la clave pública de estas dos cuentas es la misma, y luego verificamos la firma del propietario. Esto responde la segunda pregunta: para garantizar que solo los usuarios con privilegios puedan invocar la instrucción open, necesitamos verificar el propietario y el firmante de la cuenta. La instrucción close es similar a open y los detalles se pueden encontrar en el código.
Desplegamos el programa en la red de pruebas y se puede encontrar en el siguiente enlace.
https://explorer.solana.com/address/2Q7FFMWCthBvc6ubLQRx9TRswvaimmd66VaCAfHwsYuC?cluster=testnet
Todas las transacciones de prueba se enumeran a continuación. El proceso completo de esta transacción es 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 Transacción de Ataque
Para mostrar la importancia de la verificación del propietario y la verificación del firmante, utilizamos dos escenarios de ataque como ejemplos.
Primer Escenario
El primero es que el propietario de la 'door' intenta abrir la puerta cuando la config está bloqueada. Para lograrlo, creamos una cuenta config falsa en otro programa y asignamos el atributo is_lock con el valor false. El código del programa personalizado se muestra a continuación.
Enviamos la transacción para crear la cuenta config falsa; la clave pública de la cuenta config falsa es: 2MtSrbWp24VjPZQcSUkiWrvNro7qqKemVCsh3Yxc8LTy.
https://explorer.solana.com/tx/2qSyrL5gdQXmgGCFzmzMm1StFQRkDgWpss9A9jV11q2fgDGM5C1XRuXvbX1N5Dt3q2pRqnmyXHVtXGF5dqadAzpJ?cluster=testnet
Una vez creada la cuenta config falsa, la introducimos en el programa (línea 423).

El resultado se muestra a continuación; el registro imprime incorrect program id for instruction, lo que significa que el propietario de la cuenta config debe ser el programa. Por lo tanto, el atacante no puede eludir esta verificación.

Segundo Escenario
El segundo escenario es que un usuario malicioso intenta abrir la puerta cuando esta está desbloqueada.

En este caso, introducimos la cuenta del propietario real en el programa (línea 419) y enviamos la transacción. El resultado se muestra a continuación.

Se imprime Signature verification failed, lo que significa que el propietario real debe firmar la transacción para abrir la puerta, por lo que nuestro segundo ataque también falla.
4. Resumen
En Solana, las instrucciones implementan lógica específica basada en diferentes cuentas, que son proporcionadas por clientes u otros programas. Por lo tanto, la verificación adecuada de las cuentas es sumamente importante.
En este artículo, presentamos cómo verificar correctamente las cuentas y usamos dos escenarios de ataque para ilustrar la importancia de estas verificaciones. Continúa siguiéndonos y se compartirán más artículos.
Lee otros artículos de esta serie:
- Asegurando el Ecosistema Solana (1) — Hola Solana
- Asegurando el Ecosistema Solana (2) — Llamadas entre Programas
- Asegurando el Ecosistema Solana (3) — Actualización de Programas
- Asegurando el Ecosistema Solana (5) — Multi-Sig
- Asegurando el Ecosistema Solana (6) — Multi-Sig2
- Asegurando el Ecosistema Solana (7) — Confusión de Tipos
Acerca de BlockSec
BlockSec es una empresa pionera en seguridad blockchain fundada en 2021 por un grupo de expertos en seguridad de renombre mundial. La empresa está comprometida con mejorar la seguridad y la usabilidad del emergente mundo Web3 para facilitar su adopción masiva. Con este fin, BlockSec ofrece servicios de auditoría de seguridad de contratos inteligentes y cadenas EVM, la plataforma Phalcon para el desarrollo de seguridad y el bloqueo proactivo de amenazas, la plataforma MetaSleuth para el rastreo e investigación de fondos, y la extensión MetaSuites para que los desarrolladores de web3 naveguen eficientemente en el mundo cripto.
Hasta la fecha, la empresa ha atendido a más de 300 distinguidos clientes como MetaMask, Uniswap Foundation, Compound, Forta y PancakeSwap, y ha recibido decenas de millones de dólares estadounidenses en dos rondas de financiación de inversores prominentes, entre ellos Matrix Partners, Vitalbridge Capital y Fenbushi Capital.
Sitio web oficial: https://blocksec.com/
Cuenta oficial de Twitter: https://twitter.com/BlockSecTeam




