安全/隐私问题:DiscourseConnect Provider 重定向 URL 中暴露了电子邮件

描述错误

当使用 Discourse 作为 DiscourseConnect 提供商(SSO 提供商)时,用户的电子邮件地址会暴露在重定向到依赖方的 302 重定向 URL 中。这是因为 lib/second_factor/actions/discourse_connect_provider.rb 中的 populate_user_data 方法总是设置电子邮件:

  def populate_user_data(sso)
    sso.name = current_user.name
    sso.username = current_user.username
    sso.email = current_user.email  # <-- 总是包含
    sso.external_id = current_user.id.to_s
    # ...
  end

然后,此电子邮件会被 Base64 编码并包含在重定向 URL 中:
https://target-site.com/callback?sso=<base64_payload>&sig=<hmac_signature>

解码 base64 有效负载会以纯文本形式显示电子邮件地址。

影响

  1. 浏览器历史记录:电子邮件记录在浏览器历史记录中
  2. Nginx 日志:完整的 URL 会记录在 nginx 访问日志中
  3. 目标站点日志:依赖方在未经用户明确同意的情况下接收到电子邮件
  4. 用户预期:用户通常授权是为了证明“我是合法用户”——他们不希望自己的电子邮件被共享

预期行为

用户应该能够控制是否与依赖方共享其电子邮件。应该有一个配置选项,类似于 discourse_connect_overrides_groupsdiscourse_connect_overrides_avatar 等。

目前没有站点设置可以禁用此行为。编写插件来覆盖此行为是可能的,但并非理想选择。

重现步骤

  1. 启用 enable_discourse_connect_provider
  2. 配置 discourse_connect_provider_secrets(例如,*.example.com|secret123
  3. 让用户通过 DiscourseConnect 提供商进行身份验证
  4. 检查 302 重定向 URL - 电子邮件在 URL 参数中可见

重定向 URL 如下所示:
https://relying-party.com/sso?sso=nonce=xxx&sig=xxx

解码 sso 参数显示:
nonce=xxx&return_sso_url=xxx&email=user@example.com&external_id=123

环境

  • Discourse 版本:(最新)
  • 自托管

可能的修复建议

  1. 添加一个站点设置,如 discourse_connect_provider_includes_email(默认为 true 以向后兼容),以控制是否在响应中包含电子邮件
  2. 或者,实现基于 POST 的回调而不是 GET 302 重定向,以避免 URL 日志记录
1 个赞

那不也是用共享密钥加密的吗?

1 个赞

您好,Falco,

HMAC 签名仅确保载荷未被篡改——它不会加密数据。Base64 是编码,不是加密,因此任何人都可以对其解码以读取内容。

核心问题是:我们不希望向“使用 Discourse 进行 SSO 登录的第三方网站”泄露不必要的用户信息(如电子邮件)。用户授权只是为了证明“我是一个合法用户”——他们不希望自己的电子邮件被共享。

一个控制是否返回电子邮件的站点设置是否可以接受?

我很好奇,实现了我们自定义 SSO 协议的下游第三方是什么?

我会说这是一个 pr-welcome,只要它不是默认设置,这样我们就不会破坏现有的站点。

感谢您的反馈!

为了给您提供一些关于用例的背景信息:我们的论坛是一个“校园论坛”,一名学生为其他学生建立了一个免费网站供他们使用。他们希望使用我们基于 Discourse 的校园论坛来验证用户是否确实是我们学校的学生——本质上是证明“我是这里的合法学生”。

在这种情况下,外部网站只需要知道“这是一个来自我们校园论坛的有效用户”——他们不一定需要用户的电子邮件,因为电子邮件是敏感信息,不应不必要地共享。

我将着手处理一个拉取请求(PR),以添加一个站点设置来控制此行为,默认设置将保持对现有安装的向后兼容性。

2 个赞