musl libc
können Sie ändern , uid
um root
mit selbst nach angeblich fallen Berechtigungen setuid(1000)
. Ich kann das Problem mit nicht reproduzieren glibc
.
Code:
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
int main(void) {
uid_t r, e, s;
getresuid(&r, &e, &s);
printf("%d %d %d\n", r, e, s);
if (setuid(1000) != 0)
puts("setuid(1000) failed");
else
puts("setuid(1000) succeded");
getresuid(&r, &e, &s);
printf("%d %d %d\n", r, e, s);
if (setuid(0) != 0)
puts("setuid(0) failed");
else
puts("setuid(0) succeded");
getresuid(&r, &e, &s);
printf("%d %d %d\n", r, e, s);
return 0;
}
Dies gcc -o setuidtest setuidtest.c
erzeugt nach dem Kompilieren mit die folgende Ausgabe, wenn es als root ausgeführt wird
0 0 0
setuid(1000) succeded
1000 1000 1000
setuid(0) succeded
0 0 0
Ich verwende Void Linux mit Kernel-Version 4.18_1
und Musl-Version 1.1.20_2
, Glibc-Version2.28_3
Woher kommt dieses Problem? Ist es mein Kernel, musl libc oder ist mein Testcode einfach falsch? Ist dieses Problem für andere Personen reproduzierbar?
strace output (musl unpriviledged)
$ strace ./setuidtest (unpriviledged)
execve("./setuidtest", ["./setuidtest"], 0x7ffdd15f69e0 /* 24 vars */) = 0
arch_prctl(ARCH_SET_FS, 0x7f538925cb28) = 0
set_tid_address(0x7f538925cb68) = 6299
mprotect(0x7f5389259000, 4096, PROT_READ) = 0
mprotect(0x55e9c5e75000, 4096, PROT_READ) = 0
getresuid([1000], [1000], [1000]) = 0
ioctl(1, TIOCGWINSZ, 0x7ffd2faf3160) = -1 ENOTTY (Not a tty)
writev(1, [{iov_base="1000 1000 1000", iov_len=14}, {iov_base="\n", iov_len=1}], 21000 1000 1000
) = 15
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0
setuid(1000) = 0
futex(0x7f538925cfd8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
getresuid([1000], [1000], [1000]) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0
setuid(0) = -1 EPERM (Operation not permitted)
futex(0x7f538925cfd8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
getresuid([1000], [1000], [1000]) = 0
writev(1, [{iov_base="setuid(1000) succeded\n1000 1000 "..., iov_len=69}, {iov_base=NULL, iov_len=0}], 2setuid(1000) succeded
1000 1000 1000
setuid(0) failed
1000 1000 1000
) = 69
exit_group(0) = ?
+++ exited with 0 +++
strace output (musl als wurzel)
# strace ./setuidtest (as root)
execve("./setuidtest", ["./setuidtest"], 0x7ffe19286eb0 /* 18 vars */) = 0
arch_prctl(ARCH_SET_FS, 0x7f08b2619b28) = 0
set_tid_address(0x7f08b2619b68) = 6409
mprotect(0x7f08b2616000, 4096, PROT_READ) = 0
mprotect(0x561507eb4000, 4096, PROT_READ) = 0
getresuid([0], [0], [0]) = 0
ioctl(1, TIOCGWINSZ, 0x7fffb222bff0) = -1 ENOTTY (Not a tty)
writev(1, [{iov_base="0 0 0", iov_len=5}, {iov_base="\n", iov_len=1}], 20 0 0
) = 6
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0
setuid(1000) = 0
futex(0x7f08b2619fd8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
getresuid([1000], [1000], [1000]) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1 RT_2], [], 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[], NULL, 8) = 0
setuid(0) = 0
futex(0x7f08b2619fd8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
getresuid([0], [0], [0]) = 0
writev(1, [{iov_base="setuid(1000) succeded\n1000 1000 "..., iov_len=62}, {iov_base=NULL, iov_len=0}], 2setuid(1000) succeded
1000 1000 1000
setuid(0) succeded
0 0 0
) = 62
exit_group(0) = ?
+++ exited with 0 +++
strace output (glibc unprivilegiert)
$ strace ./setuidtest
execve("./setuidtest", ["./setuidtest"], 0x7fff673b2c20 /* 14 vars */) = 0
brk(NULL) = 0x558b5fbb1000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/x86_64/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64/x86_64", 0x7ffc25da1650) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64", 0x7ffc25da1650) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64", 0x7ffc25da1650) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls", 0x7ffc25da1650) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64/x86_64", 0x7ffc25da1650) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64", 0x7ffc25da1650) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64", 0x7ffc25da1650) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\3604\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=18248368, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbcd7093000
mmap(NULL, 3921920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fbcd6ab1000
mprotect(0x7fbcd6c65000, 2097152, PROT_NONE) = 0
mmap(0x7fbcd6e65000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x7fbcd6e65000
mmap(0x7fbcd6e6b000, 14336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fbcd6e6b000
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7fbcd7094500) = 0
mprotect(0x7fbcd6e65000, 16384, PROT_READ) = 0
mprotect(0x558b5f5c0000, 4096, PROT_READ) = 0
mprotect(0x7fbcd7095000, 4096, PROT_READ) = 0
getresuid([1000], [1000], [1000]) = 0
fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
brk(NULL) = 0x558b5fbb1000
brk(0x558b5fbd2000) = 0x558b5fbd2000
setuid(1000) = 0
getresuid([1000], [1000], [1000]) = 0
setuid(0) = -1 EPERM (Operation not permitted)
getresuid([1000], [1000], [1000]) = 0
write(1, "1000 1000 1000\nsetuid(1000) succ"..., 841000 1000 1000
setuid(1000) succeded
1000 1000 1000
setuid(0) failed
1000 1000 1000
) = 84
exit_group(0) = ?
+++ exited with 0 +++
strace output (glibc als root)
# strace ./setuidtest
execve("./test", ["./test"], 0x7ffc9176d3f0 /* 15 vars */) = 0
brk(NULL) = 0x5653f4910000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/x86_64/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64/x86_64", 0x7ffe7d0c9550) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64", 0x7ffe7d0c9550) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls/x86_64", 0x7ffe7d0c9550) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/tls", 0x7ffe7d0c9550) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64/x86_64", 0x7ffe7d0c9550) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64", 0x7ffe7d0c9550) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
stat("/usr/lib/x86_64", 0x7ffe7d0c9550) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\3604\2\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=18248368, ...}) = 0
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fb18f5af000
mmap(NULL, 3921920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7fb18efcd000
mprotect(0x7fb18f181000, 2097152, PROT_NONE) = 0
mmap(0x7fb18f381000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b4000) = 0x7fb18f381000
mmap(0x7fb18f387000, 14336, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7fb18f387000
close(3) = 0
arch_prctl(ARCH_SET_FS, 0x7fb18f5b0500) = 0
mprotect(0x7fb18f381000, 16384, PROT_READ) = 0
mprotect(0x5653f40df000, 4096, PROT_READ) = 0
mprotect(0x7fb18f5b1000, 4096, PROT_READ) = 0
getresuid([0], [0], [0]) = 0
fstat(1, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
brk(NULL) = 0x5653f4910000
brk(0x5653f4931000) = 0x5653f4931000
setuid(1000) = 0
getresuid([1000], [1000], [1000]) = 0
setuid(0) = -1 EPERM (Operation not permitted)
getresuid([1000], [1000], [1000]) = 0
write(1, "0 0 0\nsetuid(1000) succeded\n1000"..., 750 0 0
setuid(1000) succeded
1000 1000 1000
setuid(0) failed
1000 1000 1000
) = 75
exit_group(0) = ?
+++ exited with 0 +++
strace
beide Versionen Ihres Programms ausführen und der Frage die entsprechenden Zeilen (get | set * uid) hinzufügen?Antworten:
Das Problem kam in der Tat weder vom Kernel noch vom Muslim, sondern von den Fähigkeiten. Es stellte sich heraus, dass es einen Unterschied zwischen meinen beiden Testsystemen gab -
glibc
undmusl
-, der den Anschein erweckte, als hätte es etwas mit ihnen zu tun.Das Problem wurde tatsächlich durch das
pam_rundir.so
Modul verursacht, das dasSECBIT_NO_SETUID_FIXUP
sichere Bit gesetzt hat, wodurch der Kernel die Funktionen für das Programm danachsetuid
beibehält (wodurch ichsetuid
zurückkehren kannroot
).quelle