客户端/服务器应用程序,如何在不将用户名/密码传输到远程系统的情况下,以域用户身份在远程系统上创建进程? [英] Client/Server app, how to create process on remote system as a domain user without transferring that users username/password to the remote system?

查看:133
本文介绍了客户端/服务器应用程序,如何在不将用户名/密码传输到远程系统的情况下,以域用户身份在远程系统上创建进程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个系统都在运行C#客户端/服务器软件代码.我想从计算机1作为计算机2上的给定Active Directory域用户创建一个进程,而不必让我的客户端/服务器软件将AD用户的纯文本用户名和密码从计算机1发送到计算机2.

I have two systems both running my C# client/server software code. I want to from Computer 1 create a process as a given Active Directory domain user on Computer 2 without having to have my client/server software send the plain text username and password of the AD user from Computer 1 to Computer 2.

我得到的最接近的信号似乎是我可以在计算机1上使用函数KerberosRequestorSecurityToken来生成kerberos票证,然后通过我的客户机/服务器代码将该byte []结果发送到计算机2,然后它应该能够对传递的byte [] kerberos票证调用KerberosReceiverSecurityToken.如果所有方法都起作用,则KerberosReceiverSecurityToken将具有WindowsIdentity属性,然后我可以使用该属性在计算机2上创建一个进程,该进程最初是通过KerberosRequestorSecurityToken流在计算机1上指定的用户帐户.

The closest I have gotten is it seemed like I could use the function KerberosRequestorSecurityToken on Computer 1 to generate a kerberos ticket and then send that byte[] result via my client/server code to Computer 2 where it should then be able to call KerberosReceiverSecurityToken against the byte[] kerberos ticket that was passed. If all that works then KerberosReceiverSecurityToken would have a WindowsIdentity property that I could then use to create a process on Computer 2 with the user account initially specified on Computer 1 via the KerberosRequestorSecurityToken flow.

相对于注册服务帐户SPN,我需要使用要模拟的现有域用户帐户.这是问题的症结所在,最初发布问题时我没有提到.

I need to use existing Domain User accounts that I want to impersonate vs. registering a service account SPN. This is the crux of the issue that I failed to mention when I originally posted the question.

我似乎无法使它工作,但更多,所以我什至不知道这是否真的可能-例如这些API是否应该允许我做我想做的事?

I cannot seem to get this to work but more so I do not even know if this is actually possible - e.g. should these APIs even allow me to do what I want?

用于生成kerberos票证的计算机1代码.其byte []结果通过我的客户端/服务器应用程序发送到计算机2.

Computer 1 code to generate kerberos ticket. The byte[] result of this is sent via my client/server app to Computer 2.

public static byte[] GetRequestToken(string userName, string password, string domain)
{
    using (var domainContext = new PrincipalContext(ContextType.Domain, domain))
    {
        using (var foundUser = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName))
        {
            Console.WriteLine("User Principal name" + UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName);
            string spn = UserPrincipal.FindByIdentity(domainContext, IdentityType.SamAccountName, userName).UserPrincipalName;
            KerberosSecurityTokenProvider k1 = new KerberosSecurityTokenProvider(spn, TokenImpersonationLevel.Impersonation, new NetworkCredential(userName, password, domain));
            KerberosRequestorSecurityToken T1 = k1.GetToken(TimeSpan.FromMinutes(1)) as KerberosRequestorSecurityToken;
            var req = T1.GetRequest();
            return req;
        }
    }
}

计算机2拿到了得到的byte [] kerberos票证,并试图接收它来访问WindowsIdentity,但它抛出异常,表明登录无效.

Computer 2 takes that resulting byte[] kerberos ticket and attempts to recieve it to access a WindowsIdentity but it throws an exception saying invalid logon.

KerberosReceiverSecurityToken receiverToken = new KerberosReceiverSecurityToken(requestToken);
byte[] receiverTokenTicket = receiverToken.GetRequest();

//Identity for impersonation
var impersonatedIdentity = receiverToken.WindowsIdentity;

推荐答案

第一段代码的来源在功能上是错误的. SPN必须是接收票证的目标,而不是请求票证的用户.因此,您需要执行以下操作...

The origin of the first block of code is functionally wrong. The SPN must be the target receiving the ticket, not the user requesting the ticket. So you need to do the following things...

  1. 在AD中注册服务主体帐户(用户/计算机).
  2. 将服务主体名称添加为格式为foo/host.domain.com的帐户,其中foo是您的服务名称,例如httphostmyapp.
  3. 客户需要申请前往foo/host.domain.com
  4. 的门票
  5. KerberosReceiverSecurityToken应该解析 票证
  1. Register a service principal account (user/computer) in AD.
  2. Add a service principal name to that account of the form foo/host.domain.com where foo is your service name, e.g. http or host, or myapp.
  3. Client needs to request a ticket to foo/host.domain.com
  4. KerberosReceiverSecurityToken should parse that ticket

现在,您具有一些不同的模拟级别身份.该模拟级别决定了您是否可以以该用户身份启动进程.碰巧的是……您不能,因为那不是Windows安全性的工作方式.因为您要模拟用户,所以您具有模拟NT令牌,而您需要一个主NT令牌才能启动进程.

Now you have an identity of some varying impersonation level. That impersonation level dictates whether you can start a process as that user. As it happens... you just can't because that's not how Windows security works. You have an impersonation NT token since you're impersonating a user, whereas you need a primary NT token to start processes.

因此,您需要使用 DuplicateTokenEx ,您实际上需要成为SYSTEM来做到这一点.

So you need to convert that to a primary token using DuplicateTokenEx, and you effectively need to be SYSTEM to do that.

一旦有了主要令牌,就可以调用

Once you have the primary token you can call CreateProcessAsUser.

此时,您可能已经以用户身份启动了该过程,但是它没有任何凭据可以访问其他网络属性,例如网络共享或Web服务.您可以在服务主体上启用约束委派,以便对此进行任何下游服务.

At this point you might have started the process as the user, but it doesn't have any credentials to reach other network properties like network shares or web services. You can enable constrained delegation on the service principal to any downstream services for that.

另一种选择,也许是更安全,更容易的选择,而是以低特权用户身份启动工作进程,并告知 该进程要模拟.请参阅此答案

An alternative, and probably safer and easier, option is instead to start a worker process as a low privilege user and tell that process to impersonate. See this answer for more information on that.

这篇关于客户端/服务器应用程序,如何在不将用户名/密码传输到远程系统的情况下,以域用户身份在远程系统上创建进程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆