macOS Electron Applications Injection
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Basic Information
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.
Electron Fuses
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 varELECTRON_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 loadedasar
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 finallydefault_app.asar
. It will only check and use app.asar, thus ensuring that when combined with theembeddedAsarIntegrityValidation
fuse it is impossible to load non-validated code.LoadBrowserProcessSpecificV8Snapshot
: If enabled, the browser process uses the file calledbrowser_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.
Checking Electron Fuses
You can check these flags from an application with:
Modifying Electron Fuses
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.
RCE adding code to Electron Applications
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 fusesembeddedAsarIntegrityValidation
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:
RCE with ELECTRON_RUN_AS_NODE
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.
Injection from the App Plist
As proposed here, you could abuse this env variable in a plist to maintain persistence:
RCE with NODE_OPTIONS
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.
Injection from the App Plist
You could abuse this env variable in a plist to maintain persistence adding these keys:
RCE with inspecting
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.
Injection from the App Plist
You could abuse this env variable in a plist to maintain persistence adding these keys:
TCC Bypass abusing Older Versions
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).
Run non JS Code
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.
Automatic Injection
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:
References
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Last updated