Bybit - Compromised Safe Wallet UI
Safe Wallet UI was compromised by gaining access to the host machine.
Description
Bybit suffered from a security breach in Safe’s hosting infrastructure losing 1.4bn USD.
The attackers, the lazarus group, gained access to the server and was able to modify the served Safe Wallet frontend. More on the attack: https://x.com/safe/status/1894768522720350673
The malicious code was specifically targeting Bybit’s next transaction. As of today, it is commonly agreed that the signers of the transaction were shown a fake UI, seeming to be the intended transaction to sign, but in fact it was a malicious transaction.
Unfortunately, it is often very hard to verify the correctness of the message that is signed in software or hardware wallets.
Attack steps:
- Attackers gained access to the hosting server by compromising a developer’s machine.
- A malicious frontend was uploaded to the server, which targeted Bybit’s next transaction.
- The frontend would show the intended transaction but in fact the message to be signed was malicious
- The malicious message was a delegate call which would change the implementation of the Safe’s proxycontract
How assertions could have prevented this
In Safe’s proxy implementation, the first storage slot is the implementation address.
The malicious transaction was executing a delegate call to a malicious contract, effectively changing the implementation address of Bybit’s proxy contract. A change of the implementation address allows an attacker to almost completely exchange the logic of the contract. Therefore it was possible to be able to drain all the assets of the Safe without the need of any additional approvals by the original owners.
It should be highlighted that even if there is no logic to change the implemenation address in the implementation by safe, delegate calls can modify storage slots of the calling contract. This allows for full flexibility but opens up the possibility for attacks.
Preventing attacks through assertions
It might be fair to assume that most users of safes would never actually want to change the implementation address of their safe, but they have no way to express their preferences.
Assertions give users the ability to express additional invariants on the state of the contract. A change of the implementation address could be prevented by analyzing the state changes within a transaction.
PhEvm precompiles used:
- forkPreState allowing to fork the state of the contract before a transaction
- load reading specific storage slots
- getStateChangesAddress getting all state changes within a transaction for a given slot
To even enhance security properties, a complentary assertion could enforce transfers to a whitelist of addresses. In the below example, the assertion checks if the balance of the safe decreased while the balance of the whitelisted addresses increased with the respective amount.