聊天缩略图绕过 s3_cdn_url 并使用原始 S3 存储桶 URL

, ,

我最近配置了 Cloudflare R2 上传存储桶,结果聊天缩略图显示异常。于是我深入排查并快速修复了配置,随后发现了这个主题:https://meta.discourse.org/t/cloudflare-r2-image-url-display-issue-detailed-explanation-and-fix/358204。无论如何,我查看了其他 S3 上传存储桶的配置,发现这个问题并非 Cloudflare 特有。


描述

当为上传配置了外部 S3 或兼容的对象存储时,聊天缩略图会绕过 CDN,直接从存储桶 URL 加载。

对于像 Cloudflare R2 这样需要安全配置的外部 S3 兼容存储桶,聊天缩略图会损坏且无法显示。

根本问题在于聊天序列化器未能将 s3_cdn_url 设置应用于缩略图。图像未通过配置的 CDN 进行路由,而是将原始的 S3 存储桶内部 URL 直接泄露到了浏览器负载中。

复现步骤

在 Meta 及其他使用 S3 上传存储桶的站点上均可复现此问题:

  1. 在聊天或频道中发布一张图片
  2. 在控制台检查缩略图图片的 URL
  3. 点击图片以获取更大的原图,并检查其 URL
  4. 将其与缩略图 URL 进行对比

以下是来自 Meta 聊天的示例:

缩略图 URL:来自存储桶

https://cdck-file-uploads-global.s3.dualstack.us-west-2.amazonaws.com/meta/optimized/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532_2_375x500.jpeg

原图 URL:通过 CDN

https://global.discourse-cdn.com/meta/original/4X/4/7/9/479815360e0e6e0cd9f4ba565891776e84aea532.jpeg

在控制台中,缩略图的 HTML 代码 <img... 包含 data-large-src(CloudFront CDN URL)和 src(AWS 存储桶 URL)。

截图

影响:

  • 对于像 Cloudflare R2 这样默认安全且阻止未授权访问原始存储桶端点的 S3 兼容存储,聊天缩略图(优化后的)会损坏。
  • 对于允许访问原始存储桶端点的 AWS 及其他 S3 兼容对象存储桶,会导致带宽泄露,因为聊天完全绕过了 CDN;这将导致为所有聊天缩略图流量支付直接的 S3 出站费用。
  • 基础设施泄露:原始后端存储 URL(包括内部存储桶名称,有时甚至包括账户 ID)正被暴露在客户端 JSON 负载中。

拉取请求(PR):

我提交了一个修复该问题的 PR:

看起来 Sam 添加了 getURLWithCDN 到聊天编辑器预览中——不过,我认为它并没有应用到聊天流中?

我想知道编辑器的修复是否在某些 S3 配置下也失败了,因为 getURLWithCDN 在协议不匹配(//https://)时会崩溃?无论如何,上述 PR 通过为聊天流添加包装器并使其与协议无关,扩展了 Sam 的工作。

临时解决方案:

在我意识到这不仅仅是 Cloudflare 的问题之前,我制作了一个轻量级的主题组件。它在浏览器尝试下载之前,拦截聊天 DOM 中的原始 S3 域名,并将其替换为正确的 CDN 域名。这正确地路由了流量并堵住了带宽泄露的漏洞。我对其进行了适配,使其适用于任何 S3 兼容的对象存储。只需两个设置——「原始 S3 存储桶 URL」和「S3 CDN URL」。

(不知道为什么 GitHub 的自动链接在这里失效了) 现已修复

2 个赞

可能与网站迁移有关……我刚重新烘焙了内容。

1 个赞