Löschen von Root-Rechten

Lesezeit: 6 Minuten

Ich habe einen Daemon, der als Root gestartet wird (damit er an niedrige Ports binden kann). Nach der Initialisierung möchte ich aus Sicherheitsgründen gerne die Root-Rechte verlieren.

Kann mir jemand einen Hinweis geben richtig bekannt Stück Code in C, der dies tun wird?

Ich habe die Manpages gelesen, ich habe mir verschiedene Implementierungen davon in verschiedenen Anwendungen angesehen, und sie sind alle unterschiedlich und einige von ihnen sind wirklich komplex. Dies ist sicherheitsrelevanter Code, und ich möchte wirklich nicht die gleichen Fehler neu erfinden, die andere Leute machen. Was ich suche, ist eine bewährte, bekannte gute, portable Bibliotheksfunktion, die ich in dem Wissen verwenden kann, dass sie es richtig machen wird. Gibt es so etwas?

Als Referenz: Ich fange als root an; Ich muss ändern, um unter einer anderen uid und gid zu laufen; Ich muss die Zusatzgruppen korrekt einrichten lassen; Ich muss danach nicht wieder zu Root-Rechten wechseln.

  • Dies variiert ziemlich stark zwischen den Unixen – gibt es bestimmte? Wenn Sie eine “portable” Lösung brauchen, wird es chaotisch, und Sie greifen am besten zB auf die permanent_set_uid()-Funktion von OpenSSH – in der uidswap.c-Datei

    – Nr

    28. Juli 2010 um 22:05 Uhr

  • Vielleicht eine bessere Strategie, erfordert kein Root, damit es nicht gelöscht werden muss. Siehe auch Nicht-Root-Prozess erlauben, sich an Port 80 und 443 zu binden? Ein verwandtes Thema ist Setuid entmystifiziert Tschüss Chen, Dean und Wagner. Verschiedene Varianten von Unix haben leicht unterschiedliche Verhaltensweisen. Dies ist ein weiterer Grund, Ihren nicht privilegierten Prozess zu punten und zuzulassen, dass er sich an den Port bindet.

    – jww

    2. Januar 2019 um 9:30 Uhr


  • Siehe auch Setuid entmystifiziert auf Usenix.

    – jww

    26. Juni 2019 um 14:41 Uhr


Benutzeravatar von Juliano
Juliano

Um alle Privilegien (Benutzer und Gruppe) zu löschen, müssen Sie die Gruppe vor dem Benutzer löschen. Angesichts dessen userid und groupid enthält die IDs des Benutzers und der Gruppe, zu der Sie wechseln möchten, und unter der Annahme, dass die effektiven IDs auch root sind, wird dies durch Aufrufen erreicht setuid() und setgid():

if (getuid() == 0) {
    /* process is running as root, drop privileges */
    if (setgid(groupid) != 0)
        fatal("setgid: Unable to drop group privileges: %s", strerror(errno));
    if (setuid(userid) != 0)
        fatal("setuid: Unable to drop user privileges: %S", strerror(errno));
}

Wenn Sie paranoid sind, können Sie versuchen, Ihre Root-Rechte zurückzubekommen, was fehlschlagen sollte. Wenn es nicht fehlschlägt, retten Sie:

 if (setuid(0) != -1)
     fatal("ERROR: Managed to regain root privileges?");

Auch wenn Sie immer noch paranoid sind, möchten Sie vielleicht seteuid() und setegid() auch, aber es sollte nicht notwendig sein, da setuid() und setgid() bereits alle IDs setzen, wenn der Prozess root gehört.

Die Ergänzungsgruppenliste ist ein Problem, weil es keine POSIX-Funktion gibt, um Ergänzungsgruppen zu setzen (es gibt getgroups(), aber keine setgroups()). Es gibt eine BSD- und eine Linux-Erweiterung setgroups() die Sie verwenden können, wenn es Sie betrifft.

Du solltest auch chdir("https://stackoverflow.com/") oder in ein beliebiges anderes Verzeichnis, sodass der Prozess nicht in einem root-eigenen Verzeichnis verbleibt.

Da sich Ihre Frage allgemein auf Unix bezieht, ist dies der sehr allgemeine Ansatz. Beachten Sie, dass dies unter Linux nicht mehr der bevorzugte Ansatz ist. In aktuellen Linux-Versionen sollten Sie die CAP_NET_BIND_SERVICE Fähigkeit auf der ausführbaren Datei und führen Sie sie als normaler Benutzer aus. Es ist kein Root-Zugriff erforderlich.

  • Sie möchten auch die gid festlegen – und dies kann je nach Unix leicht variieren, wenn es darum geht, ob setuid / setgid tatsächlich auch mit den echten und gespeicherten IDs durcheinander kommt

    – Nr

    28. Juli 2010 um 22:06 Uhr


  • Dies muss in der Tat eine portable Lösung sein, also ist keine Linux-Fähigkeit erlaubt, fürchte ich. Und ich habe tatsächlich den einfachen Ansatz mit setuid() und setgid(); es setzt die Gruppen nicht richtig (und wenn Sie setgroups() nicht aufrufen, können Sie anscheinend immer noch Mitglied einiger Gruppen von root sein!).

    – David gegeben

    28. Juli 2010 um 22:14 Uhr

  • @nos Danke. Erweitert um Gruppen abzudecken. Wenn der Prozess root gehört (wie im OP erwähnt) oder wenn er setuid-root ist, dann setzen setuid() und setgid() bereits alle IDs (real, effektiv und gespeichert). Das steht in der Spezifikation. Andernfalls wäre die Implementierung nicht POSIX-konform.

    – Juliano

    28. Juli 2010 um 22:59 Uhr

  • Sie können verwenden initgroups(3) Um die zusätzlichen Gruppen zurückzusetzen, ist es portabel genug (zumindest BSD und GNU libc haben es).

    – Daniel Röthlisberger

    18. März 2012 um 13:57 Uhr

  • Löschen Sie auch immer die Zusatzgruppen. initgroups existiert auf AIX, Solaris, HP-UX, FreeBSD, Darwin, Linux und wahrscheinlich anderen. Schließen Sie es ein, damit der Build fehlschlägt, wenn es nicht gefunden werden kann. Wenn nicht alle Gruppen gelöscht werden, kann dies zu schwerwiegenden Systemkompromittierungen und CVEs führen. Ich glaube nicht, dass chdir irgendwelche Auswirkungen auf die Sicherheit hat, oder?

    – Nicolas Wilson

    22. Februar 2013 um 23:04 Uhr

Sie suchen diesen Artikel:

POS36-C. Beachten Sie die korrekte Widerrufsreihenfolge beim Verzicht auf Privilegien

Ich bin mir nicht sicher, wie ich einige Informationen dort am besten platzieren kann, ohne den Inhalt dieser Seite zu duplizieren …

  • (sehr spät) Genau das, wonach ich gesucht habe! Vielen Dank!

    – David gegeben

    8. August 2015 um 20:37 Uhr

  • Sie sollten Ihren Code bereitstellen und erklären. Es gibt viel zu erklären.

    – jww

    2. Januar 2019 um 9:27 Uhr

  • Link oben ist tot. Hier ist ein Link zur Way Back Machine der Internet Archives: web.archive.org/web/20201025080250/https://wiki.sei.cmu.edu/…

    – Joshua Briefmann

    29. Juni 2021 um 9:26 Uhr

Das konnte ich am besten:

#define _GNU_SOURCE  // for secure_getenv()


int drop_root_privileges(void) {  // returns 0 on success and -1 on failure
    gid_t gid;
    uid_t uid;

    // no need to "drop" the privileges that you don't have in the first place!
    if (getuid() != 0) {
        return 0;
    }

    // when your program is invoked with sudo, getuid() will return 0 and you
    // won't be able to drop your privileges
    if ((uid = getuid()) == 0) {
        const char *sudo_uid = secure_getenv("SUDO_UID");
        if (sudo_uid == NULL) {
            printf("environment variable `SUDO_UID` not found\n");
            return -1;
        }
        errno = 0;
        uid = (uid_t) strtoll(sudo_uid, NULL, 10);
        if (errno != 0) {
            perror("under-/over-flow in converting `SUDO_UID` to integer");
            return -1;
        }
    }

    // again, in case your program is invoked using sudo
    if ((gid = getgid()) == 0) {
        const char *sudo_gid = secure_getenv("SUDO_GID");
        if (sudo_gid == NULL) {
            printf("environment variable `SUDO_GID` not found\n");
            return -1;
        }
        errno = 0;
        gid = (gid_t) strtoll(sudo_gid, NULL, 10);
        if (errno != 0) {
            perror("under-/over-flow in converting `SUDO_GID` to integer");
            return -1;
        }
    }

    if (setgid(gid) != 0) {
        perror("setgid");
        return -1;
    }
    if (setuid(uid) != 0) {
        perror("setgid");
        return -1;    
    }

    // change your directory to somewhere else, just in case if you are in a
    // root-owned one (e.g. /root)
    if (chdir("https://stackoverflow.com/") != 0) {
        perror("chdir");
        return -1;
    }

    // check if we successfully dropped the root privileges
    if (setuid(0) == 0 || seteuid(0) == 0) {
        printf("could not drop root privileges!\n");
        return -1;
    }

    return 0;
}

  • Ich denke, der erste Check sollte kommen geteuid() seit getuid() gibt die echte UID zurück.

    – Mirko Banchi

    14. September um 8:03 Uhr

1413180cookie-checkLöschen von Root-Rechten

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy