進階說明
應用說明:
- 本應用分為以下部份:
- TaskMgr 程式:以 root 身份執行。
- (1) 使用者輸入 GID。
- 若 GID 為 -1 則終止程式。
- (2) 使用者輸入 UID。
- (3) 執行 UserShell2 外部程式。
- (4) 再返回 (1) 要求使用者輸入。
- (1) 使用者輸入 GID。
- UserShell2 程式:
- (1) 轉換為指定群組〈如:dasadm1〉下用戶〈如:dasusr1〉。
- (2) 在該群組用戶下,執行外部程式 getID。
- getID 程式:
- (1) 透過 getgid()、getuid() 等系統 API 取得當前群組及用戶 ID。
- (2) 執行外部程式 /usr/bin/whoami。
- (3) 執行外部程式 /usr/bin/id。
- TaskMgr 程式:以 root 身份執行。
- 討論:
- (1) 不應在 TaskMgr 轉換群組用戶原因:
- 先進作業系統對於 setgid()、setuid() 等系統 API 有安全考量,防止木馬程式在較高權限帳號下,恣意任為。
- 當由較高權限帳號下轉換群組及用戶時,又透過 Shell 執行外部程式,此時作業系統程序控制區塊〈Process Control Block〉中群組及用戶已經改變為較低權限之帳號。
- 一但轉換為較低權限之帳號,再調用 setgid()、setuid() 等系統 API 時,受到作業系統安全保護,將不允許由權限帳號轉換為較高權限帳號。
- (2) 應該在 UserShell2 外部程式轉換群組用戶原因:
- 由自身程式轉換為該外部程式指定之權限帳號,確保程式運行環境為指定權限。
- 若調用外部程式者之權限較低,則程式轉換指定權限帳號會失敗,作業系統安全機制避免非法執行較高權限程式。
- (1) 不應在 TaskMgr 轉換群組用戶原因:
/* * TaskMgr.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <sys/wait.h> #include <errno.h> struct INFO { gid_t GID; uid_t UID; }; char *runnerHomeDir = "/home/rich.lee/Workspace/UserShell/src"; char *runnerShell = "UserShell2"; void runShell(struct INFO *newInfo) { char shellCmd[64]; memset(shellCmd, 0, sizeof(shellCmd)); sprintf(shellCmd, "%s/%s %d %d", runnerHomeDir, runnerShell, newInfo->GID, newInfo->UID); system(shellCmd); } int main(int argc, char *argv[]) { struct INFO newInfo; while (1) { printf("GID="); scanf("%d", &newInfo.GID); if (newInfo.GID == -1) break; printf("UID="); scanf("%d", &newInfo.UID); runShell(&newInfo); } }
/* * UserShell2.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <string.h> #include <sys/wait.h> #include <errno.h> char *cmd = "/usr/local/bin/getID"; struct INFO { gid_t GID; uid_t UID; }; int getEnv(int argc, char *argv[], struct INFO *newInfo) { int ret = -1; if (argc < 2) return ret; newInfo->GID = atoi(argv[1]); newInfo->UID = atoi(argv[2]); ret = 0; return ret; } void userTask(struct INFO *newInfo) { if (setgid(newInfo->GID) != -1) { if (setuid(newInfo->UID) != -1) { system(cmd); } else { perror("userTask::setuid() Error"); } } else { perror("userTask::setgid() Error"); } } int main(int argc, char *argv[]) { struct INFO newInfo; if (getEnv(argc, argv, &newInfo)) return EXIT_FAILURE; userTask(&newInfo); return EXIT_SUCCESS; }
/* * getID.c */ #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <string.h> struct INFO { uid_t UID; gid_t GID; } currentInfo; int main(void) { memset(¤tInfo, 0, sizeof(struct INFO)); currentInfo.UID = getuid(); currentInfo.GID = getgid(); printf("%d:%d\n", currentInfo.GID, currentInfo.UID); system("whoami;id"); return EXIT_SUCCESS; }