File-Descriptors
Set-UID 能力洩漏攻擊
我有一個
C
程序來展示capability leak
關於 set-uid 的攻擊。// cap_leak.c #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> void main() { int fd; char *v[2]; /* Assume that /etc/zzz is an important system file, and it is owned by root with permission 0644. Before running this program, you should create the file /etc/zzz first. */ fd = open("/etc/zzz", O_RDWR | O_APPEND); // Print out the file descriptor value printf("fd is %d\n", fd); if (fd == -1) { printf("Cannot open /etc/zzz\n"); exit(0); } // Permanently disable the privilege by making the // effective uid the same as the real uid setuid(getuid()); printf("Real user id is %d\n", getuid()); printf("Effective user id is %d\n", geteuid()); // Execute /bin/sh v[0] = "/bin/sh"; v[1] = 0; execve(v[0], v, 0); }
最初,
cat /etc/zzz
給出:this is a very important file
現在我編譯這個程序:
gcc -o cap_leak cap_leak.c
將所有者更改為 root 並打開 setuid 位:
sudo chown root cap_root sudo chmod 4755 cap_root
現在,當我從普通使用者執行程序時,我得到一個 shell 提示:
fd is 3 Real user id is 1000 Effective user id is 1000 $whoami $seed $echo bbbbbb >&3 $cat /etc/zzz $this is a very important file bbbbbb
最後一次寫入
fd = 3
ie/etc/zzz
是成功的,儘管在打開文件後setuid()
呼叫了該函式,該函式基本上將真實、有效和保存的 uid 設置為原始 uid。我的問題是,為什麼最後一次寫入是成功的,即使它是在之後執行的,setuid()
並且在這種情況下為了防止能力洩漏,應該把setuid()
它放在哪裡,為什麼?
沒有其他地方應該放置
setuid()
,您不應該讓文件保持打開狀態以供寫入。原因是在打開文件時檢查權限,而不是在每次
write()
呼叫時檢查。如果非特權 shell 不應該寫入該文件,則沒有理由讓文件以寫訪問權限打開。