前言
记录一些常见的非漏洞(配置不当)提权笔记;还有一些linux内核版本可能会产生漏洞需要自行google.
suid提权
- 只对可执行文件生效,任何用户执行该文件都是以文件所属者身份运行的。
- SUID(Set User ID)是一种权限位,用于在执行文件时暂时将进程的有效用户 ID 更改为文件所有者的用户 ID。它是一种特殊权限设置,可让非特权用户以超级用户权限运行具有 SUID 标志的可执行文件。
查找具有s权限的二进制文件
1 | find / -perm -u=s -type f 2>/dev/null |
find
做一个实验使得find
命令有s
权限,来提权、
1 | ┌──(kali㉿kali)-[~] |
cp
做一个实验使得cp
命令有s
权限,来提权、当然不止于find
,cp
命令,可以参考这个网址:click me
当cp有suid权限时,可以改写只能root访问的文件,比如/etc/passwd
或/etc/shadow
中的内容
首先用openssl生成一个密码,passwd参数表示生成一个密码,-1表示md5,-salk表示盐(随意指定),最后跟要加密的值
1 | └─$ openssl passwd -1 -salt 1 123abc |
然后往/etc/passwd
文件中添加一个新用户,用户名随意取,密码不要用x
,要用我们上面生成的密码,其他的按照root的写即可
1 | ┌──(kali㉿kali)-[~/桌面] |
去修改/etc/sudoers
应该简单点
补充一下
linux的shadow文件中的第二个字段保存了加密后的密码,加密数据的格式为 $type$salt$encrypted,其中type是提示符,salt是随机生成的字符串,encrypted是明文密码和salt通过crypt函数加密后的结果。在加密数据中的提示符type用来标识采用了哪种加密方式,这样的标识符有以下几种:
1 代表采用了MD5加密方式
2 Blowfish,是最早的版本,有一些缺陷,不推荐使用
2a Blowfish,是修复了一些缺陷后的版本,但仍然有一些问题,不推荐使用
2b Blowfish,是修复了2a中的问题后的版本,是安全、常用的版本
2y Blowfish,Eksblowfish版本
y 是Yescrypt加密方式的前缀,是Blowfish加密方式的一个变种,提供了更高的安全性和性能
5 代表采用了SHA256加密方式
6 代表采用了SHA512加密方式
在线哈希识别器:click me
/etc/shadow
中的密码可以用john
工具(kali自带)破解,能不能破解成功取决于你的dict。
1 | ┌──(kali㉿kali)-[~/桌面] |
当然john还有很多用法,比如破解受密码保护的Zip压缩文件,我不一一记录; 可以参考 官方Wiki
再docker中su username
,可能会报must be run from terminal
;解决方案:clink me
用的比较多的解决方案:
1 | python3 -c "import pty; pty.spawn('/bin/bash')" |
sudo提权
sudo
提权基本离不开/etc/sudoers
文件,
/etc/sudoers
文件是一个用于配置sudo
命令的文件,它定义了哪些用户或用户组有权利以root用户的权限来执行特定的命令。这个文件通常位于Linux系统中的/etc目录下。sudoers文件的内容可以指定哪些用户可以以root用户的权限执行哪些命令,以及是否需要输入密码等安全设置。编辑sudoers文件需要特殊的权限,并且通常使用visudo命令来进行编辑,以确保在保存文件时能够检查语法错误,以避免导致系统安全性问题。
假如我们(root用户)要给普通用户test分配sudo权限,请输出vim /etc/sudoers
打开文件进行编辑,找到root权限root ALL=(ALL:ALL) ALL
,在下一行输入test ALL(ALL:ALL) NOPASSWD:ALL
,保存后退出,这样即表示用户test可以使用sudo调用root权限执行命令。
/etc/sudoers
也可以指定用户执行指定的sudo命令
test ALL(ALL:ALL) /usr/bin/ls
,但是这样还是得输入密码才能执行,也可以配置不需要密码:test ALL(ALL:ALL) NOPASSWD:/usr/bin/ls
,
在Vim中,当你输入:!/bin/bash并按下回车时,Vim会执行你输入的命令,其中!表示执行外部命令的意思。因此,Vim会启动一个新的shell进程并执行/bin/bash。这是Vim的一个功能,允许用户在编辑器中执行外部命令,当然vim
,只是sudo提权命令之一,还有很多其他的命令,比如:less,python等等,可以参考上面那个网站
1 | ┌──(kali㉿kali)-[~/桌面] |
再试试python
,在/etc/sudoers
中添加zixyd ALL=(ALL:ALL) NOPASSWD:/usr/bin/less,/usr/bin/python,
1 | ┌──(zixyd㉿kali)-[/home/kali/桌面] |
NFS提权
NFS是network file system缩写,网络文件系统,用来挂在某个目录或文件进行共享,默认是2049端口,功能类似于windows的共享。
首先安装nfs服务端:
1 | sudo apt-get install nfs-kernel-server |
安装后修改配置文件/etc/exports,这里将home目录进行挂载共享,内容如下:
1 | /home *(rw,no_root_squash) |
其中/home是要挂载的目录,*代表允许连接的主机,这里是所有,rw是读写权限,no_root_squash代表客户端允许以root权限访问nfs。
随后重启相关服务:
1 | nfs通过rpc通信,这里把rpcbind也重启下 |
此时就配置好了,可以通过showmount命令来列出目标机的共享目录,e参数显示NFS服务器的输出清单。
1 | showmount -e ip |
NFS配置不当可提权
当nfs配置了读写权限,且允许客户端以root访问时,就会存在安全隐患。测试如下:
首先客户端把目标机nfs的共享挂载到本地,然后把bash复制进去并赋予suid权限,操作如下图。
此时目标机的home目录下就会有一个具有suid权限的bash。
普通用户执行即可获取root权限,这里注意需要加上p参数,否则权限还是当前用户的。
p参数说明:不提供的情况下,打开bash权限是当前实际用户,提供的情况下,会打开特权模式,像上继承euid,因为bash有suid权限,所以这里是root。
使用场景:这个和suid提权很像,给程序赋予suid权限然后利用。不同的是前两篇suid提权是当前用户使用sudo chmod自己修改的,在sudoers禁用sudo命令等情况下,就行不通了。而nfs配置利用,是客户端挂载到本地赋权的,目标机的普通用户只需执行就可以。
其它命令
除了可以直接得到shell的,还有其他一些程序不能直接获取,例如nano、vi等。
例如nano被共享了,则可以给nano一个suid权限,然后来读取敏感文件,爆破密码从而登录。
PATH提权
Linux中的PATH
是一个环境变量,它指定了可执行程序所在的目录,例如bin和sbin目录,当我们在终端运行一个命令时,系统就会根据PATH来查找相关的可执行文件。
首先编译以下c代码,这里用whoami
命令来做实验,gcc shell.c -o whoami_shell
1 |
|
1 | ┌──(kali㉿kali)-[~/桌面] |
利用:到tmp目录下,把bash写到一个whoami
文件中,然后修改PATH变量添加tmp目录,再去执行shell,就会获得一个root权限。
1 | ┌──(kali㉿kali)-[~/桌面] |
过程:root给一个可执行文件赋予了suid,而此文件又调用了一个环境变量的命令,这时修改PATH把tmp添加到头的位置,系统再执行就会先去tmp目录下找,tmp目录下放的是恶意程序,从而导致恶意程序以root权限运行。
注意,用export PATH=/tmp:$PATH
改变PATH只在此次终端才有效,对其他终端无效
LD_PRELOAD提权
LD_PRELOAD
是Linux下的一个环境变量,程序运行时都会加载一些so文件,类似于windows下程序加载dll,而LD_PRELOAD可以指定程序运行前加载的动态连接库。
测试前先按如下配置一下sudoers文件,以zixyd用户为例,添加一个find命令和一个LD_PRELOAD。
1 | zixyd ALL=(ALL:ALL) NOPASSWD:/usr/bin/find |
这里记录下env_keep
的说明。
例如aaa用户有一个aaa_pach的环境变量,当通过su切换到bbb用户时,再查看env环境变量,aaa_pach就没有了,也就意味着用户的切换不会带着环境变量一块切过去。而想保持某个环境不受用户切换的影响,那么可以在sudoers文件中设置env_keep。
如果并设置Defaults env_keep += LD_PRELOAD
,会报错
1 | ┌──(zixyd㉿kali)-[~] |
切换回普通用户,查看sudo权限。
1 | ┌──(zixyd㉿kali)-[~] |
我们有一个find的sudo权,且env_keep中定义了LD_PRELOAD,那么我们就可以定义一个恶意的so文件,然后sudo运行find时指定LD_PRELOAD来加载我们自己的so文件,就可以实现提权。
so文件的c代码如下。
1 |
|
然后进行编译-fPIC -shared参数简单理解就是动态编辑共享库,可以进行公共调用,nostartfiles参数代表该库运行不会去调用系统的其它库,避免影响自己的程序执行。
1 | gcc ld_preload_shell.c -fPIC -shared -o shell.so -nostartfiles |
编译后我们使用sudo运行find并指定LD_PRELOAD为我们编译的shell.so文件,这时find就会先调用shell.so,导致我们的代码被执行,返回的权限为root。
1 | ┌──(zixyd㉿kali)-[~] |
思考:
再sudo提权时可以用到LD_PRELOAD
,那么suid行不行呢?我用suid没有成功
1 | ┌──(zixyd㉿kali)-[~] |
注意点:如果使用自己攻击机编译的so文件,传到目标机可能普通用户没有执行权限,这时需要加下权限。如果目标机支持gcc编译,也可以直接在目标机编译。
总结
使用情况就是sudoers
中的env_keep
定义了LD_PRELOAD
,然后sudo
有相关的命令,那么sudo运行命令时就可以通过LD_PRELOAD来指定恶意so文件。
cronjobs提权
cronjobs是定时任务,在特定的日期和时间执行计划任务。例如定期备份或者定期清理某个目录等都会用到,定义格式如下:
文件覆盖
这里以root用户创建一下测试环境,首先创建一个cron,运行一个脚本,该脚本功能是定时清除特定文件,例如/tmp/test。
1 | ┌──(kali㉿kali)-[~/桌面] |
创建clear.py脚本,并赋可执行权限chmod +x /tmp/clear.py
1 | #!/usr/bin/env python3 |
修改crontab
文件,每分钟以root身份执行一次/tmp/clear.py文件
1 | sudo vim /etc/crontab |
提权:
如果可以修改定时任务的文件(clear.py),就可以提权,例如将上面的**/tmp/clear.py**修改内容如下
1 | #!/usr/bin/env python3 |
在执行/bin/bash -p
命令即可得到root权限,-p参数在本文章上面有解释;
通配符注入
而在操作过程中,如果有文件名的名字是一个参数,那么执行过程中,就会被当作参数运行。例如一个目录下有一个叫–help的文件,当cat查看该文件内容时,实际上确是cat的帮助信息。
常见的定时任务除了定时清除文件外,定时压缩也会很常见,例如有一个定时任务,每分钟回去执行/var/www/html/crontab.sh
脚本,该脚本是备份html网站,脚本内容如下。
1 | !/bin/bash |
修改/etc/crontab
:
1 | */1 * * * * root /var/www/html/crontab.sh |
查看是否备份成功
1 | ┌──(kali㉿kali)-[/var/backups] |
在tar命令中有一个checkpoint
参数,即检查点,比如checkpoint=1,则代表压缩过程中每压缩一个文件就去执行一个检查操作。
而这个检查操作的参数是--checkpoint-action=exec=
,后面可以跟要执行的命令。
利用思路就是我们写入一个sh脚本,该脚本作用是修改sudoers文件,把当前用户添加进去,获得sudo所有权,从而进行提权。然后利用checkpoint-action=exec=接一个执行sh脚本的命令即可。
利用过程:首先创建两个文件,名字为参数名,然后再创建一个sh脚本,内容为向sudoers追加权限,相关命令如下:
1 | echo 'echo "zixyd ALL=(root) NOPASSWD: ALL" >> /etc/sudoers' > test.sh |
等待一分钟后,sudoers就会被追加zixyd用户的权限
1 | sudo cat /etc/sudoers |
docker提权
在docker中,是允许访问root用户和docker组中的其它用户的,测试如下,(这句话表达的不是很清楚,大概意思就是只要用户在docker组下,就可以未授权访问root用户和docker组中的其他用户)
需要将用户添加到docker组中
1 | usermod -G docker kali |
这里有意思的是,我没有输入这条命令,我在我的kali用户已经是dockr组了(意思就是我没有设置实验环境,我的kali机器已经存在可以提权的点了)
上网找原因:在某些Linux系统中,安装Docker后会自动创建一个名为”docker”的用户组,并将当前用户加入该组,以便用户可以在不使用sudo的情况下运行Docker命令。这通常是Docker安装过程中的默认行为。
1 | ┌──(kali㉿kali)-[~/桌面] |
随后使用docker run来允许alpine镜像,v参数进行挂载,是将宿主机的root目录挂载到alpine的mnt下,使用冒号分隔。i参数是保持打开状态,t参数是分配一个tty终端,it一般结合使用,即保持通讯终端的打开。
这时访问docker
镜像alpine,就相当于访问宿主机的root目录,权限变成了root,可以执行任意命令
1 | ┌──(kali㉿kali)-[~/桌面] |
capability提权
capability翻译为能力的意思,linux中能力的概念和suid类似,是用来让普通用户也可以做超级用户的工作,从而设置的一个机制,原来linux分的是普通用户和超级用户,后来加了能力,即赋予某某账号能力,这个账号有能力了,就可以去做事了。
capability可分割root权限,把root特权分割成不同的能力,然后给与普通用户不同的能力,每一种能力都代表着一种特权。下面是一些能力参考:
1 | - CAP_CHOWN:修改文件属主的权限 |
在设置程序能力时,有三个选项可选:
1,inheritable,简称i,表示是否可继承。
2,permitted,简称p,表示是否允许使用。
3,effective,简称e,表示特权是否有效。
setcap命令用来设置能力,例如setcap cap_setuid+ep /home/demo/python3
,就表示home/demo/python3
这个程序添加了setuid能力,即改变进程uid的能力,+ep就表示能力有效,且允许使用。
capability测试
setcap设置能力,getcat读取能力。
getcap通过r参数来读取指定目录下有能力的程序。
1 | ┌──(kali㉿kali)-[/tmp] |
能力滥用导致的提权
例如管理员要为python3程序(其他程序类似)设置超级权限给zixyd用户,但没有用suid或sudo授权,而用的是capabilities
,通过的是以下命令来设置的。
因为root只想给zixyd用户的python3能力,所以这里是将程序复制到了zixyd用户下,如果直接设置bin下的python3程序,那么意味着任何用户都具有了相关能力
1 | ┌──(zixyd㉿kali)-[~] |