官网:http://securitytech.cc/
当 GPT 呼叫“家”时:利用 ChatGPT 自定义 Actions 发动 SSRF

在网络安全领域,你会逐渐培养出一种黑客心态或“第六感”。你开始不仅看到事物本来的样子,更会想到它可能被怎样利用。所以,当我在 ChatGPT 里创建我的第一个自定义 GPT,并到达 “Actions”(动作)部分时,那种感觉就开始发麻!我当时根本不是在找漏洞,只是对自定义 GPT 功能感到好奇并在构建一个定制助手。目标是让 GPT 从我自己的外部 API 拉取数据,但一旦我意识到该功能会对用户提供的 URL 发起请求,警报就响起来了,黑客本能驱使我去检查是否存在 SSRF 漏洞。
我的 SSRF 蜘蛛感开始发麻了
什么是 SSRF?
服务器端请求伪造(Server-Side Request Forgery,SSRF)是一种 Web 安全漏洞,允许攻击者诱使应用向非预期目标发起请求。如果用户提供的 URL 未被正确校验,攻击者就可以滥用服务器自身的权限去访问内部网络资源或云元数据服务。SSRF 是那类非常能展示开发者对系统“如何被使用”与“实际会被如何使用”之间差距的漏洞之一。
随着现代 Web 与 AI 应用加入了像 URL 预览这类便利功能,SSRF 变得越来越常见,甚至在 2021 年首次出现在 OWASP Top 10 列表中。服务从本地部署迁移到云端也显著扩大了这一类漏洞的潜在影响范围,因为许多云供应商存在不安全的默认配置。
SSRF 的影响
SSRF 的基本影响很简单:它能让攻击者诱使服务器发起攻击者本身无法直接发起的网络请求。真正的危险来自于服务器本身能访问到什么。SSRF 有两种类型:全读取(full-read)与盲(blind)。在全读取 SSRF 中,攻击者能直接获得目标服务的响应数据,从而很容易从内部服务中窃取数据。盲 SSRF 不会把目标的响应返回给攻击者,但仍然危险,因为攻击者可以与内部服务交互,并用比如通过响应时间做端口扫描之类的方法判断开放端口。过去,我曾经通过 SSRF 和 gopher 协议与内部 redis 服务交互,将 Yahoo Mail 的完全盲 SSRF 提权为远程命令执行(RCE)。(相关文章链接见原文)

基本盲 SSRF

基本全读取 SSRF
云环境中的 SSRF 影响
在云环境中,全读取 SSRF 的影响通常非常严重,因为所有主要云提供商(AWS、Azure、GCP)都依赖内部元数据服务(metadata service)供计算节点正常工作。该服务可通过 http://169.254.169.254 访问,这是一个安全的私有 API,仅本机可查询,里面保存了关于该机器环境的所有关键信息,比如名称、网络细节以及访问凭证。
这是合法功能,但它可能允许攻击者把一个简单的 SSRF 转化为对云环境的完全入侵,具体取决于 IMDS 身份所被赋予的权限。事实上,在 Open Security 的多次渗透测试中,我们就利用过这一攻击链;例如通过利用一个有 SSRF 漏洞的发票生成功能,我们完全攻破了一家大型跨国金融公司在云环境中的基础设施,几乎在其 200 台 EC2 实例上执行了代码。那这和 ChatGPT 有什么关系?下面我们快速剖析一下我如何利用一个可被利用的功能取得 ChatGPT 的 Azure IMDS 身份,从而直接访问他们的云 API。
ChatGPT 的自定义 GPT 功能
要理解该漏洞,必须先了解 ChatGPT 中自定义 GPT 的功能。自定义 GPT(ChatGPT Plus 的一项功能)允许你创建一个经过配置的专用版本 ChatGPT,包含指令、知识与各种能力。基本用法是:写入 bot 的系统指令、命名、添加示例提示,并可以上传文档作为其知识来源。有各种功能,例如网页浏览和图片生成,但对我最有意思的是 Add Actions(添加动作),它允许你通过提供 OpenAPI schema 来定义 GPT 可以调用的外部 API。当模型认为需要调用某个动作时,它会向该 API 提交请求并在回复中使用结果。
Add Action 功能
我们来快速看看这个功能,以便理解我们将如何触发此漏洞。下面示例展示了向 GPT 添加的一个基本 API 动作:一个提供指定位置温度的 API,当用户询问天气时 GPT 就能查询它。
按回车或点击可查看大图

示例天气 API
该功能接受一个 OpenAPI Schema,说明 GPT 如何与 API 交互。可用的 “Test” 按钮可以提交一个测试请求到 API 并查看其响应数据。还有一个认证部分,允许我们为请求设置 API key 与认证头。
SSRF 利用
我对 SSRF 的想法很简单:创建一个 action,把 API 的 URL 指向内部服务(比如元数据服务),尝试提取云环境的 API 访问令牌。不幸的是,我第一次针对元数据服务的 SSRF 尝试失败了(在黑客中这很常见),因为 API 规范中只允许 HTTPS URL,而 IMDS 只能通过 HTTP 访问。

Server URL http://169.254.169.254 被拒,因为它是 HTTP 而非 HTTPS
为绕过这个限制,我用了老把戏——302 重定向(顺便致谢 ssrf.cvssadvisor.com/,这是个很棒的工具,类… Burp Collaborator 和 Interactsh,但允许自定义服务器响应,使得测试各种 SSRF 绕过(例如重定向)变得非常容易)。
按回车或点击可查看大图

服务器响应被设置为 302 重定向到内部元数据 URL
现在如果我把这个重定向 URL 放到 API 规范中,由于它是 HTTPS,会被允许;但是当 GPT 访问该 API 时,重定向应会跟随到 http://169.254.169.254。果然,它生效了!
因为服务器跟随了 302 重定向,它返回了来自内部元数据 URL 的响应。任务完成了,对吧?并非如此。来自元数据服务的响应表明缺少一个必需的请求头(这是 Azure 的特定要求,不同云会要求不同头,从而提供不同程度的 SSRF 保护):
按回车或点击可查看大图

来自 Azure IMDS 的响应错误:缺少 Metadata 头
Azure IMDS 要求必须设置 Metadata: True 头才能访问任何数据。若无法设置该头,我就不能访问任何数据。起初我尝试直接通过 OpenAPI Spec 设置该头,但被拒,因为不允许设置自定义头:
按回车或点击可查看大图

在 API 规范中设置自定义头被拒绝
尽管这条路不通,我最终想到可以通过认证设置去设置自定义头。它允许我设置一个自定义 API key,于是我创建了一个名为 Metadata 的 key,并把值设为 True。
按回车或点击可查看大图

创建名为 Metadata 的 API key 并将其值设为 True
我再次提交请求,成功了!正确的头被设置了,我看到了来自内部元数据 URL 的响应数据!既然我现在可以读取元数据 URL 的内容,我就生成了一个 Azure 管理 API 访问令牌,调用的 URL 如下:
http://169.254.169.254/metadata/identity/oauth2/token?resource=https://management.azure.com/&api-version=2025–04–07
按回车或点击可查看大图

GPT 返回 Azure 管理 API 访问令牌
我确认该令牌有效后立即通过 Bugcrowd 向 OpenAI 的漏洞悬赏项目上报。虽然对自定义 GPT 的 Azure 云环境访问并不是我们见过最严重的漏洞(以前在几乎 200 台 EC2 实例上实现 RCE 那次更严重),OpenAI 仍将此评为高危(High Severity)并几乎立刻修补了它!从发麻的第六感到利用一个流行服务的漏洞,仅用了几个小时,这是一次很棒的体验。继续下一个漏洞吧!