没有明文密码的 Exchange Web 服务服务器到服务器身份验证?

Exchange Web Services server-to-server authentication without plaintext password?

我正在构建一个运行自动化流程的服务器应用程序,该流程需要与 Exchange 服务器兼容至 2007 版。我目前通过 Azure AD 使用 OAuth 进行 Office 365 连接,但我仍在尝试寻找一个2013 年之前的本地 Exchange 解决方案。

我一直在阅读有关 Exchange 身份验证(基本、NTLM 等)的信息,但我似乎找不到任何对允许我设置一次性使用身份验证的长期令牌系统的引用密码。我 非常强烈地宁愿不 将用户密码存储在中央数据库中,加密与否,因为它是一个巨大的安全责任,并且可以被逆向工程。

有什么我遗漏的吗?

有没有办法每次都无需密码即可对 Exchange 进行身份验证?

恐怕不会。连接将需要本地服务器的密码。

回答我自己的问题作为后续行动,因为我对一些回复不满意 and/or 我通过广泛搜索找到的内容。

在对 Exchange 服务器、它们的身份验证方式以及支持和使用的协议进行大量研究后,我发现了我认为最好的选择:NTLM

现在,让我解释一下。

我试图实现的目标如下:

  • 能够向 Exchange 2007+ 服务器进行身份验证
  • 通过初始过程
  • 进行身份验证 "one-time-setup"
  • 切勿存储纯文本密码(尤其是在 platform/service 中央数据存储中)

考虑到这些要点:

  • 我无法使用 "Basic" 身份验证,因为它需要将用户密码以纯文本形式存储在中央数据存储中
  • OAuth 不起作用,因为它仅在 Exchange 2013+ 上受支持

这样一来,我真的只剩下 NTLM 了。不幸的是,我知道 NTLM 在其多年的历史遗留下来的安全漏洞中有着一段艰难的历史,但我更深入地研究它,看看它是否能够以某种方式满足我的要求。

不幸的是,NTLM 在其规范方面长期以来一直保持着 "secret" 的一点。这是专有规范,因此不幸的是,有关其内部结构的信息很少见。长期以来,有关 NTLM 规范信息的唯一真正来源实际上是 info that was reverse-engineered (thanks Eric Glass!). Thankfully, though, Microsoft did finally start to publish documentation on NTLM on their MSDN site more recently.

在仔细研究了协议之后,运行 在测试 Exchange 服务器上以许多不同的配置排列进行了一些测试之后,我意识到 NTLM 实际上可以满足我的所有要求。如何?好吧,由于协议的工作方式,一旦凭证被散列(以规范 [LM, NTv1, NTv2] 中可能的 3 种方式之一),它 不需要为相同的目标再次散列 。这意味着,类似于对典型注册机制的用户密码进行哈希处理,您可以简单地预先询问 Exchange/NTLM 凭据,然后对凭据进行一次哈希处理。


注意!!!有个问题!

请记住,能够对凭证进行一次哈希处理并多次使用它意味着哈希有点像 "password equivalent"。我的意思是,一旦知道散列值,它就可以像密码一样使用 ,因为它是将来验证所需的唯一信息之一。 (这通俗地称为 "pass-the-hash")。

然而,考虑到以纯文本形式存储密码的替代方案,这仍然要好得多。为什么?因为至少您没有存储可以在 任何 其他身份验证方案中使用的原始凭据,也没有泄露可能在其他环境中共享的密码(是的,不幸的是人们确实这样做了).

鉴于这些知识,在存储这些散列凭据时仍应格外小心。最后,如果可以使用其他更强大的身份验证方案,请使用它。


因此,由于 NTLM 协议的工作方式,它符合要求:

  • 能够向 Exchange 2007+ 服务器进行身份验证
    • NTLM 可用于所有 Exchange 服务器 2007+
  • 通过初始过程进行身份验证 "one-time-setup"
    • 凭据和目标只需输入一次,因为一旦与服务器进行了初始握手,您就会知道身份验证方案有效。 (这当然没有考虑到远程 Exchange 服务器的配置可以随时更改。所以正确的错误处理仍然非常到位)
  • 永远不要存储纯文本密码(特别是在 platform/service 中央数据存储中)
    • 改为存储散列凭据。但是,由于 "catch" 在前面的说明中解释过,因此应该非常小心,使用潜在的双重加密技术。

无论如何,我希望其他人能在某个时候找到它,这样他们就不必像我那样做那么多的规范阅读和实验。

此外,就其价值而言,我注意到 NTLM 的开源实现不仅很少见,而且更常见的是只完成了一半,我的团队在 PHP 中开源了我们的 NTLM 实现. It's available on GitHub.