Ngày 2 tháng 2 năm 2022, wormhole bridge hack đã làm sửng sốt thế giới crypto. Kẻ tấn công bypass signature verification của 19 institutional guardian và mint 120.000 wrapped ETH (wETH) trên Ethereum — trị giá $326 triệu tại thời điểm đó — mà không deposit một wei nào trên Solana. Lỗ hổng không phải cryptographic break mà là control-flow bypass: một missing sysvar validation cho phép kẻ tấn công skip toàn bộ guardian signature loop. Đây là câu chuyện về wormhole 326 million exploit, cuộc bailout chưa từng có của Jump Crypto, và những gì nó tiết lộ về giả định trust mong manh của cross-chain bridge.
TL;DR
- Chuyện gì xảy ra: Kẻ tấn công submit malicious VAA với fake sysvar account, skip toàn bộ 19 guardian signature check, mint 120K wETH ($326M) trên Ethereum
- Khi nào: 2 tháng 2, 2022 (exploit); 3 tháng 2 (bailout, patch)
- Nguyên nhân gốc:
verifySignaturestrên Solana chấp nhận fake sysvar account, timestamp check pass (0 < now), signature verification loop skip hoàn toàn
- Attribution: Kẻ tấn công ẩn danh (tinh vi, hiểu sâu Solana internals); không xác nhận liên kết nation-state
- Tác động: DeFi hack lớn nhất lúc đó; Jump Crypto inject $325M để make user whole; guardian set upgrade
- Fix: Thêm sysvar key validation (
account.key == SYSVAR_CLOCK_PUBKEY), emergency guardian rotation mechanism
Architecture: Guardian, VAA, và Cross-Chain Trust
Wormhole là generic message-passing bridge kết nối Ethereum, Solana, và chain khác. Trust model dựa trên 19 guardian — institutional node operator (Jump Crypto, Certus One, Chorus One, Everstake, v.v.) — observe event trên một chain, sign payload, produce VAA (Verifiable Action Approval). VAA chứa payload + 19 signature. Target chain verify mọi signature với guardian set hiện tại. Nếu valid, message được execute.
Giả định critical: verifySignatures validate đúng mọi 19 signature. Bridge không có trust anchor khác — n
ếu verification pass, message là truth.
Lỗ hổng: Fake Sysvar, Skipped Signature
Trên Solana, verifySignatures thực hiện 2 check:
1. Timestamp validity: VAA timestamp < current time (từ Clock sysvar)
2. Signature validity: Loop qua 19 guardian, verify mỗi ECDSA signature
Bug: function retrieve Clock sysvar qua account_info pass bởi caller, không verify account ĐÓ là actual Clock sysvar. Kẻ tấn công có thể pass fake account:
key != SYSVAR_CLOCK_PUBKEY(không phải real sysvar)
- Return timestamp = 0 (luôn < current time)
- Không có signature data
Khi timestamp = 0, check timestamp < current_time pass. Nhưng fake account không có signature data, nên signature loop iterate zero lần và return Ok(()) — không signature nào được verify.
// Simplified vulnerable logic (conceptual)
pub fn verify_signatures(ctx: Context, vaa: &VAA) -> Result<()> {
// BUG: No check that clock.key == SYSVAR_CLOCK_PUBKEY
let clock = &ctx.accounts.clock; // Attacker-controlled account!
// Timestamp check passes (attacker sets timestamp = 0)
require!(vaa.timestamp < clock.unix_timestamp, TimestampError);
// Signature loop: iterates over guardian set
// But if vaa.signatures is empty (attacker provides empty), loop runs 0 times
for (i, guardian) in guardian_set.iter().enumerate() {
// Never executes if vaa.signatures.len() == 0
verify_signature(vaa.signatures[i], guardian.pubkey, vaa.payload)?;
}
Ok(()) // Returns success with ZERO signatures verified!
}
Kẻ tấn công craft VAA claim "deposit 120.000 ETH trên Solana" (chưa từng xảy ra), attach empty signature array, pass fake Clock sysvar với timestamp = 0. Solana bridge chấp nhận, emit "deposit completed" event, và
Ethereum bridge — thấy valid VAA — mint 120.000 wETH cho kẻ tấn công.
Attack Timeline: 48 Giờ Làm Chấn Động DeFi
2 tháng 2, 2022, ~18:30 UTC — Kẻ tấn công submit malicious VAA đầu tiên cho Wormhole core bridge trên Solana. VAA chứa empty signature + fake Clock sysvar.
18:35 UTC — Ethereum bridge process VAA. verifySignatures pass (signature loop skip). 120.000 wETH mint cho attacker address 0x75D145....
19:00 UTC — Wormhole team detect anomalous minting. Guardian set paused. Bridge halted.
20:00 UTC — Security researcher (Neodyme, CertiK) identify root cause: verifySignatures sysvar substitution.
3 tháng 2, ~06:00 UTC — Jump Crypto công bố $325M capital injection để backstop Wormhole user. VC bailout chưa từng có trong DeFi.
12:00 UTC — Guardian set upgrade (emergency rotation). Patch verifySignatures deploy với require!(clock.key == SYSVAR_CLOCK_PUBKEY).
4-5 tháng 2 — Kẻ tấn công trả ~$200M sau đàm phán; $10M bounty paid. Tổng ~$326M steal, ~$200M trả lại, user made whole qua Jump injection.

Con số: $326M Stolen, User Made Whole
| Metric | Value |
|---|---|
| wETH minted | 120.000 |
| USD value (lúc đó) | ~$326 triệu |
| ETH price | ~$2.720 |
| Transaction | 1 exploit VAA + 1 mint tx |
| Time to detect | ~30 phút |
| Bailout amount | $325M (Jump Crypto) |
| Attacker return | ~$200M |
| Whitehat bounty | $10M |
| User loss | $0 (fully backed by Jump) |
Đây là "mint out of thin air" exploit — kẻ tấn công không steal locked ETH; họ lừa bridge rằng deposit đã xảy ra khi không hề. 120K wETH trên Ethereum unbacked. Jump Crypto injection effectively recapitalized bridge.

Phân tích nguyên nhân gốc: verifySignatures Bypass
Solana Sysvar Model
Solana cung cấp sysvar — special account với system data (Clock cho timestamp, Rent cho rent, StakeHistory cho stake). Program access qua account_info pass trong instruction. Convention: program nên verify account.key == EXPECTED_SYSVAR_PUBKEY trước khi trust data.
Missing Check
verify_signatures instruction của Wormhole chấp nhận clock: Sysvar account parameter. Anchor framework auto deserialize account data NẾU account là correct sysvar. Nhưng Wormhole dùng generic AccountInfo và manual deserialization, bypass Anchor built-in check.
// Vulnerable: accepts ANY account as "clock"
#[derive(Accounts)]
pub struct VerifySignatures<'info> {
pub clock: AccountInfo<'info>, // No constraint!
// ...
}
// Should have been:
#[derive(Accounts)]
pub struct VerifySignatures<'info> {
#[account(address = solana_program::sysvar::clock::ID)]
pub clock: Sysvar<'info, Clock>, // Anchor enforces correct sysvar
// ...
}
Exploit Construction
1. Kẻ tấn công tạo fake account với:
- key = random (không SYSVAR_CLOCK_PUBKEY)
- data = serialized Clock { unix_timestamp: 0, ... }
- Không signature data
2. Kẻ tấn công build VAA với:
- Payload: "deposit 120.000 ETH trên Solana" (fake)
- signatures: empty array
- timestamp: 0
3. Kẻ tấn công gọi verify_signatures với fake clock account + malicious VAA
4. timestamp < clock.unix_timestamp → 0 < current_time ✓
5. Signature loop: for sig in vaa.signatures → 0 iteration ✓
6. Return Ok(()) — zero signature verified
Jump Crypto Bailout: Chưa Từng Có Trong DeFi
Jump Crypto, major Wormhole investor và guardian operator, công bố $325M USDC injection ngày 3 tháng 2 để "make all Wormhole user whole." Đây là:
- Không phải loan — capital injection để backstop bridge
- Không phải insurance — không premium paid, không claim process
- VC bailout — set precedent rằng well-funded bridge được rescue
Hệ quả:
- User made whole (120K wETH backed by Jump USDC)
- Moral hazard: VC-backed bridge có thể underinvest security
- Narrative "too big to fail" enter DeFi
- Wormhole governance giờ include "guardian emergency upgrade" mechanism
Bài học: Cái gì đã ngăn chặn được
1. Luôn validate sysvar account. Fix là một dòng: require!(clock.key == SYSVAR_CLOCK_PUBKEY, InvalidSysvar);. Pattern này phải mandatory cho MỌI sysvar usage trong Solana program.
2. Defense-in-depth: verify signature kể cả khi timestamp pass. Signature loop nên execute regardless của timestamp check. Timestamp check là validation supplementary, không phải substitute cho signature verification.
3. Formal verification verification code. Function verify_signatures chỉ ~50 dòng code critical. Nên được formally verified (Certora, Coq, Agda), không chỉ audit. Một check miss đã tốn $326M.
4. Guardian set emergency upgrade mechanism. Wormhole thêm "guardian rotation" instruction post-exploit. Nó nên tồn tại trước launch — khả năng nhanh rotate compromised key là essential.
5. Bridge user protection fund. Bailout của Jump work vì họ có capital và incentive. Protocol-owned insurance fund (như Maker's Surplus Buffer hay dedicated bridge protection pool) sẽ institutionalize điều này.
6. Cross-chain asset backing transparency. wETH holder không có real-time visibility rằng asset unbacked. Bridge nên publish real-time reserve proof (Merkle tree, ZK proof) để user verify backing.

Câu hỏi thường gặp
Bao nhiêu bị steal trong Wormhole hack?
120.000 wETH mint trên Ethereum, trị giá ~$326M tại ~$2.720/ETH. Không user deposit bị steal trực tiếp — kẻ tấn công mint unbacked wETH.
Đây là cryptographic break (ECDSA broken)?
Không. ECDSA signature chưa bao giờ verify — code path bị skip hoàn toàn qua fake sysvar account. Đây là control-flow vulnerability, không phải crypto break.
Ai hack Wormhole?
Không rõ. Kẻ tấn công thể hiện hiểu biết sâu về Solana internals (sysvar model, instruction construction). Không attribution nation-state công khai.
User có mất tiền không?
Không — Jump Crypto inject $325M để backstop toàn bộ wETH. User made whole. Tuy nhiên, điều này dựa vào VC bailout, không phải protocol mechanism.
Tại sao Jump Crypto bail out Wormhole mà không hack khác?
Jump là major Wormhole investor và guardian operator với capital sâu. Hầu hết DeFi protocol thiếu backstop như vậy. Điều này highlight centralization của VC-backed bridge.
VAA là gì và forge thế nào?
VAA (Verifiable Action Approval) là payload + 19 guardian signature. Kẻ tấn công không forge signature — họ submit VAA với zero signature và lừa verifier skip signature check hoàn toàn.
Wormhole đã fix bridge chưa?
Rồi. Function verifySignatures giờ validate clock.key == SYSVAR_CLOCK_PUBKEY. Guardian set có thể emergency-upgrade. Jump Crypto tiếp tục làm backstop.
Bridge nào vulnerable với attack tương tự?
Bất kỳ bridge nào dùng Solana sysvar không key validation, hoặc verification code với control-flow bypass. Pattern: "check A pass → skip check B" là vulnerability class đã biết.
Technical Appendix: Correct verifySignatures Flow
Cho developer, đây là verification flow đúng mà Wormhole đã thiếu:
1. Receive VAA + clock account từ caller
2. CHECK: clock.key == SYSVAR_CLOCK_PUBKEY
- Nếu false: REJECT (đây là cái Wormhole miss)
3. Deserialize clock.unix_timestamp
4. CHECK: vaa.timestamp < clock.unix_timestamp
- Nếu false: REJECT (stale/future VAA)
5. FOR mỗi guardian trong guardian_set:
- CHECK: guardian_index < vaa.signatures.len()
- Nếu false: REJECT (missing signature)
- VERIFY: ECDSA.verify(vaa.signatures[i], guardian.pubkey, vaa.payload)
- Nếu false: REJECT (invalid signature)
6. Nếu mọi check pass: ACCEPT VAA, execute payload
Missing CHECK ở step 2 đã tốn $326M.
Bài viết thuộc series DeFi Hacks. Để xem phân tích sâu hơn về bridge exploit, xem phân tích Ronin Bridge hack, BNB Chain bridge hack, và Nomad bridge hack.
