Hi,
On Monday April 14, DFINITY’s security team was involved to investigate the Odin.fun security incident where user funds were stolen (Odin’s postmortem tweet). We identified a critical vulnerability in the sign-in with Bitcoin (SIWB) canister developed by AstroX and deployed by Odin.fun, allowing people to sign in directly by signing a message using their Bitcoin wallet. In short, SIWB was missing a check to validate that the public key used to verify the signature created by the Bitcoin wallet is associated with the wallet’s Bitcoin address, making it possible to impersonate users by simply providing a signed message including the address of the victim but signed with a key generated by the attacker. More details can be found in the technical forum post and the GitHub security advisory.
On the same day, we developed a proof of concept to exploit the vulnerability which allowed us to confirm the patch successfully mitigated the issue. AstroX quickly developed and released the patch, which was then used by Odin.fun. Since teams deploy their own copy of the SIWB canister, it’s important to roll out this patch as soon as possible. If your project is affected, it’s advised to halt all sensitive operations such as trading, withdrawals, etc. They should only be enabled after patching and after an additional waiting period to allow the current user sessions (delegations) to expire.
It’s hard to avoid security bugs completely, and thus very helpful to be prepared for attacks. We would like to take this opportunity to discuss a few thoughts and best practices.
What can be done to make security bugs less likely?
In the SIWB example we saw that authentication protocol designs and implementations are susceptible to subtle bugs. A missing check which could be as small as one line of code can potentially lead to account compromises. While the absence of bugs is difficult and expensive to verify and achieve with absolute certainty, some measures can help to increase confidence in security critical components:
- Whenever possible, use vetted libraries or platform features for security-critical functionality and do not implement it on your own. If you use third-party components that are security-critical, make sure they went through a security audit and ideally have a bug bounty program in place. A bug bounty program can incentivize and motivate people to look for and responsibly report bugs they find (see e.g. DFINITY’s bug bounty program).
- Similarly, if you write security-critical components yourself and stakes are high, perform security audits and consider running a bug bounty program. Furthermore, ideally the development processes aim at high quality and security. Thorough design and peer reviews and testing increase confidence. The ICP security best practices should be used as a reference.
What can be done to be better prepared for attacks?
- Observability - make sure you notice attacks. Ideally, projects implement automated alerting for suspicious activities, such as exceptionally large transfers, spikes in usage or logins, etc.
- Store data to enable forensic investigations. Logging important user actions such as authentication, transfers, withdrawals, etc. can prove very useful to retrospectively understand an attack, identify victims and attackers, trace funds and enable forensic investigations in general.
Considerations for disclosing vulnerabilities
Security advisories such as the one for SIWB are very useful to inform the community or developers if an action is needed. On the one hand, it’s great to publish them as early as possible. On the other hand, if it is known that a quick disclosure puts known projects at risk, consider giving those projects a heads-up so they can patch before publishing the advisory, as it would put them at risk.
Finally, we will also discuss if DFINITY can help to make security critical core components safer, e.g. along the lines of this post.
Please ask questions and discuss in this thread!
Robin - team lead, DFINITY Product Security team