Calling another powershell script with Get-Credentials - Odd result - powershell

Edited:
I have a powershell script that calls another script as elevated domain admin which returns an access denied error as follows:
Exception calling "Add" with "1" argument(s): "Access is denied.
"
At \\server\software$\!SystemSetup\PS_Scripts\LocalAdmin.ps1:16 char:5
+ $AdminGroup.Add($User.Path)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : CatchFromBaseAdapterMethodInvokeTI
Using this method to call the script produces the error:
$Cred = Get-Credential
Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile -NoExit -ExecutionPolicy Bypass -File $ScriptLocation" -Credential $Cred
However, If I just right click and run as administrator and enter my domain credentials to call the script (without using $Cred) works fine:
Start-Process -FilePath "powershell.exe" -ArgumentList "-NoProfile -NoExit -ExecutionPolicy Bypass -File $ScriptLocation"
The script that I am calling looks like this:
$WindowsVersion = Get-WmiObject -Class Win32_OperatingSystem | ForEach-Object -MemberName Caption
If ($WindowsVersion -match 'Microsoft Windows 10 Enterprise') {
$DomainName = "DOMAIN.COM"
$ComputerName = (hostname)
$Username = (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty UserName).Split('\')[1]
$AdminGroup = [ADSI]"WinNT://$ComputerName/Administrators,group"
$User = [ADSI]"WinNT://$DomainName/$UserName,user"
$AdminGroup.Add($User.Path)
Write-Host "$Username added to Administrators"
} Elseif ($WindowsVersion -match 'Microsoft Windows 7 Enterprise' -or $WindowsVersion -match 'Microsoft Windows 7 Professional') {
$DomainName = "DOMAIN.COM"
$ComputerName = (hostname)
$Username = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty UserName).Split('\')[1]
$AdminGroup = [ADSI]"WinNT://$ComputerName/Administrators,group"
$User = [ADSI]"WinNT://$DomainName/$UserName,user"
$AdminGroup.Add($User.Path)
Write-Host "$Username added to Administrators"
} Else {
Write-Host "Could not determine OS version"
}
I cannot figure out why storing my domain admin credentials in $Cred and passing it to the script gives me the access denied once it gets to $AdminGroup.Add($User.Path)

Going off of TheIncorrigible1's comment, You can add this to your script at the beginning to check if it is running as admin. If it is not, it will relaunch as admin
If (-Not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) {
$Arguments = "& '" + $MyInvocation.MyCommand.Definition + "'"
Start-Process Powershell -Verb RunAs -ArgumentList $Arguments
Break
}
Then depending on your UAC setting you may be prompted to allow it to run with elevated privilege.

Related

I want to store encrypted credentials and use them to open a powershell instance and run a script that makes a change to a field in AD

Below is my code, I've used the same process for connecting to sftp securely. I'm getting the error at the bottom of my post. Not sure if I'm missing a step in the creation of the key and password. Thanks.
#Set the credentials
$Password = Get-Content "c:\password.txt" |
ConvertTo-SecureString -Key (Get-Content "c:\aes.key")
$Credential = New-Object System.Management.Automation.PSCredential ('serviceaccount', $Password)
# Start a new instance of Windows PowerShell using the credentials
# stored in $Credential and run the script in $scriptblock
$powershellPath = "$env:windir\system32\windowspowershell\v1.0\powershell.exe"
$process = Start-Process $powershellPath -Credential $Credential -NoNewWindow `
-ArgumentList ("-ExecutionPolicy Bypass -noninteractive -noprofile " + $scriptBlock) -PassThru
# Script to execute in the new PowerShell instance
$scriptBlock = {
Import-Module ActiveDirectory
Get-ADUser ecarlsson | Set-ADUser -Manager bbob
Read-Host
}
I tried the code above and go the password error below.
Start-Process : This command cannot be run due to the error: The user name or password is incorrect.
At\filepath \\fV3.ps1:7 char:12
+ $process = Start-Process $powershellPath -Credential $Credential -NoN ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand

Powershell start process with runas and credentials

I'm trying to run a process with a hardcoded user and pwd however i seem to only be able to specify either the credential or runas, but never both:
$username = "[redacted]"
$password = "[redacted]"
$credentials = New-Object System.Management.Automation.PSCredential -ArgumentList #($username,(ConvertTo-SecureString -String $password -AsPlainText -Force))
# Self-elevate the script if required
# From: https://blog.expta.com/2017/03/how-to-self-elevate-powershell-script.html
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-noexit -noprofile -File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process Powershell -Verb Runas -ArgumentList $CommandLine # work, but no credential
# Start-Process PowerShell -Cred $credentials -Verb Runas -ArgumentList $CommandLine # both credential and runas, doesnt work.
Exit
}
}
How can i run Start-Process with both credentials and runas?

run powershell command over cmd

I'm trying to run this powershell command over cmd.. it worked when i run it directly from powershell.. but when i try to run if from cmd i get errors
Powershell Command:
(Get-WmiObject -Class Win32_Product -Filter "Name='Symantec Endpoint Protection'" -ComputerName localhost. ).Uninstall()
How I run it (cmd):
powershell.exe -Command (Get-WmiObject -Class Win32_Product -Filter Name='Symantec Endpoint Protection' -ComputerName localhost. ).Uninstall()
Output:
Get-WmiObject : Invalid query "select * from Win32_Product where Name=Symantec
Endpoint Protection"
At line:1 char:2
+ (Get-WmiObject -Class Win32_Product -Filter Name='Symantec Endpoint P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Get-WmiObject], Management
Exception
+ FullyQualifiedErrorId : GetWMIManagementException,Microsoft.PowerShell.C
ommands.GetWmiObjectCommand
You cannot call a method on a null-valued expression.
At line:1 char:1
+ (Get-WmiObject -Class Win32_Product -Filter Name='Symantec Endpoint P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
The other answers already answer your question of running powershell over CMD. I'd like to recommend you stop using the Win32_Product wmi class. You can read any of the never ending articles explaining why. As for building commands with arguments, I recommend splatting. As a bonus specifically regarding removing SEP, here is a snippet from a production script used to remove Symantec Endpoint using MSIexec and the guid.
$DateStamp = get-date -Format yyyyMMddTHHmmss
$logFile = '{0}-{1}-{2}.log' -f 'SymantecUninstall',$PC,$DateStamp
$locallog = join-path 'c:\windows\temp' -ChildPath $logFile
$uninstalljobs = Foreach($PC in $SomeList){
start-job -name $pc -ScriptBlock {
Param($PC,$locallog)
$script = {
Param($locallog)
$MSIArguments = #(
"/x"
('"{0}"' -f '{A0CFB412-0C01-4D2E-BAC9-3610AD36B4C8}')
"/qn"
"/norestart"
"/L*v"
$locallog
)
Start-Process "msiexec.exe" -ArgumentList $MSIArguments -Wait -NoNewWindow
}
Invoke-Command -ComputerName $pc -ArgumentList $locallog -ScriptBlock $script
} -ArgumentList $PC,$locallog
}
Just update the guid to match your product. If you want to pull the uninstall string from the registry and use that, it would also be preferable to Win32_Product.
Here are a couple of ways you can find the uninstallstring.
$script = {
$ErrorActionPreference = 'stop'
"HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach{
try
{
$key = reg query $_ /f "Symantec Endpoint" /s | select -skip 1 -first 1
$key = $key -replace 'HKEY_LOCAL_MACHINE','HKLM:'
(Get-ItemProperty $key -Name UninstallString).UninstallString
}
catch{}
}
}
powershell.exe -command $script
or
$script = {
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall" | foreach{
Get-childitem $_ |
Where {($_ | get-itemproperty -Name displayname -ea 0).displayname -like 'Symantec Endpoint*'} |
Get-ItemPropertyValue -name UninstallString
}
}
powershell.exe -command $script
Try this:
powershell.exe -Command "& {(Get-WmiObject -Class Win32_Product -Filter """Name='Symantec Endpoint Protection'""" -ComputerName XOS-MS182. ).Uninstall()}"
Try these. The parentheses mean something special to cmd. The filter would require two sets of quotes. Since the pipe is inside the double quotes, cmd ignores it.
powershell "(Get-WmiObject -Class Win32_Product -ComputerName localhost | where name -eq 'symantec endpoint protection').Uninstall()"
powershell "Get-WmiObject win32_product -cn localhost | ? name -eq 'symantec endpoint protection' | remove-wmiobject"
You don't need to use powershell for this task, from an elevated Windows Command Prompt, (cmd), you could use wmic instead:
WMIC.exe Product Where "Name='Symantec Endpoint Protection'" Call Uninstall

Powershell core to powershell

I'm running an Ubuntu EC2 instance with Pwsh installed to remote execute AD commands on one of our servers. 2sd hop is set-up correctly and i'm able to run AD commands but when executing my script i get the following error (Scripts works fine directly on the 2sd hop machine):
The search filter cannot be recognized
+ CategoryInfo : NotSpecified: (:) [Get-ADUser], ADException + FullyQualifiedErrorId : ActiveDirectoryServer:8254,Microsoft.ActiveDirectory.Management.Commands.GetADUser
+ PSComputerName : corpmaint02
#!/usr/bin/pwsh
$employeeEmail = 'myemail#contoso.com'
$session = New-PSSession -ComputerName corpmaint02 -ConfigurationName corpmaint02 -Credential contoso\myadminaccount
Invoke-Command -Session $session -ArgumentList $employeeEmail -ScriptBlock{
Get-ADUser -Filter "EmailAddress -eq '$employeeEmail'" -Properties EmailAddress | Disable-ADAccount
Write-Host $employeeEmail has been 'disabled.'
}
Remove-PSSession -ID $session.ID
[GC]::Collect()
Any help would be appreciated.
Update: new code:
#!/usr/bin/pwsh
$cred=Get-Credential domain\myadmin
$employeeEmail = 'myemail#contoso.com'
Invoke-Command -ComputerName corpmaint02 -Credential $cred -ConfigurationName corpmaint02 -Authentication Negotiate -ArgumentList $employeeEmail -$
Get-ADUser -Filter "EmailAddress -eq '$($Args[0])'" -Properties EmailAddress | Disable-ADAccount -verbose
Write-Host $employeeEmail has been 'disabled.'
}
I modified my code as follow and it works expect for the lack of permissions to disable the account which odd because my admin account has rights to do so.
Insufficient access rights to perform the operation
+ CategoryInfo : NotSpecified: (CN=xxxxx\domain,DC=com:ADUser) [Disable-ADAccount], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8344,Microsoft.ActiveDirectory.Management.Commands.DisableADAccount
+ PSComputerName : corpmaint02
New code to elevate:
#!/usr/bin/pwsh
$cred=Get-Credential domain\myadmin
$employeeEmail = 'user1#contoso.com'
Invoke-Command -ComputerName corpmaint02 -Credential $cred -ConfigurationName corpmaint02 -Authentication Negotiate -ArgumentList $employeeEmail,$cred -ScriptBlock{
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$testadmin = $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
if ($testadmin -eq $false) {
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
exit $LASTEXITCODE
}
Get-ADUser -Filter "EmailAddress -eq '$($Args[0])'" -Properties EmailAddress | Disable-ADAccount -verbose -Credential $Args[1]
}
Write-Host $employeeEmail 'has been disabled.'
Invoke-Command isn't running with elevated rights, so you can retrieve data but not make changes.
https://ss64.com/ps/syntax-elevate.html
If you use Invoke-Command to run a script or command on a remote computer, then it will not run elevated even if the local session is. This is because any prompt for elevation will happen on the remote machine in a non-interactive session and so will fail.
You can try self elevating in the Invoke-Command scriptblock (from the link above)
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
# Relaunch as an elevated process:
Start-Process powershell.exe "-File",('"{0}"' -f $MyInvocation.MyCommand.Path) -Verb RunAs
exit
}
# Now running elevated so launch the script:
& "d:\long path name\script name.ps1" "Long Argument 1" "Long Argument 2"

Powershell Start-Process permission denied

Could anyone tell me, why do I get an Error if I invoke:
$log = $env:TEMP + "\File.log"
$stdErrLog = $env:TEMP + "\stderr.log"
$stdOutLog = $env:TEMP + "\stdout.log"
$argument = "Get-Childitem c:\"
Start-Process powershell.exe -Credential $credentials -WindowStyle hidden -WorkingDirectory c:\ -ArgumentList $argument -RedirectStandardOutput $stdOutLog -RedirectStandardError $stdErrLog -wait
but there is no Error if I invoke:
Start-Process powershell.exe -Credential $credentials -WindowStyle hidden -WorkingDirectory c:\ -ArgumentList $argument -RedirectStandardOutput $stdOutLog -RedirectStandardError $stdErrLog
But I need the "-wait" or is there any alternative?
Error:
Start-Process : Permission denied
In Zeile:1 Zeichen:1
+ Start-Process powershell.exe -Credential $cred -WorkingDirectory c:\ -ArgumentLi ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Start-Process], Win32Exception
+ FullyQualifiedErrorId : System.ComponentModel.Win32Exception,Microsoft.PowerShell.Commands.StartProcessCommand
Sounds like your current user doesn't have access to see processes running as the 2nd account. Launch a PowerShell window under the other account, then run the script below as yourself to see if it's visible. If not, you may need to elevate permissions or run as admin.
Get-Process powershell | select -ExpandProperty startinfo | select -expandproperty environmentvariables | ?{$_.Name -eq USERNAME}