你让 Agent 整理服务器日志,它第一步不是读日志,而是悄悄读取了 /etc/passwd。沙盒没有拦它,因为读文件这个动作本身是允许的。这不是漏洞,而是 Agent 安全最麻烦的现实:你不可能把智能体所有可能的意图都提前写进白名单。所以安全界有个共识:沙盒负责限制行动范围,审计负责回答它到底做了什么。

我先踩的坑:沙盒不是保险箱
我最早做 Agent 安全时,以为沙盒就是终点。后来发现两个问题。第一,Agent 极易被提示注入诱导,执行一串表面上合法、实际上越权的操作。比如它为了完成任务,去读取了不该读的环境变量,再通过一次正常的 connect 调用把结果外发出去。第二,沙盒的边界是人配的,配置一旦有疏漏,所有防护归零。审计的逻辑不一样:它不尝试预判所有攻击,而是把 Agent 的所有动作记录在案,事后再问一句:这些动作是不是越权?这听起来简单,做起来难点不少。
系统调用:Agent 在沙盒里唯一的动作接口
要记录动作,先理解 Agent 在沙盒里怎么和世界打交道。任何进程要访问文件、网络、设备,都必须通过操作系统内核,而内核暴露给用户程序的唯一入口就是系统调用(syscall)。你可以把系统调用想象成一道传送带:用户程序想从操作系统拿任何东西,都把请求写成标准卡片放到传送带上,内核审核后把结果送回来。Linux 上系统调用有几百个,比如 openat 打开文件、read 读取内容、connect 建立网络连接、execve 执行新程序,绕不过它们。所以,记录系统调用就等于给 Agent 的一举一动录了像。
- 系统调用(syscall)
- 用户程序请求内核服务的唯一接口,如打开文件、网络读写、创建进程。
- 沙盒
- 一个受限运行环境,通过限制进程能访问的资源与能调用的系统调用来缩小攻击面。
- 审计
- 记录关键事件并生成日志,用于事后追踪与分析。
- 越权行为
- Agent 执行了超出用户或任务授权范围的操作。
记录工具选型:只有三种适合上生产
Linux 上记录系统调用的方案不止一种。最早我想到的是 strace,每个调试过 Linux 程序的人都知道它。但 strace 用 ptrace 拦截每次调用,性能开销极大,Agent 一跑起来系统就抖,根本没法上生产。真正适合生产的有三种。
- auditd:Linux 内核自带的审计子系统,可以按进程、用户、系统调用类型过滤并记录事件,同时保持较低开销。日志默认写到
/var/log/audit/audit.log,常用于合规和取证。具体规则写在内核文档里。 - seccomp:与其说它是审计,不如说它是限制。它允许你给进程设置系统调用白名单,白名单之外的调用直接拒绝。但这也意味着你要精确预知 Agent 需要哪些调用,否则业务随时会被打断。
- Falco:CNCF 下的运行时安全项目,用 eBPF 在内核层做事件采集,比 ptrace 高效得多。它不仅能记录,还能实时检测可疑模式并触发告警,规则语法见 Falco 官网。
| 方案 | 机制 | 能实时阻断吗 | 生产可用性 |
|---|---|---|---|
| strace | ptrace 拦截 | 否 | 只适合调试 |
| auditd | 内核审计模块 | 否,只记录 | 高,日志可长期留存 |
| seccomp | 内核过滤器 | 能,拒绝调用 | 高,但易误杀 |
| Falco | eBPF 事件流 | 可联动响应 | 高,适合实时检测 |
实际落地上,我倾向用 seccomp 划定底线,用 auditd 记录全量调用,再用 Falco 做实时异常检测。三层各司其职:seccomp 管不能做什么,auditd 管做了什么,Falco 管正在做什么异常的。
怎么判断越权?白名单、规则和基线
拿到日志之后,核心问题来了:怎么知道哪条调用是越权?最朴素的办法是白名单比对。启动 Agent 前,把它的任务可能访问的文件路径、网络地址、可执行程序都列出来,审计日志逐条比对,超出范围就标红。比如你想记录每一次打开文件的操作,可以这样给 auditd 加规则:
auditctl -a always,exit -S openat -F success=1 -k agent_file_access
这条规则会让内核记录所有成功的 openat 调用,并打上 agent_file_access 标签,之后用 ausearch 就能按标签快速检索。但白名单有两个问题。一是定义成本高,Agent 行为有不可预测性,任务稍复杂,白名单就不得不放宽到形同虚设。二是它只看单条调用,看不出调用组合里的恶意。比如 Agent 连续读取 30 个配置文件,又向外部 IP 发起连接,单独看都合法,组合起来就是在测绘你的基础设施。所以更有效的方式是规则与基线结合。以 Falco 为例,你可以写一条规则:任何沙盒内的 Agent 进程读取 /etc 下大量文件并建立外部连接,触发告警。简化版规则长这样:
- rule: agent-suspicious-data-exfiltration
desc: Agent reads sensitive files and connects to network
condition: evt.type in (openat, connect) and fd.name startswith /etc and outbound
output: Flagged system call: %evt.type %fd.name
priority: WARNING
规则不是万能的,但好处是你可以把业务授权和威胁情报写进去,形成一层可解释的检测逻辑。再往下走一步,还有异常检测。用正常任务跑一段 Agent,收集系统调用序列做成行为基线,之后每次任务对照基线,偏离到阈值就告警。问题在于,Agent 的探索行为天然随机,基线很容易误报。我目前的经验是:异常检测适合做线索,不适合做结论,最终判断还得回到规则和白名单。
审计日志必须远程保存
这里我栽过跟头。有一段时间我以为把审计日志存进沙盒本地磁盘就够了。直到一次测试中,Agent 被提示注入诱导执行了清理命令,把审计日志一起删了。那一刻我才真正意识到:审计日志必须远程流式传输到沙盒外部,最好进集中式日志平台,任何 Agent 进程都无权访问。否则,案发现场的监控录像就在凶手手里。审计还有一个绕不开的挑战:日志量。一个活跃的 Agent 每分钟可能产生数万条系统调用事件。全量记录成本会失控。我目前的做法是:全量记录安全相关的调用(文件、网络、进程),普通读写性能类调用做降采样。说白了,审计也要做业务分层。
审计的边界:能记录行为,不能解释意图
日志告诉你 Agent 打开了某个文件,但日志不告诉你它为什么打开。要判断越权,必须结合任务上下文、用户授权范围和会话内容。这也意味着审计不能单独存在。再往后推一步:如果沙盒所在的内核被攻破,攻击者完全可以篡改日志流。所以审计不是绝对的信任,只是深度防御的一环。OWASP 的 LLM 应用 Top 10把不安全的插件设计和过度授权列为独立风险,这恰好印证了审计存在的意义:你无法消灭风险,但可以把风险缩小到可观测、可问责的范围。
常见误区:审计能代替安全限制吗?
不能。审计是事后视角,限制是事前视角。没有 seccomp 或 cgroup 兜底,Agent 可能在一个晚上把生产环境玩坏,审计只能帮你复盘损失。反过来,没有审计,你连被入侵了哪台机器都不知道。
记录所有系统调用就等于知道一切吗?
不完全是。系统调用是主路,但不是唯一的信息泄露途径。例如 Agent 可以通过轮询 /proc、测量 CPU 时间推测其他进程的活动。更完整的审计需要结合网络流量、文件完整性监控和平台侧日志。但系统调用日志仍然是目前覆盖最全、最底层的行为证据。
最后说说我的判断。Agent 沙盒审计不是一个能一键防住所有攻击的产品,它更像是安全体系里的档案部:平时没人注意,出事时它就是唯一能还原真相的记录。对一个要接入生产系统的 Agent 来说,精准的限制、实时的检测、完整的审计,三者缺一不可。而审计这一环,恰恰是很多团队最后才补的。如果你的 Agent 还在裸奔,先从开启审计做起。至少你还有机会知道,它昨天到底在服务器上干了什么。
原创文章,作者:guanweilu,如若转载,请注明出处:https://guanweilu.cn/article/551.html