2

I have a script that utilizes $env:appdata which results in C:\Users\username\AppData\Roaming. This works great if I run the script manually, even in an "administrative" prompt. However, when it runs as part of a scheduled task under "SYSTEM" with "Highest Priveleges", it instead outputs c:\windows\system32\config\system.

I am able to get the logged in username using (Get-CimInstance CIM_ComputerSystem).Username. How can I get other environment variables, especially the AppData path?

1 Answers1

1

The problem here is that running under SYSTEM is that SYSTEM is actually the built-in machine account with the highest privileges you can achieve. This is an account that supersedes even the built-in local Administrator. If you are running something as SYSTEM, its user profile is C:\Windows\System32\config\system. This is all running as expected and designed.

If you need to run in the context of another user, the best solution is to create the task to execute as that user and delegate permissions to the principal appropriately. In fact, running something as SYSTEM is almost never the right solution, unless you need to perform one of the specific functions it alone can do by default (for these functions it's generally not recommended to delegate those permissions out).

If it needs to run under SYSTEM, well, you know where the SYSTEM profile is, so seed its AppData appropriately or retrieve artifacts after the task is complete from there. But it sounds like you really want to run this as another user, which is what you should configure your task to run as instead.


I don't recommend doing this from the SYSTEM user, but if you need to view another user's environment variables for some other reason, you can load their registry hive as long as another process doesn't have the hive opened (like if that user is using regedit.exe or has it loaded like I'm about to show you themselves):

Two things first:

  1. You will need to know the location of their user profile to do this

  2. PowerShell cannot load another user's hive itself so we must use the reg.exe command to do this

    • The Registry provider can still access the data, it just cannot load it.
    reg load HKEY_Users\username "C:\Users\username\NTUSER.DAT"
    
    # If we can't load it then no point continuing
    if( $? ) {
      try {
        # Read envvars into variable
        $uservars = Get-ItemProperty HKEY_Users:\Environment
      } finally {
        reg unload HKEY_Users\username
    
        if ( !$? ) {
          Write-Warning "Unable to unload userhive, see previous error message for details"
        }
      }
    
      # Do what you need here
      # $uservars is a `PSCustomObject` containing the other user's
      # environment variables.
    } else {
      throw "Unable to load userhive, logon script could not complete"
    }
    
codewario
  • 19,553
  • 20
  • 90
  • 159
  • 1
    The reason I was running it as SYSTEM is because I needed to run it *at the logon for each user* AND with admin rights (even if the user is not an admin) and was previously unable to do that. However I have just discovered that it seems to work as desired if I run as `builtin\users`. Still testing. –  Oct 18 '21 at 20:16
  • I added how to load another user's registry hive. Usually logon script sources are trusted and this is considered an acceptable reason to use them. I just warn against abusing `SYSTEM` because many folks use it because "well I don't have to rotate a password for it" or similar trivial reasons. – codewario Oct 18 '21 at 20:20
  • Interesting. `builtin\users` is a group consisting of local users by default, so I don't know how that would get the user elevated permissions beyond what they have been granted. Same with the `builtin\INTERACTIVE` group. I don't know too much about these ones though, I usually work with domain principals and products, not really end user accounts. – codewario Oct 18 '21 at 20:28
  • 1
    At this point I've confused myself so thoroughly that I'm not even sure the command I've been testing with (`reg add` to set lock screen) requires admin access anyway. All I know is it *seems* to be working how I need with `BUILTIN\Users` and no UAC prompt. –  Oct 18 '21 at 20:53
  • I went ahead and accepted your answer since it does explain how to load env vars from another user. –  Oct 18 '21 at 20:54
  • Interesting, that is a machine level setting and requires updating HKLM. Normally end users cannot change this themselves unless they configure the screensaver settings. In that case though if the timeout exceeds the system lock timeout setting it basically has no effect. – codewario Oct 18 '21 at 20:59
  • 1
    This is something you normally set by GPO. If you do that users can't change it even with admin. Modifying with a logon script doesn't prevent a user with admin access from changing it how they want. – codewario Oct 18 '21 at 21:01
  • FYI I'm setting the lock screen image, not the timeout. That is done via Intune/MEM. –  Oct 19 '21 at 12:51