Execute PowerShell scripts as SYSTEM
We frequently experience situations where PowerShell scripts need to be run as local system (NT AUTHORITY\SYSTEM). For one of our customers, we wanted to use this method to store a password encrypted by Export-Clixml with the key of the local system, so that another process can decrypt and use it again with Import-Clixml.
What are the options?
Several sources on the internet describe two basic options: On the one hand the program PsExec.exe, on the other hand the Windows Task Scheduler. In the latter case, however, only the use of the graphical user interface is shown. PowerShell can also be used to create and execute a task.
Which code do we want to execute?
First, here is the PowerShell code to run as the local system:
[CmdletBinding()] Param( [Parameter(Position = 0, Mandatory = $true)][string]$UserName, [Parameter(Position = 1, Mandatory = $true)][string]$Password, [Parameter(Position = 2, Mandatory = $false)][string]$Path = "$env:LOCALAPPDATA\Credential.xml" ) $secureString = ConvertTo-SecureString -String $Password -AsPlainText -Force $credential = [PSCredential]::new($UserName, $secureString) $credential | Export-Clixml -Path $Path
The script takes the information for username and password in plain text, so that these can later be passed as command line parameters. Optionally, the location for the file to be created can be specified. We usually use the environment variable LOCALAPPDATA for this, which is set to “C:\Windows\system32\config\systemprofile\AppData\Local” for the local system.
The script is saved as “C:\tmp\ExportCredential.ps1” in our case, this path is needed in the following code.
How do we create a task with PowerShell?
The following code does not necessarily have to be saved as a script, and can simply be customized and executed via the PowerShell ISE. The only important thing to keep in mind is to use an elevated PowerShell session.
First the business part, which asks the user for the password to be encrypted and assembles the arguments for PowerShell execution:
$scriptFile = 'C:\tmp\ExportCredential.ps1' $credential = Get-Credential -Message 'Enter credential to be exported as SYSTEM' $password = $credential.GetNetworkCredential().Password $actionArgument = "-File $scriptFile -UserName $($credential.UserName) -Password $password"
Then the task can be created and executed:
$action = New-ScheduledTaskAction -Execute powershell -Argument $actionArgument $principal = New-ScheduledTaskPrincipal -UserId SYSTEM $task = New-ScheduledTask -Action $action -Principal $principal $regTask = $task | Register-ScheduledTask ExportCredential $regTask | Start-ScheduledTask $regTask | Unregister-ScheduledTask -Confirm:$false
Since the task is deleted immediately afterward, the password is only available in plain text for a very short time. Thus, this variant is also preferable to using the graphical interface for security reasons.
Bonus: How are the environment variables of the local system set?
If you want to run very little PowerShell code, for example, export only the values of all environment variables of the local system to a file, then set the value of the $actionArgument variable like this and use it to create the task:
$actionArgument = '-Command "& { gci Env: | tee C:\tmp\env_system.txt }"'
Conclusion
With a few lines of PowerShell, the Windows Task Scheduler can be controlled to create and execute a task at short notice. This allows scripts to be executed quite easily as the local system.
Principal Consultant bei ORDIX
Bei Updates im Blog, informieren wir per E-Mail.
Kommentare 2
Thanks.
Ive compressed this to one script to run in an Administrative ISE session:
https://gist.github.com/MacsInSpace/cbe96cdc3123a05f520db2d5f6933acf
Hi Craig! Thanks for sharing your gist.