-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Resolve security questions around ZIP 321 and zcash: handler registration by malicious apps #60
Comments
User must willfully select the malicious app to handle the intent? Doesn't seem like a realistic or practical attack from my understanding. |
Wallet-specific URIs wouldn't be useful or convenient. Seems like a bad idea. |
No, it's not correct that a user must willfully select the malicious app. Here's a write-up that covers that misperception. Background on potential attacksURI handler interceptionIt is not possible, on either Android or iOS, for a wallet app to reliably ensure that only it (or only other genuine wallet apps) can register as handlers for a given URI scheme. On iOS, the behaviour is particularly unhelpful: one of the apps that registers for that scheme will be selected, but there is no user input, no reliable or documented specification of how the selection is made, and nothing in the UI that would indicate to the user that other apps are registered for that scheme. On Android, the user is presented with a list of apps that have registered for the scheme, but there is no way to prevent a malicious app from having a confusingly similar name and icon to the correct app. Activating the wrong app can have both privacy implications (the intercepting app gets the URI, and can potentially use the address, amount, etc. for social engineering attacks or in chain analysis), and integrity implications (the intercepting app could pass a modified URI, perhaps paying to the attacker's own address, to the real wallet app that has the user's spending keys). Clipboard interceptionThe clipboard is not secure on either iOS or Android. Arbitrary apps can intercept and modify the clipboard contents, and there is no practical way to prevent this. The visibility of this attack to the user depends on the platform version and the permissions granted to the malicious app. Modifying the clipboard contents (without reading them) never notifies the user on iOS or Android. There was also no visibility to the user of an app reading clipboard contents before Android 12 or iOS 14. After those versions, a system notification is supposed to be displayed (e.g. "${short app name} pasted from your clipboard" for Android). However, certain permissions allow this notification to be overdrawn on Android. Proposed solutionIt is safe to parse The message should convey to the user that they need to manually open the wallet they intend to use, and scan Hypothesis: this will be more convincing if the security problems are explained to the user. Proposed wording of the warning screenYou have scanned or followed a On $OS there is no way to ensure that this way of using If a malicious app were installed on your device, it could:
These attack possibilities apply when scanning a QR code, following a link, or copying and pasting a link from the clipboard. To maintain your privacy and security, please instead manually open the Zcash wallet app that you intend to pay with, and use its scanning feature to scan QR codes. If you do this in future then it will be faster as well as more secure: you won't need to go through this screen again, and you will be safer from any malicious apps. For Zashi the scanner is [brief description of how to get to it]. We can't automatically open Zashi for you because this screen could also be faked by a malicious app. Thanks for reading, and sorry for the inconvenience.
|
@LukasKorba and @true-jared raised the issue that according to iOS documentation and previous versions of Apple's Human Interface Guidelines (although I cannot find it in the current guidelines), an app should not quit programmatically. Instead it's intended that users tap the Home control to go back to the home screen (there is no equivalent of the Back control on Android). It is definitely possible to adapt the behaviour to both follow the human interface guidelines and meet the security requirements. The warning screen tells the user to tap the Home button and go into the app again. The app detects the resulting |
If the app instead just takes the user into the scanning UI in Zashi, how is that any worse? A malicious app that emulates this behavior can't gain any additional capabilities that it didn't already have. I think that the UX cost of what you're proposing here is too high for too little gain, vs. educating the user and then taking them to the camera to re-scan. |
That UI doesn't solve the "URI leaks information to malicious app" problem. You have to train the user not to use the system scanner for things that might be payment links in order to solve that. If they get directly to the place they need to be by doing the wrong thing, then they'll continue to do the wrong thing. Don't think of just the specific case in which the link got intercepted, think of every future case with that user. |
To summarize what was decided:
|
Unfortunately, this is not a solution for me. First of all, on both Android and iOS, camera access is indeed governed by strict permissions, sandboxing, and hardware-level protections. However, if an attacker gains elevated privileges—whether by exploiting a vulnerability or by rooting/jailbreaking the device—they may intercept the camera’s data flow. This could involve installing a kernel-level driver or modifying system libraries so that the raw camera stream is intercepted or altered before reaching the intended application. Additionally, instructing users to scan a QR code through Zashi’s internal scanner does not resolve the issue. When a user browses a website on their mobile device and then attempts to pay via Zashi, they cannot scan a QR code that appears on the same screen. While a user might take a screenshot of the QR code and then scan it from their photo gallery, a malicious app could modify even the screenshot. Thus, the problem persists in the current Zashi implementation. Furthermore the payment link does not necessarily have to be encoded exclusively as a QR code; it can also be presented as a clickable HTML anchor tag (e.g., Pay with Zcash). Rejecting the registration of the “zcash:” URL scheme does not provide a security benefit. In fact, allowing multiple apps to register the URL scheme may be preferable, as it presents the user with a choice - alerting them to a potential anomaly - rather than having Zashi completely opt out and potentially enabling a malicious app to always intercept the URL! This approach preserves user experience and interoperability while also offering a visible indication that something unusual may be occurring, at least on Android. In summary, rejecting URL scheme registration outright sacrifices crucial user experience without delivering a proportional security benefit. Allowing multiple apps to register the URL scheme is better than opting out. One proposed solution is to implement a ZIP specification that defines how a payment URL is transformed—via a cryptographic hash function—into a short control hash. This hash would be displayed on the website generating the payment link alongside the zcash: payment link. When the user initiates a payment by clicking a zcash: link, it would open in Zashi, and the user can verify that the control hash shown on the website matches the hash generated from the payment URL. This additional verification step would help ensure that the URL has not been most likely tampered with by a malicious intermediary, thereby alerting the user to any discrepancies in a clear and transparent manner. Please reopen this ticket |
@Tomas-M the problem here is with iOS: on iOS, if multiple handlers are registered for the I like your idea of adding a convention around verifying a control hash, but unfortunately since the control hash is out-of-band it just provides extra assurance for cautious users (who should be verifying the proposed transaction anyway) and doesn't actually increase the security of the protocol. |
@nuttycom having a random application to open the URI is better than having it GUARANTEED that malicious app opens it every time just because Zashi refused to register the URL scheme. |
@Tomas-M Zashi does register the URL scheme; when selected by the system it displays an informational page to the user to encourage them to scan Zcash payment URIs directly using their preferred wallet app, and then allows them to open the Zashi scanner. |
Nowadays, people use mobile phones more than ever. Even for browsing websites. If user uses his mobile phone, and the QR code for payment is displayed on the screen of the mobile phone, how should he scan it? There is no way. He has to make a screenshot and we have the same problem like before because the screenshot can be changed by malicious app. There must be a way to solve this. Furthermore Zashi should support opening of the Zashi app by clicking a link (or even clicking on the qr code itself) if user is on the same device and cannot scan it. Clicking So, people, heads up! There is a solution for this problem! Domain links, also known as universal links (iOS) or app links (Android), allow a specific website URL to directly open an associated app. Here’s how it works and why it’s an ideal solution for ensuring that Zcash payments always open in the correct application (Zashi): Secure Association: The domain owner (in this case, the Zcash team) hosts an association file on a dedicated domain (e.g., pay.z.cash). For iOS, this is an apple-app-site-association file, and for Android, an assetlinks.json file. These files explicitly list the app identifiers (such as Zashi’s bundle ID) that are authorized to handle links from this domain. User Interaction: When a user clicks a payment link formatted as a standard HTTPS URL (for example, https://pay.z.cash/?amount=...&address=...&memo=...), the operating system checks the association file on pay.z.cash. If Zashi is installed and registered, the OS launches it directly to process the payment. If not, the link simply opens in a web browser, providing a fallback - the website can display the QR code with zcash: scheme, and also links to download Zashi application. Most users will never reach the website, only those who do not have the app installed. Enhanced Security and User Experience: Because the association is verified by the operating system, only the app specified by the domain (Zashi) can claim the link. This prevents malicious apps from intercepting or hijacking the payment URL. Moreover, the user benefits from a seamless experience—clicking a link immediately opens Zashi without ambiguity or the need to choose from multiple options. App Side Configuration: The app (Zashi) must declare support for specific domains by adding the associated domain (e.g., pay.z.cash) to its manifest or entitlements file. This registration tells the operating system that the app is authorized to handle links from that domain, ensuring that when users tap a payment link, the OS directs them to Zashi. Domain Side Configuration: The domain owner must host an association file on the domain’s server (an apple-app-site-association file for iOS or an assetlinks.json file for Android) that lists the approved app identifiers. This file validates that only the registered app can claim the links, securely binding the payment URL to the correct application. Example For example alza.cz (which is something like an Amazon but in Czech Republic) opens its own application instead web URLs, because they have the support in their app, and they have this file online http://alza.cz/.well-known/assetlinks.json Summary By switching from a custom URL scheme like zcash: to a domain-based URL (e.g., https://pay.z.cash/?amount=...), you ensure that the payment link is securely bound to the correct app. This approach leverages established OS-level mechanisms to maintain both security and a user-friendly experience, ensuring that all payment requests are handled reliably by Zashi. |
We absolutely considered this option, on a number of occasions. The problem is that using an applink means that a single entity (the entity in control of that domain) becomes a point of failure for the entire ecosystem that adopts the use of that domain. Individual app developers could choose to register their own domains for trusted applinks, but then you end up with not being able to have a single standard for the whole ecosystem. If there were a single entity that held that domain, you'd always run the risk that someone scanning such a link would, in resolving it, end up exposing the relationship between their phone's IP address and their interest in that particular payment request. This is an unacceptable level of centralization and information leakage. We considered registering a domain and ensuring that it could never be resolved, but that just results in an ongoing risk to the ecosystem. For example, a government could sieze control of the domain and use it to collect IP addresses of Zcash users. |
I understand that adopting a domain-based solution might introduce an additional point of failure. Fair enough. However, taking a step back, I believe that the existing zcash: URL scheme is just fine. Rejecting proper URL scheme registration undermines essential user experience while failing to provide a corresponding security benefit. Ultimately, many users will copy and paste receiver addresses via the clipboard, and it is impossible to protect everyone. Moreover, it is not our responsibility to safeguard users who knowingly or even unintentionally install potentially malicious applications on their devices. My motivation for addressing this issue stems from the anticipated wide adoption of Zcash payments. I am developing software that relies entirely on Zcash transactions, and when it goes live, it may introduce hundreds of thousands of new users to the ecosystem. Requiring these users to take a screenshot of a QR code and then manually open the Zashi app to scan that image is both impractical and inefficient. Moreover, it is relatively simple for an app to modify screenshots of QR codes to alter receiver addresses, meaning that the practical implications of such a design decision could be far more severe than anticipated. In light of these concerns, I am seriously considering forking the existing wallet apps to create a better solution for my users. |
@Tomas-M I feel like we're talking at cross-purposes here. I recommend the following experiment to you:
There is no requirement to screenshot the QR code. |
Note, I just noticed there's a bug (at least on iOS) such that the flow only works properly if the app is already active in the background; something related to the biometric auth seems to interfere with the flow from the system scanner if the app is fully unloaded. |
I want to click the link on the same phone that has the wallet, not have 2 screens. I don't know about iOS and this "select random" business - sounds like something that should be escalated with Apple. The way Ywallet and Zingo handle it on Android (and Mac Desktop and Linux) is fine. If iOS has a terrible bug where any app can register for Go here, click the donate button, and then click the |
@nuttycom How should I do it?
For users who use mobile phones, no PC, it would be beneficial to allow them to click some |
Indeed, that's essentially what you find on a f2z profile |
Ah, okay, I understand the problem you're referring to better now. Sorry that I was slow on the uptake there.
I know that it's hard to believe that iOS has such a disastrous issue, but yes, that's actually the issue; see the note here: https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app#Register-your-URL-scheme and also the answers to https://stackoverflow.com/questions/13130442/multiple-apps-with-the-same-url-scheme-ios It's been brought up to Apple by probably thousands of developers and they flatly refuse to fix it. |
Well, that's their problem IMHO. I'm still trying to put my black hat on and figure out how I can profit off of this but I'm not seeing anything great I can do with a malicious app. |
In this case, if users have problems with malicious software stealing their money, blame apple, that's just it. |
I imagine (only imagine) that they think that the malicious app could modify receiver address, and then open zashi with prefilled send form, so the user would unintentionally send money to that modified address. But I have no idea if this is a real threat |
Basically, the malicious app can steal the information about what the user is trying to buy (and also deanonymize users who are trying to buy from the |
Reopening due to #60 (comment) |
That's not the problem we were trying to fix — because it's unfixable. It is still important to prevent attacks by malicious apps in the case where those apps are not able to obtain elevated privileges.
That's not acceptable; we have to build on the platforms as they are, not as we would want them to be. As @nuttycom pointed out, this is documented and intended behaviour of the platform. |
We keep going around in circles with the idea that a fraudulent app could register zcash: URL scheme and can cause nasty things, and for that reason, you don't want to register URL schema for the Zashi wallet. But we probably forgot something. If
Voila, user will follow the onscreen instructions and paste the address. If you register the URL schema, there is always greater than zero chance that Zashi will handle the link instead of the malicious app, compared to zero chance if you do not register the URL schema at all. So, your decision to reject registering the url scheme helps nobody. |
@Tomas-M You have stirred a big team discussion, we appreciate all your input and advocacy for usability. 😎 We have some additional ideas for potential improvements! Please let us evaluate this internally, and let you know the outcome. |
No description provided.
The text was updated successfully, but these errors were encountered: