Security Research & Writeups

Pentest, 0-day hunting, smart-contract audits & CTF writeups — code snippets & proofs of concept.

#Web2 #Web3 #SmartContract #CTF

Posts

[DVD-07] Puppet: thao túng giá oracle Uniswap V1 để vay toàn bộ pool với gần 0 collateral

Mục tiêu là rút toàn bộ 100.000 DVT khỏi PuppetPool trong một giao dịch. Lỗ hổng nằm ở _computeOraclePrice() dùng trực tiếp số dư spot của pair Uniswap V1 làm giá — chỉ cần swap lượng lớn token vào pair là giá suy giảm mạnh, collateral yêu cầu giảm gần về 0.

Difficulty: easy

[DVD-06] Compromised: hai private key của oracle source bị lộ, thao túng median price để mua rẻ bán đắt

TrustfulOracle lấy median giá từ 3 trusted source; hai trong số đó bị lộ private key qua một chuỗi hex → ASCII → base64. Với 2/3 số phiếu, attacker hoàn toàn kiểm soát median: hạ giá DVNFT về 0 để mua NFT với chi phí tối thiểu, đẩy giá lên bằng đúng số dư exchange để bán lại rút toàn bộ 999 ETH, rồi khôi phục giá ban đầu.

Difficulty: easy

[DVD-05] The Rewarder: claim lặp cùng một Merkle proof để rút cạn quỹ airdrop

claimRewards() của TheRewarderDistributor chỉ kiểm tra và đánh dấu trạng thái 'đã claim' một lần cho cả chuỗi claim liên tiếp cùng token, nhưng lại chuyển token không điều kiện cho từng entry. Player — một beneficiary hợp lệ — lặp lại claim của chính mình hàng trăm lần trong một giao dịch để rút gần như toàn bộ quỹ DVT và WETH.

Difficulty: easy

[DVD-04] Side Entrance: trả nợ flash loan bằng cách deposit vào chính pool

SideEntranceLenderPool kiểm tra hoàn trả flash loan bằng tổng số dư ETH của pool thay vì theo dõi khoản vay cụ thể. Attacker vay toàn bộ pool, rồi trong callback deposit số ETH vừa vay vào tài khoản của chính mình — pool đủ tiền nên check pass, còn attacker giữ quyền rút toàn bộ số tiền đó.

Difficulty: easy

[DVD-03] Truster: arbitrary call khiến pool tự approve token cho attacker

TrusterLenderPool cho phép borrower chỉ định target và calldata tùy ý trong flashLoan, rồi pool tự thực thi lời gọi đó trong context của chính mình. Attacker chỉ cần khiến pool gọi token.approve(attacker, toàn bộ số dư) trong một khoản vay amount = 0, sau đó rút sạch pool bằng transferFrom — tất cả trong một giao dịch duy nhất.

Difficulty: easy

[DVD-02] Naive Receiver: forced flash loan rút phí victim và mạo danh fee receiver qua trusted forwarder

NaiveReceiverPool không kiểm tra initiator của flash loan, cho phép bất kỳ ai bắt FlashLoanReceiver trả phí cố định 1 WETH mỗi lần. Sau khi receiver cạn tiền, lỗ hổng _msgSender() của trusted forwarder kết hợp multicall giúp player mạo danh deployer để rút toàn bộ pool trong đúng 2 giao dịch.

Difficulty: easy

[DVD-01] Unstoppable: phá vỡ invariant ERC4626 bằng một khoản donate để khóa vault

Mục tiêu là làm cho mọi flash loan của UnstoppableVault thất bại để monitor pause vault. Lỗ hổng nằm ở chỗ totalAssets() đọc balanceOf trực tiếp, khiến invariant ERC4626 convertToShares(totalSupply) == totalAssets() bị phá vỡ chỉ bằng một khoản transfer 1 wei.

Difficulty: easy

Tags