是否有可能欺骗此WindowsIdentity代码使用错误的用户?

TL; DR可以欺骗WindowsIdentityToken属性(例如someIdentity.Token )中包含的用户令牌,以便:

 var validated = new WindowsIdentity(someIdentity.Token); 

…将返回一个声称代表用户的实例,该用户实际上已经过身份validation,但IsAuthenticated设置为true ,有效.Name.User属性等?

下面我对此进行了一些界定; 它可能不可能完全欺骗。


全文:

在这个答案中 , Damien_The_Unbeliever巧妙地certificate了我的一些代码可能被欺骗,相信它在WindowsIdentity实例中没有有效的身份validation用户。 简而言之,我的代码假设如果Thread.CurrentPrincipal.IdentityWindowsIdentity一个实例并且IsAuthorizedtrue ,它代表一个经过身份validation的用户,我可以依赖.User的SID:

 WindowsIdentity identity = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.Identity as WindowsIdentity; if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { // ...use and trust the SID in identity.User, the // username in identity.Name, etc.... } 

(这个代码使用线程而不是WindowsIdentity.GetCurrent()是有原因的。)

他的代码欺骗(稍加修改):

 var ident = WindowsIdentity.GetCurrent(); Thread.CurrentPrincipal = new WindowsPrincipal(ident); var fakeSid = new SecurityIdentifier("S-1-3-0"/* Eg, some SID you want to trick me into believing is the real user */); typeof(WindowsIdentity).GetField("m_user", BindingFlags.Instance | BindingFlags.NonPublic) .SetValue(ident, fakeSid); 

当然,如果你这样做,然后调用上面的代码,我的代码就会被愚弄。 Kudos Damien。

所以在真正的军备竞赛方式中,这是我修改后的代码,它可以捕获欺骗并拒绝它:

 WindowsIdentity identity = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.Identity as WindowsIdentity; if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { var validated = new WindowsIdentity(identity.Token); if (!validated.User.Equals(identity.User) || !validated.IsAuthenticated || validated.IsAnonymous) { // Something fishy is going on, don't trust it } else { // Good! Use the validated one identity = validated; // ...use and trust the SID in identity.User, the // username in identity.Name, etc.... } } 

如您所见,它从提供的标识中获取Token ,并使用该标记创建新的 WindowsIdentity实例。 如果身份的SID匹配,我们继续,信任经过validation的身份。 ( WindowsIdentity(IntPtr token)的文档说IsAuthenticated的初始值将为false ,但在我的测试中,假设我使用有效的用户令牌创建它,那就完全错了。)

我可以看到可以被欺骗的唯一方法是使用欺骗性的用户令牌,但仍然通过Windows对其进行的validation。 这对我来说似乎不太可能。 但是,这对我来说是一个无知的领域。


边界

我应该注意到,我只是在这里拍摄合理程度的单点登录安全性,尽我所能。 如果一个恶意应用程序已成功开始拦截系统调用/受到威胁的Windows本身,那么,我将无法做很多事情。 正如Damien在对其他问题的评论中指出的那样,他可能会构建一个完全忽略强命名的主机容器(因此可能会给我一个完全假的WindowsIdentity类型)。 很公平。 完美杀死。 我只是不想像Damien亲切地展示的那样打开门。 如果我发布了一个系统并且它很容易在现场被黑客攻击,那么我会非常尴尬。 🙂

为了certificate这是可行的,让我们使用名为“ Microsoft Fakes ”的酷炫Visual Studio插件(名称本身意味着很多……)。

伪造本身与Visual Studio的测试function有关,但它将certificate这一点。 您可以按照标准教程设置项目,并为System添加一个fakes程序集(实际上是mscorlib +系统)

这是你在库项目中的代码(我在各地都使用了exception,因为它在测试条件中更容易……)。

 namespace ClassLibrary1 { public class Class1 { public static void MyCheck() { WindowsIdentity identity = Thread.CurrentPrincipal == null ? null : Thread.CurrentPrincipal.Identity as WindowsIdentity; if (identity != null && identity.IsAuthenticated && !identity.IsAnonymous) { var validated = new WindowsIdentity(identity.Token); if (!validated.User.Equals(identity.User) || !validated.IsAuthenticated || validated.IsAnonymous) throw new Exception("Something fishy is going on, don't trust it"); else throw new Exception("Good! Use the validated one. name is:" + validated.Name); } else throw new Exception("not in"); } } } 

这是测试项目中的测试代码:

 namespace UnitTestProject1 { [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { using (ShimsContext.Create()) { System.Security.Principal.Fakes.ShimWindowsIdentity.AllInstances.NameGet = (i) => { return "Simon the hacker"; }; WindowsIdentity wi = WindowsIdentity.GetCurrent(); // this is the real one "Simon". Thread.CurrentPrincipal = new WindowsPrincipal(wi); Class1.MyCheck(); } } } } 

这是Visual Studio中的项目布局:

在此处输入图像描述

还要确保修改自动生成的mscorlib.fakes文件,如下所示:

        

这意味着我想要整个System.Security.Principal命名空间,我建议你为两个项目使用框架4.6并添加相应的TargetFrameworkVersion属性。

现在,当您运行测试时,您将看到以下内容:

在此处输入图像描述

好吧,在你的特定场景中,我可能无法使用假货,但它所依赖的底层技术只是重新路由所有API(实际上它比.NET低,它叫做Detours )我相信并允许所有这些hackery。

总结一下:如果它在我的机器上运行,我可以破解它(除非我没有物理访问我的机器)。