资讯动态

Agent安全加固:文件访问控制、SSRF拦截与响应脱敏实战

发布时间:2026/10/18 20:38:12 来源:尧图企业网站定制
做 Agent 开发的这两年我一直觉得 Agent 的能力边界是清晰的但它的安全边界非常模糊。工具调用、文件读写、网络请求这些能力组合起来就是一个能真正动手的智能体。可一旦不加约束它也可能变成一台无意识的攻击机器对内探测、对外泄露每一步都有潜在风险。这篇文章要聊的是我最近在做一个 Agent 平台时给它补上的三道护栏文件三级访问控制、SSRF 拦截以及带校验位的响应脱敏。这是从一个真实项目中提炼出来的安全加固方案适合正在做 Agent 开发、AI 应用集成或者准备在企业环境里把 Agent 真正落地运转的团队参考。无论你是做触达隐私数据的内部助手还是面向公网的工具型 Agent这三层防护的思路基本通用。1. 项目概述与核心设计思路1.1 为什么 Agent 必须上护栏先说我踩过的一个坑。早期版本的 Agent 只接了一些公开 API我以为不会出什么事。结果有一次测试让 Agent 帮我看一下本地项目结构它直接顺着默认路径往系统目录遍历虽然没有造成实际破坏但日志里已经能看到它尝试读取非授权文件的行为。后来又发现Agent 在解析用户提供的 URL 时如果不去校验目标地址它就可能在用户诱导下访问内网的管理接口——这不是 Agent 的错而是我在设计阶段没有给它设定边界。Agent 和传统后端服务的本质区别在于它的行为路径是动态的、由模型决策驱动的不能用静态的接口白名单来限制。你没办法穷举它可能调用的每一个文件路径、每一个网络地址所以必须建立一套通用的、可拦截的访问控制层。这套护栏不需要理解 Agent 的意图只需要在每一次文件访问、每一次网络请求、每一次响应输出经过时按规则检验放行。这也是我把这三件事放在一起做的原因文件访问是 Agent 读取上下文的入口网络请求是 Agent 获取外部信息的通道响应输出是 Agent 与外界交互的出口。入口、通道、出口三处都设卡才能把风险压制在一定范围内。1.2 三层护栏的整体架构我最终实现的架构是在 Agent 的运行时外面包了一层网关层不侵入 Agent 主流程而是以拦截器的方式串在工具调用链上。每个工具请求都会经过三个模块文件访问控制器负责路径解析、权限校验、内容检测决定 Agent 能否读写某个路径。网络请求防火墙负责 URL 解析、DNS 解析、IP 判定、重定向跟踪决定 Agent 能否访问某个网络资源。响应脱敏引擎负责扫描输出中的敏感数据进行脱敏并计算校验位供下游验证响应是否被篡改。这三个模块是独立的服务通过 gRPC 和 Agent 运行时通信。这样做的另一个好处是策略更新不需要重启 Agent 主进程下发配置即可生效。后面我会逐个拆开讲实现细节。2. 文件三级访问控制从路径到内容的层层设卡2.1 第一级路径沙箱与白名单校验文件访问的第一道关卡是解决Agent 能看哪些路径的问题。我采用的是沙箱根目录 路径规范化的方案为每个 Agent 会话分配一个专属的工作目录Agent 的所有文件读写操作都必须在这个目录范围内完成。这里最容易踩的坑是路径穿越。用户输入../../etc/passwd这类路径时如果你只做了简单的字符串前缀匹配黑客用一个..就能绕过去。我的做法是先调用path.CleanGo 语言里是filepath.CleanPython 里是os.path.normpath将路径规范化再对 Symlink 做解析确保最终得到的绝对路径真实存在于工作根目录之下。提示Symlink 是一个常见的绕行漏洞。即使路径已经检查过如果工作目录里有一个指向/etc的软链接/data/agent1/link_to_etc/passwd依然能读到系统文件。所以我在校验时强制解析所有 SymlinkGo 里用filepath.EvalSymlinks用解析后的真实路径做判断。除了防穿越我还加了一个基于 Globs 的路径形态校验。比如明文禁止路径段中出现..、禁止以.ssh、.aws之类的隐藏敏感目录开头禁止访问配置文件扩展名.env、.pem、.key。这一步不是用来兜底的而是为了尽早拦截明显恶意的请求降低后续计算的负载。2.2 第二级权限矩阵与会话级授权路径沙箱解决的是能不能到这个地方的问题但还没解决到了之后能不能读、能不能写的问题。所以第二级我引入了一个权限矩阵核心概念是每个 Agent 会话关联一组授权标签Scope每个路径资源声明它需要的标签请求必须匹配才能放行。我构建了一张简化的权限表资源范围需要的授权标签允许的操作说明/sessions/{session_id}/workspaceworkspace:read读会话自己的工作区/sessions/{session_id}/workspaceworkspace:write写仅当任务声明需要/shared/datasets/{dataset_id}dataset:{dataset_id}:read读共享数据集按 ID 隔离/system/config无无全部拒绝/tmptmp:read读、写临时文件但有大小限制这张表看着简单但它帮我解决了一个隐含问题Agent 框架比如 LangChain、Spring AI 这类通常会自己缓存一些配置或临时文件如果权限矩阵设得太严框架本身会崩设得太松又等于没设。最后我的策略是对 Agent 运行时自己的目录给读权限但写权限必须显式声明。每个任务在启动时运行时都会声明这次任务需要写哪些路径如果有任务结束后还尝试写额外路径直接被拦截并写入审计日志。2.3 第三级落地前的静态与动态检测前两级管住了路径和权限第三级管的是内容。因为即使 Agent 有权限读某个路径路径里也可能装着不该被带出沙箱的数据——比如一份包含手机号的订单表、一个存储 API 密钥的配置文件。内容检测我分两段做。静态检测在文件读取后立即执行用一组正则和指纹库快速匹配手机号、身份证号、私人密钥格式sk-开头、AKIA开头等。动态检测则交给一个轻量的分类模型在读取的内容进入模型上下文之前判断它是否包含高敏数据。如果命中文件访问控制器会返回拒绝读取而不是返回内容。这里有一个我试过觉得有效的细节静态检测中的正则不要直接匹配完整的敏感字段而是匹配敏感字段的上下文。比如注册码通常是sk-加 24 位字符你可以检测(?i)\bsk-[a-z0-9]{20,}\b这种模式但要小心误杀普通文本我会在上报时保留命中的上下文片段方便人工判断是真是假。3. SSRF 拦截把内网探测的路堵死3.1 SSRF 在 Agent 场景里的真实危害SSRF服务端请求伪造很多人以为是 Web 应用的老问题但在 Agent 场景里危害更大。因为 Agent 通常会有一个帮用户访问链接、抓取网页的工具这个工具天然就是 SSRF 的入口。攻击者只需要诱导 Agent 访问http://127.0.0.1:8080/admin或者云上元数据地址http://169.254.169.254/latest/meta-data/Agent 就会代替攻击者发起请求而且因为请求来自内网很多防火墙不会拦截。我在设计时参考了主流 WAF 和云厂商的防护规则梳理出三类必须拦截的目标回环地址与本地地址127.0.0.0/8、::1、localhost等主要防攻击者探测本机端口。私有网段与链路本地地址10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16防内网探测与云元数据窃取。保留与特殊地址0.0.0.0/8、100.64.0.0/10CGNAT、多播地址等。3.2 DNS 解析与重绑定防护单纯做 IP 黑名单是不够的最大的坑在 DNS 重绑定。攻击者第一次让 DNS 解析返回一个公网 IP通过校验后第二次解析却返回内网 IP。程序如果只做一次 DNS 查询就可能在校验通过之后访问到真正的内网地址。我的解法是双解析 二次校验先解析一次拿到 IP 列表逐个校验然后在对目标发起连接时强制使用同一 IP而不是重新走系统 DNS。这一步要求 HTTP 客户端必须支持自定义 DialContextGo 的标准库自带这个能力Python 的urllib3可以通过socket.create_connection包装实现。如果 Agent 运行环境是容器或者 Kubernetes我更推荐直接用网络策略卡死出网方向让 Agent Pod 只能访问白名单网段其他全部拒绝。这样即使代码层有漏洞网络层还能兜住。注意URL 解析时要处理各种绕行写法。http://2130706433/这样的十进制 IPhttp://0x7f000001/这样的十六进制写法还有http://[::ffff:127.0.0.1]/这种 IPv4 映射的 IPv6 写法都必须统一归一化成标准 IP 再做拦截。我踩过这个坑早期只拦了127.0.0.1结果测试用0x7f000001轻松绕过。3.3 重定向与协议过滤的细节处理SSRF 拦截里很容易被忽略的还有重定向。一个公网 URL 可能 302 跳转到内网地址如果拦截器只检查了第一个请求的 URL后面跟重定向时不做检查那这条链路就被打穿了。我实现了一个跟随重定向但每次跳转都重新走完整校验的逻辑重定向次数限制在 5 次以内超过直接拒绝。协议过滤同样重要。Agent 的网络工具应该只允许http和httpsfile、gopher、dict、ftp这类协议必须禁用。gopher协议尤其危险因为攻击者可以用它在非 HTTP 端口上伪造任意字节流——经典的打法就是用 gopher 打 Redis 未授权访问通过 Agent 发起一条写计划任务的命令从而拿下服务器。虽然现在很多 Redis 默认配置已经加了保护但这个风险在 Agent 这个好人身上依然存在Agent 会用高权限身份去访问内网一旦被诱导到 Redis 6379 端口危害远大于普通攻击者手动探测。接着是端口限制。我给网络请求工具设了默认只允许80、443、8080、8443这类标准 Web 端口其他端口默认拒绝除非管理员显式加白。这一步能有效压缩攻击面至少不会让 Agent 去访问内网任意的 Redis、MySQL、Elasticsearch 端口。4. 带校验位的响应脱敏防泄漏还得防篡改4.1 为什么要给脱敏结果加校验位响应脱敏听起来不复杂把 Agent 输出里的电话号码、身份证、密钥等敏感数据打码就行。但在真实场景里我遇到一个进阶问题脱敏引擎在网关层运行而下游消费方比如调用 Agent API 的业务系统并不知道该信多少。如果响应在脱敏后被中间环节篡改比如把脱敏后的138****1234还原成另一个真实号码下游该怎么发现这就是校验位存在的意义。我在脱敏后的响应体里附带一个基于原始内容的 HMAC 值叫做校验位。下游拿到响应后用它自己的密钥重新计算脱敏后内容的 HMAC如果与校验位不一致说明内容在传输或处理过程中被改过应当丢弃或告警。这里有一个关键设计决策校验位也是对脱敏后的内容算的而不是对原始内容算的。因为一旦对原始内容计算 HMAC校验位本身就变成了泄露通道——攻击者可以拿着响应和校验位做离线字典攻击验证他猜的原始值对不对脱敏就形同虚设了。4.2 脱敏规则与校验位的协同设计脱敏规则我按数据类别划分每一类都有对应的掩码策略和上下文保留策略数据类型掩码策略上下文保留比例示例手机号保留前 3 后 4中间打码高138****1234身份证号保留前 4 后 4低1101**********1234邮箱保留首字符和域名中a***example.comAPI 密钥全部打码仅显示类型无[REDACTED_API_KEY]地址保留省市级隐藏门牌中北京市朝阳区***这样一个设计能保持业务可用性下游如果只是做展示掩码后的号码完全够了如果需要核验可以比对掩码后的部分是否匹配而不是拿完整原文。校验位的计算我用的是 HMAC-SHA256密钥由配置中心下发按会话粒度轮换。校验位不放在 HTTP 头里而是放在响应体的一个固定字段中方便不同语言的客户端统一处理。每次脱敏操作都会记录日志包含本次命中的敏感类型数量、命中字段分类以及校验位的前 8 位方便排查时快速定位。4.3 校验位与日志审计的联动这里想分享一个容易被忽略的经验脱敏引擎必须保持状态无关。它对每一次响应都独立处理不要把上一次的结果缓存起来因为 Agent 的响应可能是流式的逐片段输出。我一开始为了实现简单用了全局缓存记录这次会话脱敏过哪些内容后来发现两个问题一是 Agent 响应较长时会漏掉后半段二是并发请求会串数据。改成状态无关后逻辑变成了每个响应片段独立扫描、独立脱敏、独立计算校验位片段与片段之间用序号关联。下游聚合时把所有片段的校验位合并成最终的校验位。这个方案在流式输出的场景下实测稳定代价是会多出一点点计算量但对安全性是值得的。5. 常见问题与排查技巧实录5.1 误杀与漏放并存怎么平衡脱敏最怕的就是误杀太多正常业务全被拦截同时也怕漏放敏感数据堂而皇之流出去。我踩过几次坑之后总结出一条策略脱敏按层级逐步放开而不是一次性全拦。具体做法是第一轮先用最严格的正则只放行完全不含任何敏感模式的响应第二轮对命中敏感模式的内容做掩码而不是直接拒绝整个响应第三轮再根据命中类型决定是掩码还是阻断。这样业务方拿到的响应基本可用只是敏感字段被处理了。如果某类内容频繁误杀可以在配置中心单独加白而不是下调全局阈值。5.2 性能开销与延迟优化加上这三层护栏之后一个工具调用的耗时大约增加了 20 到 40 毫秒在大多数场景下可接受。但如果遇到大文件读取或超大响应体检测耗时可能会翻倍。我的优化思路是分层提前退出路径检查、权限检查、内容检查、网络校验每一层都是独立模块能提前拒绝就直接返回不再往下走。实际测试中大多数恶意请求被第一层路径沙箱就拦截了根本走不到后面的高开销检测。网络请求部分我加了响应体大小的上限默认 2MB防止攻击者用超大响应拖垮 Agent 进程。文件读取同样有大小限制超过 10MB 的文件会被截断或者拒绝读取具体看任务类型。5.3 联动测试真实攻击模拟的几条经验最后分享一个我觉得很有价值的测试方法不要只测正向功能要把这三层护栏当成一个整体做攻击链模拟。攻击者上传一个包含软链接的压缩包诱导 Agent 解压后读取链接指向的系统文件。这时候第一层路径沙箱必须通过EvalSymlinks拦下来。攻击者给一个看似正常的公网 URL但 URL 本身会 302 跳转到内网地址。这时候网络请求防火墙的重定向重新校验机制必须生效。攻击者诱导 Agent 访问云元数据接口拿到临时密钥后写入工作区再诱导 Agent 在回复里带上密钥。这时候响应脱敏引擎要能在输出前把密钥特征扫出来并打码同时校验位确保下游拿到的响应是完整的、未被篡改的。这三条链路我分别压测过最终的结论是单层防护一定有漏洞但三层叠加之后攻击者想要绕过的成本会大幅上升。每一层都只做自己的事不依赖前一层的结果这样即使某一层被绕过后面还有兜底。给 Agent 上护栏这件事本质上是在能力和信任之间划一条线。Agent 的能力越强这一步就越不能省。我现在的体会是安全设计要在 Agent 架构的早期就介入等业务跑起来了再回头补改造成本会翻好几倍。你可以在自己的项目里先拿文件访问和 SSRF 这两层起步它们相对独立、见效快跑顺了再补响应脱敏和校验位一步一步把边界扎紧。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑