Original author: Moonbeam
Timeline
February 21, 2025: Bybit multi-signature wallet was attacked, and $1.5 billion flowed out through legal signature transactions.
On-chain tracking: Funds are transferred to anonymous addresses and split into mixed coins. The attacker has a potential connection with some verification nodes.
Post-mortem analysis: A security audit found that attackers used supply chain vulnerabilities in the Safe front end to implant malicious scripts.
Why the attack happened
The hacker used malicious front-end code to convince the signers of the bybit multi-signature wallet that this was a legitimate transaction (such as a routine token transfer), which actually induced them to sign illegal transactions. In order to prevent the signers from discovering problems with the transaction content through other means, the hacker even forged this attack into a transfer transaction, so that the bybit signers would try not to check the transaction calldata through other means. (The transaction content is usually called calldata)
In short, the attack method is as follows:
The hacker obtained the developer privileges of the Safe front-end, modified the front-end code, and implanted a malicious script targeting bybit attacks;
A bybit multi-signature member visited the contaminated webpage and saw fake transaction information:
The page they see: Transfer 100 ETH to address A
What is actually required to be signed is: Modify cold wallet logic
This is like an ATM machine with a replaced display screen. The screen shows that 100 yuan is withdrawn, but the actual operation is to withdraw 1 million yuan.
Official APP - Users trust blind spot
The multi-signature transaction process in the users perception is very simple: see the transaction → sign → submit to the chain, but in fact it implies a key separation:
Transactions seen by users
The actual signed transaction
Using the official app will greatly reduce the users vigilance, so that they will ignore this layer of separation. If the official app page is hacked, the users signature will be real, they just dont know what they signed at this time.
At this time, if there is an independent channel to verify the authenticity of the signature content, the risk of front-end attacks can be eliminated to a great extent. This is what blockchain advocates: Dont trust it, VERIFY it.
Theoretical foundation of independent channel verification
Let’s first look at how the Safe contract works (so far, the Safe contract is still safe enough):
First, calculate a hash value for the transaction content (similar to generating a fingerprint of the transaction)
Sign this hash value with the private key
When enough signatures are collected, submit the original transaction and these signatures to the chain
The chain recalculates the hash value based on the original text and verifies whether the signatures are valid. If enough valid transactions are collected, they will be executed, otherwise they will be rejected.
There is no doubt that the security and hard-to-forge properties of hashes and signatures are the two cornerstones of blockchain work.
Therefore, if there is an independent channel that can obtain the original transaction text and signature before the transaction is submitted to the chain, it is possible to verify what exactly the transaction signed by the user is and whether the user has signed the transaction.
Therefore, even if the frontend or backend is attacked, the worst case scenario is that wrong data is returned. However, wrong data in the independent channel will produce the following situations:
Wrong transaction text, wrong signature - user refuses to send transaction to chain
Wrong transaction text, valid signature - user refuses to send transaction to chain
Wrong transaction text, wrong signature - user refuses to send transaction to chain
We can see that the worst case scenario is that the transaction will not be sent to the chain, and other than that, no chain loss will be caused. Therefore, the best way to deal with such display attacks is to verify through multiple channels, which is also in line with the spirit of blockchain: dont trust it, VERIFY it.
Existing solutions
Multiple multi-signature products verify each other
There are many safe-compatible multi-signature products on the market. For example, Safe itself has deployed two independent front-end pages:
https://eternalsafe.vercel.app/welcome/
https://eternalsafe.eth.limo/welcome/
After a user signs a multi-signature transaction, he or the subsequent signer logs in to the page of another multi-signature product and views the original transaction again. If different multi-signature products display exactly the same transaction content analysis, then the user can be confident that the transaction content to be signed is correct.
However, this requires that different multi-signature products all use {Safe}s backend to store off-chain transactions and signature data, and also send their collected signature data to {Safe}s backend, which places very demanding requirements on the collaboration between products; and Safe is not friendly to the original text parsing of some unconventional transactions. Even if multiple Safe front-ends display the same calldata, if it is just a meaningless string of 0x abcdefsf, it will discourage signers.
Note: Currently, the two independent alternative websites provided by Safe both require you to provide your own RPC links:
Independent Safe transaction verification tool
The community responded quickly to the Safe front-end attack. We found in the official Safe telegram group that someone had provided an independent Safe transaction parsing tool, which seemed simpler and more direct.
We have also verified this tool. As shown in the figure, you only need to paste the transaction sharing link in the safe page, and you can automatically read the Safe backend data and independently verify the correctness of the hash value and signature of the original transaction. In short, if you are sure that the calldata parsing in the figure is the transaction you want, and the SafeHash Check and Signature Check verifications are passed, you can think that this is the transaction you want to send and you have signed it correctly.
Of course, to be on the safe side, we must also carefully check the Safe Address, the signer address parsed through the signature, the interactive contract address , and the operation type , whether it is Call or Delegatecall. For example, the transaction that was attacked by bybit this time was a transaction in which delegatecall and transfer appeared at the same time. A developer with a little experience will know that such a combination is very strange.
If you encounter unreadable transaction information:
You can click Decode to provide the ABI of the transaction method, such as:
You can display readable transaction information:
Stay Safe - VERIFY, dont trust
Bybit’s multi-signature attack once again reminds us that front-end trust does not equal transaction security. Even if an official application is used, the transaction content may still be tampered with, and the signer must have an independent way to verify the content he signed.
Dont trust it, VERIFY it. is the core principle of Web3 security. I hope that in the future, the Safe ecosystem and more multi-signature products can strengthen the independent signature verification mechanism to prevent similar attacks from happening again.