DESCRIPTION OF EVENTS
"The standard for secure blockchain applications. OpenZeppelin provides security products to build, automate, and operate decentralized applications. We also protect leading organizations by performing security audits on their systems and products."
"OpenZeppelin Contracts includes several proxy contracts 7 for enabling upgradeability. All are based on the same concept: each upgradeable deployment consists of an implementation contract, which holds the code to be executed, and a proxy contract, which holds the state. Whenever a user calls the proxy contract, the proxy delegates execution to the implementation contract. In order to upgrade the contract, the proxy is pointed to a different implementation contract, thus changing the code being executed but preserving the same address and state. You can read more about how this pattern works here 11."
"The two most popular patterns in the library are the Transparent proxy and the UUPS proxy. As described here 6, the main difference between them is where the upgrade logic resides. In the Transparent proxy, the upgrade logic is in the proxy. In the UUPS pattern, the proxy delegates all calls to the implementation, which handles both the business logic and upgrade logic. This allows users to decide the authorization logic used for upgrades, such as Ownable 3 or AccessControl 2, or any other custom solution. To facilitate this, the library provides a base UUPSUpgradeable 12 contract that implementation contracts should extend from."
"The internal upgrade logic in UUPSUpgradeable performs several tasks. Besides changing the implementation contract stored in the proxy, it also executes a DELEGATECALL to the new implementation to atomically execute any migration function, as part of an upgradeToAndCall 9 action."
"In early September, we received two independent reports of a vulnerability in the UUPSUpgradeable base contract of the OpenZeppelin Contracts library, first released 9 in version 4.0 in April, 2021." "Upgradeable contracts using UUPSUpgradeable may be vulnerable to an attack affecting uninitialized implementation contracts." "Thank you Raymond Yeh 8 of Bluejay Finance 7 for disclosing this vulnerability 6 to us, including a working proof-of-concept of the exploit 20, on September 3rd."
"The vulnerability lies in the DELEGATECALL instructions in the upgrade function, exposed by the UUPSUpgradeable base contract. As described here 29, a DELEGATECALL can be exploited by an attacker by having the implementation contract call into another contract that SELFDESTRUCTs itself, causing the caller to be destroyed."
"Given an UUPS implementation contract, an attacker can initialize it 26 and appoint themselves as upgrade administrators. This allows them to call the upgradeToAndCall 9 function on the implementation directly, instead of on the proxy, and use it to DELEGATECALL into a malicious contract with a SELFDESTRUCT operation."
"If the attack is successful, any proxy contracts backed by this implementation become unusable, as any calls to them are delegated to an address with no executable code. Furthermore, since the upgrade logic resided in the implementation and not the proxy, it is not possible to upgrade the proxy to a valid implementation. This effectively bricks the contract, and impedes access to any assets held on it."
"On Sep 10, one week after initial contact, the team managed to setup a script to run a fix for 170 contracts across different chains and announce the initial fix on Twitter (for projects they might have missed)"
"Update September 14th: We have published a security advisory 9 and released Contracts v4.3.2 19 with a hotfix for this vulnerability."
"The mitigation for this vulnerability is simple: initializing the implementation contract. If the implementation is initialized, an attacker can no longer pass the authorization check of calling upgradeToAndCall in it. We shared this 14 on September 9th as a public security advisory before disclosing the fix and vulnerability, to minimize its impact." "Do not leave an implementation contract uninitialized. An uninitialized implementation contract can be taken over by an attacker, which may impact the proxy."
"Due to a vulnerability in OpenZeppelin Contracts v4.1.0 through v4.3.1 9, all projects using the UUPS proxy pattern should initialize their implementation contracts." "A transaction must be sent to the implementation contract (not the proxy) to invoke the initialize method. You can find out the address of the implementation contract given a proxy in Etherscan (if your contract source code is verified) on the “Read as Proxy” tab of the “Contract” section." "To help mitigate this situation, we have already executed transactions to initialize over 150 implementation contracts from multiple projects we identified across Mainnet, Polygon, xDAI, Binance, and Avalanche."
"Our team will thoroughly review the rollback test mechanism for the next release of the library. While the code provides solid guarantees against accidentally bricking the contract, it also requires the usage of the potentially dangerous DELEGATECALL operation. We will evaluate removing this check in favor of a simpler one, and adding more safeguards on the tooling side 6."
"In terms of processes, we plan to increase the number of required reviews for all major features in Contracts, especially when it involves a code change that requires going against a security recommendation, as is the case here."
"Last but not least, we are working on setting up active monitoring infrastructure to alert in the event of a deployment of a vulnerable uninitialized implementation contract. We will be sharing more news about this soon."
The OpenZeppelin smart contract framework had a vulnerability which would allow an adversary to take over the smart contract, if it hadn't been initialized yet. It's unclear if it was possible to take any funds using this method, however it was certainly possible to destroy existing smart contracts, thereby freezing funds.
blocksec-incidents/2021.md at main · openblocksec/blocksec-incidents · GitHub (Aug 11)
OpenZeppelin (Oct 14)
Security advisory: Initialize UUPS implementation contracts - Announcements - OpenZeppelin Community (Dec 4)
UUPSUpgradeable vulnerability in OpenZeppelin Contracts · Advisory · OpenZeppelin/openzeppelin-contracts · GitHub (Dec 4)
UUPSUpgradeable Vulnerability Post-mortem - Announcements - OpenZeppelin Community (Dec 4)
My Journey To Disclosing A Vulnerability That Can Lock Up Millions In Ethereum (Dec 4)
Perma-brick UUPS proxies with this one trick (devs hate this!) | iosiro (Dec 4)
GitHub - yehjxraymond/exploding-kitten (Dec 4)