簡體   English   中英

刪除root權限

[英]Dropping root privileges

我有一個以root身份啟動的守護進程(因此它可以綁定到低端口)。 在初始化之后,我非常希望出於安全原因讓它刪除root權限。

任何人都可以指出我在C中已知的正確代碼片段會這樣做嗎?

我已經閱讀了手冊頁,我已經在不同的應用程序中查看了它的各種實現,它們都是不同的,其中一些非常復雜。 這是與安全相關的代碼,我真的不想重新發明其他人犯的錯誤。 我正在尋找的是一個最佳實踐,已知良好的,可移植的庫函數,我可以使用它知道它將正確。 這樣的事情存在嗎?

供參考:我是從根本上開始的; 我需要改變以在不同的uid和gid下運行; 我需要正確設置補充組; 之后我不需要改回root權限。

要刪除所有權限(用戶和組),您需要在用戶之前刪除該組。 鑒於useridgroupid包含要刪除的用戶和組的ID,並假設有效ID也是root,這可以通過調用setuid()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));
}

如果你是偏執狂,你可以嘗試恢復你的root權限,這應該失敗。 如果它沒有失敗,你就救助:

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

此外,如果您仍然偏執,您可能也想要seteuid()setegid() ,但它不應該是必要的,因為如果進程由root擁有,setuid()和setgid()已經設置了所有ID。

補充組列表是一個問題,因為沒有POSIX函數來設置補充組(有getgroups() ,但沒有setgroups())。 您可以使用BSD和Linux擴展setgroups() ,這會讓您感到擔憂。

您還應該chdir("/")或任何其他目錄,以便該進程不會保留在root擁有的目錄中。

由於你的問題一般是關於Unix的,所以這是非常通用的方法。 請注意,在Linux中,這不再是首選方法。 在當前的Linux版本中,您應該在可執行文件上設置CAP_NET_BIND_SERVICE功能 ,並以普通用戶身份運行它。 無需root訪問權限。

你正在尋找這篇文章:

POS36-C。 在放棄特權時觀察正確的撤銷順序

不確定如何最好地在那里放置一些信息而不重復該頁面的內容......

這是我最擅長的:

#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("/") != 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;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM