Let's take Discord as an example. When you are surfing the internet and you click a button to join a discord channel, automatically, your desktop Discord app opens. In other words, a webpage is opening an application of your system. How the **** could be this possible? Is this really secure?
General mechanisms
Actual browsers have different type of methods to handle the communication between Website to Applications. In this entry I will only focus in some of these mechanisms so, I highly encourage to read this serie of articles link by ericlaw. These articles provides a bigger picture and a detailed explainition of some of them. Also, he provides a really good discussion of the security risk inherited by this mechanisms. Following tables provides a summary list.
Mechanism | DesktopOS independent | Type |
---|---|---|
App protocol (websec://) | Yes | Fire-and-forget |
File downloads | Yes | Fire-and-forget |
File System Access API | Yes | Read-and-write |
Extension (Native Message API) | Yes (ÂżSafari?) | Bi-directional communication |
Drag&Drop | Yes | Fire-and-forget |
System clipboard | Yes | Fire-and-forget |
Local Web Server | Yes | Bi-directional communication |
DirectInvoke/ClickOnce | Windows only | Fire-and-forget |
getInstalledRelatedApps() | Windows only (caniuse) | Bi-directional communication |
AppLinks | Deprecated | Fire-and-forget |
Legacy Plugins/Active X architecture | Deprecated | Bi-directional communication |
Mobile specific:
Mechanism | MobileOS independent | Type |
---|---|---|
Android Intents | Android | Fire-and-forget |
Android Instant Apps | Android | Fire-and-forget |
Browser dev specific:
- Site-Locked Private APIs
- Native Url Protocols
In the following sections I will focus in Application protocols and Local Web Servers.
App protocols
A simple explanation of application protocols would be to define a new âprotocolâ. So, instead of using âhttpâ or âfileâ, you define a new special key (e.g., âwebsec://â). Defining a new protocol allows to describe how this protocol must be handle by the browser. In technical words, the idea is to define a new URL scheme that will open a desktop application. As the reader might notice, improperly parsing URI schemes could produce critical vulnerabilities. One of the application I found that this mechanisms is used is Microsoft Teams (msteams://). In the following code snippet you can see how through the Chromium code comments developers could be also confused of URL parsing.
Security Risk
These mechanisms inherits some security risks (e.g., Browser Sandbox Scape). As ericlaw describe in his blog, main security risk are:
âInput Sanitization: App Protocols were not designed with the expectation that the app could be exposed to potentially dangerous data from the web at large.â
âContext information: When the protocol is invoked by the browser, it simply bundles up the URL and passes it on the command line to the target application. The app doesnât get any information about the caller (e.g. âWhat browser or app invoked this?â, âWhat origin invoked this?â, etc) and thus it must make any decisions solely on the basis of the received URL..â
Default schemes/protocol
Chromium based browser have a set of defined protocols in the code. It could be that this set of âdefaultâ protocols may vary depending on the browser or the OS. In the case of Brave Browser, they have a small wiki on their github Wiki: Adding a protocol scheme to Brave. The standard schemes defined in HTML spec
are:
- http/https: Normal scheme used for HTTP/s protocol navigation.
- file: Allows to retrieve/view local files (e.g., file:///home/websec/Downloads/Syllabus.pdf).
- chromium or browser family (e.g., microsoft-edge, brave): Used for internal browser pages (e.g., chromium://settings).
- mailto: It opens your default mail application to send an email to the person that follows the scheme (e.g., mailto:websec@abc.com).
- tel: If you have your phone connected to your computer, it allows to make calls.
- All: bitcoin ftp ftps geo im irc ircs magnet mailto matrix mms news nntp openpgp4fpr sftp sip sms smsto ssh tel urn webcal wtai xmpp
The following class diagram by jfernandez post at Igaliaâs blog illustrates the multi-process architecture of the Custom Handler logic.
In order to have deeper look into how schemes are added, jfernandez provides us with another class diagram.
Despite jfernandez provides us with a class diagram, it is really hard to take a look the real code running inside the browser. However, I encourage you to go and see it for yourself (Chromium code).
Custom protocol handlers
Chromium based browsers when a custom, not blocked, protocol is used prompt a popup asking if the link should be open or not.
If you want to disable this behavior in chromium-based browsers, you need to go to Settings > Site settings > Additional permissions > Protocol handlers. In the case you want to check the behavior of your browser, I found this website. In chromium-based browser you can check the allowed/ignored custom protocol in the Preferences file inside the configuration of your browsers. In GNU/Linux, this file is located at ~/.config/BROWSER/Default/Preferences
. In Firefox the file we need to found is handlers.json
or opening the browser Settings > General > Applications
. If you are using snap
store, the browser config is inside this folder.
How to create a custom protocol/scheme handler
As I explained before, if the chromium-based browser doesnât know how to handle a custom protocol, it will use the OS preferences of the user. In my case, this default application is xdg-open. In the following lines, I will create a new custom protocol ânote://â. For Safari check the link. First, I created a simple script that will print the arguments received from the browser.
1 |
|
After creating the script, we need to configure âxdg-openâ to use this script when a specific MimeType is matched. For this task, we need to create a â.desktopâ file like the following one:
1 | [Desktop Entry] |
Finally, we need to install this entry using the command âxdg-desktop-menu install path/to/file.desktopâ. I used the previous named website to test the protocol and after accepting the prompt, our scripts receives the input:
Local Web Server
Another mechanisms is to define a local web server. When the Desktop application is running, a local socket is opened waiting for a connection. Websites only have to create a WebSocket to the used port and the communication will take place. This mechanisms is used by Discord, explained more in depth in the following section. In order to find any of this local web server, you may run netstat -tlpn
in Linux and netstat -ab
in Windows. This command will print opened ports and the application that is listening. One of the key protection used by this method is âoriginâ. Origin Header indicates the scheme, hostname and port of the website creating the websocket. Origin is a restricted header that could not be change it.
Case Study: Discord
In this section I will use Discord (discord documentation) to take a look how this âLocal Web Serverâ mechanisms is implemented. As I mentioned before, we can see in the following screenshot that Discord Desktop App is listening in a specific port for the connection.
If we visit an invitation link on Discord website we would see how a WebSocket is created to âws://127.0.0.1:6463â in which Discord Desktop App is listening.
In the following screenshot you could see all the messages exchanged between the Discord Website and Discord Desktop App.
In order to interact with the websocket created by the Discord Desktop App, I created the following snippet written in python. Notice origin header declaration on the script.
1 | from websocket import create_connection |
Local Web Server Discovery
As the reader may be wondering, a website could create scanner of localhost to check for Local Web Servers. One example of this behavior was found in a bank, where the bank scanned computers to try to find any general Remote Access Trojans (RATs). Another example was found in Ebay, where the same behavior was observed.
File System Access API (a.k.a. Native File System API)
I recently discovered the FSA API (article), a powerful Web API that enables websites to interact with the file system and edit files. One notable example of this API in action is in Visual Studio, where users can read and modify files seamlessly. With FSA API, itâs possible to edit your project folder directly from the browser, making it easy to update your local code from the website. By using this API, users can grant access (accepting the popup) to specific files or folders, giving websites the ability to make local modifications to them. Take a look at this demo webpage. Although itâs not a standard API, it has been implemented in browsers like Chromium, Microsoft Edge and Chrome. Partially supported by Opera and Safari.
References:
- Recommended: Article: Web-to-App Communication: App Protocols.
- Recommended: Article: Browser Architecture: Web-to-App Communication Overview.
- Recommended: Article: Bypassing App Protocol Prompts.
- Article: New Custom Handlers component for Chrome. TL;DR: Chromium src.
- Article: Discovering Chromeâs pre-defined Custom Handlers. TL;DR: Chromium src.
- Exploiting: localghost: Escaping the Browser Sandbox Without 0-Days.