同一个suid+system程序,不同系统输出不同

A same suid + system program, different outputs on different systems

我编写了一个名为 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 用户,但输出不同。

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

这取决于 /bin/sh 是 bash 还是 dash 在您的分配上。 Bashalways drops setuid/setgid privileges unless invoked with the option -p。 Dash 没有对权限做任何特殊处理。

在 Ubuntu 上,system 函数调用 sh,即 /bin/sh,即破折号,不会删除特权。在 Kali 上,system 函数调用 sh,即 /bin/sh,即 bash,这会降低权限。这是 shell 发行版安装为 sh 的问题,而不是发行版的最新程度。

Bash的行为可以作为一种安全对策,但不是很有效。这是防止误导配置或编写错误的程序的第二道防线,这些程序 运行 具有他们不应该拥有的特权,并允许对 system 等函数进行不受信任的输入。但是,此类程序通常还有其他漏洞,使潜在的攻击者无论如何都可以进行攻击,例如写入文件的能力。

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

My Amazon Linux system(3) 的实例说明:

Do not use system() from a program with set-user-ID or set-group-ID privileges, because strange values for some environment variables might be used to subvert system integrity. Use the exec(3) family of functions instead, but not execlp(3) or execvp(3). system() will not, in fact, work properly from programs with set-user-ID or set-group-ID privileges on systems on which /bin/sh is bash version 2, since bash 2 drops privileges on startup. (Debian uses a modified bash which does not do this when invoked as sh.)

来自 setuid 程序的

运行 system() 超级危险 因为它比你想象的更容易颠覆你的意图(劫持 $IFS 将是一个很好的起点)。

使用其中一个 exec 功能至少可以避开 shell,但通常还有另一个 shell。

如果您绝对必须这样做,您可以在 system() 之前调用 setuid(geteuid());,这基本上会消除您处于 setuid 环境中的事实 - 真正有效的用户是不同 - 通过说 both 是提升的用户。同样与组。这可能是个糟糕的主意。

我可能会建议,如果您必须询问 SO 如何执行 setuid,您可能不处于安全执行此操作的最佳位置。