System.Security.Principal.WindowsIdentity的使用是否合理安全?

时间:2015-11-06 09:43:34

标签: c# .net security

System.Security.Principal.WindowsIdentity 是否合理安全不被黑客攻击,以便我从Thread.CurrentPrincipalIdentityWindowsIdentity.GetCurrent()获得{{}}的实例1}} true为我的集会提供虚假身份信息?当然,没有什么是完全防篡改的,但鉴于微软对.Net的承诺和依赖,我希望像这样的关键API Locked Down Hard 并且难以篡改。这对我来说是一个有效的假设吗?

我的目标是在我的程序集中提供合理的最佳实践SSO。如果Windows本身受到了损害,那是我无法控制的,但是如果(例如)对于链接到我的程序集的应用程序而言,这是一个直接的问题,以便向我提供虚假信息,那就是因为我没有做尽职调查。这对我来说是一个无知的大区域。

要明确的是,我正在寻找难以获得的信息,而不是袖手旁观。所以,已发布的漏洞利用,或以一种欺骗我的代码的方式展示了IsAuthenticated构造函数的使用等。或者在“那是一个有效的假设”方面,支持它的固体文章,已知的用途依赖于它,我找到它们并没有太多运气,但我已经把我在目前为止在分频器下面找到的内容包括在内。

以下是我打算如何使用WindowsIdentity

WindowsIdentity

这是在一个DLL程序集中 - 遗憾的是我们停留在.Net 3.5上 - 为可能受用户权限限制的资源提供公共API。它可能在桌面应用程序中使用,或者在使用Windows身份验证的ASP.Net IIS应用程序中使用(ASP.Net在使用Windows身份验证时在using System.Security.Principal; using System.Threading; // ... // I only want Windows-authenticated users WindowsIdentity identity = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.Identity as WindowsIdentity; SecurityIdentifier sid; // I can't imagine how an authenticated account would be anonymous, but... if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { // SSO success from thread identity sid = identity.User; // ...check that that SID is allowed to use our system... } else { identity = WindowsIdentity.GetCurrent(); if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { // SSO success from current Windows user sid = identity.User; // ...check that that SID is allowed to use our system... } else { // SSO fail } } 上设置WindowsIdentity实例;我们不支持其他类型的IIS目前正在认证。

我是否可以合理地信任那些声称要经过身份验证的来自Thread.CurrentPrincipal.Identity实例的SID?

我不想知道这是否合适( doh!),直到this question用户lc.提出一个问题,即程序集容易受到影响被与之链接的恶意应用程序欺骗并“伪造”该信息。他没有任何具体的证据来指出为什么这可能是一个重要的问题,因此,这个问题。

到目前为止,我发现了什么(小):

  • This answer提出索赔

      

    您可以相信当前的WindowsIdentity就是它所说的人,只要您可以信任您应用中的任何特定数据。

  • 本书Hacking the Code声称ASP.Net在进行文件授权检查时需要WindowsIdentity与请求相关联,如果为真,这似乎是说微软的相当坚实的基础,至少,认为它足够好。

  • 我可以找到很多人在他们的代码中愉快地使用WindowsIdentity信息的例子,但他们中的大多数都不会问他们是否安全。有一个暗示,但是......

1 个答案:

答案 0 :(得分:10)

你不能相信来自Thread.CurrentPrincipal的那个,没有。没有什么可以阻止代码通过欺骗来完全信任。

我能在这样的环境中欺骗它:

var admin = new WindowsIdentity(@"Administrator");
var princ = new WindowsPrincipal(admin);
System.Threading.Thread.CurrentPrincipal = princ;

...在调用代码之前。在我的计算机上,创建的WindowsIdentity对象的IsAuthenticatedtrueIsAnonymous为false,因此,当然,您的代码会提取我的域管理员的SID。

这在所有环境中都不起作用,但如果正在运行的代码具有足够的权限来使用反射,则应该这样做:

var ident = WindowsIdentity.GetCurrent();
Thread.CurrentPrincipal = new WindowsPrincipal(ident);
var userSid = ident.User;

var fakeSid = new SecurityIdentifier("S-1-3-0");

typeof (WindowsIdentity).GetField("m_user",
  BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ident, fakeSid);

(再次,在调用代码之前完成。)

基本上,没有什么可以阻止在同一个进程中在完全信任下运行的两段代码互相说谎。