BlockThreat - Week 11, 2024
NFP | Blastoff | Mozaic | Charlotte Fang | Zero Name Service | Polyhedra | MO Token
Greetings!
More than $21M were stolen this week across 7 incidents including the first known hack on Blast chain and a massive wallet draining campaign on BSC. As always we will dive into some of the compromises and discuss important lessons, but first a quick note from our sponsors about a fantastic product - OpenZeppelin Defender! I’m particularly excited about highly configurable security monitoring and automated incident response workflows. In the industry where projects get drained in just a few minutes, Defender is the one product which may just save your bacon. Check it out!
OpenZeppelin Defender 2.0 is now generally available!
OpenZeppelin Defender is a mission-critical developer security platform to code, audit, deploy, monitor, and operate blockchain applications with confidence. Integrating directly into the developer workflow, Defender makes it easy and fast for developers and operators to prevent and fix security issues pre and post-deployment. Built as the result of 7 years of developing and auditing the world’s most popular smart contracts, Defender embeds OpenZeppelin’s industry-leading expertise and world-class intelligence across all stages of your project’s lifecycle.
A recently launched Blast blockchain experienced its first major compromise. Blastoff project vault lost about $600K due to insufficient checks on stake withdrawals. Below is a snippet of the vulnerable repayWithStakeToken function:
function repayWithStakeToken(
uint256 poolId,
uint256 stakeId
) external payable override {
LockedPoolInfo memory pool = poolInfo[poolId];
if (pool.timelock == 0) revert PoolNotExisted(poolId);
StakingInfo memory staking = stakeInfo[poolId][stakeId];
if (staking.amount == 0) revert NoStaking();
_updateAccYield(pool.stakeToken);
uint256 yieldedAmnt = (staking.amount *
accYieldPerStaked[pool.stakeToken]) /
1e24 -
staking.yieldDebt;
uint256 requireAmnt = 0;
if (staking.yieldAmount > yieldedAmnt) {
requireAmnt = staking.yieldAmount - yieldedAmnt;
}
if (pool.stakeToken == address(0) && msg.value < requireAmnt)
revert InsufficientAmount(requireAmnt);
[..snip..]
// return stake
TokenTransfer._transferToken(pool.stakeToken, msg.sender, staking.amount);
emit Repay(poolId, stakeId, pool.stakeToken, staking.amount, requireAmnt);
}
The idea behind the repayWithStakeToken method was to allow users to unstake their ETH early by paying off generated yield. Unfortunately there was no check for who can make the unstaking request. So the attacker systematically went through the entire pool, paid off everyone’s remaining yields, and withdrew their staked ETH.
As always, these incidents yield some hard earned lessons from audit, operations, and incident response perspectives:
The project likely went live without a thorough audit that would have caught a clear case of insufficient access control in one of the unstaking functions.
The attack lasted for about 8 hours with the majority of funds drained in the first 10 minutes.
Folks at Blastoff responded to the incident by closing the vulnerable pool for new deposits after 6 hours.
The team was likely alerted by victims failing to unstake their ETH, rather than a monitoring system.
No evidence of automated incident response. High signal heuristics like most of the vault funds suddenly disappearing could have caught the hack in progress.
Without a true transaction pause function the draining continued.
The usual “bounty” negotiation is in progress with what appears to be a new norm of 20%. However, the attacker is likely to send stolen assets to Tornado Cash from where they first obtained ETH for gas.
Attacks continue on high profile individuals in the crypto ecosystem. Charlotte Fang (Milady NFT) lost more than $1.8M due to suspected spear phishing attack.
NFP project made an announcement on March 15, 2024 about bad actors compromising a number of wallets including those of administrators to steal NFP tokens. The report did not have any additional information about the hack. However, a possibly related, FixedFloat and Tornado Cash funded wallet (Fake_Phishing118154) accumulated about $16M worth of NFP tokens on March 13, 2024 from more than 2500 wallets. After aggregating users’ funds it quickly moved them to MEXC, Binance, Bybit and started swapping the rest on DEXs.
On the more positive side, the malicious insider incident at Mozaic concluded with most funds being recovered thanks to MEXC freezing funds. Malicious insider threat requires difficult to solve human-level security control which was made even more difficult by North Korean actors actively trying to join crypto startups.
The premium version of the newsletter includes detailed exploit information, PoC code, and indicators on the incidents discussed above as well as two private key theft incidents involving Polyhedra and Zero Name Service, IT token reward manipulation, and others.
To gain access to comprehensive vulnerability write-ups, post-mortems, exploit proof of concepts (PoCs), attacker addresses, and additional data regarding this week’s compromises, please subscribe to the premium plan below.
Let’s dive into the news!