macOS Electron Applications Injection
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
If you don't know what Electron is you can find lots of information here. But for now just know that Electron runs node. And node has some parameters and env variables that can be use to make it execute other code apart from the indicated file.
These techniques will be discussed next, but in recent times Electron has added several security flags to prevent them. These are the Electron Fuses and these are the ones used to prevent Electron apps in macOS from loading arbitrary code:
RunAsNode
: If disabled, it prevents the use of the env var ELECTRON_RUN_AS_NODE
to inject code.
EnableNodeCliInspectArguments
: If disabled, params like --inspect
, --inspect-brk
won't be respected. Avoiding his way to inject code.
EnableEmbeddedAsarIntegrityValidation
: If enabled, the loaded asar
file will be validated by macOS. Preventing this way code injection by modifying the contents of this file.
OnlyLoadAppFromAsar
: If this is enabled, instead of searching to load in the following order: app.asar
, app
and finally default_app.asar
. It will only check and use app.asar, thus ensuring that when combined with the embeddedAsarIntegrityValidation
fuse it is impossible to load non-validated code.
LoadBrowserProcessSpecificV8Snapshot
: If enabled, the browser process uses the file called browser_v8_context_snapshot.bin
for its V8 snapshot.
Another interesting fuse that won't be preventing code injection is:
EnableCookieEncryption: If enabled, the cookie store on disk is encrypted using OS level cryptography keys.
You can check these flags from an application with:
As the docs mention, the configuration of the Electron Fuses are configured inside the Electron binary which contains somewhere the string dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX
.
In macOS applications this is typically in application.app/Contents/Frameworks/Electron Framework.framework/Electron Framework
You could load this file in https://hexed.it/ and search for the previous string. After this string you can see in ASCII a number "0" or "1" indicating if each fuse is disabled or enabled. Just modify the hex code (0x30
is 0
and 0x31
is 1
) to modify the fuse values.
Note that if you try to overwrite the Electron Framework
binary inside an application with these bytes modified, the app won't run.
There could be external JS/HTML files that an Electron App is using, so an attacker could inject code in these files whose signature won't be checked and execute arbitrary code in the context of the app.
However, at the moment there are 2 limitations:
The kTCCServiceSystemPolicyAppBundles
permission is needed to modify an App, so by default this is no longer possible.
The compiled asap
file usually has the fuses embeddedAsarIntegrityValidation
and
onlyLoadAppFromAsar
enabled
Making this attack path more complicated (or impossible).
Note that it's possible to bypass the requirement of kTCCServiceSystemPolicyAppBundles
by copying the application to another directory (like /tmp
), renaming the folder app.app/Contents
to app.app/NotCon
, modifying the asar file with your malicious code, renaming it back to app.app/Contents
and executing it.
You can unpack the code from the asar file with:
And pack it back after having modified it with:
ELECTRON_RUN_AS_NODE
According to the docs, if this env variable is set, it will start the process as a normal Node.js process.
If the fuse RunAsNode
is disabled the env var ELECTRON_RUN_AS_NODE
will be ignored, and this won't work.
As proposed here, you could abuse this env variable in a plist to maintain persistence:
NODE_OPTIONS
You can store the payload in a different file and execute it:
If the fuse EnableNodeOptionsEnvironmentVariable
is disabled, the app will ignore the env var NODE_OPTIONS when launched unless the env variable ELECTRON_RUN_AS_NODE
is set, which will be also ignored if the fuse RunAsNode
is disabled.
If you don't set ELECTRON_RUN_AS_NODE
, you will find the error: Most NODE_OPTIONs are not supported in packaged apps. See documentation for more details.
You could abuse this env variable in a plist to maintain persistence adding these keys:
According to this, if you execute an Electron application with flags such as --inspect
, --inspect-brk
and --remote-debugging-port
, a debug port will be open so you can connect to it (for example from Chrome in chrome://inspect
) and you will be able to inject code on it or even launch new processes.
For example:
If the fuse EnableNodeCliInspectArguments
is disabled, the app will ignore node parameters (such as --inspect
) when launched unless the env variable ELECTRON_RUN_AS_NODE
is set, which will be also ignored if the fuse RunAsNode
is disabled.
However, you could still use the electron param --remote-debugging-port=9229
but the previous payload won't work to execute other processes.
Using the param --remote-debugging-port=9222
it's possible to steal some information from the Electron App like the history (with GET commands) or the cookies of the browser (as they are decrypted inside the browser and there is a json endpoint that will give them).
You can learn how to do that in here and here and use the automatic tool WhiteChocolateMacademiaNut or a simple script like:
In this blogpost, this debugging is abused to make a headless chrome download arbitrary files in arbitrary locations.
You could abuse this env variable in a plist to maintain persistence adding these keys:
The TCC daemon from macOS doesn't check the executed version of the application. So if you cannot inject code in an Electron application with any of the previous techniques you could download a previous version of the APP and inject code on it as it will still get the TCC privileges (unless Trust Cache prevents it).
The previous techniques will allow you to run JS code inside the process of the electron application. However, remember that the child processes run under the same sandbox profile as the parent application and inherit their TCC permissions. Therefore, if you want to abuse entitlements to access the camera or microphone for example, you could just run another binary from the process.
The tool electroniz3r can be easily used to find vulnerable electron applications installed and inject code on them. This tool will try to use the --inspect
technique:
You need to compile it yourself and can use it like this:
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)