1

I'm one of the IT admins in our company. Lately, cyber-security want to get stricter on how easily users can read and/or write data on USB sticks and external mass storage. In addition all new users getting new Windows notebooks will only have "non admin" permissions. All requests to install software etc must come through the IT desk.

An Active Directory OU has been created and some test notebooks have been assigned to it. My boss would like to me to write and test some Powershell scripts that would allow my colleagues and I (in a screen-sharing session with the user) to temporarily delete the registry keys that control USB storage access (until the next group policy update comes along). The hard part has already been taken care of. The intention is that script will be stored as a Nal-Object on ZenWorks, so the user would not be able to see the source code (kinda similar to an exe file that is just double-clicked on).

The code that is causing hassle...

# self-elevate to admin user - code at the very top of the PS file..
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
exit;}

# all the main code follows..

Here, if I run the script (in an non-admin account) I am prompted by UAC to enter the name and password of a local (or domain) admin account, a new window/session in PS opens and I can run whatever main commands need running.

The problem however is that is that when prompted for credentials and then type the correct password for a local non-admin account (as some users are inevitably going to do!) a new empty PS window/session just keeps opening indefinitely in a periodic fashion.

I've also tried adding an 'else clause' to the if-statement (to show an alert to the user and/or force quit Powershell, but it never seems to be get executed).

When I test this on a computer is that non part of any domain etc, I just get a "user is not authorised" kind of alert in UAC and no error gets the chance to propagate.

Is there any kind of workaround for this? It would be great too if the UAC prompt just defaulted to the name "ROOT\install". Nobody knows that password to this account except for IT admins.

I've also run Get-ExecutionPolicy -List... MachinePolicy and LocalMachine are "RemoteSigned", everything else is "Undefined".

I don't think execution policy plays a role in this strange loop, but I am open to being wrong. The script I am testing has not been through any signing procedures etc and is just sitting locally on the Desktop of one of the test computers.

Thanks.

8
  • So, you're just looking to loop until a correct credential is input? Also, you can use the -Credential parameter pointing to a pscredential object. This should give you more flexibility since you can populate Get-Credential with a username, something like: Get-Credential -UserName 'ROOT\Install' -Message 'test'. Commented Nov 21, 2022 at 16:32
  • A loop is what I am trying to avoid. If a non-admin user submits his correct AD user name and password a never-ending cycle of new/empty PS windows results. I'd much rather see the user see a GUI alert and have PS just close. Commented Nov 21, 2022 at 16:35
  • 3
    So ask the user to stop submitting credentials? Commented Nov 21, 2022 at 16:44
  • Are you asking how you can add an additional check to stop creating new processes if the user is not an admin? Commented Nov 21, 2022 at 16:59
  • 1
    but if the user provides incorrect credentials no new session is popping up just an error stating that the credentials were invalid right? Commented Nov 21, 2022 at 17:40

1 Answer 1

3

Your symptom is mysterious; it implies the following:

  • The UAC prompt triggered by Start-Process -Verb RunAs mistakenly accepts a NON-admin user's credentials.

  • On re-entry into the script, the test for whether the session is elevated (!([Security.Principal.WindowsPrincipal] ...) then fails, and Start-Process -Verb RunAs is run again, at which point no UAC prompt is shown, because Start-Process does think the session is elevated and instantly spawns a new window.

    • The result is an infinite loop of new windows getting opened.

I have no idea what would cause this discrepancy - do tell us if you ever find out.


As workaround, you can try the following approach:

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
  $passThruArgs = "-NoProfile -ExecutionPolicy Bypass -NoExit -Command `"cd \`"$pwd\`"; & \`"$PSCommandPath\`""
  if ([Environment]::CommandLine -match [regex]::Escape($passThruArgs)) {
    throw "You entered non-admin credentials. Please try again with admin credentials."
  }
  Start-Process -Verb RunAs PowerShell $passThruArgs
  exit
}

# all the main code follows..
'Now running elevated...'

That is, the on re-entry the process command line is examined for containing the same arguments that were passed on elevated re-invocation. If so, the implication is that even though the UAC prompt accepted the credentials, the new session still isn't elevated, and an error is thrown.

Note that I've added -NoExit to the re-invocation, so that the new window stays open, which allows the results to be examined.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.