TT Lab
博客 开始
学习 学习路径 课程

LLM 应用安全——从注入到输出处理

模型选中的工具以谁的权限执行——过度授权

在 TT Lab 中继续学习

一句话总结

智能体以服务账号的权限运行,而模型会不加区分地照做用户的话和文档中的话。所以执行什么,要由服务器按请求用户的权限来决定而不是由模型决定,参数要校验,无法撤销的事要由人来确认。

为什么需要它

假设我们要做一个文件助手。给模型列表、读取、写入、删除工具,由应用服务器执行工具。应用服务器以能触碰所有用户文件的账号运行。这时 viewer 用户说“把这个文件删掉”,会发生什么?模型选择工具,服务器照样执行。有权限的代理人替没有权限的人办事,这就是安全领域中由来已久的**混淆代理人(confused deputy)**问题。再叠加提示注入,提出请求的就不再是用户,而是文档中的一句话。

OWASP LLM Top 10 2025 把它列为过度授权(LLM06 Excessive Agency),并把根源分为三类——不必要的功能(工具太多)、不必要的权限(工具能触及的范围太广)、不必要的自主性(无需人工确认就做无法撤销的事)。

它如何工作

根源 修复的位置 本实验中的函数
功能 按角色精简展示给模型的工具。开发用工具(shell)干脆去掉,不在列表中的名称不执行 offered_tools, allowed
权限 执行前夕,再按请求用户的角色检查一次许可。与模型选了什么无关 allowed
权限(参数) 把路径参数解析为真实路径(..、绝对路径、符号链接),检查是否在该用户的主目录内 resolve
自主性 删除总是搁置,只有请求者本人另发一次请求确认时才执行一次 run_call, handle_confirm

最后一行很微妙。“删除工具要有 confirm: true 参数才会删除”看起来像是确认,但填写这个参数的是模型。文档中的指令一放入 confirm,确认就不复存在。确认必须来自模型无法书写的通道——收到搁置 id 的人发出的第二次请求。

用单独的通道接收确认,还能多得到一样东西:可以在画面上展示被搁置的行为是“做什么、在哪里、以谁的权限”。人要确认的对象不应是模型的话(“我来帮您整理”),而应是服务器实际要执行的调用。而且确认 id 要绑定到请求者本人,用过一次就作废,确认之后仍要重新通过角色和路径检查。否则,搁置就成了绕过检查的后门。

路径校验如果用字符串来做也会漏。查找 .. 并拒绝,绝对路径会溜过去;两者都挡住了,放在主目录内的符号链接仍可能指向外面。先解析为真实路径(os.path.realpath),再与基准目录比较公共祖先,才是安全的。

这门课程的假模型只要文档中有指令,就总会调用那个工具。真实模型大部分时候按用户的意思行事,只是偶尔不这样。这个“偶尔”无法靠测试全部找出来,所以权限要在模型之外施加。如果说 mcp-server 课程讲的是工具服务器一侧的约定(允许列表、只读、确认),这里讲的就是应用把最终用户的身份和角色一直带到工具执行的问题。

现场遇到的情形

常见的情形有:内部文档智能体按一个只有读取权限的员工的请求,把共享文件夹整理掉了;因为共享来的会议纪要中的一句话,智能体自己标记“已确认”并删除了文件;开发时挂上的 shell 工具留在了生产环境中。调查时,要针对每个消失的文件,在执行记录中查看是谁(角色)、以什么句子和上下文、发出了什么工具调用。同时还要分辨出:由所有者本人确认后删除的不算事故。

恢复也是一种判断。从备份全部恢复很简单,但这样连用户故意删除的东西也会回来,违背用户的意愿;如果那是在处理删除个人信息的请求,这本身就成了新的事故。所以要先用记录分辨“是谁的意愿”,只恢复因事故被删除的。执行记录中必须留有请求句子和上下文,才能做出这个判断——从这一点来说,过度授权问题的调查与上一个模块的记录设计是相连的。

角色表本身也是设计对象。如果像“admin 什么都能做”这样放得很宽,混在 admin 请求中的一行文档就会动用最大的权限。把每个工具限定为只给真正需要的角色,并让无法撤销的工具同时要求角色和确认,这样即使注入成功,损害所及的范围也会缩小。

接下来的实验要做什么

在文件助手过去的执行记录中,统计超出角色的执行和主目录之外的路径,然后依次加入角色检查、精简工具列表、路径校验以及通过单独通道的确认。在最后的故障事件中,分辨三个人的文件消失的不同原因,只恢复被误删的。