locked
CreateProcessAsUser and Delegation RRS feed

  • Question

  •  I have a service running as 'NT AUTHORITY\SYSTEM'.  This service can call an external program.  However when the external program is called it also runs as SYSTEM.  That's no good.  I want it to run as a domain user that I specify.  I was able to accomplish this by calling LogonUser, DuplicateTokenEx and CreateProcessAsUser.  This works great, however I do not want a user password hard coded in the LogonUser call.  So I tried delegation.  The computer running this service is trusted for delegation to any service in the ADUC (see http://www.pluralsight.com/wiki/default.aspx/Keith.GuideBook/WhatIsProtocolTransition.html). 


    Below is my test:
    CMD = 'c:\test.bat'
    ARG = 'remotePCname'

    TEST.BAT contents:
    c:\windows\system32\sc.exe \\%1 stop spooler > log.txt

    First I tried running the RunProcAs function using the LogonUser call with a hardcoded password to obtain the token.  I passed the token to CreateProcessAsUser and the test.bat completed with success.

    Then I tried running the RunProcAs function using delegation, bypassing the LogonUser call, duplicating the token from DelegatedIdentity into a primary token and using the primary token to CreateProcessAsUser.  This time 'sc.exe' generated an Access Denied error.

    Using Process Monitor I verified that in both cases that the 'sc.exe' application was indeed running as 'domain\username' and not SYSTEM.


    Anyone have any idea as to why this is happening?



    1 Public Function RunProcAs(ByVal CMD As String, ByVal ARG As String) As String  
    2         '  
    3         'This function only works when inititated from SYSTEM account.  
    4         '  
    5         Dim note As String = "()" 
    6         Dim er As Int16  
    7         Dim exitCode As System.UInt32 = Convert.ToUInt32(123)  
    8         Dim stdOut As String = "" 
    9  
    10         Dim saThreadAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES  
    11         saThreadAttributes.nLength = Marshal.SizeOf(saThreadAttributes)  
    12  
    13  
    14         Dim impToken As System.IntPtr = IntPtr.Zero  
    15         Dim priToken As System.IntPtr = IntPtr.Zero  
    16  
    17         'computer/service delegation!  
    18         Dim DelegatedIdentity As WindowsIdentity = Nothing 
    19  
    20         Try  
    21             DelegatedIdentity = New WindowsIdentity("username@domain.com")  
    22             note = "(delegate) " 
    23         Catch ex As Exception  
    24             'can't be delegated  
    25             note = "(no delegate) " 
    26         End Try  
    27  
    28         If DelegatedIdentity Is Nothing Then  
    29             If LogonUser("username", "domain", "pass_goes_here", LogonType.LOGON32_LOGON_INTERACTIVE, _  
    30                            LogonProvider.LOGON32_PROVIDER_DEFAULT, impToken) Then  
    31                 'logonuser func success  
    32                 notenote = note & "(logonuser) "  
    33             Else  
    34                 'logonuser func failed  
    35                 er = Marshal.GetLastWin32Error  
    36                 RunProcAs = ("err logonuser  " & er)  
    37             End If  
    38  
    39         Else  
    40             notenote = note & "(delegate auth:" & DelegatedIdentity.IsAuthenticated & ") "  
    41             impToken = DelegatedIdentity.Token  
    42         End If  
    43  
    44         If DuplicateTokenEx(impToken, MAXIMUM_ALLOWED, Nothing, _  
    45                             SecurityImpersonationLevel.SecurityDelegation, TOKEN_TYPE.TokenPrimary, priToken) Then  
    46             'duptoken func success  
    47             'got PRITOKEN  
    48             notenote = note & "(duptoken) "  
    49         Else  
    50             'duptoken func failed  
    51             er = Marshal.GetLastWin32Error  
    52             RunProcAs = ("err duptoken  " & er)  
    53         End If  
    54  
    55         If priToken <> IntPtr.Zero Then  
    56  
    57  
    58             Dim pi As PROCESS_INFORMATION = New PROCESS_INFORMATION  
    59             Dim si As STARTUPINFO = New STARTUPINFO  
    60  
    61             Dim saProcessAttributes As SECURITY_ATTRIBUTES = New SECURITY_ATTRIBUTES  
    62             saProcessAttributes.nLength = Marshal.SizeOf(saProcessAttributes)  
    63  
    64  
    65  
    66             si.cb = Marshal.SizeOf(si)  
    67             si.lpDesktop = IntPtr.Zero  
    68  
    69  
    70  
    71             If Not CreateProcessAsUser(priToken, CMD, Chr(34) & CMD & Chr(34) & " " & ARG, saProcessAttributes, _  
    72             saThreadAttributes, False, 0, IntPtr.Zero, "c:\", si, pi) Then  
    73  
    74                 er = Marshal.GetLastWin32Error  
    75                 RunProcAs = note & ("err runas  " & er)  
    76  
    77             Else  
    78  
    79                 Dim wi As New System.Security.Principal.WindowsIdentity(priToken)  
    80  
    81                 er = Marshal.GetLastWin32Error  
    82                 WaitForSingleObject(pi.hProcess, Infinite)  
    83                 GetExitCodeProcess(pi.hProcess, exitCode)  
    84                 RunProcAs = note & ("Process Started  [" & er & "] as " & wi.Name & " : Exit Code [" & exitCode.ToString & "]")  
    85                 wi = Nothing 
    86  
    87             End If  
    88             CloseHandle(priToken)  
    89             CloseHandle(impToken)  
    90             CloseHandle(pi.hProcess)  
    91             CloseHandle(pi.hThread)  
    92         Else  
    93             RunProcAs = "pritoken zero" 
    94         End If  
    95  
    96     End Function 

     

    • Moved by nobugz Wednesday, June 25, 2008 1:02 AM Off topic for CLR, try a security newsgroup
    Tuesday, June 24, 2008 8:43 PM

Answers