Answered by:
CreateProcessAsUser and Delegation

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
-
Hi,
Thank you for your post! I would suggest posting your question in one of the MS Forums,
MSDN > Forums Home > .NET Development > ASMX Web Services and XML Serialization
located here: http://social.msdn.microsoft.com/Forums/en-US/asmxandxml/threads/
Have a great day!- Proposed as answer by Shrikant Maske Monday, November 10, 2008 12:14 PM
- Marked as answer by Shrikant Maske Monday, March 23, 2009 12:04 PM
Monday, November 10, 2008 12:14 PM