支持命令执行的常见二进制文件,如 `awk` 和 `vim`,不考虑 setuid 位?

Shu*_*eng 1 setuid suid

我硬化Linux系统,并希望测试(setuid-基)壳使用共同二进制文件,像转义awkvim等,支持命令执行。

但是,我测试过的所有二进制文件除了sh并且bash不尊重它们的setuid位。

特别是,awk继续以普通用户身份执行:

$ ls -lL /usr/bin/awk
-rwsr-xr-x 1 root root 121976 Mar 23  2012 /usr/bin/awk
$ id
uid=1000(bob) gid=1000(bob) groups=1000(bob)
$ awk 'BEGIN{system("id")}'
uid=1000(bob) gid=1000(bob) groups=1000(bob)
Run Code Online (Sandbox Code Playgroud)

相反,当给定选项时bash执行:root-p

$ ls -la /bin/bash
-rwsr-xr-x 1 root root 1168776 Apr 18  2019 /bin/bash
$ /bin/bash -p
# id
uid=1000(bob) gid=1000(bob) euid=0(root) groups=1000(bob)
Run Code Online (Sandbox Code Playgroud)

有什么方法可以使awk, vim,less等尊重setuid位并执行命令root吗?

操作系统

# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
Run Code Online (Sandbox Code Playgroud)

更新

parallels@debian-gnu-linux-vm:~$ ls -la /proc/self/fd/0 /dev/fd/0 /dev/stdin
lrwx------ 1 parallels parallels 64 Mar 26 08:15 /dev/fd/0 -> /dev/pts/1
lrwxrwxrwx 1 root      root      15 Mar 20 19:56 /dev/stdin -> /proc/self/fd/0
lrwx------ 1 parallels parallels 64 Mar 26 08:15 /proc/self/fd/0 -> /dev/pts/1
Run Code Online (Sandbox Code Playgroud)

mos*_*svy 7

$ ls -lL /usr/bin/awk
-rwsr-xr-x 1 root root 121976 Mar 23  2012 /usr/bin/awk
$ awk 'BEGIN{system("id")}'
uid=1000(bob) gid=1000(bob) groups=1000(bob)
Run Code Online (Sandbox Code Playgroud)

在您的示例中,不是awk删除权限或不“尊重其 setuid 位”,而是/bin/shawk 用于实现其system()功能的命令。

就像它的 C 语言一样,awksystem()不直接解析和运行命令,而是将它作为参数传递给/bin/sh -c. 如果/bin/sh是 bash(或 dash 的 Debian 版本,或从 bash 复制此错误功能的其他几个 shell),它会将其有效 uid 重置回真实的 uid。

同样的事情适用于 awkprint | "cmd""cmd" | getline在 awk 中——它们是通过popen(3)which calls实现的/bin/sh -c。请注意,它始终是/bin/sh(或系统的 shell,例如/system/bin/sh在 Android 上),而不是用户的登录 shell 或来自$SHELL环境变量的登录 shell 。[1]

这在 perl 中是不同的:如果使用多个参数调用perl 的system, exec, open "|-", open2, open3, 等将直接运行命令,或者如果命令不包含 shell 元字符:

$ id -nu
ahq
$ ls -l /tmp/perl
-rwsr-xr-x 1 dummy_user dummy_user 3197768 Mar 24 18:13 /tmp/perl
$ env - /tmp/perl -e 'system("id -nu")'
dummy_user
$ env - /tmp/perl -e 'system("{ id -nu; }")'
ahq
Run Code Online (Sandbox Code Playgroud)

这个例子是在 Debian 10 上。在 FreeBSD 或更旧的 Debian 等其他系统上,这两个命令将打印相同的内容,因为它们/bin/sh不会删除权限。[2]


笔记:

[1]其他程序喜欢vimless确实使用$SHELL环境变量,因此通过将其指向某个包装器,它们很容易“修复”。在vim您也可以使用:set shcf=-pc传递-p选项用于外壳:!和类似的命令。

[2] perl 示例也可以像在 FreeBSD 上一样在 OpenBSD 上工作,前提是您将 替换env - /tmp/perl 'script'为更钝的echo 'script' | /tmp/perl /dev/fd/0

OpenBSD的perl的将拒绝该-e参数,并拒绝从标准输入读取它的脚本的setuid模式下运行时(见该是结束这里- OpenBSD中理应有安全的setuid脚本)。

但这并不适用于/dev/fd/N,当作为脚本名称(仅表单,而不是或)给出时,perl 会自行处理/dev/fd/N/dev/stdin/proc/self/fd/N

obsd66$ ls -l /tmp/perl
-rwsr-xr-x  1 dummy_user  dummy_user  10728 Mar 25 18:34 /tmp/perl

obsd66$ env - /tmp/perl -e 'system("{ id -nu; }")'
No -e allowed while running setuid.

obsd66$ echo 'system("{ id -nu; }")' | env - /tmp/perl
No program input from stdin allowed while running setuid.

obsd66$ echo 'system("{ id -nu; }")' | env - /tmp/perl /dev/stdin
Can't open perl script "/dev/stdin": Operation not permitted

obsd66$ echo 'system("{ id -nu; }")' | env - /tmp/perl /dev/fd/0
dummy_user
Run Code Online (Sandbox Code Playgroud)
debian10$ su - other_user -c 'perl /dev/fd/7' 7<<<'print "OK\n"'
OK
debian10$ su - other_user -c 'perl /proc/self/fd/7' 7<<<'print "OK\n"'
Can't open perl script "/proc/self/fd/7": Permission denied
Run Code Online (Sandbox Code Playgroud)