
Apple MacOS Screen Sharing: lettura/scrittura arbitraria di file -> RCE
Per la prima volta dopo un po', abbiamo una RCE su MacOS.
Scoperta originariamente da @osxreverser, e successivamente ampliata da bynar.io. Vedi https://blog.calif.io/p/no-country-for-old-passwords per maggiori informazioni.
Questo è in gran parte derivato dal lavoro di @panchocosil (beh, Claude...), che ha pubblicato una PoC di sola lettura. Il repository di @HORKimhab sembra essere un po' una bufala, soprattutto perché get-svn.sh sembra un tentativo di un successivo attacco alla supply chain.
Comunque, sono riuscito a far funzionare la scrittura e da lì, RCE.
usage: exploit.py [-h] [-w LOCAL] [-m MODE] [-p PORT] [-u USER] [-r RETRIES] [-t TIMEOUT] [-o FILE] ip [path]
-o per scrivere il file letto in un file locale. Utile per i binari-w per scrivere un file locale in [path].In qualche modo possibile. Su MacOS, eseguire read su una directory (piuttosto che su un file) riversa il contenuto grezzo della directory (ogni file al suo interno). Quindi non essere in grado di elencare i file non è un problema.
Quindi prima un po' di ricognizione. python3 exploit.py <ip_addr> /Library/Preferences/com.apple.loginwindow.plist ti dà il nome utente degli utenti connessi. Poi, puoi leggere /User/<username>/.ssh/ e sperare che forse anche ssh sia abilitato (di solito quando VNC lo è, anche SSH lo è).
Dato che la lettura avviene da root e ignora TCC (da quello che ho capito), puoi direttamente scaricare le cronologie dei browser e (forse?) i cookie. Di solito è abbastanza.
In ogni caso, puoi scrivere in /Library/LaunchDaemons/ e aspettare un riavvio. A quel punto hai persistenza. Ma ovviamente siamo impazienti, quindi ci sono modi migliori.
Spesso ci saranno record esistenti che puoi sovrascrivere. Per esempio, /Library/PrivilegedHelperTools/com.microsoft.autoupdate.helper, us.zoom.ZoomDaemon e com.microsoft.teams.TeamsUpdaterDaemon sono comunemente installati.
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AbandonProcessGroup</key>
<true/>
<key>Label</key>
<string>com.microsoft.EdgeUpdater.wake.system</string>
<key>LimitLoadToSessionType</key>
<string>System</string>
<key>ProgramArguments</key>
<array>
<string>/Library/Application Support/Microsoft/EdgeUpdater/Current/EdgeUpdater.app/Contents/MacOS/EdgeUpdater</string>
<string>--wake-all</string>
<string>--enable-logging</string>
<string>--vmodule=*/components/update_client/*=2,*/chrome/updater/*=2</string>
<string>--system</string>
</array>
<key>StartInterval</key>
<integer>3600</integer>
</dict>
</plist>
Guardando questo, possiamo vedere che il binario in /Library/Application Support/Microsoft/EdgeUpdater/Current/EdgeUpdater.app/Contents/MacOS/EdgeUpdater viene eseguito a un intervallo prestabilito.
Possiamo quindi sostituire quel binario e, anche senza dover avere a che fare con launchctl, abbiamo una RCE!
Roba divertente.