The BadgerDAO Hack: What really happened and why it matters

Tl;dr: On December 2nd, 2021, over $120 million worth of cryptocurrency was stolen in a matter of minutes. Attackers were able to exploit users of the Decentralized Autonomous Organization (DAO) known as BadgerDao. As part of Zengo’s ongoing research into blockchain security and security incidents, we have analyzed the attack and were able to find some overlooked aspects. Primary among them: Hackers exploited a design issue in how crypto wallets ask their users to approve of certain transactions. Read below to learn more about the attack, our insights, and actionable security recommendations.

As part of our research, we fully recreated what the victims were shown when interacting with the infected BadgerDAO application. Ask yourself: Would you have fallen for this request?

BadgerDAO app with a MetaMask wallet as seen by victims, recreated by Zengo (Source: Zengo Github)

What is BadgerDAO?

BadgerDAO is a DAO focused on bringing Bitcoin to the web3 world of decentralized finance (DeFi), built on Ethereum smart contracts. Until now, most of the web3 innovation in DeFi has taken place on the Ethereum blockchain, making it difficult for Bitcoin investors to gain access to everything that DeFi has to offer, including interest on assets. According to its website, BadgerDAO aims to provide tools that allow Bitcoin owners to gain access to the web3 world of DeFi through a multistep process.

BadgerDAO Landing Page

Understanding web3 approvals

To understand this attack, we first need to know how web3 apps interact with users, and specifically with their ERC20 tokens.

When a web3 app wants its user to perform an action on the blockchain (e.g. send token A to app, to get token B from it), it initiates the following 4 steps:

  1. It prepares the requested transaction for the user
  2. It sends the transaction to the user’s wallet via a bridge or gateway (like WalletConnect or a web extension)
  3. The user signs the transaction via their wallet
  4. The user sends the signed transaction to the blockchain via their wallet

When the web3 app needs to be paid by an ERC20 token, users cannot just simply send the required amount of tokens to the app’s smart contract address. Instead, users need to approve the app’s request to withdraw tokens, so the app can withdraw these tokens on the users’ behalf later on.

While this sounds like a semantic difference, it’s an important one: In practice, many apps request for the approval of a practically unbounded amount of tokens instead of requesting the approval of just the required amount. This is oftentimes done in order to reduce transaction costs. Because transaction fees can be quite high, instead of requesting approval for each transaction – which itself requires a processing fee – this “unbounded token request” has become an industry practice embraced by many.

We had highlighted the obvious drawbacks of this approach in the past, in our “BaDApprove” research.

As a result, web3 users are accustomed to approving relatively unlimited amounts. The user’s  only line of defense is making sure they are interacting with a trustworthy app and that the approval request is logical in the context of their current interaction.

The Hack: Stealing unbounded tokens 

The hackers were able to obtain access to the Badger app’s website and inject malicious javascript code. This code generated rogue transaction approvals, which, if approved by users, would allow the hackers to pull funds to their own wallets instead of those controlled by BadgerDAO at a future date.

Based on BadgerDAO’s own post mortem, hackers deployed this code quietly during November 2021. On November 20th, 2021, the hackers were successful in getting their first rogue approval, but waited patiently for a big enough victim to fall into their trap. On December 1st, 2021, it happened. A user, allegedly related to Celsius with $50M worth of an ERC20 token, approved the attackers’ access to their funds.

The victims approved on 19:57, the attackers withdrew all of their funds 6 hours later (Source: Debank)

The attackers quickly responded by withdrawing all of this victim’s funds worth $50M, and then followed by draining the accessible accounts of all other victims accumulated over the span of the attacker’s operation, for an overall $120M gain.

The Insight: Attackers took advantage of a crypto wallet visual design issue 

When looking carefully at the data over the blockchain, we were able to observe a change between the attackers first successful attack and their last attack.

In the first set of attempted attacks, attackers used the well-known “approve method” discussed at the beginning of this post. Later, they  changed the requested transaction type to the “increaseAllowance”.

First transaction uses approve function (Source: Etherscan)

Latter transaction uses increaseAllowance function (Source: Etherscan)

While they are virtually the same in their functionality, the latter is much less known by users and less supported by wallets.

To test wallet behavior with respect to the lesser known “increaseAllowance” method, we created a test environment with a test web3 app that uses this function. According to some reports, the aforementioned $50M victim was using the popular web3 wallet Metamask. Therefore, we were interested in testing this wallet specifically.

Metamask clearly displays “Approve” in a meaningful way and also shows this as an ERC20 token transaction. The visual design for this approval also creates a sense of urgency, suggesting that the user take close care in deciding whether or not to approve this request.

“Approve” is clearly displayed to the user on Metamask
“increaseAllowance” is not clear to the user on Metamask

However, when displaying an “increaseAllowance” approval, the visual cues are not nearly as strong, and provide no indication that this is an ERC20 related interaction, suggesting to the user that this is a standard action with insignificant impact and thus does not require a critical eye.

By analyzing the attackers’ injected script (see the detailed analysis in Zengo’s GitHub), we can conclude that attackers actively changed the function of the transaction from “approve” to “increaseAllowance.” We believe this was done in response to the difference in wallet user experience, which appeared to materially increase attack success.

We have since reported this issue to Metamask and they have confirmed that they “are currently working on some confirmation review-ability improvements.”

Conclusions and recommendations

Currently the wallet user experience of approving ERC20 transactions is the last and only line of defense of the user against such attacks.

Therefore, it is critical that wallets make it clear when they are asking their users to grant practically unlimited funding access to web3 applications, and implement visual cues that highlight the critical nature of these approvals and potential anomalies to their users. We certainly plan to address such issues in our upcoming implementation of web3 applications in Zengo.