Machtspielchen: Posix-Userrechte und ruby 0

Posted by fwoeck
on Wednesday, April 29

Bei Systemdiensten und ähnlichen Abläufen ist es oft hilfreich, den Prozess mit root-Zugriff anzustoßen und ihn so zu konstruieren, dass er später selbsttätig seine Rechte degradiert. Ein Beispiel wäre ein Netzwerdienst, der root-Rechte benötigt, um sich an einen privilegierten TCP-Port zu binden (0..1024), dessen arbeitende Teile dann aber unter einer anderen Userid laufen, um einen möglichen Schaden bei Fremdeinwirkung zu begrenzen.

Ruby bietet das Modul Process an, mit der sich die verschiedenen Ids manipulieren lassen, unter der ein Prozess läuft. Es sind im einzelnen

  1. die reale Id (Process.uid), das ist die, mit der der Prozess ursprünglich gestartet wurde
  2. die effektive Id (Process.euid), also die, die konkret (effektiv) für die Berechtigung zu einer bestimmten Aktion herangezogen wird
  3. die gespeicherte (saved) Id, die verwendet wird, um einen Prozess, dessen Userrechte verändert wurden wieder auf seinen ursprünglichen Level zu befördern

Die Letzte von den dreien ist, soweit ich es sehe nichts, was man in diesem Kontext unmittelbar anfasst.

ein Beispiel

Die folgende Shell wird mit root-Rechten gestartet – reale und effektive Userid sind Anfangs 0. Setzt man die euid, so verändern sich die faktischen Rechte der Shell. Die UID bleibt aber 0 und man kann später zu ihr zurückkehren:

# irb

> Process.uid
=> 0

> Process.euid
=> 0

> `cat /root/id_rsa-gsg-keypair`
=> "-----BEGIN RSA PRIVATE KEY-----\nftu97MIIEAwr05 ...

> require 'etc';

> Etc.getpwnam("me")
=> #<struct Struct::Passwd name="me", passwd="x", uid=1000, gid=1000, ... >

> Process.euid = 1000
=> 1000

> Process.uid
=> 0

> `cat /root/id_rsa-gsg-keypair`;
cat: /root/id_rsa-gsg-keypair: Permission denied

ohne Rückticket

Möchte man den Rechteverlust unumkehrbar machen, so ist auf posixkonformen Systemen (z. B. Linux) die Funktion Process::Sys.setuid angesagt. Sie setzt alle drei Rechte auf eine beliebige Uid, sofern man dazu berechtigt, aka root ist:

# irb

> Process::Sys.setuid(1000);

> Process.uid
=> 1000

> Process.euid
=> 1000

> `cat /root/id_rsa-gsg-keypair`;
cat: /root/id_rsa-gsg-keypair: Permission denied

> Process::Sys.setuid(0)
Errno::EPERM: Operation not permitted

> Process.euid = 0
Errno::EPERM: Operation not permitted

> Process.uid = 0
Errno::EPERM: Operation not permitted ...

Eine etwas ausführlichere Beschreibung, vor allem auch in Bezug auf andere Plattformen findet man hier:

Weblink

  1. 5-things-you-dont-know-about-user-ids-that-will-destroy-you