Modify

Opened 7 years ago

Closed 7 years ago

Last modified 7 years ago

#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 Changed 7 years ago by caplant@…

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

comment:2 Changed 7 years ago by Valik

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 Changed 7 years ago by Valik

  • Milestone set to 3.3.9.0
  • Owner set to Valik
  • Resolution set to Fixed
  • Status changed from new to closed

Fixed by revision [6764] in version: 3.3.9.0

comment:4 Changed 7 years ago by caplant@…

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 Changed 7 years ago by Valik

  • Resolution Fixed deleted
  • Status changed from closed to reopened

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 Changed 7 years ago by TicketCleanup

  • Milestone 3.3.9.0 deleted

Automatic ticket cleanup.

comment:7 Changed 7 years ago by Valik

  • Milestone set to 3.3.9.1
  • Resolution set to Fixed
  • Status changed from reopened to closed

Fixed by revision [6820] in version: 3.3.9.1

comment:8 Changed 7 years ago by Valik

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 Changed 7 years ago by caplant@…

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

Guidelines for posting comments:

  • You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
  • In-depth discussions should take place on the forum.

For more information see the full version of the ticket guidelines here.

Add Comment

Modify Ticket

Action
as closed The owner will remain Valik.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.