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

时间:2015-11-06 18:58:22

标签: c# .net authentication

TL; DR WindowsIdentity的{​​{1}}属性(例如,Token)中包含的用户令牌是否可以欺骗:

someIdentity.Token

...将返回一个声称代表用户的实例,该用户实际上未经过身份验证,但var validated = new WindowsIdentity(someIdentity.Token); 设置IsAuthenticated,有效true和{{ 1}}属性等?

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

全文:

this answer中,Damien_The_Unbeliever巧妙地证明了我的某些代码可能会被误认为它在.Name实例中有一个有效的经过身份验证的用户。长话短说,我的代码假设如果.UserWindowsIdentity的实例且Thread.CurrentPrincipal.IdentityWindowsIdentity,那么它代表了经过身份验证的用户,我可以依赖于SID在IsAuthorized

true

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

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

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....
}

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

因此,在真正的军备竞赛方式中,这是我修改后的代码,它会抓住恶搞并否认它:

WindowsIdentity.GetCurrent()

如您所见,它从提供的标识中获取var ident = WindowsIdentity.GetCurrent(); Thread.CurrentPrincipal = new WindowsPrincipal(ident); var fakeSid = new SecurityIdentifier("S-1-3-0"/* E.g., 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); ,并使用该标记创建 new 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.... } } 实例。如果身份的SID匹配,我们继续,信任经过验证的身份。 (documentation for WindowsIdentity(IntPtr token)表示Token的初始值为WindowsIdentity,但在我的测试中这是错误的,假设我使用有效的用户令牌创建了它。)

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

边界

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

1 个答案:

答案 0 :(得分:7)

为了证明这是可行的,让我们使用名为" Microsoft Fakes"的一个很酷的Visual Studio插件。 (名称本身意味着很多......)。

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

这是您在图书馆项目中的代码(我在各地都使用了异常,因为它在测试条件方面更容易......)。

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中的项目布局:

enter image description here

还要确保修改自动生成的mscorlib.fakes文件:

<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true" TargetFrameworkVersion="v4.6">
  <Assembly Name="mscorlib" />
  <ShimGeneration>
    <Clear />
    <Add Namespace="System.Security.Principal" />
  </ShimGeneration>
</Fakes>

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

现在,当你运行测试时,这就是你所看到的:

enter image description here

好的,在您的特定场景中,我可能无法使用假货,但它所依赖的基础技术只是重新路由所有API(它实际上低于.NET,它被称为{ {3}})我相信并允许所有这些hackery。

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

相关问题