Start · Sprachen · PHP · Referenz · posix_setuid

posix_setuid

Funktion

Setzt die Benutzer-ID (UID) des aktuellen Prozesses auf den angegebenen Wert.

seit PHP 4.0.0 Kategorie: misc

Signatur

posix_setuid(int $user_id): bool

Beschreibung

posix_setuid() setzt die reale Benutzer-ID (UID) des aktuellen Prozesses. Dies entspricht dem POSIX-Systemaufruf setuid(2). Die Funktion ist typischerweise in Daemon-Prozessen oder CLI-Skripten nützlich, die mit Root-Rechten gestartet werden, nach der Initialisierung jedoch auf einen unprivilegierten Benutzer wechseln sollen, um das Sicherheitsprinzip der minimalen Rechtevergabe (Principle of Least Privilege) umzusetzen.

Wenn der Prozess als Root (UID 0) läuft, werden sowohl die reale, die effektive als auch die gespeicherte Benutzer-ID auf $user_id gesetzt. Läuft der Prozess als normaler Benutzer, darf er die UID nur auf seine eigene setzen. Ein Wechsel zu einer anderen UID schlägt in diesem Fall fehl und gibt false zurück.

Die Funktion ist ausschließlich auf POSIX-kompatiblen Systemen verfügbar (Linux, macOS, BSD usw.) und steht unter Windows nicht zur Verfügung. Sie erfordert zudem, dass die POSIX-Erweiterung (ext/posix) in PHP aktiviert ist.

Im Fehlerfall kann mit posix_get_last_error() und posix_strerror() die genaue Fehlerursache ermittelt werden.

Parameter

Name Typ Default Beschreibung
$user_id Pflicht int Die numerische Benutzer-ID (UID), auf die der aktuelle Prozess gesetzt werden soll. Die UID 0 entspricht dem Root-Benutzer.

Rückgabewert

Typ
bool
Beschreibung
Gibt true zurück, wenn die Benutzer-ID erfolgreich gesetzt wurde, andernfalls false. Im Fehlerfall kann posix_get_last_error() für Details herangezogen werden.

Beispiele

Privilegien nach Initialisierung abgeben

<?php
// Skript läuft zunächst als Root, um privilegierte Ressourcen zu öffnen
// Danach wird auf einen unprivilegierten Benutzer gewechselt

$targetUser = posix_getpwnam('www-data');

if ($targetUser === false) {
    die('Benutzer www-data nicht gefunden.' . PHP_EOL);
}

// Privilegierten Teil des Prozesses hier ausführen...

// Nun UID auf www-data wechseln
if (posix_setuid($targetUser['uid'])) {
    echo 'UID erfolgreich auf ' . $targetUser['uid'] . ' gesetzt.' . PHP_EOL;
    echo 'Aktuelle UID: ' . posix_getuid() . PHP_EOL;
} else {
    $errno = posix_get_last_error();
    echo 'Fehler beim Setzen der UID: ' . posix_strerror($errno) . PHP_EOL;
}
UID erfolgreich auf 33 gesetzt. Aktuelle UID: 33

Prüfen ob Root-Rechte vorhanden sind, bevor UID gewechselt wird

<?php
$currentUid = posix_getuid();

if ($currentUid !== 0) {
    echo 'Warnung: Prozess läuft nicht als Root (UID: ' . $currentUid . ').' . PHP_EOL;
    echo 'UID-Wechsel zu einem anderen Benutzer wird fehlschlagen.' . PHP_EOL;
} else {
    $nobodyUser = posix_getpwnam('nobody');
    if ($nobodyUser !== false && posix_setuid($nobodyUser['uid'])) {
        echo 'Erfolgreich auf nobody (UID ' . $nobodyUser['uid'] . ') gewechselt.' . PHP_EOL;
    } else {
        $errno = posix_get_last_error();
        echo 'UID-Wechsel fehlgeschlagen: ' . posix_strerror($errno) . PHP_EOL;
    }
}
Erfolgreich auf nobody (UID 65534) gewechselt.

// Wichtig · Fallstricke

Sicherheitshinweis: Ein UID-Wechsel mit posix_setuid() ist in der Regel irreversibel, wenn der Prozess als Root läuft und die UID auf einen Nicht-Root-Benutzer gesetzt wird. Nachdem die UID gewechselt wurde, kann der Prozess nicht mehr auf Root-Rechte zurückgreifen. Dies ist ausdrücklich gewünscht für sicherheitskritische Anwendungen.

Achtung: posix_setuid() setzt nur die UID, nicht die Gruppen-ID (GID). Um auch die Gruppenrechte zu entziehen, sollte zusätzlich posix_setgid() aufgerufen werden — und zwar vor posix_setuid(), da nach dem UID-Wechsel möglicherweise keine Berechtigung mehr besteht, die GID zu ändern.

Unter Linux kann das Verhalten durch Kernel-Capabilities beeinflusst werden. Prozesse mit der Capability CAP_SETUID können die UID beliebig setzen, auch ohne UID 0.