多站点 + 短链接 + 安全上传 + S3

好的,我本周似乎正在开展一次漏洞搜寻行动。

我们有一个启用了 secure_uploads 的论坛,所有上传文件都存储在(官方的)AWS S3 上。

问题:短链接似乎无法正常工作,URL 中缺少 uploads/{database_id} 部分。

问题代码似乎位于 UploadsController::show_short 中:

if upload = Upload.find_by(sha1: sha1)
  return handle_secure_upload_request(upload, Discourse.store.get_path_for_upload(upload)) 
     if upload.secure? && SiteSetting.secure_media?

  if Discourse.store.internal?
    send_file_local_upload(upload)
  else
    redirect_to Discourse.store.url_for(upload, force_download: params[:dl] == "1")
  end
else
  render_404
end

因此,如果 upload.secure? && SiteSetting.secure_media? 为真,则请求将由 handle_secure_upload_request(upload, Discourse.store.get_path_for_upload(upload)) 处理。

现在,Discourse.store.get_path_for_upload(upload) 返回的 URL 缺少 uploads/{database_id} 部分:

`original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png"

因此,handle_secure_upload_request 返回的签名 URL 也缺少该部分,因为它以 /original 开头:

https://redacted.s3.us-east-2.amazonaws.com/original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKI....

如果 upload.secure? && SiteSetting.secure_media? 为假(实际上并非如此),则请求将由 Discourse.store.url_for(upload, force_download: params[:dl] == "1") 处理。

而该方法确实返回了正确的 URL:

https://redacted.s3.us-east-2.amazonaws.com/uploads/db3999/original/3X/f/d/fd0b5775899541b9d42e67f8e0dd6bf587a179d3.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKI...

因此,显然存在一个 url_for 和一个 get_path_for_upload,它们的行为不同,而目前似乎使用了错误的那个?

7 个赞

感谢提交报告,这个问题应该很容易修复;handle_secure_upload_request 只是没有考虑到多站点连接。我今天会着手修复,完成后向您反馈。

8 个赞

已在此修复:

9 个赞