El 25 de agosto de 2025, con la asistencia de Cantina y Seal911, Panoptic llevó a cabo una operación de rescate de sombrero blanco, asegurando aproximadamente $400K en fondos en riesgo [1]. La causa raíz fue una falla en la construcción de s_positionsHash: el protocolo utilizó XOR para agregar hashes Keccak256 de IDs de posición en una única huella digital. Si bien los hashes Keccak256 individuales siguen siendo resistentes a colisiones, la linealidad matemática del XOR hace que la huella digital compuesta sea insegura. Un atacante puede generar un conjunto de IDs de posición falsificados cuyo hash agregado por XOR coincida con cualquier huella digital objetivo, eludiendo la verificación de posiciones del protocolo y retirando colateral sin reembolsar la deuda.
Antecedentes
Panoptic es un protocolo descentralizado de trading de opciones perpetuas construido sobre Ethereum que permite a los usuarios operar con opciones de compra y venta.
La función withdraw() tiene un parámetro de entrada positionList, que consiste en un conjunto de tokenIds. Cada tokenId representa una posición. La función withdraw() verifica el estado de deuda de cada posición basándose en s_positionsHash y luego recupera el colateral del usuario.
Para ahorrar gas, el protocolo no almacena cada posición (es decir, tokenId) del usuario. En cambio, calcula una huella digital basada en todos los tokenIds del usuario y la registra en s_positionsHash. Los 8 bits más significativos de cada s_positionsHash representan numLegs, mientras que los 248 bits inferiores representan el user position hash.
Para cada tokenId recibido, el protocolo calcula su hash, toma los 248 bits inferiores y actualiza el user position hash realizando un XOR bit a bit con los 248 bits inferiores del s_positionsHash actual.
Simultáneamente, countLegs se ajusta según el rango numérico del tokenId: permanece sin cambios cuando el tokenId es inferior a , y aumenta en 1, 2 o 3 cuando está en los rangos , y respectivamente. Esto finalmente se escribe en los 8 bits superiores de s_positionsHash para actualizar numLegs.
Análisis de Vulnerabilidad
La causa raíz es una falla en el algoritmo del contrato para construir s_positionsHash, específicamente el uso de la operación XOR para agregar resultados de hashes Keccak256. Si bien una función hash individual sigue siendo segura, la linealidad matemática de la operación XOR hace que el algoritmo general de huella digital (es decir, la suma XOR de hashes) sea inseguro [2].
La linealidad implica que un atacante no necesita romper la función hash en sí misma (es decir, revertir el tokenId desde el hash). En cambio, puede emplear una estrategia combinatoria: generar una gran cantidad de tokenIds aleatorios, calcular su Keccak256(tokenId), y a partir de estos valores de hash, seleccionar un subconjunto específico tal que la suma XOR de estos hashes de tokenId coincida exactamente con la huella digital objetivo de la víctima.
Esto permite a un atacante pasar un conjunto de tokenIds falsificados al llamar a withdraw() para superar la verificación de salud y recuperar todo el colateral correspondiente a s_positionsHash.
Teoría
Supongamos que la huella digital de posición del usuario s_positionsHash tiene un user position hash de y numLegs de , con tokenIds de usuario . Por lo tanto:
Aquí, cada valor hash de 248 bits puede verse como un vector de 248 dimensiones.
Por lo tanto, reside en un espacio de 248 dimensiones compuesto por 0s y 1s (). En este espacio, la operación XOR es equivalente a la suma vectorial (Apéndice I).
El objetivo del atacante es encontrar vectores de 248 dimensiones del conjunto de todos los vectores disponibles, tal que los 248 bits inferiores de su suma XOR sean iguales a . Por lo tanto, podemos formular el objetivo del atacante como un sistema de ecuaciones lineales:
Específicamente, no necesitamos intentar construir directamente. En cambio, seleccionamos vectores hash linealmente independientes (donde es igual a la dimensión 248) y los usamos como vectores columna para construir una matriz :
El problema se transforma entonces en encontrar un vector de coeficientes tal que:
Donde , y .
Según la teoría del álgebra lineal, siempre que la matriz tenga rango completo, abarca todo el espacio de dimensiones. Esto significa que para cualquier objetivo , el sistema de ecuaciones tiene una solución única. Después de resolver , simplemente conservamos aquellos vectores para los cuales ; su suma XOR es .
Ejemplo
Para facilitar la comprensión, demostramos este proceso de construcción con un caso de estudio. Supongamos que los vectores son de 3 dimensiones, con cada dimensión compuesta únicamente por 0 o 1, y el valor hash objetivo es 101, es decir, .
A continuación, generamos aleatoriamente 3 valores hash:
Construimos la matriz usando estos tres vectores como columnas y planteamos la ecuación :
Resolviendo mediante eliminación gaussiana, obtenemos . Esto significa que debemos seleccionar y (correspondientes a ), y su suma XOR es exactamente igual al objetivo .
Selección de n Vectores Linealmente Independientes
Como se mencionó anteriormente, para resolver , necesitamos construir una matriz de rango completo. Dado que estamos trabajando con un espacio vectorial extremadamente grande (), la pregunta central es: ¿Cómo seleccionamos rápidamente vectores linealmente independientes de este vasto espacio?
Consideremos el método más sencillo: generar aleatoriamente tokenIds y seleccionar sus resultados de hash como vectores.
Sobre , la probabilidad de que vectores de dimensiones seleccionados aleatoriamente formen una matriz de rango completo es:
Cuando es grande (en este ejemplo, ), esta probabilidad converge a una constante (Apéndice II):
Esto significa que cada intento aleatorio tiene aproximadamente un 28,9% de probabilidad de éxito. En promedio, un atacante solo necesita aproximadamente 3,5 intentos para encontrar un conjunto de vectores linealmente independientes. Por lo tanto, el costo computacional es extremadamente bajo, y el atacante puede construir rápidamente una matriz que satisfaga las condiciones.
Para controlar el countLegs en los 8 bits superiores, solo necesitamos ajustar el rango de los valores tokenId generados aleatoriamente según el countLegs objetivo.
Por ejemplo, si queremos que el numLegs en la huella digital falsificada sea 0, simplemente nos aseguramos de que los tokenIds generados aleatoriamente sean todos menores que . Dado que el incremento de legs para tokenIds en este rango es 0, independientemente de qué vectores seleccione la solución de la eliminación gaussiana, el numLegs acumulado final será inevitablemente 0.
Análisis del Ataque
El rescatador de sombrero blanco inició múltiples transacciones de rescate. Por simplicidad, la siguiente discusión se basa en solo una de estas transacciones [3].
La lógica central consta de los siguientes 5 pasos:
- Tomar prestados 0,23e8 WBTC y 28e18 WETH mediante préstamo flash de Aave.
- Depositar 0,23e8 WBTC y 28e18 WETH en el contrato poWBTC y el contrato 0x1f8d_poWETH.
- Llamar a
mintOptions()del contratoPanopticPoolcon unpositionIdListnormal para tomar fondos prestados y abrir una posición apalancada. - Llamar a
withdraw(), pasando lostokenIds falsificados. Debido a que estas posiciones falsificadas tienen unpositionSizede 0, la función devuelvetokenRequiredcomo 0, lo que significa que el colateral total requerido para todas las posiciones se calcula erróneamente como cero. Mientras tanto, els_positionsHashgenerado por estostokenIds es exactamente igual al generado en el paso 3, lo que permite al rescatador recuperar todo el colateral sin reembolsar ninguna deuda. - Reembolsar el préstamo flash y ejecutar la siguiente ronda.
Resumen
Este incidente pone de relieve dos fallas combinadas que juntas permitieron el retiro no autorizado de colateral.
- XOR no es una función de agregación segura para hashes. Keccak256 es resistente a colisiones, pero la linealidad del XOR significa que la suma XOR de múltiples hashes no hereda esa propiedad. Construir un conjunto de entradas cuyos hashes hagan XOR a cualquier valor objetivo se reduce a resolver un sistema de ecuaciones lineales sobre , lo cual es computacionalmente trivial. La composición de hashes requiere operaciones que preserven la resistencia a colisiones, como la concatenación seguida de un nuevo hash.
- Falta de validación de IDs de posición. El protocolo no verificó si los
positionIds pasados correspondían a posiciones de opciones válidas. Los valores por debajo de tienen uncountLegsde 0 y unpositionSizede 0, lo que significa que las posiciones falsificadas no incurren en deuda. Esto permitió al atacante superar la verificación de salud con requisito de colateral cero mientras coincidía con la huella digital objetivo.
Referencias
Apéndice
Los siguientes dos apéndices proporcionan una explicación matemática y demostración de las afirmaciones del texto principal, a saber, que la operación XOR es equivalente a la suma vectorial (Apéndice I) y la probabilidad de que una matriz aleatoria tenga rango completo (Apéndice II).
Apéndice I
En el campo finito , la adición se define como la adición módulo 2:
Se puede observar que esto es idéntico a la operación lógica OR Exclusivo (XOR, símbolo ).
Para el espacio vectorial de dimensiones (en este caso ), la adición de dos vectores y se define como la adición módulo 2 componente a componente:
Por lo tanto, en el espacio vectorial , la suma vectorial es equivalente a la operación XOR bit a bit sobre los componentes del vector.
Apéndice II
Para que la matriz tenga rango completo, estos vectores deben ser linealmente independientes.
El primer vector puede ser cualquier vector en excepto el vector cero, lo que proporciona opciones; el segundo vector no debe residir en el subespacio generado por , que contiene vectores, dejando opciones; siguiendo esta lógica, el -ésimo vector no puede estar en el subespacio generado por los vectores anteriores, resultando en opciones posibles.
El número total de tales matrices (es decir, el orden de ) es:
Y el número total de todas las posibles matrices es .
Por lo tanto, la probabilidad es:
Haciendo , podemos reescribir esta expresión como:
Cuando , este producto converge a una constante:
Esto significa que para grande, la probabilidad de que una matriz aleatoria tenga rango completo es aproximadamente 28,9%.
Acerca de BlockSec
BlockSec es un proveedor integral de seguridad blockchain y cumplimiento de criptomonedas. 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 AML/CFT, a lo largo de todo el ciclo de vida de los protocolos y plataformas.
BlockSec ha publicado múltiples artículos de seguridad blockchain en conferencias prestigiosas, reportado varios ataques de día cero en aplicaciones DeFi, bloqueado múltiples hackeos para rescatar más de 20 millones de dólares, y asegurado miles de millones en criptomonedas.
-
Sitio web oficial: https://blocksec.com/
-
Cuenta oficial de Twitter: https://twitter.com/BlockSecTeam



