#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 13 years ago by caplant@…
comment:2 Changed 13 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 13 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 13 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 13 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:7 Changed 13 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 13 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 13 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.
!! Also requires Authenticated Users be added to 'Adjust memort quotas for a process' to fail.