The emergence of Web3 heralds a new era of cybersecurity challenges and opportunities. New security considerations span designs built on smart contracts, blockchain technology, decentralized finance (DeFi), and tokenomics. Among the prominent security concerns in Web3 are flash loan attacks, re-entrancy vulnerabilities, price (or price oracle) manipulation, denial of service attacks on blockchain nodes, bank runs, and exit scams.
However, it's essential to acknowledge the interplay between Web3 innovations and traditional Web 2.0 components. Many Web3 products incorporate Web 2.0 elements, rendering Web 2.0 security risks an important consideration in the Web3 context. Consider decentralized applications (dApps): While they often rely on smart contracts for backend operations, their user interfaces frequently mirror Web 2.0 designs, with front-end interfaces for user interaction and sometimes even traditional backends complete with API servers and databases for enhanced functionality. This fusion of Web 2.0 and Web3 elements opens the door to a range of Web 2.0 attack vectors. Vulnerabilities like SQL injection can compromise databases, remote code execution might target APIs or servers, and cross-site scripting (XSS) can introduce malicious code into the front-end, leading to potential data theft, compromised accounts, and fraudulent transactions. Moreover, significant financial impacts, such as those witnessed in crypto exchange and bridge hacks, are frequently a consequence of Web 2.0-style social engineering attacks.
At CertiK, it’s our mission to secure the Web3 world against these threats. Our team has safeguarded thousands of clients against both Web 2.0 and Web3 vulnerabilities. In this post, we explore a Web 2.0 vulnerability we uncovered in the API of a popular wallet communication protocol used in Web3.
WalletConnect is an innovative open-source protocol designed to connect decentralized applications (DApps) with cryptocurrency wallets. It serves as a crucial link between users and a variety of DApps, enabling interactions through self-custodial Web3 crypto wallets like Trust Wallet. To initiate a connection, users scan a QR code provided by the DApp, which presents details such as the DApp's name, icon, and origin. However, this information is DApp-supplied and not authenticated by wallets, posing a risk of phishing attacks – a concern highlighted by the Web3 security community, including us at CertiK. In response, WalletConnect introduced the "Verify API".
The Verify API is a proactive security enhancement for WalletConnect-integrated wallets. It alerts users when connecting to potentially suspicious or malicious domains, thereby helping prevent phishing attacks. This API utilizes WalletConnect’s domain registry and Blowfish's domain scanner to scrutinize connection requests. When users attempt to connect with a DApp, the Verify API enables wallets to present four critical states, assisting users in evaluating the safety of the domain and discerning potential malicious intent. For detailed insights into the Verify API, please consult the official documentation.
The discovery of the vulnerability in the WalletConnect protocol was an unintended byproduct of a routine penetration test conducted for a client. During the initial stages of a penetration test, comprehensive exploration of the application is critical. It provides an understanding of the application's functionality and the services it interacts with. In this case, the client’s web application used WalletConnect, a popular protocol for integrating digital wallets into applications. Our monitoring of the HTTP traffic revealed requests made to WalletConnect endpoints. One, in particular, caught our attention.
Before delving into the specifics of this vulnerability, let's look at the HTTP request flow for the Verify API from the DApp’s perspective:
The embedded WalletConnect SDK dispatches a request to verify.walletconnect.com
including the project ID in its path. If registered with WalletConnect, the server responds with a link to an index.js
file and a CSRF token.
The SDK then performs a GET request to obtain the JavaScript code snippet for the attestation
request, utilizing the path and CSRF token acquired earlier.
Upon a user’s decision to connect their wallet through WalletConnect and generate the QR code, the SDK sends a POST request to the /attestation
endpoint. This request includes the attestationId
and original
, establishing the id<>origin
pair and completing the initial DApp setup.
When examining the HTTP responses, we noticed that the HTML body included a token value directly embedded in a JavaScript code block. To a seasoned Web 2.0 hacker, this pattern suggested a potential vulnerability to HTML injection or XSS (Cross-Site Scripting) attacks. We tested this hypothesis by modifying the token in the request to an XSS payload <svg/onload=alert(document.domain)>
, which successfully executed the script.
https://verify.walletconnect.com/index.js?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.%3Csvg/onload=alert(document.domain)%3E
XSS is a form of injection attack where malicious scripts are embedded into trustworthy websites. In Web 2.0, attackers commonly exploit XSS vulnerabilities to access a user's session cookie, hijacking their session and account control. Other tactics include redirecting users to harmful sites or initiating unauthorized requests. In the Web3 context, XSS attacks could manipulate a crypto wallet connection, tricking users into signing harmful transactions, potentially emptying their wallets.
Further investigation into the XSS issue included testing various payloads to assess if the vulnerability could escalate to more severe risks like SQL injection or remote code execution. We found that the Verify API was open source and, upon reviewing its code, understood the root cause of the XSS vulnerability.
The issue stemmed from the way the validate_format
function validated the token format.
if !CsrfToken::validate_format(&query.token) {
While it checked if the token had a valid JWT header, it failed to thoroughly inspect the entire token, making it susceptible to XSS attacks via payloads attached to valid JWT tokens.
fn validate_format(s: &str) -> bool { jsonwebtoken::decode_header(s).is_ok() }
The identified reflected XSS vulnerability could be manipulated to create a convincing phishing site. This site would urge victims to link their wallets and unknowingly sign a malicious token approval transaction. The exploit leverages the trust associated with the https://verify.walletconnect.com/ domain, heightening the phishing attack's credibility. For users not well-versed in the technical nuances, it can be particularly challenging to verify the authenticity of transaction requests, making them more vulnerable to these sophisticated phishing attempts. Successful exploitation of this vulnerability could lead to substantial asset losses for users and tarnish the reputation of the domain. Our research did not uncover any methods to intensify the impact of this vulnerability, such as compromising other aspects of WalletConnect or exploiting users passively.
To validate the potential threat, our security experts crafted a demonstration payload. This payload was designed to create a phishing website that would prompt users to consent to a transaction, essentially granting token allowances without their knowledge.
Upon detecting the XSS vulnerability, our team swiftly compiled a detailed report and reached out to WalletConnect via the contact information provided on their security page. WalletConnect's team promptly acknowledged our findings and outlined a timeline for resolving the issue. The remediation included an update to the validate_format
function, as seen in this commit. This update adopts a whitelist approach, permitting only alphanumeric characters and the symbols -
, .
, and _
in the "token" value. While text injection remains theoretically possible, this critical update significantly diminishes the risk of XSS exploitation.
Oct. 14, 2023: CertiK reported the vulnerability to WalletConnect.
Oct. 16, 2023: WalletConnect acknowledged the receipt of the report and confirmed the issue.
Oct. 20, 2023: WalletConnect updated the source code and pushed the fix to the live Verify API.
Oct. 20, 2023: CertiK confirmed that the XSS vulnerability was mitigated.
Oct. 25, 2023: CertiK received the bug bounty reward from WalletConnect.
This incident underscores a vital lesson: vulnerabilities characteristic of Web 2.0 not only persist in Web3 environments but also evolve, presenting new modes of exploitation with potentially amplified impacts. Therefore, a proactive stance on security is crucial. Regular audits and penetration tests, vigilant vulnerability assessment, and staying abreast of the latest security developments are key practices for organizations to preemptively identify and address emerging threats.
For DeFi users, vigilance is paramount. Always verify the URL of any website or platform you access. Scammers frequently mimic legitimate sites to deceive users into executing harmful transactions or divulging sensitive information. When conducting transactions, meticulously review all details presented by your wallet. Understanding the wallet's notifications and confirming the accuracy of the destination address is essential for safe transactions.
In this post, we have detailed the discovery and implications of a reflected XSS vulnerability within WalletConnect's Verify API, highlighting a notable security risk from a Web 2.0 attack vector in the Web3 context. We commend WalletConnect for their swift response and effective remediation efforts. Their commitment to providing tools that serve the Web3 community without compromising on security, evidenced by their prompt action to our report and subsequent patch, is a testament to their role as a leading provider in wallet communication protocols.