
Apple MacOS Screen Sharing — lecture/écriture arbitraire de fichiers -> RCE
Pour la première fois depuis un moment, nous avons un RCE sur MacOS.
Découvert à l'origine par @osxreverser, puis développé par bynar.io. Voir https://blog.calif.io/p/no-country-for-old-passwords pour plus d'informations.
Ceci est principalement dérivé du travail de @panchocosil (enfin, de Claude...), qui a publié une preuve de concept en lecture seule. Le dépôt de @HORKimhab semble être un peu bidon, en particulier ce get-svn.sh qui ressemble à une tentative ultérieure d'attaque de la chaîne d'approvisionnement.
Bref, j'ai réussi à faire fonctionner l'écriture et, à partir de là, un RCE.
usage: exploit.py [-h] [-w LOCAL] [-m MODE] [-p PORT] [-u USER] [-r RETRIES] [-t TIMEOUT] [-o FILE] ip [path]
-o pour écrire le fichier lu dans un fichier local. Utile pour les binaires-w pour écrire un fichier local vers [path].Partiellement possible. Sur MacOS, exécuter la lecture sur un répertoire (plutôt qu'un fichier) vide le contenu brut du répertoire (chaque fichier qu'il contient). Donc ne pas pouvoir lister les fichiers n'est pas un problème.
Donc d'abord un peu de reconnaissance. python3 exploit.py <ip_addr> /Library/Preferences/com.apple.loginwindow.plist vous donne le nom d'utilisateur des utilisateurs connectés. Ensuite, vous pouvez lire /User/<username>/.ssh/ et espérer que SSH est aussi activé (généralement, quand VNC l'est, SSH l'est aussi).
Comme la lecture se fait en tant que root et ignore TCC (d'après ce que je comprends), vous pouvez directement extraire les historiques de navigateur et (peut-être ?) les cookies. En général, cela suffit.
Dans tous les cas, vous pouvez écrire dans /Library/LaunchDaemons/ et attendre un redémarrage. Vous avez alors une persistance. Mais bien sûr, nous sommes impatients, il existe donc de meilleures méthodes.
Il y aura souvent des enregistrements existants que vous pouvez écraser. Par exemple, /Library/PrivilegedHelperTools/com.microsoft.autoupdate.helper, us.zoom.ZoomDaemon et com.microsoft.teams.TeamsUpdaterDaemon sont couramment installés.
<!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>
En regardant cela, on voit que le binaire situé à /Library/Application Support/Microsoft/EdgeUpdater/Current/EdgeUpdater.app/Contents/MacOS/EdgeUpdater est exécuté à un intervalle défini.
Nous pouvons alors remplacer ce binaire et, même sans avoir à toucher à launchctl, nous obtenons un RCE !
Sympa.