Windows C# Is there a way to create a new process with the Kerberos ticket of parent process?

元气小坏坏 提交于 2019-12-11 08:47:10

问题


I'm able to create a new process via CreateProcessAsUser from code I found here: https://odetocode.com/blogs/scott/archive/2004/10/28/createprocessasuser.aspx

It works fine, but the new process does not contain the Kerberos ticket of the new user which was impersonated by IIS Asp.net Impersonation. I know IIS has the Kerberos ticket, I just don't know programmatic how to get it from from the parent worker process to the new process I spawn which invokes OpenSSH.

Edit: Updated Impersonation block with DupliateHandlers function as mentioned by @Steve

var CurrentIdentity = ((WindowsIdentity)User.Identity).Token;
            IntPtr parentHandle = IntPtr.Zero;

            QuerySecurityContextToken(ref CurrentIdentity, out parentHandle);


            using (WindowsImpersonationContext impersonationContext = ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate())
            {
                IntPtr childHandle = CreateProcessAsUser();

                IntPtr lpTargetHandle = IntPtr.Zero;

                if (CloneParentProcessToken.DuplicateHandle(parentHandle, null, childHandle, out lpTargetHandle,
                    null, true, DuplicateOptions.DUPLICATE_SAME_ACCESS, ) > 0)
                {
                    if(ImpersonateLoggedOnUser(lpTargetHandle))
                    {

                    }
                }


                impersonationContext.Undo();
            }

private void CreateProcessAsUser()
    {
        IntPtr hToken = WindowsIdentity.GetCurrent().Token;
        IntPtr hDupedToken = IntPtr.Zero;

        ProcessUtility.PROCESS_INFORMATION pi = new ProcessUtility.PROCESS_INFORMATION();

        try
        {
            ProcessUtility.SECURITY_ATTRIBUTES sa = new ProcessUtility.SECURITY_ATTRIBUTES();
            sa.Length = Marshal.SizeOf(sa);

            bool result = ProcessUtility.DuplicateTokenEx(
                  hToken,
                  ProcessUtility.GENERIC_ALL_ACCESS,
                  ref sa,
                  (int)ProcessUtility.SECURITY_IMPERSONATION_LEVEL.SecurityIdentification,
                  (int)ProcessUtility.TOKEN_TYPE.TokenPrimary,
                  ref hDupedToken
               );

            if (!result)
            {
                throw new ApplicationException("DuplicateTokenEx failed");
            }


            ProcessUtility.STARTUPINFO si = new ProcessUtility.STARTUPINFO();
            si.cb = Marshal.SizeOf(si);
            si.lpDesktop = String.Empty;

            result = ProcessUtility.CreateProcessAsUser(
                                 hDupedToken,
                                 null,
                                 "powershell.exe -Command SSHCommand.ps1",
                                 ref sa, ref sa,
                                 true, 0, IntPtr.Zero,
                                 @"C:\", ref si, ref pi
                           );

            if (!result)
            {
                int error = Marshal.GetLastWin32Error();
                string message = String.Format("CreateProcessAsUser Error: {0}", error);
                throw new ApplicationException(message);
            }
        }
        finally
        {
            if (pi.hProcess != IntPtr.Zero)
                ProcessUtility.CloseHandle(pi.hProcess);
            if (pi.hThread != IntPtr.Zero)
                ProcessUtility.CloseHandle(pi.hThread);
            if (hDupedToken != IntPtr.Zero)
                ProcessUtility.CloseHandle(hDupedToken);
        }
    }

}

public class ProcessUtility
{
    [StructLayout(LayoutKind.Sequential)]
    public struct STARTUPINFO
    {
        public Int32 cb;
        public string lpReserved;
        public string lpDesktop;
        public string lpTitle;
        public Int32 dwX;
        public Int32 dwY;
        public Int32 dwXSize;
        public Int32 dwXCountChars;
        public Int32 dwYCountChars;
        public Int32 dwFillAttribute;
        public Int32 dwFlags;
        public Int16 wShowWindow;
        public Int16 cbReserved2;
        public IntPtr lpReserved2;
        public IntPtr hStdInput;
        public IntPtr hStdOutput;
        public IntPtr hStdError;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct PROCESS_INFORMATION
    {
        public IntPtr hProcess;
        public IntPtr hThread;
        public Int32 dwProcessID;
        public Int32 dwThreadID;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SECURITY_ATTRIBUTES
    {
        public Int32 Length;
        public IntPtr lpSecurityDescriptor;
        public bool bInheritHandle;
    }

    public enum SECURITY_IMPERSONATION_LEVEL
    {
        SecurityAnonymous,
        SecurityIdentification,
        SecurityImpersonation,
        SecurityDelegation
    }

    public enum TOKEN_TYPE
    {
        TokenPrimary = 1,
        TokenImpersonation
    }

    public const int GENERIC_ALL_ACCESS = 0x10000000;
    public const int TOKEN_ASSIGN_PRIMARY = 0x0001;

    [
       DllImport("kernel32.dll",
          EntryPoint = "CloseHandle", SetLastError = true,
          CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)
    ]
    public static extern bool CloseHandle(IntPtr handle);

    [
       DllImport("advapi32.dll",
          EntryPoint = "CreateProcessAsUser", SetLastError = true,
          CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)
    ]
    public static extern bool
       CreateProcessAsUser(IntPtr hToken, string lpApplicationName, string lpCommandLine,
                           ref SECURITY_ATTRIBUTES lpProcessAttributes, ref SECURITY_ATTRIBUTES lpThreadAttributes,
                           bool bInheritHandle, Int32 dwCreationFlags, IntPtr lpEnvrionment,
                           string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo,
                           ref PROCESS_INFORMATION lpProcessInformation);

    [
       DllImport("advapi32.dll",
          EntryPoint = "DuplicateTokenEx")
    ]
    public static extern bool
       DuplicateTokenEx(IntPtr hExistingToken, Int32 dwDesiredAccess,
                        ref SECURITY_ATTRIBUTES lpThreadAttributes,
                        Int32 ImpersonationLevel, Int32 dwTokenType,
                        ref IntPtr phNewToken);
}

回答1:


This should be a comment but I cannot add comments. I do not know if it makes any difference but I think your STARTUPINFO structure is missing an element dwYSize after dwXSize



来源:https://stackoverflow.com/questions/57379058/windows-c-sharp-is-there-a-way-to-create-a-new-process-with-the-kerberos-ticket

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!