CreateProcessAsUser and Delegation



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@xxxxxxxxxx")
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



.