使用System.Security.Principal.WindowsIdentity是否合理安全
本文关键字:安全 是否 WindowsIdentity System Security Principal 使用 | 更新日期: 2023-09-27 18:20:45
System.Security.Principal.WindowsIdentity
是否合理地防止被黑客攻击,从而使我从Thread.CurrentPrincipal
的Identity
或WindowsIdentity.GetCurrent()
获得的实例(其中true
用于IsAuthenticated
)为我的程序集提供虚假身份信息?当然,没有什么是完全防篡改的,但考虑到微软对.Net的承诺和依赖,我预计像这样的关键API会被严格锁定,很难被篡改。这对我来说是一个有效的假设吗?
我的目标是在我的程序集中提供合理的最佳实践SSO。如果Windows本身被泄露,那就超出了我的控制范围,但如果(例如)一个与我的程序集链接的应用程序向我提供虚假信息是一件简单的事情,那将是我没有尽职调查的责任。这对我来说是一个很大的无知领域。
需要明确的是,我在寻找确凿的信息,而不是即兴的意见。因此,以欺骗我的代码的方式发布了对WindowsIdentity
构造函数的利用或演示使用;这是一个有效的假设;侧面,支持它的坚实文章,依赖它的已知用途,等等。我没有很幸运地找到它们,但我已经在分隔符下面列出了我迄今为止发现的内容。
以下是我打算如何使用WindowsIdentity
:
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
}
}
这是在一个DLL程序集中-遗憾的是,我们被困在.Net 3.5上-它为可能受到用户权限限制的资源提供了一个公共的API。它可能用于桌面应用程序,或具有Windows身份验证的ASP.Net IIS应用程序(ASP.Net在使用Windows身份验证时在Thread.CurrentPrincipal.Identity
上设置WindowsIdentity
实例;我们目前不支持其他类型的IIS身份验证)。
我可以合理地信任那些声称通过身份验证的来源的WindowsIdentity
实例的SID吗?
我没有想到这是否可以(doh!),直到在这个问题中,用户lc.提出了一个问题,即程序集很容易被与其链接的恶意应用程序欺骗;伪造的";这些信息。不过,他没有任何具体的证据来说明为什么这可能是一个重大问题,因此提出了这个问题。
到目前为止,我发现了什么:
这个答案使索赔
只要您可以信任应用程序中的任何给定数据,您就可以信任当前的
WindowsIdentity
。《破解代码》一书声称,ASP.Net在进行文件授权检查时需要将
WindowsIdentity
与请求关联起来,如果这是真的,这似乎是一个相当坚实的基础,可以说微软至少认为它足够好。我可以找到很多人在代码中愉快地使用
WindowsIdentity
信息的例子,但他们中的大多数人都不会问它们是否安全。有一个含义,但是。。。
你不能信任Thread.CurrentPrincipal
中的那个。没有什么可以阻止完全信任运行的代码欺骗它。
我可以在我的环境中这样欺骗它:
var admin = new WindowsIdentity(@"Administrator");
var princ = new WindowsPrincipal(admin);
System.Threading.Thread.CurrentPrincipal = princ;
在调用代码之前。在我的机器上,创建的WindowsIdentity
对象的IsAuthenticated
为true
,IsAnonymous
为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);
(同样,在调用代码之前完成。)
基本上,没有什么可以阻止同一进程中在完全信任下运行的两段代码相互撒谎。