Improper URL handling with host suffix
Description
The in-app embedded browser recognizes trusted dApps by downloading a list of well-known hosts. The WCAppMappingsManager
class is responsible for matching the URL of the origin of an RPC request to a known dApp.
The match is done by first attempting to match the precise URL against a list of known dApp URLs. If this first check fails to find a match, all the existing known dApp hostnames are matched against the URL that originated the RPC request. We speculate this is done to recognize subdomains.
private func getMappedInfo(from url: BaseURI) -> (baseURI: BaseURI, mapping: WalletConnectAppMapping)? {
return self.mappings.withLock { mappings in
if let mappedInfo: WalletConnectAppMapping = mappings[url] {
return (url, mappedInfo)
} else {
for key in mappings.keys {
if url.value.hasSuffix(key.value), let mapping = mappings[key] {
return (key, mapping)
}
}
return nil
}
}
}
This check can be bypassed by using a domain that ends like a known dApp URL. For instance, an attacker could spoof knowndapp.com by registering the domain attacker-knowndapp.com and tricking the user to visit the malicious domain.
Impact
This issue allows an attacker to spoof the origin of an RPC request. When the wallet recognizes a known dApp, it adds additional UI elements (e.g., a blue checkmark) that reassure the user about the origin of the request and automatically populates the dApp name, icon, and domain into confirmation screens.
The following screenshot shows what a spoofed RPC signing request would look like:
Recommendations
Ideally, match known dApps against a strict list of hostnames. Alternatively, prepend a period character .
to the list of known hostnames. Note that this does not fully resolve the issue, as an attacker could leverage a subdomain takeover to spoof the origin of an RPC request. An attacker could also perform an MITM attack on a user and redirect them to a spoofed HTTP version of a legitimate dApp. Therefore, we also recommend to restrict known dApp matching to secure (HTTPS) contexts.
Remediation
This issue was remediated in the following commits:
238149578fe19dda3c904d30a651e8e9c1a9cbb1