【问题标题】:Secure windows Impersonation?安全的 Windows 模拟?
【发布时间】:2014-10-28 01:37:42
【问题描述】:

在我的 WPF 应用程序中,我想允许管理员使用集成安全性为各种其他用户测试数据库连接。所以我有一个表单,允许管理员输入域、用户名和密码,然后进行测试。我能够安全地处理密码,直到我在 advapi32.dll 中调用 LogonUser,这需要 string password

LogonUser(UserName, Domain, Password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref UserHandle)

我编写了一个实用函数,它将 SecureString 转换为尽可能安全的字符串,然后我在 LogonUser 调用中使用密码调用它:

LogonUser(UserName, Domain, Helper.ConvertSafely(Password), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref UserHandle)

由于 LogonUser 的签名采用字符串,除非 LogonUser 在执行过程中妥善保管密码,否则在调用返回后,它仍可能以纯文本形式存在于我的调用堆栈中。有没有更安全的方式来模拟用户,我可以确信 PW 始终是安全的?

基本上我只需要一个WindowsImpersonationContext,但我想在没有纯文本密码的情况下获取它。

【问题讨论】:

  • 我已经编辑了你的标题。请参阅“Should questions include “tags” in their titles?”,其中的共识是“不,他们不应该”。
  • 好问题,实际上。但是,如果您真的关心安全性,那么我建议您也考虑非技术性安全漏洞:您的管理员不得也不需要任何关于您用户密码的知识。您正在创建用户名/密码屏幕这一事实表明管理员将输入用户凭据。这对我来说似乎很错误。 (如果不是管理员,而是用户自己,填写他们的凭据,那么首先RUNAS他们自己登录下的应用程序,你不需要做模拟。)
  • 原始表单输入字段不会使用常规字符串吗?此外,您可能有兴趣使用我的SimpleImpersonation 库简化您的LogonUser 代码,如here 所述。虽然我也不在那里使用SecureString
  • @stakx 服务将使用该连接进行连接,因此管理员应该拥有运行该服务的用户的凭据。然而,管理员在配置连接时将在他自己的用户上下文下运行。
  • 如果您要模拟的用户未登录机器(例如在另一个会话中),您必须向 LogonUser 提供密码(在堆栈中,在内存中)以进行标准身份验证包。因此,如果您真的想要模拟,则必须在某个地方传递密码。 (如果他在这里登录是一个答案:stackoverflow.com/questions/8304398/…)。否则,请确保您为此使用 postlagerkarte 的示例链接代码。你真的不能做得更多。

标签: c# wpf security impersonation


【解决方案1】:

在您的托管应用程序中,您可以使用 SecureString 类来处理敏感信息。通常不需要推出自己的安全字符串机制。

就在您进入 LogonUser 之前,您将传递非托管副本 SecureString 密码。为此,您使用 Marshal.SecureStringToGlobalAllocUnicode 方法。因此,您的应用程序域中永远不会有代表密码的托管对象。

您可以在this 文章中找到示例代码。

如果您需要更高的安全性,我建议您禁止 wpf 客户端直接连接数据库。您可以引入中间层。因此,安全性从客户端转移到了这台服务器。客户端和应用服务器之间的通信是加密的,只有应用服务器与数据库对话。

【讨论】:

  • 这正是我正在做的,我只是担心 LogonUser 调用会将不安全的密码留在我无法控制的堆栈上。
  • 是的,你是对的。你可能想在你的问题中更清楚。始终可以在 API LogonUser 条目上设置断点并转储调用堆栈。所以问题更多的是围绕本机 LogonUser 函数。
  • 我不确定我能否让问题更清楚,我试过了。但是是的,问题在于非托管代码 LogonUser,如果有更安全的方法来获取 WindowsImpersonationContext 而不必担心非托管代码如何处理密码,它似乎以纯文本形式使用密码。跨度>
【解决方案2】:

更新:

您可以实现一个加密的app.config。您可以通过几种不同的方法做到这一点:

因此,这是如何工作的,当管理员插入凭据时,您将解密 app.config 使用新凭据修改 key/value。然后一旦插入它就会再次加密配置文件。

因此它的暴露程度最低,但数据也是通过封装插入的,这也有助于隐藏它。

这是一种方法,尽管 SecureString 会起作用,但它需要 char[]。在某些情况下,通过advapi32.dll 连接时可能并不理想。

【讨论】:

  • 我很困惑。加密凭据如何从配置传递给 LogonUser?
  • 我的代码中的安全性不是问题,密码存储在 SecureString 中,当我调用非托管代码 LogonUser 时,它使用的是纯文本密码。
  • @user1336827 所以非托管代码实际上是在纯文本中调用它?
  • LogonUser 的签名采用字符串: public static extern bool LogonUser(string pszUsername, string pszDomain, string pszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);我正在使用函数调用中建议的 Postlagerkarte 方法转换secureString
【解决方案3】:

如果您要模拟的用户已经登录机器(例如在另一个会话中),这里是一个答案:Is it possible for a Windows service impersonate a user without a password?

如果不是,您必须向 LogonUser 提供密码。并且此密码必须至少在内存中驻留一小段时间,因为这是定义 LogonUser 的方式。请注意,并非所有身份验证包都需要密码(如生物识别或智能卡:Windows Authentication Overview)。

因此,如果您真的想要模拟,则必须在某个地方传递密码。在这种情况下,请确保您使用 Microsoft 的 postlagerkarte 代码:Marshal.SecureStringToGlobalAllocUnicode Method sample code

你真的不能做更多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-05
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 2011-11-29
    • 2013-03-09
    相关资源
    最近更新 更多