Modify

#2111 closed Bug (Fixed)

RunAs broken when Authenticated Users added to Replace a process level token

Reported by: caplant@… Owned by: Valik
Milestone: 3.3.9.1 Component: AutoIt
Version: 3.3.6.1 Severity: None
Keywords: RunAs, Replace a process level token Cc:

Description

We have an application that adds 'Authenticated Users' to 'Replace a process level token' security on XP machines (via secpol.msc). Once this is in place & the PC rebooted AutoIt's RunAs fails.

I'm using RunAs to grant local support staff access to an Admin Console so they don't have to logoff the current user. This feature is broken on several thousand machines where the bogus security modifying app is installed. The problem has existed for a several years now & we JUST found the root cause.

These are XP SP3 x86 devices joined to a domain.

Working (Windows Default):
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\Replace a process level token

Network Service, Local System

Broken:
Computer Configuration\Windows Settings\Security Settings\Local Policies\User Rights Assignment\Replace a process level token

Authenticated Users, Network Service, Local System

http://technet.microsoft.com/en-us/library/cc784623(WS.10).aspx

Attachments (0)

Change History (9)

comment:1 by caplant@…, on Jan 23, 2012 at 10:12:17 PM

!! Also requires Authenticated Users be added to 'Adjust memort quotas for a process' to fail.

comment:2 by Valik, on Jan 23, 2012 at 11:33:54 PM

Doh. We'll call this an oversight on my part. To be fair, I'm not really sure where this would be documented. You have the right privileges but they are disabled. They must be enabled before they can be used. Pretty trivial for AutoIt to do that, of course. I didn't realize it was necessary because the SYSTEM account always has those privileges enabled.

comment:3 by Valik, on Feb 4, 2012 at 10:21:15 PM

Milestone: 3.3.9.0
Owner: set to Valik
Resolution: Fixed
Status: newclosed

Fixed by revision [6764] in version: 3.3.9.0

comment:4 by caplant@…, on Feb 21, 2012 at 6:47:01 PM

It still appears to be broken in 3.3.9.0 compiled scripts. Here's my testing example:

;constants
Global Const $tagBOOL = "int"
Global Const $tagSTRING64 = "char[64]"
Global Const $tagSTRING128 = "char[128]"
Global Const $tagSTRING256 = "char[256]"
Global Const $tagSTRING32767 = "char[32767]"
Global Const $tagSTRING_CRED_MAX_USERNAME_LENGTH = "char[513]"
Global Const $tagCREDUI_INFO = "DWORD cbSize;HWND hwndParent;PTR pszMessageText;PTR pszCaptionText;HBITMAP hbmBanner"

;Flags for CredUIPromptForCredentials
Global Const $CRED_MAX_USERNAME_LENGTH = (256+1+256)
Global Const $CREDUI_MAX_PASSWORD_LENGTH = 256
Global Const $CRED_MAX_GENERIC_TARGET_NAME_LENGTH = 32767
Global Const $CRED_MAX_STRING_LENGTH  = 256
Global Const $CREDUI_FLAGS_INCORRECT_PASSWORD = 0x00001		;indicates the username is valid, but password is not
Global Const $CREDUI_FLAGS_DO_NOT_PERSIST = 0x00002			;Do not show "Save" checkbox, and do not persist credentials
Global Const $CREDUI_FLAGS_REQUEST_ADMINISTRATOR = 0x00004	;Populate list box with admin accounts
Global Const $CREDUI_FLAGS_EXCLUDE_CERTIFICATES = 0x00008	;do not include certificates in the drop list
Global Const $CREDUI_FLAGS_REQUIRE_CERTIFICATE = 0x00010
Global Const $CREDUI_FLAGS_SHOW_SAVE_CHECK_BOX = 0x00040
Global Const $CREDUI_FLAGS_ALWAYS_SHOW_UI = 0x00080
Global Const $CREDUI_FLAGS_REQUIRE_SMARTCARD = 0x00100
Global Const $CREDUI_FLAGS_PASSWORD_ONLY_OK = 0x00200
Global Const $CREDUI_FLAGS_VALIDATE_USERNAME = 0x00400
Global Const $CREDUI_FLAGS_COMPLETE_USERNAME = 0x00800     
Global Const $CREDUI_FLAGS_PERSIST = 0x01000				;Do not show "Save" checkbox, but persist credentials anyway
Global Const $CREDUI_FLAGS_SERVER_CREDENTIAL = 0x04000
Global Const $CREDUI_FLAGS_EXPECT_CONFIRMATION = 0x20000	;do not persist unless caller later confirms credential via CredUIConfirmCredential() api
Global Const $CREDUI_FLAGS_GENERIC_CREDENTIALS = 0x40000	;Credential is a generic credential
Global Const $CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS = 0x80000 ;Credential has a username as the target
Global Const $CREDUI_FLAGS_KEEP_USERNAME = 0x100000			;don't allow the user to change the supplied username


If IsArray($cmdline) Then
	If UBound($cmdline) > 1 Then
		If $cmdline[1] = "/AdminConsole" Then
			MsgBox(0,"Admin Console",@username & @CRLF & @WorkingDir)
			Exit
		EndIf
	EndIf
EndIf
CredTest()
Exit


Func CredTest()
	Local $lCreds, $lBslashLoc, $lDomain, $lUser, $lRPID
	$lCreds = _CredUIPromptForCredentials(0, "", "", "", " Admin Console", "", "", "", "", -1)
	If IsArray($lCreds) Then
		If $lCreds[0] = 1223 Then
			;user canceled credentials box
			$lDone = 1
		ElseIf $lCreds[1] <> "" Then
			If StringInStr($lCreds[1],"\") Then
				$lBslashLoc = StringInStr($lCreds[1],"\")
				$lDomain = StringLeft($lCreds[1], $lBslashLoc - 1)
				$lUser = StringTrimLeft($lCreds[1], $lBslashLoc)
			ElseIf StringInStr($lCreds[1],"@") Then
				$lBslashLoc = StringInStr($lCreds[1],"@")
				$lUser = StringLeft($lCreds[1], $lBslashLoc - 1)
				$lDomain = StringTrimLeft($lCreds[1], $lBslashLoc)
			EndIf
			If ($lUser <> "") And ($lDomain <> "") And ($lCreds[2] <> "") Then				
				;RunAs ( "username", "domain", "password", logon_flag, "filename" [, "workingdir" [, show_flag [, opt_flag ]]] )
				$lRPID = RunAs($lUser, $lDomain, $lCreds[2],1,'"' & @ScriptFullPath & '" /AdminConsole', @SystemDir)
				MsgBox(0,"Creds",$lUser & @CRLF & $lDomain & @CRLF & "PWLen: " & StringLen($lCreds[2]) & @CRLF & "PID: " & $lRPID)
				If $lRPID = 0 Then
					;log- Admin Console - Access Denied. Unknown user name or bad password
					$lMsgRslt = MsgBox(BitOR(0x1,0x30,0x40000)," Admin Console","Access Denied" & @CRLF & @CRLF & "Unknown user name or bad password." & @CRLF & "RunAs process could not be created.",120)
					If ($lMsgRslt = -1) or ($lMsgRslt = 2) Then
						;user has canceled or the message timed out
						$lDone = 1
					EndIf
				Else
					;admin console was started
					$lDone = 1
				EndIf
			EndIf
		EndIf
	Else
		MsgBox(0,Default,"Array not returned")
	EndIf
EndFunc

Func _CredUIPromptForCredentials($lHWndParentUI = 0, $lpszMessageText = "", $lpszCaptionText = "", $lhbmBanner = "", $lpszTargetName = "", $ldwAuthError = "", $lpszUserName = "", $lpszPassword = "", $lpfSave = "", $ldwFlags = "")
	Local $sCREDUI_INFO, $spszMessageText, $spszCaptionText
	Local $spszTargetName, $spszUserName, $spszPassword, $spfSave, $lCredUIPromptForCredentials, $retArray[4]
	
	;configure CREDUI_INFO structures
	$spszMessageText = DllStructCreate($tagSTRING32767)
	$spszCaptionText = DllStructCreate($tagSTRING128)
	DllStructSetData($spszMessageText, 1, $lpszMessageText)
	DllStructSetData($spszCaptionText, 1, $lpszCaptionText)
	
	$sCREDUI_INFO = DllStructCreate($tagCREDUI_INFO)
	DllStructSetData($sCREDUI_INFO, "cbSize", DllStructGetSize($sCREDUI_INFO))
	DllStructSetData($sCREDUI_INFO, "hwndParent", $lHWndParentUI)
	DllStructSetData($sCREDUI_INFO, "pszMessageText", DllStructGetPtr($spszMessageText))
	DllStructSetData($sCREDUI_INFO, "pszCaptionText", DllStructGetPtr($spszCaptionText))
	DllStructSetData($sCREDUI_INFO, "hbmBanner", $lhbmBanner)
	
	;configure CredUIPromptForCredentials structures
	$spszTargetName = DllStructCreate($tagSTRING32767)
	$spszUserName = DllStructCreate($tagSTRING_CRED_MAX_USERNAME_LENGTH)
	$spszPassword = DllStructCreate($tagSTRING256)
	$spfSave = DllStructCreate($tagBOOL)
	
	DllStructSetData($spszTargetName,1,$lpszTargetName)
	DllStructSetData($spszUserName,1,$lpszUserName)
	DllStructSetData($spszPassword,1,$lpszPassword)
	DllStructSetData($spfSave,1,$lpfSave)
	
	;configure default prompting options
	If $ldwFlags = -1 Then
		$ldwFlags = BitOR($CREDUI_FLAGS_DO_NOT_PERSIST,$CREDUI_FLAGS_USERNAME_TARGET_CREDENTIALS,$CREDUI_FLAGS_REQUEST_ADMINISTRATOR)
	EndIf	
	
	;prompting for credentials
	$lCredUIPromptForCredentials = DllCall("Credui.dll","DWORD", "CredUIPromptForCredentials","ptr", DllStructGetPtr($sCREDUI_INFO), "ptr", DllStructGetPtr($spszTargetName),"ptr", "", "DWORD", $ldwAuthError, "ptr", DllStructGetPtr($spszUserName),"ULONG", $CRED_MAX_USERNAME_LENGTH, "ptr", DllStructGetPtr($spszPassword), "ULONG", $CREDUI_MAX_PASSWORD_LENGTH, "ptr", DllStructGetPtr($spfSave), "DWORD", $ldwFlags)
	
	;results array
	If IsArray($lCredUIPromptForCredentials) Then
		$retArray[0] = $lCredUIPromptForCredentials[0]
		$retArray[1] = DllStructGetData($spszUserName,1)
		$retArray[2] = DllStructGetData($spszPassword,1)
		$retArray[3] = DllStructGetData($spfSave,1)
	EndIf
	
	;release structures
	$spszMessageText = 0
	$spszCaptionText = 0
	$sCREDUI_INFO = 0
	$spszTargetName = 0
	$spszUserName = 0
	$spszPassword = 0
	$spfSave = 0
	
	Return $retArray
EndFunc

;script end

comment:5 by Valik, on Feb 23, 2012 at 3:59:39 AM

Resolution: Fixed
Status: closedreopened

I'm more interested in seeing what privileges the account in question has than a test script. Download the following program. It's a custom program I wrote that lists the privileges an access token has. Run it using the account where RunAs() fails. Show me the output so I can see what privileges the account in question has and what state they are in.

comment:6 by TicketCleanup, on Feb 23, 2012 at 6:00:05 AM

Milestone: 3.3.9.0

Automatic ticket cleanup.

comment:7 by Valik, on Feb 26, 2012 at 11:09:53 PM

Milestone: 3.3.9.1
Resolution: Fixed
Status: reopenedclosed

Fixed by revision [6820] in version: 3.3.9.1

comment:8 by Valik, on Feb 26, 2012 at 11:11:17 PM

There were a couple additional privileges that are required. In addition the calling user must be in the administrators group. These conditions are now tested for and the code correctly falls back onto alternate methods unless all conditions are met.

comment:9 by caplant@…, on Mar 6, 2012 at 10:17:06 PM

I verified it's fixed with our whacky vendor app & 3.3.9.1 compiled scripts. Thanks Valik!

Modify Ticket

Action
as closed The owner will remain Valik.

Add Comment


E-mail address and name can be saved in the Preferences .
 
Note: See TracTickets for help on using tickets.