
Docker-basierter Proof-of-Concept, der eine TOCTOU-Race-Condition-Ausnutzung gegen die Digest_Spec-Funktion von sudo (CVE-2015-8239) demonstriert, wobei inotify für dateiübergreifende Ersetzungsangriffe verwendet wird.
Digest_Spec TOCTOU POCAlyssa Milburn (https://twitter.com/noopwafel) entdeckte einen TOCTOU-Race-Condition-Bug in sudo, wenn die Einstellung Digest_Spec verwendet wird. Die Einstellung Digest_Spec kann verwendet werden, um einem Benutzer zu erlauben, ein Binary mit sudo auszuführen, genau dann, wenn dessen Hash einem vorgegebenen Wert entspricht. Siehe man sudoers und suchen Sie nach Digest_Spec für weitere Informationen zu dieser Funktion, und siehe http://noopwafel.net/notes/2015/sudo-digest-race-condition.html für weitere Informationen zu dem von Alyssa entdeckten Bug. Das Problem wurde als CVE-2015-8239 zugewiesen.
Das Problem wurde entschärft, indem der Dokumentation von man sudoers eine Warnung vor der Möglichkeit einer Race Condition hinzugefügt wurde, und indem etwas fexecve()-Magie zu sudo hinzugefügt wurde, um zu versuchen, bestimmte Arten von Dateiänderungen unwirksam zu machen.
Interessanterweise sagte cve-assign Folgendes auf 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.
Dieser POC zeigt, dass diese Aussage nicht unbedingt wahr ist, vorausgesetzt, der „writer“-Benutzer kann persistenten Code auf dem System ausführen. Der „writer“-Benutzer kann inotify nutzen, um zu erkennen, wann der „executor“-Benutzer die Datei mit sudo ausführt, und kann zu diesem Zeitpunkt einen Dateiaustausch-Angriff versuchen.
Dieses Projekt erstellt ein Docker-Image, das:
/opt/sudoable hat, die vom Benutzer editor beschreibbar ist und vom Benutzer executor mit sudo ausgeführt werden kann, genau dann, wenn ihr SHA256-Hash einem bestimmten Wert entspricht./opt/hello (die „gute“ Datei, deren SHA256-Hash in sudoers eingetragen ist) und eine Datei unter /opt/goodbye (eine „böse“ Datei) hat./opt ist nur vom Benutzer root beschreibbar (daher kann der Benutzer editor den Inhalt von /opt/sudoable ersetzen, aber keinen Dateisystem-Dateiaustauschvorgang durchführen)./home/editor/exploit/exploit.py.Wenn /home/editor/exploit/exploit.py vom Benutzer editor ausgeführt wird, wird inotify verwendet, um Dateisystemereignisse zu überwachen. Wenn auf die Datei /opt/sudoable zugegriffen wird, wird sie durch /opt/goodbye ersetzt. Nachdem die Datei dann geschlossen wurde, wird sie durch /opt/hello ersetzt, um einen „normalen“ Zustand zu hinterlassen.
Angenommen, diese Race gelingt, wenn der Benutzer executor sudo /opt/sudoable ausführt (was auf meinem Rechner die meiste Zeit der Fall ist), kann der Benutzer editor bewirken, dass der Benutzer executor ein schädliches Binary als root ausführt, unabhängig davon, dass der SHA256-Hash als Digest_Spec-Wert in sudoers angegeben ist.
Führen Sie make all aus
./instantiate.sh austmux new-session aus und teilen Sie den Bereich (Ctrl+b dann "; verwenden Sie Ctrl+b dann Auf/Ab, um zwischen den Bereichen zu wechseln)sudo -u executor sudo /opt/sudoable aus und beobachten Sie die Ausgabe Hello uid=0sudo -u editor cp /opt/goodbye /opt/sudoable aussudo -u executor sudo /opt/sudoable aus und beobachten Sie, dass Sie nach einem Passwort gefragt werden (d.h. der sudo-Vorgang ist aufgrund einer Hash-Abweichung fehlgeschlagen)sudo -u editor /home/editor/exploit/exploit.py aussudo -u executor sudo /opt/sudoable einige Male aus und beobachten Sie die gelegentliche Ausgabe von Oberer Bereich:
root@c600efec2da8:/# sudo -u executor sudo /opt/sudoable
Hello uid=0
Unterer Bereich:
root@c600efec2da8:/# sudo -u editor cp /opt/goodbye /opt/sudoable
Oberer Bereich:
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:
Unterer Bereich:
root@c600efec2da8:/# sudo -u editor /home/editor/exploit/exploit.py
Oberer Bereich:
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 welchen Fällen ist die fexecve()-Entschärfung tatsächlich wirksam? Wenn ein Benutzer Schreibzugriff auf die sudoable-Datei, aber nicht auf das Verzeichnis hat, in dem sie sich befindet, kann er die von sudo geöffnete Datei ändern. Wenn der Benutzer Schreibzugriff auf das Verzeichnis, aber nicht auf die Datei hat, kann er die Datei aus dem Weg verschieben und neu erstellen, sodass er sie ändern kann, und wir sind wieder am Ausgangspunkt.
Danke an Luke (https://twitter.com/lukejahnke) dafür, dass er mir von der Einstellung Digest_Spec erzählt, einige Ideen ausgetauscht und die Verwendung von inotify für einen sauberen Cross-User-POC vorgeschlagen hat.
Goodbye uid=0