简体   繁体   English

Windows假冒:美中不足的一个缺陷

[英]Windows Impersonation: A Flaw in the Ointment

In my journey to master the nuances of user impersonation in Windows I first had an issue about getting impersonation to a remote database to occur at all (see this SO question ) but I finally figured that out. 在我掌握Windows中用户模仿的细微差别的过程中,我首先遇到了一个关于冒充远程数据库的问题 (请参阅此SO问题 ),但我终于明白了。 My next hurdle is undoing/cancelling/reverting (choose your favorite verb) impersonation. 我的下一个障碍是撤消/取消/恢复(选择你最喜欢的动词)模仿。

I have tried a couple different impersonation libraries that seem credible to me: 我尝试了几个不同的模拟库,这对我来说是可信的:

The results are identical with both libraries. 结果与两个库相同。 Best practices dictate using the LOGON32_LOGON_NEW_CREDENTIALS logon type (see the Windows API LogonUser function ) for a remote DB connection. 最佳实践要求使用LOGON32_LOGON_NEW_CREDENTIALS登录类型(请参阅Windows API LogonUser函数 )进行远程数据库连接。 When I do that here is what my sample code produces: 当我这样做时,这是我的示例代码产生的:

// SCENARIO A
BEGIN impersonation.
Local user = MyDomain\MyUser
DB reports: MyDomain\ImpersonatedUser
END impersonation.
Local user = MyDomain\MyUser
DB reports: MyDomain\ImpersonatedUser << NOT EXPECTED HERE!!

The only workaround I have found is to use the LOGON32_LOGON_INTERACTIVE logon type and then I get this: 我找到的唯一解决方法是使用LOGON32_LOGON_INTERACTIVE登录类型,然后我得到:

// SCENARIO B
BEGIN impersonation.
Local user = MyDomain\ImpersonatedUser << EXPECTED, BUT NOT WANTED!
DB reports: MyDomain\ImpersonatedUser
END impersonation.
Local user = MyDomain\MyUser
DB reports: MyDomain\MyUser

From the terse description of the WindowsImpersonationContext.Undo method it sure seems like it should have worked in Scenario A. WindowsImpersonationContext.Undo方法的简洁描述来看,它似乎应该在方案A中起作用。

Is it possible to revert using the LOGON32_LOGON_NEW_CREDENTIALS logon type? 是否可以使用LOGON32_LOGON_NEW_CREDENTIALS登录类型进行恢复?

Thanks to input from Harry Johnston (in comments attached to the question) and Phil Harding (in separate communication) I was able to determine that SQL Server connection pooling was the culprit here. 感谢Harry Johnston(在问题附带的评论中)和Phil Harding(在单独的通信中)的输入,我能够确定SQL Server 连接池是这里的罪魁祸首。 Since pooling is determined by uniqueness of the connection string, by slightly varying the connection string (eg reversing order of parameters within, or even just adding a space on the end) I then observed the behaviors I expected. 由于池是由连接字符串的唯一性决定的,通过稍微改变连接字符串(例如,在其中的参数的反转顺序,或者甚至只是在末尾添加空格),然后我观察了我期望的行为。

===== TEST WITH SAME CONN STRING: True
BEGIN impersonation
Local user: MyDomain\msorens
DB reports: MyDomain\testuser
END impersonation
Local user: MyDomain\msorens
DB reports: MyDomain\testuser <<<<< still impersonating !!

===== TEST WITH SAME CONN STRING: False
BEGIN impersonation
Local user: MyDomain\msorens
DB reports: MyDomain\testuser
END impersonation
Local user: MyDomain\msorens
DB reports: MyDomain\msorens  <<<<< this is what I wanted to get

I dug into the internals of the connection pooling, and it turns out that Windows credentials are not considered a part of the connection pooling key at all. 我挖到了连接池的内部,结果证明Windows凭据根本不被视为连接池密钥的一部分。 Only SQL logins would be taken into account. 只考虑SQL登录。

So if there is an available connection that was opened under user A and you are now impersonating user B, it will still use it and SQL will see you as user A. The reverse is also true. 因此,如果在用户A下打开了可用连接,并且您现在正在模拟用户B,它仍然会使用它,并且SQL会将您视为用户A.反过来也是如此。

The approach of changing the connection string slightly for the two different users is fine. 为两个不同的用户稍微改变连接字符串的方法很好。 You might do this if you have a "normal" user and then you need to impersonate for some "elevated" user. 如果您有一个“普通”用户,那么您可能会这样做,然后您需要冒充一些“提升”用户。 Of course, you don't want a different string for every user of your application - otherwise you might as well disable connection pooling completely. 当然,您不希望为应用程序的每个用户使用不同的字符串 - 否则您也可以完全禁用连接池。

When tweaking your connection string, you might consider appending the impersonated username to either the Application Name or Workstation ID fields. 调整连接字符串时,可以考虑将模拟的用户名附加到“ Application Name或“ Workstation ID字段。 This would have the benefit of setting up a separate pool for each impersonated user. 这样可以为每个模拟用户设置一个单独的池。

I have found that the login type LOGON32_LOGON_NETWORK_CLEARTEXT does not have a problem with connections being re-used across impersonation contexts and works as expected without varying the connection string. 我发现登录类型LOGON32_LOGON_NETWORK_CLEARTEXT没有在模拟上下文中重复使用连接的问题,并且在不改变连接字符串的情况下按预期工作。

According to this thread, the "cleartext" part of this login type seems to be local to the server. 根据这个帖子,这个登录类型的“明文”部分似乎是服务器的本地。 I only keep the token alive for the duration of the database query or set of queries, so the token is very short-lived. 我只在数据库查询或查询集的持续时间内保持令牌处于活动状态,因此令牌非常短暂。 Using this login type for long-lived tokens may or may not be a security risk. 对长期令牌使用此登录类型可能存在安全风险,也可能不存在安全风险。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM