Log in to a DC with local user - windows

Short but complicated question : is there any way to log on to a Domaincontroler with Servername\Username?
Ive got a Script wich specificly uses a Local Account (since 99% of our Servers are not in a Domain + you can create Local user accounts on almost Every Windows machine, but not on a DC sadly).
So basicly what im asking is : is there a way to trick a DC to accept Servername\Username as a domain login? is there a way by rights? Changing the Script is not an option sadly since the infrastructure behind it is too big to change, and i dont want to add a server specific exception.
Update : It worked on 2 2003 DCs but still no luck with the 2008 DC. is/was there a Change in microsofts server Policy?
the Script part im Using :
$SecurePassWord = ConvertTo-SecureString -AsPlainText $($Row['Passwort']) -Force
$Cred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList "$($Row['ServerName'])\$($Row['Benutzername'])", $SecurePassWord
$pssessionoption = new-pssessionoption -operationtimeout 7200000 -IdleTimeout 7200000
Try {
$Session = New-PSSession -ComputerName $($Row['ServerName']) -credential $Cred -sessionOption $pssessionoption -EA Stop
Remove-PSSession -Session $Session
}
Catch [system.exception]
{
write-host "not working"
}
Anybody has an Explanation?

No, you cannot create a local users on a DC and therefore cannot use local credentials. Ever. This question should really be Server Fault.

Related

Powershell Running Command Line as Admin User

So I have automation that logs into a Windows Server 2019 machine as one user, but then needs to run a command (Invoke-AdminCommand is application specific, not a built-in Windows cmdlet) as an admin user (and I do not want to add the logged in user as an Admin). I've followed answers from here (if you think this is a duplicate question) and none have worked. In the script I do a "whoami" to be sure the session is the correct user, and it is. But the command returns an application specific error stating the user does not have the correct permissions. If I RDP into the same machine as the admin user and run the same command through a Powershell CLI - it works fine.
$username = "domain\adminUser"
$password = "**********" | ConvertTo-SecureString -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList $username,$password
$s = New-PSSession -credential $cred
$sc = {
whoami
Invoke-AdminCommand -Register -Verbose
}
Invoke-Command -Session $s -Scriptblock $sc
Remove-PSSession $s
You may be hitting the double-hop problem. You are remoting to another server to run another command which itself requires authentication. If you can't lean on CredSSP (security risk) or proper account delegation (potentially high overhead in effort to maintain delegations at volume but this is the correct way to go about it).
Note: Basic auth will also work around this issue but I highly highly highly do not recommend using basic auth without at least setting up WinRM over SSL and removing non-HTTPS WinRM listeners.
Whether you are using Kerberos (without proper delegation or CredSSP) or NTLM (at all as NTLM cannot forward tokens) as the authentication scheme you can work around this by passing the credential information into Invoke-Command and building the credential in that script block, and using Start-Process to start it as a different user. Note that if you needed to elevate for UAC, the code would be different and this code will only work when you don't need UAC elevation:
# We will create the SecureString inside the Invoke-Command block
$password = "********"
# Use of a Dictionary instead of positional arguments and `param` in the block
# is a little trick you can use here.
Invoke-Command -Session $s -ArgumentList #{ Username = $username; Password = $password } {
$cred =
[PSCredential]::new($args.Username, ( $args.Password | ConvertTo-SecureString -AsPlainText -Force ))
# Placeholder for next part
}
So this is the boilerplate for what you want. You send the credentials to the remote server and build it there. How you execute this at # Placeholder for next part will depend on what exactly you are running:
External Command (executable)
Use Start-Process to run the program as the other user
Start-Process -Wait -Credential $cred program.exe -ArgumentList "arguments to the program here"
Any cmdlet which accepts a -Credential parameter or any command which accepts username and password arguments
Pass the credential argument directly to the cmdlet/function, or pass $args.Username and $args.Password to an external command which has username/password parameters directly. The below however exemplifies using this with a cmdlet and the -Credential parameter.
# Note that some cmdlets don't take a credential for whatever reason
# and may have -Username and -Password arguments instead.
Invoke-AdminCommand -Credential $cred -Register -Verbose
Any Function or Cmdlet which does not accept a -Credential parameter or username/password arguments
This is similar to the first example, but this example specifically targets running a bit of PowerShell code as another user for the code you want.
# This can be invoked without splatting but am using splatting for readability
$spArgs = #{
Credential = $cred
FilePath = 'powershell.exe' # You can use `pwsh.exe` for PS Core if necessary
ArgumentList = "-Command ""exampleProgram.exe -username $($args.Username) -password $($args.Password)"""
Wait = $true
NoNewWindow = $true
}
Start-Process powershell.exe

Retrieving Windows Defender Status remotely

I am using the following script to retrieve Windows Defender status remotely.
$password = ConvertTo-SecureString “myPassword” -AsPlainText -Force
$credentials = New-Object System.Management.Automation.PSCredential (“myUserNamer”, $password)
$sessionOption = New-CimSessionOption -Protocol WsMan
$session = New-CIMSession -ComputerName myMachineName -Credential $credentials -SessionOption
Get-MpPreference -CimSession $session
However, I am quite new to PowerShell scripting and related protocols. Is this the best way of retrieving this information when I may have to run it over hundreds of computers?
Does it need to be for all the machines or selected ones?
For example:
You could run a remote session on the machine you need and then run the command.
Enter-PSSession [VMname]
Get-MpComputerStatus
Replace [VMname] with the name of the VM/Computer you're looking for.
Enter-PSSession Computer-01
Get-MpComputerStatus
If that's what you're looking for.

Need to use powershell to login to multiple IP with the same local user / password no Prompt

I have a task to check the username and password on multiple servers and report the result.
So basically i have a list of IP's And I want I have the same user and password and need to see which authenticate and which don't.
This is what I found so far but it doesn't seems to work it prompts me for password every-time.
$listofServers = Import-Csv '.\Windows Servers.csv'
$username = username
$password = password
foreach($server in $listofServers.ip)
{
try{
$Credentials = Get-Credential $server\$username $password
}
Catch
{
$errorMsg = $_.Exception.Message
}
}
As said more than once, but never too much, you should NOT store a password in plain text. Probably the simplest of the many ways you can store it as a clixml file encrypted by a specific account. You can limit access to the location it's saved to that same account that can decrypt it.
You'll need to use the same username/password in combination with the computer name/IP to build an actual PSCredential object. I assume IP as your code shows $listofservers.ip - if the CSV header is not IP, update the code accordingly. I added some feedback to show you which computer and user connected and the fact that it's able to run the command remotely proves the connection was successful.
$username = 'localadmin'
$password = ConvertTo-SecureString 'PlaintextIsaNoNo' -AsPlainText -Force
Import-Csv '.\Windows Servers.csv' | ForEach-Object {
$cred = New-Object System.Management.Automation.PSCredential ("$($_.ip)\$username", $password)
Try
{
Invoke-Command -ComputerName $_.ip -ScriptBlock {
Write-Host Sucessfully connected to $env:computername as $(whoami) -ForegroundColor Green
} -Credential $cred
}
Catch
{
$PSItem.Exception.Message
}
}
The problem with the above code is it will run one PC at a time. Invoke-Command runs asynchronously if you just give it a list of computers (up to 32 by default on PS5.1) If you change the structure, this will run much faster. This requires a pretty well known trick which is to provide the username as .\username which designates it's a local account. I've tested and it works for me, so please let me know if you see otherwise.
$username = 'localadmin'
$password = ConvertTo-SecureString 'PlaintextIsaNoNo' -AsPlainText -Force
$serverlist = Import-Csv '.\Windows Servers.csv'
$cred = New-Object System.Management.Automation.PSCredential (".\$username", $password)
Try
{
Invoke-Command -ComputerName $serverlist.ip -ScriptBlock {
Write-Host Sucessfully connected to $env:computername as $(whoami) -ForegroundColor Green
} -Credential $cred
}
Catch
{
$PSItem.Exception.Message
}
Update
Removing the previous answer because of our threads below.
Here's your issue.
You cannot do things the way you are trying because of how Windows security boundaries proper works and you'd also have to set up PowerShell Remoting properly.
You have not said whether you are in a domain or in a Workgroup scenario. Hence the previous statement about setting up PSRemoting properly.
Because you are using a local account, this is like using Workgroup mode in PSRemoting and that requires additional settings to be in place. See the details regarding 'TrustedHosts'.
about_Remote_Troubleshooting - PowerShell | Microsoft Docs
Doing a logon to a remote host as you are trying will popup the Logon dialog (Gina) by design.
On your admin machine, try it this way... (tested and validated as working)
### PSRemoting - using local machine accounts
$Creds = Get-Credential -Credential $env:USERNAME
Enable-PSRemoting -SkipNetworkProfileCheck -Force
Get-Item -Path 'WSMan:\localhost\Client\TrustedHosts'
Set-Item -Path 'WSMan:\localhost\Client\TrustedHosts' -Value '*' -Force
Get-Item -Path 'WSMan:\localhost\Client\TrustedHosts'
$TargetList = 'Lab01','172.0.0.10'
$TargetList |
ForEach-Object {
"Validating logon for $($Creds.Username) on target $PSItem"
Try
{
New-PSSession -ComputerName $PSItem -Credential $Creds
Get-PSSession | Remove-PSSession
}
Catch {$PSItem.Exception.Message}
}
Set-Item -Path 'WSMan:\localhost\Client\TrustedHosts' -Value '' -Force
# Results
<#
Validating logon for postanote on target Lab01
Id Name ComputerName ComputerType State ConfigurationName Availability
-- ---- ------------ ------------ ----- ----------------- ------------
26 WinRM26 Lab01 RemoteMachine Opened Microsoft.PowerShell Available...
Validating logon for postanote on target 172.0.0.10
27 WinRM27 172.0.0.10 RemoteMachine Opened Microsoft.PowerShell Available...
#>
Update
Here's a tweak to Doug and my approach and dropping the need to have PSRemoting proper to be involved at all. Again, tested and validated. Except for the one time prompt for the creds, no embedded plain text passwords/files/registry/CredMan storage and retrieval, etc needed.
$Creds = Get-Credential -Credential $env:USERNAME
$TargetList |
ForEach-Object {
"Processing hostname $PSItem"
Try
{
$cred = New-Object System.Management.Automation.PSCredential ("$PSItem\$($Creds.UserName)", $Creds.Password)
(Get-HotFix -ComputerName $PSItem -Credential $cred)[0]
}
Catch {$PSItem.Exception.Message}
}
# Results
<#
Processing hostname Lab01
Source Description HotFixID InstalledBy InstalledOn
------ ----------- -------- ----------- -----------
Lab01 Update KB4576478 NT AUTHORITY\SYSTEM 9/10/2020 12:00:00 AM
Processing hostname 172.0.0.10
Lab01 Update KB4576478 NT AUTHORITY\SYSTEM 9/10/2020 12:00:00 AM
#>
• Tip: Work Remotely with Windows PowerShell without using Remoting or
WinRM
https://technet.microsoft.com/en-us/library/ff699046.aspx
Some cmdlets have a –ComputerName parameter that lets you work with a remote
computer without using Windows PowerShell remoting. This means you can use
the cmdlet on any computer that is running Windows PowerShell, even if the
computer is not configured for Windows PowerShell remoting. These cmdlets
include the following:
• Get-WinEvent
• Get-Counter
• Get-EventLog
• Clear-EventLog
• Write-EventLog
• Limit-EventLog
• Show-EventLog
• New-EventLog
• Remove-EventLog
• Get-WmiObject
• Get-Process
• Get-Service
• Set-Service
• Get-HotFix
• Restart-Computer
• Stop-Computer
• Add-Computer
• Remove-Computer
• Rename-Computer
• Reset-ComputerMachinePassword

How to correctly decrypt account credentials and pass them to Add-LocalGroupMember command

I am trying to create a script which adds currently logged on user account to local admin group which is to be deployed as SCCM package to freshly deployed computers in one particular AD OU group. I have encoded a service account credentials using a .key seed and stored them in a .txt file. Unfortunately I'm unable to retrieve/pass the current user account to aforementioned command.
I've tried running package with administrative rights option enabled, skipping credential encode and using various methods without success outside of lab, hence why I had to request a service account which would have enough rights to get the job done. Ive also tried various ways of identifying user accounts, however this is the only one which retrieves the actual account of windows user rather than the one under which PS session is running.
$User = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
$Computer = $env:COMPUTERNAME $svcAcc = "xxx\xx-xx" $PasswordFile = ".\Password.txt" $KeyFile = ".\AES.key" $key = Get-Content $KeyFile
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $svcAcc,(Get-Content $PasswordFile | ConvertTo-SecureString -Key $key)
Invoke-Command -ComputerName $Computer -Credential $Cred -ScriptBlock {Add-LocalGroupMember -Group "Administratorer" -Member $User}
I expected the $User variable to be passed correctly as when I run [System.Security.Principal.WindowsIdentity]::GetCurrent().Name selection, correct details are shown. Instead I get an error
Cannot validate argument on parameter 'Member'. The argument is null or empty"
Any pointers would be greatly appreciated
Everything within the scriptblock is executed on the remote machine. That remote machine does not have access to the local variable "$User"
Use the -ArgumentList parameter to pass the $user variable to the Scriptblock.
Invoke-Command -ComputerName $Computer -ScriptBlock {Add-LocalGroupMember -Group "Administratorer" -Member $args[0]} -ArgumentList $User

Run code block locally as a different user in powershell script

This is something incredibly simple, but I just can't get anything to work. I want to run a block code in a powershell script under a specific user. The keyword is locally and I'm using powershell 2.0.
Invoke-Command seems to require a remote host? I run the following and the error message that I see seems to suggest as much:
$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Invoke-Command -ComputerName "." -scriptblock {
write-output "HI!"
} -Credential $cred
Start-Job with -ScriptBlock isn't supported with powershell 2.0? I run the following and the error message that I see seems to suggest as much:
$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Start-Job -ScriptBlock {
write-output "HI!"
} -Credential $cred
Am I doing something wrong, or is there an alternative way?
Added: Here is what I'm trying to do in the first place. I'm making a scheduled task that runs when a user logs into/unlocks a terminal that writes logon information to a file. The scheduled task runs as the local user in order to get at the username, profile, etc. information. The logon information is then written to a log file using a different user account, which is the only account that can modify the file. To deter access to the logon credentials in the script I convert the script to an EXE using PS2EXE.
Here is another way.
# Get the other user's credentials
$credential = Get-Credential
# Execute a scriptblock as another user
$commands = #'
$env:username
# ... more commands ...
'#
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-Command', $commands
# Execute a file as another user
$script = '.\path\name.ps1'
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-File', $script
With the -LoadUserProfile switch, this has the added benefit of creating the user's profile if it does not already exist.
Another approach is impersonation, it is good option if you are not willing to enable remoting.
Check this and this out.
You should just put your code between
Push-ImpersonationContext $credential
and
Pop-ImpersonationContext
It would help to see the error messages you're not showing us, but I think the answer to your question is to use PowerShell Remoting as you tried with Invoke-Command. The computer name . is fine as is localhost but you do have to have remoting enabled on your machine to do it.
To enable remoting, run Enable-PSRemoting within powershell, or run winrm quickconfig in a regular command prompt.
If you already have remoting enabled, then you might be trying to do the remoting with a non-administrative user. If that's the case, take a look at the output of Get-PSSessionConfiguration. You'll get a list of endpoints and the permissions that are applied.
The endpoint you're connecting to by default is called Microsoft.Powershell and you could change the permissions with Set-PSSessionConfiguration (be sure to use the -ShowSecurityDescriptorUI parameter unless you want to mess with SDDL).
But instead of doing that, there should already be a group given access called BUILTIN\Remote Management Users which you can add your limited user to.
If none of this helps, give more details and error messages.
Edit
After seeing the explanation of what you're ultimately trying to accomplish, I have another suggestion for you.
Your existing scheduled task writes the information to a known location.
A different scheduled task running under the privileged user account picks up that information and puts it into the file that the limited user cannot access.
Bonus: start the second task from the first task.
This could be a quick compromise to do what you want without remoting and without exposing the credentials of the privileged user.
Issues with the current approach:
The major problem I have with your original idea is that you're going to need to embed the credentials into the script, so the limited user will have access to the credentials of the account that can modify the file anyway.
Ideally:
You would have a web service that you could invoke with your limited-user powershell script in which you can only give it the login information and not get anything back. So you'd hit a URL and do a POST or whatever with the data that you want to log, but that user can't ever retrieve any info. It might be a bit beyond what you're willing to do for this.

Resources