ZenGo is a secure Web 3 wallet that uses Multi-Party Computation (MPC) technology.
Recently, CertiK’s SkyFall team conducted a thorough audit and research on numerous mobile wallets and found that ZenGo’s MPC solution provides stronger security defenses than ordinary mobile wallets - ZenGo wallet users, especially those with high-value wallets, can defend against direct attacks from advanced attackers: such as exploiting zero-day vulnerabilities or advanced malware to gain root privileges on user devices.
This threat is new and has only been discovered by the CertiK team, so MPC wallet developers must pay attention to the attack details!
Defending against privileged attackers is challenging. In our report, we proposed a new attack method and attack vector against the MPC method in ZenGo. We immediately reported this security issue to ZenGo, and ZenGo responded quickly and fixed the issue.
In this article, we dive into the technical details of our findings and share how we are working with ZenGo to improve the overall security of MPC wallets.
Based on our thorough review of ZenGo’s security design and their professional responses to questions, CertiK believes that ZenGo can be called the most secure wallet solution currently on the market.
What is MPC?
Multi-party computation (MPC), sometimes also called secure multi-party computation (SMPC), is a field of cryptography that allows multiple parties to jointly sign a transaction while ensuring that each party's secret key is not compromised.
Because MPC technology can distribute keys among multiple parties to eliminate any single point of failure, it allows users to better protect Web 3 private keys. This method is also commonly known as "threshold signatures" and has been adopted by many Web 3 custodians and wallet developers to protect Web 3 assets. Among them, ZenGo is one of the most well-known and most used MPC wallet developers.
As shown in the figure below, the wallet is not controlled by a traditional private key to sign transactions, but multiple private key shards participate in the transaction signing process and generate a final signature for verification.
General MPC design for generating signatures
Through this research, we have realized the importance of challenges and potential security risks associated with MPC methods for the protection of Web 3 assets. We want to better protect Web3 users by exploring and solving these challenges.
So we can think about this question: Why can MPC wallets provide higher security than traditional crypto wallets? How does it do it?
ZenGo MPC design and safety assurance
Through this research, we have realized the importance of challenges and potential security risks associated with MPC methods for the protection of Web 3 assets. We want to better protect Web3 users by exploring and solving these challenges.
So we can think about this question: Why can MPC wallets provide higher security than traditional crypto wallets? How does it do it?
After evaluating the designs of different Web 3 wallets, we looked into Web 3 wallets for MPC - We evaluated one of the most respected MPC wallets in the market and the leading self-custodial MPC wallet - ZenGo.
For this evaluation we used the same threat model as in our previous research overview: “If your device is infected with malware, can the wallet still protect your funds?”
Overview of ZenGo Security Architecture
As shown in the figure above, ZenGo wallet has a unique security design, and its security architecture and recovery process are more layered than traditional wallets. The security features provided by ZenGo include but are not limited to:
Two-party signature scheme: ZenGo's MPC design implements a two-party signature scheme. Each user involves two key shards when generating a transaction signature: one stored on ZenGo's server (master key ①), and the other stored on the user's device (master key ②). Neither ZenGo nor the user knows what key the other party holds.
TEE-based protection: In addition, to prevent "man-in-the-middle" and "APP hijacking" attacks, the ZenGo application uses a TEE (Trusted Execution Environment) solution and signs the HTTPS communication content with a TEE-specific key to request related APIs. This TEE-based device key is generated within the TEE when the user sets up the device, and even the operating system itself cannot extract it.
With these security features, attackers can no longer steal users' private keys from memory or storage files and control ZenGo users' assets. ZenGo also uses TEE to protect the interaction between the server and the client from being tampered with. This also means that "man-in-the-middle" and "APP hijacking" attacks are effectively blocked and defended.
Our audit confirmed that ZenGo does have a secure design and implementation that resists these attacks, and that it has the highest level of security among the audited wallets we have come across.
ZenGo's security design and implementation successfully protects against attacks including those from privileged sources, as well as the attacks described above. However, handling all types of privileged attacks is not an easy task, especially considering that the attacker can read (and in some cases write) arbitrary memory.
By auditing the entire wallet, we were able to discover an implementation issue in ZenGo that allowed us as a privileged attacker to bypass certain protections.
But before we get into the details, let’s review the security mechanism of the ZenGo wallet.
Security practices of ZenGo wallet
Through this research, we have realized the importance of challenges and potential security risks associated with MPC methods for the protection of Web 3 assets. We want to better protect Web3 users by exploring and solving these challenges.
So we can think about this question: Why can MPC wallets provide higher security than traditional crypto wallets? How does it do it?
A classic Web 3 wallet only requires a private key. However, there is always a chance that the user will reveal the private key or mnemonic phrase. Therefore, they may lose the private key and watch the attacker take possession of the assets.
The MPC wallet works differently. The wallet does not have a single private key. The user now only holds one shard of the private key and knows nothing about the rest of the shards. From this perspective, even if an attacker obtains the user's personal key, they cannot directly transfer funds. In order to further protect users, ZenGo uses a variety of means to strengthen their security design: not only the above-mentioned two-party signature scheme and TEE-based device protection, but also biometric authentication based on facial scanning and additional key encryption.
Protection measures during user registration and user account recovery
During the user registration and account recovery process, ZenGo adopts the following protection measures to protect user assets.
User identification protection: The two-party signature scheme requires that users can only spend their funds when they interact with another party (the server in ZenGo's case). In order to be able to identify the user and the associated key shares stored on the server, ZenGo requires the user's email in order to register an account.
To avoid email hacking, ZenGo uses facial scanning technology (FaceTec's Zoom) to bind biometric information to user accounts. During the account recovery process after registration and email verification, users need to "scan their faces" for authentication.
Application-Server Communication Protection: To ensure that ZenGo servers interact with legitimate users' devices, ZenGo generates and registers an asymmetric key in the TEE environment during the registration and account recovery process. All interactions between the ZenGo application and the server need to be signed by this specific key. Because it is protected by a hardware-backed security solution, this key cannot be directly read by attackers and is difficult to abuse.
ZenGo user registration and account recovery process
User key sharing protection: It is risky to let users store and back up their key shards, as this may compromise all the security measures provided by ZenGo. To address this security issue, ZenGo generates an encryption key during the registration process. The encryption key encrypts the user's key share and stores the ciphertext on its servers.
However, the encryption key is not shared with ZenGo, but is forced to be synchronized with the user's Google Drive or iCloud. The encrypted key can only be shared and further decrypted after the user passes email verification and server-based biometric authentication. The server-based biometric authentication (FaceTec face recognition) is almost impossible to be "fooled" by regular 2D/3D face reconstruction.
Generation of transaction signature ZenGo transaction process
To sign a transaction, the ZenGo application performs a series of interactions with the ZenGo server. During the interaction, ZenGo uses its open source two-party signature solution and user key sharding to generate two-party signatures. The ZenGo server then further completes the signature and broadcasts the transaction. All requests in this process are timestamped and signed in the TEE to maintain information integrity and non-replayability.
Problem Discovery in ZenGo MPC Design
As we discussed before, there are many cryptographic keys involved in ZenGo's security design, each with different responsibilities. In the table below, we show which keys ZenGo uses and how they are protected.
From this table, we can see that there are three keys used on the client: master key ②, device key and encryption key. An attacker needs to obtain both the master key ② and the device key in order to interact with the ZenGo server and steal user funds.
As introduced in the previous transaction details section, the master key ② is used as text in memory to generate the signatures of both parties, which allows an attacker to read the process memory and extract the master key ②. As a solution to this problem, all transaction requests to the ZenGo server need to be signed by the device key, which cannot be read or extracted. This process is done in the TEE and cannot be controlled by the attacker.
However, despite the many aspects of ZenGo’s security design, CertiK’s SkyFall team still found a vulnerability in it. After a detailed audit of all APIs in the ZenGo application, we noticed that certain APIs allow an attacker to spoof the ZenGo server and easily generate a new device key to use on other devices.
This device key registration API lacks necessary security protections: an attacker can generate a new NIST P-256 elliptic curve key on another device. The attacker can then use the device key registration API to register the newly generated key pair, pretend to be a new user device and request transactions.
We name this attack the device forking attack.
Device forking attack on ZenGo wallet
As mentioned above, an attacker needs to have the ZenGo user’s master key② and a valid device key to steal their assets.
Master Key ②: Master Key ② is a fixed key that is used as plaintext in memory in order to participate in the signing process of both parties. Due to the complexity and uniqueness of the signing algorithm of both parties, this process cannot be completed in TEE. Therefore, a privileged attacker can simply dump the process memory or hijack certain system APIs to extract Master Key ②. The screenshot below shows the Master Key ② that we were able to extract on the iOS platform.
Device key: During the registration or account recovery process, a valid device key is generated on the user's device in the TEE as a solution to the aforementioned plaintext extraction threat. The device key cannot be read by an attacker with privileged permissions. However, an attacker can use the same device key registration API to register another key pair and use it.
The device key registration API only has a very basic authentication mechanism: an attacker can use a plain text locally stored JWT token and the extracted master key② to authenticate the API. According to the design, the server code involved in this API should also be authenticated by Facetec biometrics. However, in practice, due to a logical flaw, the code failed to perform this step.
In our simulated attack, we simulated a privileged attacker and continuously monitored the victim's device. As soon as the ZenGo application was launched, we immediately extracted the master key from memory② and read the API token from the local database. This information is enough for the attacker to steal all the user's funds!
Once we have the API token, we generate a new device key and call the device key registration API to register the device key on the ZenGo server. We then build all the API requests to interact with the ZenGo server to initiate transactions. Generating two-party signatures is a very unique and complex process for MPC wallets. Fortunately, ZenGo's development process has always adhered to the open source spirit, so we were able to compile the two-party signature library used in the official ZenGo application and run it locally.
The above diagram shows how we extracted the master key② and registered a new device key on behalf of the victim. We then used these two keys to send 0.00222 ETH to the "attacker's account". The whole process took only a few seconds and the victim would be completely unaware.
To address this issue, ZenGo implemented FaceTec biometric authentication for device registration on the server side. The server API level fix eliminates the possibility of this attack and does not require updating client code.
Summarize
In CertiK’s assessment of ZenGo, we thoroughly examined and audited all security measures taken to protect user assets. These measures include a two-party signature scheme, TEE-based device protection, and biometrics for account registration and recovery.
Despite ZenGo’s high level of security awareness and measures taken to improve its security, CertiK discovered a critical and exploitable API access authentication vulnerability in ZenGo’s implementation. The vulnerability could allow a privileged attacker to bypass existing security measures and steal users’ funds when their devices are compromised.
ZenGo promptly addressed the issue and deployed a patch, which CeritK subsequently conducted a thorough further audit and determined had fixed the risks noted in the report.
With the deployment of the patch, we believe that ZenGo can effectively prevent privileged users from illegally accessing user funds in the future. Defending against privileged attackers is a difficult task, and ZenGo's security practices show us a safe way to fully protect users. The wallet's practices exceed the vast majority of conventional wallets on the market.
We are honored to work with ZenGo and are honored to work together with ZenGo to protect the security of Web 3 users and solve security challenges. We also thank ZenGo for its timely response to the vulnerability we discovered and its efficient vulnerability patch release action.
As practitioners in the security industry, we are very happy to see that a top Web 3 wallet company attaches so much importance to security and has such a high sense of responsibility for users and their funds. We hope that in the future security path, we can improve the security of more projects and give their users "peace of mind".
