88mph Function Initialization Bug Fix Postmortem

3 years ago 200
BOOK THIS SPACE FOR AD
ARTICLE AD

Immunefi

Summary

Whitehat Ashiq Amien, security researcher at iosiro, disclosed a critical vulnerability in 88mph’s CRV:RENWBTC, CRV:STETH, and yaLink pools to Immunefi on June 7. The vulnerability was an unprotected init() function in the code of these specific pools that would have allowed a malicious user to steal $6.5m in tokens, mostly in crvRenWBTC. Following Immunefi’s disclosure of the bug, 88mph quickly paused the affected contracts, whitehacked all user funds, and returned those funds to their rightful owners after they had been saved. In recognition of the vulnerability’s potentially devastating impact, 88mph is awarding the whitehat with a bounty of $42,069.

Vulnerability Analysis

The init() function, which is used to initialize the NFT contract on 88mph’s platform, was missing an onlyOwner modifier, and there was also no initializer modifier to prevent a re-initialization. In other words, the init() function was unprotected and was callable multiple times — and by anyone. The result of this unprotected function was that anyone could have taken ownership of the NFT contract, and ownership came with the privilege of minting pool deposit NFTs and burning any user’s NFT deposit using the mint() and burn() functions. This vulnerability would have allowed a malicious attacker to have access to any user’s NFTs and deposits.

The following contracts were vulnerable:

- 88mph yaLINK Pool Deposit: 0xF0b7DE03134857391d8D43Ed48e20EDF21461097

- 88mph yaLINK Pool: 0x904F81EFF3c35877865810CCA9a63f2D9cB7D4DD

- 88mph Harvest CRV:STETH Pool Deposit: 0x6a76f1c362f2C871BEB9d930c9eFd02B07841A28

- 88mph Harvest CRV:STETH Pool: 0x303CB7Ede0c3AD99CE017CDC3aBAcD65164Ff486

- 88mph Harvest CRV:RENWBTC Pool Deposit: 0xa08b1215ff7Ad33fa431E35569F95F684Cd9Bf9c

- 88mph Harvest CRV:RENWBTC Pool: 0x22E6b9A65163CE1225D1F65EF7942a979d093039

Additionally, if a malicious user minted NFTs through this method, pool functions such as internal _deposit() or internal _fund() could break temporarily or permanently.

Vulnerability Fix

88mph’s contracts are not by default pausable or upgradeable. During the assessment phase, Duncan Townsend, CTO of Immunefi, reviewed the code and suggested that 88mph pause the contracts by 1) deploying a dummy minter contract that reverted on every call, and 2) setting the minter to that contract. This pause method prevented frontrunning the whitehack and bought enough time to carefully capture all the funds and transfer them to the 88mph multisig wallet. The whitehack was executed on June 8th at 9:46pm UTC at the following address.

Shortly after the whitehack, 88mph returned all the funds to their rightful owners.

88mph is deploying its v3 platform soon, which will deprecate the affected contracts, so no immediate fix is needed. However, for the sake of public education, there are at least three different ways to have fixed the bug in the code itself:

Use a constructor instead of an init() functionAdd an onlyOwner modifierAdd an initializer modifier to make the init() function only callable once

Acknowledgements

We’d like to thank the 88mph team for their rapid and effective response to the bug report. The whitehack was expertly executed and the funds returned to users promptly. 88mph paid out a generous bounty of $42,069 to the whitehat. To report additional vulnerabilities, please see 88mph’s bug bounty program with Immunefi. It will be increased to $100,420.69 with the launch of 88mph’s v3. If you’re interested in protecting your project with a bug bounty like 88mph, visit the Immunefi services page and fill out the form.

Read Entire Article