Durante la semana pasada (2026/09/14 - 2026/09/20), observamos 2 incidentes de seguridad con una pérdida total estimada de aproximadamente $11.3M.
| Fecha | Incidente | Tipo | Pérdida Estimada |
|---|---|---|---|
| 2026/09/15 | Unknown Multicall Router | Control de Acceso Inadecuado | ~$7.8M |
| 2026/09/17 | Nostra Finance | Configuración Defectuosa del Oráculo | ~$3.5M |
Escaneo de Seguridad Gratuito
Un análisis de seguridad rápido con nuestro motor de análisis automatizado interno.
Escanear gratisDestacado de la Semana: Unknown Multicall Router
Este incidente fue seleccionado porque un sutil cambio de identidad del llamador a través de llamadas anidadas del router venció la autorización en una billetera Safe que ejecutaba módulos personalizados y permitió un retiro sustancial de activos.
El 15 de septiembre de 2026, un bot MEV que operaba bajo el nombre Yoink se adelantó (front-ran) a un intento de explotación contra una billetera Safe que administraba sus activos a través de módulos de estrategia personalizados, lo que resultó en una pérdida estimada de aproximadamente $7.8M [1]. Las solicitudes llegaban a esos módulos a través de un router multicall, donde un error de autorización en llamadas anidadas permitió que instrucciones no confiables pasaran a la cadena de módulos, mientras que un permiso reutilizable proporcionó soporte adicional para la operación no autorizada.
Contexto
Una billetera Safe puede habilitar un módulo Safe. Una vez habilitado, el módulo puede llamar a execTransactionFromModule() para indicar a la billetera que ejecute operaciones sin aprobación multisig, por lo que un módulo habilitado es un privilegio permanente sobre los activos de la billetera. La billetera Safe víctima había habilitado dos componentes de estrategia, el módulo Gateway y el módulo LP.
El módulo Gateway definía plantillas de comandos reutilizables, cada una describiendo una operación que la billetera Safe víctima tenía permitido realizar, con los valores concretos completados en el momento de la ejecución. Aceptaba comandos solo de llamadores que estuvieran en su propia lista de llamadores autorizados. Cada ejecución también debía llevar una prueba de Merkle, verificada contra una raíz almacenada, que autenticara la plantilla de comando que se estaba invocando. Algunas plantillas indicaban a la billetera que llamara al módulo LP, el cual realizaba operaciones de liquidez de Uniswap v4 usando los activos de la billetera. Por lo tanto, el control regresaba a través de la propia billetera en lugar de pasar directamente de un módulo a otro:
Authorized Caller
|
v
Gateway module -- verify(command, Merkle proof, root)
|
| execTransactionFromModule(...)
v
Safe wallet context
|
v
LP module --> mintPosition(...)
Los operadores en este incidente no llamaron directamente al módulo Gateway. Las solicitudes llegaban a través de un router multicall, que despachaba llamadas agrupadas en su nombre. Debido a que el router era el llamador directo cada vez que reenviaba una solicitud legítima, la lista de llamadores autorizados del módulo Gateway incluía al propio router.
A través de esta ruta, la billetera Safe víctima podía depositar aEthrsETH, el token de recibo de Aave para el rsETH suministrado, en un pool de Uniswap v4, acuñando un NFT de posición de vuelta a la billetera. Cualquier poseedor de aEthrsETH podía quemarlo a través de Aave para retirar el rsETH subyacente.
La billetera Safe víctima también había pedido prestado contra esa garantía de Aave. Por lo tanto, Aave rastreaba un factor de salud para ella, la relación entre el valor de su garantía y su deuda, y rechaza una transferencia de garantía que dejaría el factor por debajo de 1.
Análisis de la Vulnerabilidad
El router en 0x4f00...8ebC no tiene el código fuente verificado. El siguiente relato, por lo tanto, se basa en su bytecode desplegado, lógica decompilada, trazas de transacciones y una reconstrucción pública de prueba en fork, en lugar de nombres autoritativos a nivel de código fuente.
La lógica de despacho del router aceptaba un objetivo que estaba en su lista de permitidos o era la propia dirección del router, y luego verificaba la lista de llamadores autorizados de ese objetivo contra el msg.sender de la invocación actual. Nada preservaba la identidad del llamador externo original a través de una llamada que el router se hacía a sí mismo.

Cuando el router se llamaba a sí mismo, la invocación interna observaba al router como msg.sender. El asistente de autorización aceptaba al router en el caso de objetivo propio y, de otro modo, verificaba si el msg.sender actual aparecía en la lista de llamadores autorizados del siguiente objetivo. En consecuencia, una llamada interna dirigida al módulo Gateway se evaluaba como si se originara desde el router ya autorizado en lugar de desde el llamador externo. Esto permitió que instrucciones de un origen no confiable satisficieran la autorización de llamador del Gateway a través de la ruta anidada.

Un segundo defecto residía en la propia verificación de la prueba. La prueba autenticaba la plantilla de comando, pero ninguna verificación vinculaba los parámetros en tiempo de ejecución suministrados con ella. Una prueba válida emitida para un comando legítimo anterior, por lo tanto, permanecía utilizable después de que sus valores de ejecución concretos fueran cambiados. La prueba reutilizada proporcionó un permiso utilizable, pero fue el bypass de autorización anidado lo que permitió que un llamador no confiable llegara al módulo Gateway en primer lugar.
Análisis del Ataque
Una prueba de Merkle emitida previamente para la misma plantilla de comando permanecía utilizable con valores de ejecución diferentes. Esta propiedad no eludía por sí sola la autorización de llamador del Gateway, pero proporcionó un permiso utilizable después de que la ruta anidada del router satisficiera esa verificación de autorización.
El siguiente análisis se basa en la transacción 0x0e7680...a8705.
Antes de la transacción exitosa, el atacante original desplegó un contrato de ataque, un token PAT controlado por el atacante, y un segundo contrato que más tarde llevaría a cabo el intercambio de PAT.

En el siguiente bloque, el atacante llamó a prepare() para crear e inicializar un pool PAT/aEthrsETH de Uniswap v4.

El bot MEV Yoink detectó la explotación pendiente y se adelantó (front-ran) al atacante original invocando el contrato de ataque preparado. La llamada resultante entró en el router, hizo que el router se llamara a sí mismo, y luego llegó al módulo Gateway con el router como msg.sender. Al ser un módulo habilitado, el Gateway podía entonces hacer que la billetera Safe víctima ejecutara la operación suministrada sin aprobación multisig.

La instrucción hizo que la billetera Safe víctima suministrara aproximadamente 2,900 aEthrsETH como liquidez al pool PAT/aEthrsETH controlado por el atacante, dentro del rango de ticks [10, 20]. La transacción también acuñó el NFT de posición de Uniswap v4 asociado a la billetera, haciendo que la operación pareciera dentro del flujo de liquidez esperado. Esto no tomó todo el saldo de aEthrsETH de la billetera: la cantidad estaba limitada de manera que la verificación del factor de salud de Aave aún pasara, dejando la billetera con un factor de salud de 1.001182484056805114.
Luego, el contrato de ataque intercambió PAT controlado por el atacante por casi todo el aEthrsETH depositado a través de ese segundo contrato. Quemó los tokens de recibo adquiridos a través de Aave y retiró la cantidad correspondiente de rsETH. De los aproximadamente 2,900 rsETH que llegaron al bot Yoink, aproximadamente 2,882.37 rsETH fueron al destinatario de sus ganancias, mientras que aproximadamente 17.63 rsETH fueron intercambiados por ETH, y casi todo el ETH resultante fue pagado al constructor del bloque (block builder).

Conclusión
La causa raíz fue un defecto de autorización en la infraestructura personalizada conectada a una única billetera Safe, agravado por un permiso que no vinculaba todos los parámetros de ejecución. No debe atribuirse a los contratos principales de Safe, Aave, Uniswap v4 ni Kelp.
Un componente que reenvía llamadas en nombre de otros debe decidir la autorización a partir del llamador externo original, no a partir de una identidad que la cadena de llamadas recoge en el camino, y no debería ser accesible como su propio objetivo. Un permiso también debe vincular los valores concretos con los que se ejecutará una operación, no solo la plantilla a la que pertenece esa operación.
Comienza con Phalcon Explorer
Sumérgete en las Transacciones para Actuar con Inteligencia
Prueba ahora gratisMás Incidentes Esta Semana
Nostra Finance
El 17 de septiembre de 2026, el mercado monetario de Nostra en Starknet fue explotado a través de un precio inflado del oráculo de NSTR, lo que permitió pedir prestados aproximadamente $3.5M en activos contra garantías sobrevaloradas. La causa raíz fue una configuración de integración de oráculo que aceptaba muy pocas fuentes de precios, lo que permitió que una cotización manipulada de un pool poco profundo afectara materialmente el precio agregado. Nostra pausó sus mercados [2], mientras que Pragma informó que la dirección del atacante había sido congelada y que el trabajo de recuperación estaba en curso [3]. La pérdida final y las posibles recuperaciones seguían siendo desconocidas.
Contexto
Nostra operaba un mercado monetario en Starknet donde los usuarios podían suministrar garantías admitidas y pedir prestados otros activos según el valor derivado del oráculo de la garantía.
Nostra obtenía el precio de NSTR a través de su propio contrato de feed de precios, que delegaba a un contrato oráculo principal que leía de Pragma, un oráculo que publica precios agregados en Starknet. Los publicadores enviaban observaciones a Pragma bajo fuentes nombradas, incluyendo AVNU y GECKOTERMINAL, y su configuración documentada de NSTR describía una mediana entre tres de ellas [4][5]. Cada respuesta del oráculo incluía un precio, precisión decimal, marca de tiempo y recuento de fuentes contribuyentes [6]. El contrato oráculo principal almacenaba MinAggregatedSources, un número mínimo configurable de fuentes contribuyentes.
La implementación de agregación desplegada no fue leída directamente. Dos indicaciones independientes, sin embargo, apuntan en la misma dirección: el código de código abierto de Pragma devuelve el promedio de las dos entradas centrales siempre que el recuento de entradas sea par [6], y la respuesta
MEDIANobservada en este incidente fue igual al promedio aritmético de sus dos observaciones contribuyentes.
Los números detrás de esas fuentes provenían del mercado. Una observación de GECKOTERMINAL podía derivarse de pools en cadena, y uno de esos lugares en Starknet es Ekubo, un intercambio descentralizado que utiliza liquidez concentrada, similar a Uniswap v3. Los proveedores de liquidez colocan activos dentro de rangos de ticks seleccionados, y los intercambios mueven el precio del pool a través de rangos activos, mientras que los vacíos sin liquidez activa pueden separar posiciones colocadas a precios materialmente diferentes.
Nostra usaba el precio de NSTR obtenido a través de esta ruta del oráculo para valorar la garantía depositada y calcular la capacidad de endeudamiento de la cuenta.
Análisis de la Vulnerabilidad
El mercado monetario de Nostra leía los precios de NSTR desde 0x6838...5bf0, el contrato que su documentación enumera como el feed de precios de NSTR [7]. Ese contrato delegaba al oráculo principal que designaba, 0x7b05...f0ab, que tenía MinAggregatedSources configurado en 1. Pragma recomienda al menos tres fuentes de precios, e informó después del incidente que un mínimo forzado de tres fuentes habría rechazado la respuesta aceptada aquí [3].
Una respuesta que contenía dos observaciones válidas, por lo tanto, superaba el umbral configurado. Debido a que el cálculo de MEDIAN para dos observaciones se resolvía como su promedio aritmético, una sola cotización extrema podía distorsionar sustancialmente el resultado incluso cuando la otra observación permanecía cerca del precio de mercado predominante.
Esto fue una debilidad de configuración de integración en lugar de un error de escalado decimal o de implementación de la mediana. Pragma no encontró ningún defecto en ninguno de los dos cálculos [3]. El umbral insuficiente de fuentes permitió que la salida correctamente calculada de un conjunto de entradas inadecuadamente diversificado determinara el valor de la garantía y la capacidad de endeudamiento.
Análisis del Ataque
El ataque se basó en la manipulabilidad de un pool de liquidez concentrada recién creado y con poca financiación. La evidencia disponible indica que la siembra del pool por parte del atacante y su actividad repetida pueden haber influido en el pool utilizado para la observación de GECKOTERMINAL, aunque la causalidad exacta de la selección del pool no ha sido establecida.
El siguiente análisis se basa en la transacción 0x2460fd...cdf00e.
El atacante primero creó un pool NSTR/SolvBTC en Ekubo y suministró 1.5 SolvBTC como liquidez unilateral en un rango de precio inferior e inactivo. El atacante luego añadió aproximadamente 1,900 NSTR y 0.0001514751 SolvBTC alrededor del precio de mercado normal y realizó intercambios repetidos en el pool.
A continuación, el atacante colocó 190 NSTR como liquidez de un solo lado en un rango estrecho muy por encima del precio normal. Después de retirar la liquidez alrededor del precio de mercado normal, el atacante dejó un vacío de liquidez vacío antes de esta posición de precio alto.
Un intercambio que contenía solo 0.00000001 SolvBTC atravesó el rango vacío y movió el pool al tick -6645400, en el límite de la posición de precio alto. El valor manipulado del pool fue posteriormente enviado como una observación GECKOTERMINAL de NSTR/USD de $99.02439975.

La otra observación contribuyente, enviada bajo AVNU, valoró NSTR en $0.00596118. Ninguna observación de la tercera fuente configurada aparece en esa respuesta, dejando estos dos como los únicos valores que llegaron a la agregación [4].

Con dos valores, la respuesta MEDIAN fue su promedio aritmético, aproximadamente $49.51518046 por NSTR. Nostra aceptó la valoración resultante y trató el depósito de NSTR del atacante como garantía suficiente para un endeudamiento sustancial.

En la primera extracción identificada, el atacante usó una cuenta separada que poseía garantía de NSTR para pedir prestados aproximadamente 939.386010 ETH a la valoración inflada [4]. Nostra informó que la secuencia completa de préstamos también involucró STRK, USDC, USDT, WBTC y DAIv1, con un valor total prestado de aproximadamente $3.5M [2].
Conclusión
El incidente resultó de un umbral insuficiente de fuentes de oráculo en la integración de Nostra, no de un error en el manejo decimal o el cálculo de agregación de Pragma. Una respuesta de dos fuentes permaneció válida a pesar de que una observación provenía de un pool altamente manipulable.
Nostra debería exigir un mínimo de al menos tres fuentes de precios contribuyentes y rechazar cualquier respuesta del oráculo cuyo recuento de fuentes esté por debajo de ese umbral antes de usar el precio para la valoración de garantías o el endeudamiento. La elegibilidad de garantías y los límites de exposición también deberían reflejar la liquidez de mercado disponible y la profundidad requerida para manipular las fuentes de precios subyacentes de cada activo.
Referencias
[1] https://x.com/Phalcon_xyz/status/2099741447776096270
[2] https://x.com/nostrafinance/status/2100577538053493076
[3] https://www.pragma.build/updates/nostra-nstr-incident
[4] https://x.com/Phalcon_xyz/status/2100818035082952751
[5] https://www.pragma.build/asset/NSTR-USD?network=mainnet
[6] https://github.com/Astraly-Labs/pragma-oracle
[7] https://docs.nostra.finance/lend-and-borrow/deployed-contracts/money-market-mainnet
Acerca de BlockSec
BlockSec es un proveedor integral de seguridad blockchain y cumplimiento normativo cripto. Desarrollamos productos y servicios que ayudan a los clientes a realizar auditorías de código (incluyendo contratos inteligentes, blockchain y billeteras), interceptar ataques en tiempo real, analizar incidentes, rastrear fondos ilícitos y cumplir con las obligaciones de AML/CFT, a lo largo de todo el ciclo de vida de protocolos y plataformas.
BlockSec ha publicado múltiples artículos de seguridad blockchain en conferencias prestigiosas, ha reportado varios ataques de día cero de aplicaciones DeFi, ha bloqueado múltiples hackeos para rescatar más de 20 millones de dólares, y ha protegido miles de millones en criptomonedas.
-
Sitio web oficial: https://blocksec.com/
-
Cuenta oficial de Twitter: https://twitter.com/BlockSecTeam
El Mejor Auditor de Seguridad para Web3
Valida el diseño, el código y la lógica de negocio antes del lanzamiento



