1

我写了一个简单的程序,名为suid.c

int main(int argc, char* argv[]) {
        system(argv[1]);
}

用 gcc 编译它,然后设置 suid 权限(现在是 root 用户):

# gcc suid.c -o suid
# chmod +s suid

我尝试./suid id在不同的虚拟机上使用 www-data 用户运行,但输出不同。

  • kali 2019 中的输出:id=33(www-data) gid=33(www-data) groups=33(www-data)
  • ubuntu trusty(旧的 linux)中的输出:uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data)

这是为什么?Linux 有什么变化吗?

4

2 回答 2

5

这取决于/bin/sh您的发行版是 bash 还是 dash。Bash总是删除 setuid/setgid 权限,除非使用 option 调用-p。Dash 对特权没有做任何特别的事情。

在 Ubuntu 上,该system函数调用sh,即/bin/sh,即破折号,它不会放弃特权。在 Kali 上,该system函数调用sh,即/bin/sh,即 bash,它会删除特权。这是发行版安装为哪个 shell 的问题,而sh不是发行版的新近程度。

Bash 的行为可能是一种安全对策,但它不是一种非常有效的方法。这是防止错误配置或编写错误的程序的第二道防线,这些程序以不应拥有的特权运行,并允许对诸如system. 但是,此类程序通常具有其他漏洞,允许潜在的攻击者无论如何进行攻击,例如写入文件的能力。

于 2020-02-17T19:18:32.690 回答
4

如上面评论中所述,您会看到system()故意删除 setuid 的效果(间接通过 bash)。

我的 Amazon Linux 实例说明system(3)

不要在具有 set-user-ID 或 set-group-ID 权限的程序中使用 system(),因为某些环境变量的奇怪值可能会被用来破坏系统完整性。请改用 exec(3) 系列函数,但不要使用 execlp(3) 或 execvp(3)。事实上,system() 在 /bin/sh 是 bash 版本 2 的系统上无法从具有 set-user-ID 或 set-group-ID 特权的程序正常工作,因为 bash 2 在启动时会放弃特权。(Debian 使用修改后的 bash,它在作为 sh 调用时不会这样做。)

system()从 setuid 程序运行是非常危险的,因为它比你想象的更容易颠覆你的意图(劫持$IFS是一个很好的起点)。

使用其中一个exec功能至少可以让 shell 不碍事,但通常还会有另一个 shell。

如果您绝对必须这样做,您可以调用setuid(geteuid());before system(),这基本上抛弃了您处于 setuid 环境中的事实 - 真实用户和有效用户不同 - 通过说两者都是提升的用户。组也是如此。这可能是一个可怕的想法。

我可能会建议,如果你不得不问 SO 如何做 setuid,你可能不是安全地做这件事的最佳位置。

于 2020-02-17T19:23:55.527 回答