BlockSec’s Perspective on the Jump “Counter Exploit”: Does the Vulnerability Really Exist?
Recently, there has been a lot of attention on the “counter exploit” to move funds from MakerDao Vault using Oasis multisig. Meanwhile, we have received a couple of queries about whether BlockSec is the “whitehat” behind this operation since we were involved in the counter exploit to help Platypus to rescue 2.4M on Feb 18. We want to clarify that BlockSec is not involved in any of the actions in the Jump case. After a detailed analysis (Kudos to the excellent analysis published in BlockWorks By Dan Smith), we think the way involved in the Jump “counter exploit” is fundamentally different from the Platypus case.
Besides, from the statement of Oasis, the counter exploit is possible due to a vulnerability in the admin multisig access
However, from our analysis, the key steps of the counter exploit are:
- Disable the delayed execution. This is designed to be done by the owner of the Service Registry contract, which is the Oasis Multisig wallet.
- Change the registered contract address for critical roles, including AUTOMATION_EXECUTOR for the AutomationBot contract and MCD_VIEW, MULTIPLY_PROXY_ACTIONS for the CloseCommand contract. This allows the Oasis multisig wallet to directly invoke the AutomationBot to execute the close command, whose real executed operation is replaced with a new one to shift the Exploiter’s Vaults.
Our analysis suggests that these key steps are NOT due to the claimed vulnerabilities in the admin multisig access.
Disclaimer: This blog is written based on on-chain transactions and public information. If you have any questions or comments, feel free to contact us email@example.com.
The Overall Process
A couple of addresses were involved during this operation. We list some of them in the following google doc.
Specifically, the high-level idea for the Jump counter exploit is as follows.
1) The Exploiter’s Maker Vaults can be managed by Oasis AutomationBot smart contract since the Exploiter enables the automation sell and buy services offered by Oasis.
2) The AutomationBot can only be operated by the address with the role AUTOMATION_EXECUTOR. This address is a configuration in the Oasis Service Registry contract, which can be updated by the Oasis multisig wallet. However, the update to the configuration of the Oasis Service Registry contract has a delayed execution mechanism, which can be disabled by the Oasis multisig wallet.
3) The actual contract and the function executed by the AutomationBot are also configurable in the Oasis Service Registry.
So the Oasis multisig wallet first disables the delayed execution of the Oasis Service Registry contract and changes the configuration in the Oasis Service Registry contract to set the AUTOMATION_EXECUTOR role as itself (multisig wallet). The change is immediately effective. Then the multisig wallet invokes the AutomationBot to execute a command that can take over the Exploiter’s Maker Vaults (shift and give). Since the AutomationBot can manage the Exploiter’s Vaults, the whole operation can succeed.
We think this process is fundamentally different from the Platypus case, where we found a vulnerability in the attacker’s contract and shared it with Platypus. Then Platypus exploited the attacker’s contract to move the funds that belong to themselves. However, in the Jump case, the Oasis multisig disables the delayed execution mechanism, updates the critical configurations that can totally change the contract’s behavior, and leverages the management role of the AutomationBot to operate on the Maker’s Vaults on behalf of the Exploiter.
In the following, we will elaborate on the whole of the Jump “counter exploit.”
The Detailed Steps
The operation involves multiple protocols and parties, including Jump, Oasis, Wormhole Exploiter, and Maker. Note that the Maker does not take any action during the operation.
Specifically, the Exploiter creates Maker Vaults (30100 and 30179) and uses ETH as collateral, and borrows DAI from the vault. The Explotier also leveraged the automation sell and buy services offered by Oasis to manage the collateralization ratio of the Maker vault.
In order to use the Oasis automation service, a smart contract called AutomationBot offered by Oasis needs to be added to the management list of the Vault. This means the AutomationBot has control of the Maker Vault created by the Exploiter. After that, the AutomationBot can manipulate the Vault and transfer the Vault’s collateral and debt to another one, which is controlled by Jump. This is the basic process of the “counter exploit.” Note that, to invoke the AutomationBot, the transaction needs to be invoked from the address that is registered as AUTOMATION_EXECUTOR in the ServiceRegistry contract.
Step 1: add address 04e1 into the Oasis multisig wallet
The transaction adds the address 04e1 into the Oasis multisig wallet. This wallet currently has 12 addresses, with four signers’ confirmations.
Step 2: Disable the delayed execution of Oasis Service Registry
This transaction disables the delayed execution of the Oasis Service Registry by invoking changeRequiredDela(0). Note that the Oasis Service Registry is a smart contract that stores critical configuration information that will be used by the AutomationBot. Typically, the configuration change has a delayed execution mechanism for the critical operation, e.g., updateNamedService, that will be used in the “counter exploit.” Usually, the delayed execution is a security mechanism for transparency so that the update of critical information will not be effective immediately, and others can take a second look.
Note that, the execution to invoke changeRequiredDelay is restricted by the delayed execution (since the change to reqDelay) has not been effective yet.
Step 3: Perform the counter exploit
This transaction performs the counter exploit. Let’s dive into the execution trace output by Phalcon, the transaction analysis tool developed by BlockSec.
Note that this transaction is initialized from the 04e1 address and executed through the Oasis multisig wallet, which means the operation is at least signed by four signers.
Step 3.1 Disabled the delayed execution
As shown in the trace, the delay is set to zero again. This is to apply the action of disabling delayed execution in step 2.
Step 3.2: Create two contracts and update the service registry
Two new contracts are created, which will be used as the MCD_VIEW and MULTIPLY_PROXY_ACTIONS contracts.
- MCD_VIEW: 0xceca8d8410797bc6c575fd8ba957708d1e85ed36
- MULTIPLY_PROXY_ACTIONS: 0xcaef24016d0fba2c1a9427371e0d79c5781b6ea8
Then these two contracts will be updated to the Oasis service registry contract.
Step 3.3: Change the Automation Executor
The Oasis multisig is registered as the AUTOMATION_EXECUTOR in the ServiceRegistry contract. This is necessary since only the registered contract with this role can invoke the AutomationBot contract.
Step 3.4: Ask the AutomationBot to close the Exploiter’s Vault
The critical process starts from the execute function of the AutomationBot. The detailed executed functions are passed through the arguments.
To understand the whole process, we first take a look at this function.
The high-level logic is that the bot first draws DAI from the vault (line 268) and then invokes the concreted command contract to execute on the vault (specified by cdpId) (line 274 to line 278). During the process, the command address is the CloseCommand contract. After that, a check of isExecutionCorrect is needed.
The following shows the execute function of the CloseCommand contract. It gets the actual executor contract address from the service registry contract using the KEY MULTIPLY_PROXY_ACTIONS. Note that the contract address corresponding to the MULTIPLY_PROXY_ACTIONS has been updated to a new one. As such, the actual execution of the CloseCommand is controllable to perform arbitrary operations in the new contract.
Remember that the isExecutionCorrect is invoked on the CloseCommand to check whether the execution succeeded (line 278 on the AutomationBot.sol). Since the view address has been updated, the return value of the check viewerContract.getVaultInfo(cdpId) could be an arbitrary value that can pass the check on line 24 (CloseCommand.sol).
After going through the code, let’s look at the execution trace. From the trace, we can see that the automationBot invokes the CloseCommand contract. The CloseCommand contract can invoke the replaced MULTIPLY_PROXY_ACTIONS contract to open a new Vault (30231), shift the Vault 30100 (the Exploiter’s) to 30231 (the newly created one), and give the new Vault 30231 to Oasis Multisig Wallet. A similar operation is performed on the other Vault of the Exploiter (30179).
Step 3.5 Restore the state
Restore the changed entry in the Service Registry and enable the delayed execution again.
Step 3.6 Give the Vaults to address 1536
Now the new Vaults (30231 and 30232) are controlled by Oasis Multisig Wallet. Then the Vaults are given to 0x15364305a06ba3ac6ba13dfe97ca0bad639adf41 in these transactions [TX1 TX2]. Then this address can pay the debt in the Vault and withdraw the collateral (Ethereum). Since the collateralization rate is high (around 293% for vault 30100), paying back and withdrawing the collateral can get around 120K Ethereum back with the cost of paying around 76M debt from vault 30100. Readers can refer to the Maker protocol document for more information on these operations.
Learn more about BlockSec: Website | Document | Twitter | Medium | TG Group