The PolyNetwork has been hacked and more than 300 million USDs have been stolen. The attacker performed the attack on multiple chains. In this blog, we use the attack transaction on Ethereum (0xd8c1f7424593ddba11a0e072b61082bf3d931583cb75f7843fc2a8685d20033a ) to analyze the possible reason of the hack. Our initial analysis shows that one possible reason could be either the leakage of the private key that is used to sign the cross-chain message, or there is a bug in the signing process of the PolyNetwork that has been abused to sign a crafted message.
Disclaimer: This blog only contains the result of our initial analysis based on the onchain data on Ethereum. We cannot verify our findings without further information from Poly Network.
Update 2021/08/12: The further information shows that the cause of the attack is because the keeper has been modified by the attacker (not because of the leakage of the private key). We have a further analysis to answer the question why the transaction to change the keeper can be executed in the first place.
Transaction and call trace
We use our transaction analysis system to recover the trace.
Attacker -> EthCrossChainManager -> EthCrossChainData -> LockProxy -> managerProxyContractforLockProxy
- 0xc8a65fadf0e0ddaf421f28feab69bf6e2e589963: Attacker
- 0x838bf9e95cb12dd76a54c9f9d2e3082eaf928270: EthCrossChainManager
- 0xcf2afe102057ba5c16f899271045a0a37fcb10f2: EthCrossChainData
- 0x250e76987d838a75310c34bf422ea9f1ac4cc906: LockProxy
- 0x5a51e2ebf8d136926b9ca7b59b60464e7c44d2eb: managerProxyContract for LockProxy
Function Signatures:
- d450e04c (verifyHeaderAndExecuteTx)
- 69d48074 (getCurEpochConPubKeyBytes)
- 5ac40790 (getCurEpochStartHeight)
- 0586763c (checkIfFromChainTxExist)
- e90bfdcf (markFromChainTxExist(uint64,bytes32))
The main process of the attack
The main process of the attack is that the attacker passed the signed data to the function verifyHeaderAndExecuteTx(). This function will decode the data and verify the signatures that are used to sign the data. If this process passes, the method (and the contract address) specified in the message will be executed. During this attack, the unlock
function of the smart contract 0x250e76987d838a75310c34bf422ea9f1ac4cc906 is invoked to transfer the Fei to the attacker.
In summary, the attack is due to the valid parameters passed to the verifyHeaderAndExecuteTx function. And the parameters can pass the signature verification process. After that, the transaction specified in the message will be executed (like the arbitrary command execution in software security.)
To better understand this process, we recover the critical values of the call trace.
Function: verifyHeaderAndExecuteTx:
verifySig
unlock
The variable of managerProxyContract in the LockProxy. It matches the value of the caller address of the unlock function.
Conclusion
From the recovered values, we find that:
- The attacker provides a valid signed message to the function verifyHeaderAndExecuteTx
- The
onlyManagerContract
modifier in the LockProxy smart contract is NOT bypassed.
Based on these two observations, we suspect that
- The attacker may have the legitimate keys to sign the messages, which indicate the signing keys may have been leaked.
Or
- There is a bug in the signing process of the PolyNetwork that has been abused to sign a crafted message.
However, we do not have further offchain data to verify our findings. We hope our analysis can be helpful for further investigation.
Credits: Yufeng Hu, Siwei Wu, Lei Wu, Yajin Zhou @BlockSec
Twitter: https://twitter.com/BlockSecTeam