El 8 de diciembre de 2023, OpenZeppelin emitió una importante advertencia de seguridad. ¡Resulta que al compartir el estándar ERC-2771 y funciones tipo Multicall existe el riesgo de suplantación de dirección! He investigado a fondo esta vulnerabilidad y quiero compartir mis hallazgos.
El delincuente cambió 5 WETH por aproximadamente 3,455,399,346 TIME
Luego construyó parámetros de calldata astutos y llamó a [Forwarder].execute
Esta función lanzó multicall en el contrato TIME, y el calldata restante se utilizó para burn() - ¡destrucción de tokens en el puente!
¿Cómo funciona esto?
En este ataque se alinearon las estrellas: ERC-2771, Multicall y datos meticulosamente elaborados. El contrato TOKEN hereda ERC2771Context, ¡y aquí es donde comienza lo más interesante!
ERC-2771 proporciona un msg.sender virtual, permitiendo delegar transacciones a un tercero. El verdadero адрес se añade al calldata. Cuando [Forwarder] llama al contrato, _msgSender() verifica estos datos y recorta los últimos 20 bytes como el "verdadero" msg.sender.
Multicall convierte una llamada en varias, ahorrando gas. Acepta un array de llamadas y las ejecuta a través de deleGatecall().
¡Y aquí está la trampa! El atacante desplaza el calldata de tal manera que los primeros 4 bytes de los nuevos datos corresponden a la función burn(), y el parámetro es una enorme suma de tokens. En la línea 0x20 se agrega la dirección del pool de liquidez TIME-ETH, que se convierte en el msg.sender "esperado"!
Raíz del problema
En ERC-2771 [Forwarder] nunca se planeó que funcionara con multicall! El atacante agregó los parámetros _msgSender() a la llamada externa multicall. Dentro de la función multicall, algunas funciones también añadieron estos parámetros, lo que permitió simular una llamada desde CUALQUIER dirección!
Medidas de protección
La nueva versión de OpenZeppelin Multicall ahora guarda la longitud del contexto ERC-2771 y la tiene en cuenta en cada llamada hija.
ThirdWeb fue más allá y prohibió a cualquier contrato invocar multicall, evitando el uso de [Forwarder].
Esta vulnerabilidad es un claro ejemplo de cómo la combinación de componentes seguros por separado puede crear una brecha catastrófica! Todos los desarrolladores deben recordar: siempre verifiquen la interacción entre diferentes estándares.
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.
Análisis del principio de vulnerabilidad de la sustitución de una dirección arbitraria en ERC2771 Multicall de SharkTeam
El 8 de diciembre de 2023, OpenZeppelin emitió una importante advertencia de seguridad. ¡Resulta que al compartir el estándar ERC-2771 y funciones tipo Multicall existe el riesgo de suplantación de dirección! He investigado a fondo esta vulnerabilidad y quiero compartir mis hallazgos.
Análisis de ataque
Consideremos uno de los ataques:
El esquema de ataque es brillantemente simple:
¿Cómo funciona esto?
En este ataque se alinearon las estrellas: ERC-2771, Multicall y datos meticulosamente elaborados. El contrato TOKEN hereda ERC2771Context, ¡y aquí es donde comienza lo más interesante!
ERC-2771 proporciona un msg.sender virtual, permitiendo delegar transacciones a un tercero. El verdadero адрес se añade al calldata. Cuando [Forwarder] llama al contrato, _msgSender() verifica estos datos y recorta los últimos 20 bytes como el "verdadero" msg.sender.
Multicall convierte una llamada en varias, ahorrando gas. Acepta un array de llamadas y las ejecuta a través de deleGatecall().
¡Y aquí está la trampa! El atacante desplaza el calldata de tal manera que los primeros 4 bytes de los nuevos datos corresponden a la función burn(), y el parámetro es una enorme suma de tokens. En la línea 0x20 se agrega la dirección del pool de liquidez TIME-ETH, que se convierte en el msg.sender "esperado"!
Raíz del problema
En ERC-2771 [Forwarder] nunca se planeó que funcionara con multicall! El atacante agregó los parámetros _msgSender() a la llamada externa multicall. Dentro de la función multicall, algunas funciones también añadieron estos parámetros, lo que permitió simular una llamada desde CUALQUIER dirección!
Medidas de protección
La nueva versión de OpenZeppelin Multicall ahora guarda la longitud del contexto ERC-2771 y la tiene en cuenta en cada llamada hija.
ThirdWeb fue más allá y prohibió a cualquier contrato invocar multicall, evitando el uso de [Forwarder].
Esta vulnerabilidad es un claro ejemplo de cómo la combinación de componentes seguros por separado puede crear una brecha catastrófica! Todos los desarrolladores deben recordar: siempre verifiquen la interacción entre diferentes estándares.