On July 13, 2019, Beijing time, the decentralized exchange 0x agreement project said that it found serious security vulnerabilities, and urgently closed the 0x Exchange v2.0 contract, and then deployed the repaired contract. Affected by this, 0x-based exchanges and wallets, including Radar Relay, Tokenlon, Star Bit, etc., have suspended relevant transaction services.
- Zero-knowledge proof goes into a wide range of application countdowns? 0x officially released OpenZKP
PeckShield security personnel followed up and found that the 0x Exchange contract was flawed in verifying the order signature, causing the attacker to make a malicious pending order, which in turn sold the user's digital assets at a low price, disrupting the normal trading order.
The 0x protocol is a peer-to-peer transaction that implements assets on the chain based on an open protocol of Ethereum. It expects to create a standard protocol on Ethereum that will enable anyone to run a decentralized exchange based on this agreement, enabling transactions between tokens on Ethereum. The transaction on the 0x protocol is characterized by a combination of orders under the chain and settlement on the chain, where participants who provide order services for user transactions are called repeaters. The 0x project issued its own token ZRX, which on the one hand serves as a proof of decentralized governance voting rights and is also used as a transaction service fee to establish the benefits of service provided by repeaters above the 0x protocol.
The 0x protocol is favored by many decentralized exchanges and wallets. From the pie chart of Etherscan's DEX in the past seven days, the top Radar Relay and Tokenlon are based on the 0x protocol:
In addition, their rankings can also be seen from DAppTotal's DEX 24-hour trading volume rankings:
Since a large number of DEXs on the Ethereum platform use the 0x protocol, and as the most fundamental Token Tranfer main contract, this is a significant event for the entire DEX domain.
This vulnerability involves two similar vulnerabilities, isValidWalletSignature() and isValidValidatorSignature(). Since the code of the two problems is similar, this article only uses the former as an example.
The isValidWalletSignature(bytes32, address, bytes) function is used to verify that the signature information defined by a given Wallet contract is consistent with the given signature, to ensure that the Order is a transaction executed by the correct Maker/Taker. However, during the verification process of the 0x Exchange contract, there are more serious problems:
The above figure is the full logic of this function, divided into two parts:
- The specific field of the assembly signature is the ABI encoding format;
- The signature value correctness is calculated based on the assembled ABI encoded content.
Among them, the logic of step 2 is implemented in assembly in the 0x v2 contract code:
- Introduce a cdStart pointer to the corresponding location in calldata;
- Calling staticcall() on WalletAddress to calculate signature correctness,
Pay attention to the observation code, where both input and output are cdStart pointers, that is, the memory of the input/output is multiplexed;
Under the premise of WalletAddress, there is no problem with such a process. Let's first look at the execution flow of the contract in the EVM. When the PeckShield security personnel consulted the EVM source code, they found:
When the called contract (that is, WalletAddress here) has no code, that is, the EOA account, nothing is executed and returns directly. Therefore, corresponding to the isValidWalletSignature(bytes32, address, bytes) function, the memory content corresponding to cdStart does not change before and after the call to staticcall(), and then the value of isValid that determines whether the signature is correct or not I got the wrong value.
The user completes the Token sale through the fillOrder(Order, uint256, bytes) function. PeckShield security personnel found that the three parameters of this function can be freely configured by the user:
- The Order type representing the order information;
- The number of Tokens paid by the user for this order;
- Signature information corresponding to Order
The key point is that the consistency of the Order and corresponding signature information is verified by the isValidWalletSignature() function above. Therefore, when the attacker carefully constructs the signature as the SignatureTypeWallet, the signature legality check can be skipped. The user is maliciously placed a pending order (or even a low-priced pending order), so that the attacker can successfully pay the order. Since the order information is directly transmitted to the contract by the attacker, the order information is relayed offline. Can't query.
Based on the above analysis, it is found that ordinary user accounts that have been authorized to transfer on the 0x protocol Exchange will be affected:
An attacker can forge a user's pending order and get a user token at a low price.
In view of the dangers of this vulnerability, PeckShield security personnel found that the 0x project party urgently closed the Token transfer function of the 0x Exchange v2.0 contract when the vulnerability was discovered, and all the transfer functions of ERC20, ERC721, and MultiAsset were all down. Line; then deployed the repaired contract, and informed the user and all the DEX and Relayer using 0x Exchange, the relevant migration upgrade work is in progress. Affected by this, 0x-based exchanges and wallets, including Radar Relay, Tokenlon, Star Bit, etc., have suspended trading services.
PeckShield security personnel found through the data analysis of the vulnerability feature analysis that there has been no direct user asset loss caused by security vulnerabilities since the 0x Exchange 2018-09 was launched.
For DEX and wallet with 0x, the current stage needs to suspend the transaction service. If the transaction service cannot be suspended, the corresponding 0x Exchange contract address can be changed to the currently repaired contract address.
0x protocol The contract code for this vulnerability is mainly the problem of writing the signature verification function in the inline assembly code. The direct writing of the assembly code is very useful in the case that the compiler cannot optimize the contract code, and the controllability is stronger and can be improved. Execution efficiency reduces the consumption of Gas, but writing Solidity assembly code requires a very familiar understanding of the EVM operating mechanism, otherwise some features of EVM may cause the written contract to not work properly, and also lack the various security mechanisms provided by Solidity.
PeckShield security personnel hereby remind developers to check the relevant code of the contract in time to avoid the security risks caused by similar problems. For DeFi projects such as DEX, the project party needs to find a qualified security company to audit security risks before going online.