Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

%SCRIPTROOT% Cannot Be Found When Running As Custom User #138

Open
ewrightmdy opened this issue Mar 1, 2024 · 9 comments
Open

%SCRIPTROOT% Cannot Be Found When Running As Custom User #138

ewrightmdy opened this issue Mar 1, 2024 · 9 comments

Comments

@ewrightmdy
Copy link

Hello! I'm attempting to run a custom PowerShell script to kick off a PDQ deployment following the imaging process, and I'm running into some trouble with specifying account credentials in the task sequence.

The script we are calling through the Command Line step, as per this post there are issues with calling scripts through the PowerShell step (it simply opens a blank PowerShell window and does not actually execute):

powershell.exe -ExecutionPolicy Bypass %SCRIPTROOT%\PDQDeploy.ps1

When running the task sequence the script is successfully being called, however it is returning invalid credentials for our PDQ Server. I assume what's happening is that the task sequence is attempting to run the script as the local admin user, not the domain admin user which PDQ requires. So the easy fix for this should be to specify running the script as the domain admin in the task sequence, however when I do that I get the following error:

The system cannot find the file specified. (Error: 80070002; Source: Windows)]LOG]!><time="09:39:26.308+300" date="03-01-2024" component="TSManager" context="" type="3" thread="10440" file="instruction.cxx:785">

From what I can tell, by specifying the user the task sequence step is somehow losing it's access to %SCRIPTROOT%, or at least cannot locate the script we are trying to run. Of course an easy way to get around this is to run the script without specifying the user and hardcoding the credentials into the script, but I would rather not do that. If anyone knows of another workaround for this issue it would be greatly appreciated!

@technerdist
Copy link

technerdist commented Mar 1, 2024

I am a co-worker of OP's and I am working on this issue with him. My take after some further testing. All of this testing was performed without running command steps as a separate user.

First, we run a successful command step: powershell.exe -command "Set-ExecutionPolicy Bypass"

Then we call our PDQ script, with another command step: powershell.exe -file %SCRIPTROOT%\PDQDeploy.ps1

Our PDQ script contains the following lines:

netsh advfirewall set allprofiles state off
ipconfig /registerdns

psexec.exe \\server.domain.com -h -accepteula ipconfig /flushdns
psexec.exe \\server.domain.com -h -accepteula pdqdeploy.exe Deploy -Package "New-ImageApplications" -Targets
 $env:COMPUTERNAME

Start-Sleep 30
while (Test-Path "C:\Windows\AdminArsenal\PDQDeployRunner\service-1.lock") {
    Start-Sleep 30
}

Manually calling the script using PSExec from the newly imaged computer, we receive an invalid credential error. I assume a credential error maybe at fault. However, when adding credentials to the PSExec command, ran on the newly imaged computer, it works. Running the same command, with the credentials, via a command step results in the script appearing to run, but there's no response from the PDQ server.

There are no errors in the SMSTS logs. Please help us understand why our PDQ script is not executing properly. I tried to set up transcription to a log, but I'm a bit of a PS noob, and it output nothing.

Thank you for any assistance you may be able to offer.

@JerichoJones
Copy link

Can you change it to "Run Powershell Script"? With this I have found that you don't need to specify %SCRIPTROOT%.
image

@JerichoJones
Copy link

You will need to drop any supporting files (psexec) into %SCRIPTROOT% as well.

@ewrightmdy
Copy link
Author

ewrightmdy commented Mar 5, 2024

We can run it as a PowerShell step, but that doesn't solve our original problem which is that we need the script to run as a domain admin. Currently we have it running successfully by hardcoding the domain admin credentials in the script and running it as a "Run PowerShell Script" step, as you suggested. However that is a rather insecure way of going about it, we would much rather specify in the task sequence for it to run as a domain admin. This is a feature that is only available for the "Run Command Line" step though, and every time we specify the user for it to run as, it can no longer find the script.

@JerichoJones
Copy link

Yeah that would be bad.

@JerichoJones
Copy link

JerichoJones commented Mar 5, 2024

Total guess but you seem to be stuck so it might be worth a try:

  1. Open PSDCLient.xml
  2. Under step type="SMS_TaskSequence_RunCommandLineAction" name="Configure"
  3. Change <variable name="LoadProfile" property="LoadProfile">false</variable> to true

@technerdist
Copy link

We appreciate your assistance @JerichoJones but these suggestions have not been helpful for this issue.

@PowerShellCrack
Copy link
Contributor

My first ask: Why does the account need to be a Domain Admin? I would HIGHLY recommend using delegated rights. The credential info can be retrieved within winpe just by loading the task sequence module and retrieving the variable.dat file (the same can be said with MECM OSD)

IMO, I would obfuscate the password with an AES key in the PowerShell; makes it a little harder to decrypt.

$ADUser = 'contoso\admin'
#STEP 1 - create random passphase (256 AES). Save the output as a variable (copy/paste)
#NOTE: this key is unique; the same key must be used to decrypt
$AESKey = New-Object Byte[] 32
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey)
Write-host ('$AESKey = @(' + ($AESKey -join ",").ToString() + ')')

#STEP 2 - Encrypt password with AES key. Save the output as a variable (copy/paste)
$AESEncryptedPassword = ConvertTo-SecureString -String '!QAZ1qaz!QAZ1qaz' -AsPlainText -Force | ConvertFrom-SecureString -Key $AESKey
Write-host ('$ADEncryptedPassword = "' + $AESEncryptedPassword + '"')

#STEP 3 - Store as useable credentials; converts encrypted key into secure key for use (used in the script)
$SecurePass = $AESEncryptedPassword | ConvertTo-SecureString -Key $AESKey
$credential = New-Object System.Management.Automation.PsCredential($ADUser, $SecurePass)

#STEP 4 - Test password output (clear text) from creds
$credential.GetNetworkCredential().password

this will output what you need in the script.

You could take this one step further and put the AES key as a variable in the TS or in the cutomsettings.ini which makes it even harder to retrieve.

OR another option is since the PSD Wizard still uses the MDT Deployment workbench, the UI does not have the runas option for PowerShell scripts. Have you thought of running a command line but calling powershell:

powershell -ExecutionPolicy Bypass -File script.ps1

Hopefully this helps

@matsmcp
Copy link

matsmcp commented Apr 15, 2024

My first ask: Why does the account need to be a Domain Admin? I would HIGHLY recommend using delegated rights. The credential info can be retrieved within winpe just by loading the task sequence module and retrieving the variable.dat file (the same can be said with MECM OSD)

IMO, I would obfuscate the password with an AES key in the PowerShell; makes it a little harder to decrypt.

$ADUser = 'contoso\admin'
#STEP 1 - create random passphase (256 AES). Save the output as a variable (copy/paste)
#NOTE: this key is unique; the same key must be used to decrypt
$AESKey = New-Object Byte[] 32
[Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($AESKey)
Write-host ('$AESKey = @(' + ($AESKey -join ",").ToString() + ')')

#STEP 2 - Encrypt password with AES key. Save the output as a variable (copy/paste)
$AESEncryptedPassword = ConvertTo-SecureString -String '!QAZ1qaz!QAZ1qaz' -AsPlainText -Force | ConvertFrom-SecureString -Key $AESKey
Write-host ('$ADEncryptedPassword = "' + $AESEncryptedPassword + '"')

#STEP 3 - Store as useable credentials; converts encrypted key into secure key for use (used in the script)
$SecurePass = $AESEncryptedPassword | ConvertTo-SecureString -Key $AESKey
$credential = New-Object System.Management.Automation.PsCredential($ADUser, $SecurePass)

#STEP 4 - Test password output (clear text) from creds
$credential.GetNetworkCredential().password

this will output what you need in the script.

You could take this one step further and put the AES key as a variable in the TS or in the cutomsettings.ini which makes it even harder to retrieve.

OR another option is since the PSD Wizard still uses the MDT Deployment workbench, the UI does not have the runas option for PowerShell scripts. Have you thought of running a command line but calling powershell:

powershell -ExecutionPolicy Bypass -File script.ps1

Hopefully this helps

I fully agree -Domain admin in a deployment is a really bad idea.
If I read the script correctly the only things it does is to run PSexec commands as domain admin. One way of making it better would be to use restPS to create a Webservice and call the webservice from the deployment. It's still NOT a good way to do it since domain admin accounts shouldn't be required for anything automated. The correct permissions should be delegated instead

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants