我们注意到我们的人力资源系统存在一个问题,用户请求请假,此批准会发送给他们的经理,当他们的经理单击链接以批准它时,他们会看到一条错误消息,说明请假已获批准......这似乎是因为Outlook向HR系统的approval URI发送GET请求,以检查链接是否恶意;但在这样做时,它批准了员工的休假。注意:此 GET 请求甚至在电子邮件被预览之前发送/不是由收件人用户的任何操作触发。
人力资源系统是第三方,支持不力,所以他们无法证实我们对发生的事情的理论......但是,我已经通过从包含链接的外部电子邮件地址发送邮件进行测试我支持的网站(但不在 Outlook 的已验证域列表中)。查看我服务器上的日志,我看到在这封测试邮件到达我的邮件客户端后的片刻(我没有点击链接,甚至没有预览邮件的内容),果然一个 GET 请求出现在我的日志中,来自一个属于MS(根据 IP 上的 whois)。
这看起来很糟糕......但是我们与其他具有单击链接的系统一起工作(用于批准,以及许多包含unsubscribe
链接或verify my email
单击即可工作的链接/不需要手动跟进的电子邮件)和我们似乎没有类似的问题;在所有这些情况下,网站所有者似乎不太可能将与 SafeLinks 相关联的 MS IP 列入黑名单(尤其是好像它很容易绕过一样,恶意行为者也可以使用这种技巧来躲避安全链接保护)。
- 我们关于 SafeLinks 导致批准的理论可能是正确的吗?
- 如果是这样,是否有一些解释为什么它没有影响更多系统?
尽管“安全链接”导致的问题多于解决的问题有多种原因,但这也是人力资源系统中的设计缺陷和漏洞:
这样的操作应该需要身份验证,即具有操作所需权限的用户应该登录。“安全链接”不是来自经过身份验证的会话。它可以属于以下任何类别:
CWE-306:缺少关键功能的身份验证
CWE-862:缺少授权
CWE-749:暴露的危险方法或功能
即使链接有随机部分,它也不够强大,因为链接很容易泄漏或被猜测。
CWE-1390:弱认证
系统不应该根据单个
GET
请求执行批准或拒绝操作,但链接页面应该,例如,具有按钮以通过单独的POST
请求确认所需的操作。这甚至在 HTTP 语义、RFC 9110、9.2.1中被推荐:
请将此漏洞报告给软件供应商。
这违反了相关技术规范和最佳实践。
来自 RFC7231:
根据相同的标准,Get 是一个安全、幂等的请求。根据标准明确允许Outlook 执行的操作:
您的 HR 应用已损坏,应该更新。
经过更多的实验,我想我找到了原因。
没有问题的 URI 都包含查询字符串;我们有问题的那个没有。
将测试发送到https://example.com/approve?try=this而不是在我的站点日志中看到返回的确切 URI,我看到请求
GET
已发送到https://example.com/approve?try=bcce;即查询字符串中名称-值对的值部分被替换为垃圾值。也就是说,这种行为在我的测试中并不一致/我不确定 MS 在何时替换值和何时离开它们方面遵循什么规则。似乎其他人以前也遇到过这个问题;这个线程有很多很好的讨论。
从客户端的角度来看,最好的解决方法是将 URL 列入白名单,这样 SafeLinks 就不会扫描它。MS Docs中的更多信息。