在进行兵棋挑战时,我遇到了权限问题。提供的信息/proc/PID/status
不符合应授予进程的权限。
我是用户user1。我应该使用一个 SETUID 程序:
-r-sr-x--- 1 user2 user1 6297 Jun 20 2013 program
所以它应该以 user2 的有效 UID 执行。
我在启动后暂时停止该程序,以防止其终止:
~/program "test" &
PID=$!
kill -SIGSTOP $PID
echo $PID
然后,我cat /proc/$PID/status
,我看到:
Uid: 1003 1003 1003 1003
Gid: 1003 1003 1003 1003
ID 是:
$ id user1
uid=1003(user1) gid=1003(user1) groups=1003(user1)
$ id user2
uid=1035(user2) gid=1035(user2) groups=1035(user2),1003(user1)
给定手册(man 5 proc
),/proc/$PID/status
应给出Uid, Gid: Real, effective, saved set, and filesystem UIDs (GIDs).
但在这里,该进程的有效ID是user1,而它应该具有 user2 的有效 ID。
我想这可能是因为我太早停止了程序,所以我尝试附加gdb
到它,并继续执行,直到它实际执行main
函数program
(给出了源)中的代码,但给出的有效UID/proc/$PID/status
仍然是user1 而不是 user2。
我错过了什么吗?
编辑:删除挑战的来源,我可能无权发布它。
答案1
这是因为你太早了,如果你等到 UID 更改,那么你的进程就会以user2
.这对我有用:
./program "test" &
PID=$!
sleep 0.0005
kill -SIGSTOP $PID
grep ^Uid /proc/$PID/status
另一种尝试是添加延迟并在睡眠期间usleep()
发送后者。SIGSTOP
然后程序以user2
有效的 uid 运行。您可以检查这一点,但无需附加gdb
或strace
。最有可能的是某种 linux 内核内部的问题,该进程需要一些时间来更改 UID。
当从终端运行进程时,execve()
系统调用被调用;从联机帮助页:
如果在 filename [...] 指向的程序文件上设置了 set-user-ID 位,并且调用进程没有被跟踪,则调用进程的有效用户 ID 将更改为该程序所有者的用户 ID。程序文件。
当您附加gdb
到进程时,您将看不到 的 uid user2
,因为您正在ptrace
ing 该进程,如上面的手册页中所述。或者你可以附加到一个sudo
进程并获得 root 权限。
然而,这个程序永远不会出现分段错误 ( SIGSEGV
) ,除非您使用kill -SIGSEGV $PID
.如果你的程序得到一个SIGSEGV
例程launch_debugger()
被调用。这将调用 agdb
并作为参数只是您的program
二进制文件,不带任何参数,这将替换当前正在运行的进程。因此,在调试器中将拥有 的权限user2
,因此您可以在其中执行您想要的操作,并user2
具有 的权限。
例如,您可以在内部执行以下操作gdb
:
(gdb) file bash
Reading symbols from /bin/bash...(no debugging symbols found)...done.
(gdb) run
Starting program: /bin/bash
user2@host:~$ id
uid=1035(user2) gid=1003(user1) groups=1035(user2),1003(user1)
现在,考虑具有 setuid 位的相同二进制文件,并且所有者是 root。
答案2
程序是否在支持setuid
文件位 ( mount -o nosuid
) 的文件系统上运行?
getuid()
如果我正在调试这个,我会在程序启动时打印和的输出geteuid()
,以查看该setuid
位是否得到遵守。