我们注意到我们的人力资源系统存在一个问题,用户申请休假,批准信息发送给经理,当经理点击链接批准时,他们会看到一个错误,提示休假已经批准...这似乎是因为 Outlook 向人力资源系统的批准 URI 发送了一个 GET 请求,以检查链接是否是恶意的;但这样做却批准了员工的休假。注意:这个 GET 请求甚至在预览电子邮件之前就发送了,并且不是由收件人用户的任何操作触发的。
HR 系统是第三方的,支持能力较差,所以他们无法确认我们的理论……但是,我通过从外部电子邮件地址发送邮件进行了测试,该邮件包含指向我支持的网站的链接(但不在 Outlook 的已验证域列表中)。查看我的服务器上的日志,我发现这封测试电子邮件到达我的邮件客户端后不久(我没有点击链接,甚至没有预览电子邮件的内容),果然,我的日志中出现了来自属于 MS 的 IP 的 GET 请求(根据 IP 上的 whois)。
这似乎很有说服力……但是我们使用了其他具有单击链接的系统(既用于批准,也用于许多包含unsubscribe
链接或verify my email
单击即可工作的链接/不需要手动跟进的电子邮件),我们似乎没有遇到类似的问题;并且似乎在所有这些情况下,网站所有者都不太可能将与 SafeLinks 关联的 MS IP 列入黑名单(特别是如果绕过它是如此简单,恶意行为者也可以使用这种技巧来躲避安全链接保护)。
- 我们关于 SafeLinks 导致批准的理论可能正确吗?
- 如果是这样,能否解释一下为什么它没有影响更多系统?
答案1
这似乎是因为 Outlook 向人力资源系统的批准 URI 发送了 GET 请求,以检查该链接是否是恶意的;但这样做却批准了员工的休假。
这违反了相关的技术规范和最佳实践。
如果请求方法的定义语义本质上是只读的,则认为这些方法“安全”;即,客户端不会请求、也不会期望将安全方法应用于目标资源后导致源服务器发生任何状态变化。同样,合理使用安全方法不会对源服务器造成任何损害、财产损失或异常负担。
根据相同的标准,Get 是一个安全的幂等请求。Outlook 所做的是明确地根据标准允许:
在本规范定义的请求方法中,GET、HEAD、OPTIONS 和 TRACE 方法被定义为安全的。
区分安全方法和不安全方法的目的是让自动检索过程(蜘蛛)和缓存性能优化(预取)能够正常工作,而不必担心造成损害。此外,它还允许用户代理在处理可能不受信任的内容时对不安全方法的自动使用施加适当的限制。
您的 HR 应用程序已损坏,需要更新。
答案2
尽管几个原因为什么“安全链接”造成的问题比它解决的问题还多,这也是人力资源系统的设计缺陷和漏洞:
此类行动应该需要身份验证即,具有操作所需权限的用户应登录。“安全链接”不是来自经过身份验证的会话。它可以属于以下任何类别:
-
该产品不会对需要可证明用户身份或消耗大量资源的功能执行任何身份验证。
-
当参与者试图访问资源或执行操作时,软件不会执行授权检查。
-
该软件提供了应用程序编程接口(API)或类似的接口用于与外部参与者交互,但该接口包含未得到适当限制的危险方法或功能。
即使链接有随机部分,也不够强大,因为链接很容易泄露或被猜测。
-
该产品使用身份验证机制来限制特定用户或身份的访问,但该机制不足以证明所声称的身份是正确的。
-
系统不应根据单个
GET
请求执行批准或拒绝操作,但链接页面应该有按钮来通过单独的POST
请求确认所需的操作。HTTP 语义中也推荐这样做,RFC 9110, 9.2.1:
9.2.1. 安全方法
如果请求方法的定义语义本质上是只读的,则认为请求方法“安全”;即,客户端不会请求、也不会期望将安全方法应用于目标资源后导致原始服务器上的任何状态改变。- -
在本规范定义的请求方法中,GET、HEAD、OPTIONS 和 TRACE 方法被定义为安全的。
区分安全方法和不安全方法的目的是让自动检索过程(蜘蛛)和缓存性能优化(预取)能够正常工作,而不必担心造成损害。此外,它还允许用户代理在处理可能不受信任的内容时对不安全方法的自动使用施加适当的限制。
请向软件供应商报告此漏洞。
答案3
经过进一步的实验后,我想我找到了原因。
没有问题的 URI 都包含查询字符串;而我们遇到问题的 URI 没有包含查询字符串。
发送测试至https://example.com/approve?try=this我没有在网站日志中看到返回的确切 URI,而是看到GET
请求被发送到https://example.com/approve?try=bcce;即查询字符串中的名称-值对的值部分被替换为垃圾值。也就是说,这种行为在我的测试中并不一致/我不确定 MS 在何时替换值以及何时保留值方面遵循什么规则。
似乎其他人之前也讨论过这个问题;此主题。
从客户端的角度来看,最好的解决方法是将 URL 列入白名单,这样 SafeLinks 就不会扫描它。更多信息微软文档。