Automate first time password reset using powershell - powershell

I am creating a VM on the fly with powershell (on ESX with Windows Server 2012 R2). I have most of the automation pieces in place, but when it comes to resetting the Administrator password the first time we login to the VM after provisioning (as a part of windows security policy), I am having a hard time.
I have tried stuff like the following (which didn't work):
[ADSI]$vmAccount="WinNT://$vmName/$vmUserName"
$vmAccount.ChangePassword($current, $new)
It fails by saying:
Exception calling "ChangePassword" with "2" argument(s):
"The specified network password is not correct.
Any help in pointing me in the right direction is much appreciated.

This has worked for me remotely which is something that you can try:
$comp = <computer>
$user = <Username here>
$pass = <New password here>
("WinNT://$comp/$user/").SetPassword($pass)
If that doesnt work you may want to check on the security policy and see if the password matches the security policy, powershell errors can sometimes be incredibly bland.

Related

Validate user's credentials supplied during the installation (pre-install)

I'm using InstallAnywhere and due to security reasons, I need to change the Server (our application server) "Log on as" to other user than System.
I'm asking the user during the Pre-Install to supply me with a username (in a format of <Hostname\Username> or <Domain\Username>) and a password. Now I need to verify these credentials supplied by the user are valid, and if not prompt the same Panel again.
The problem is that with command line using the net start... command - I can't supply username & password.
Using the runas command - can give it the username as a parameter but not the password. (also - it was stucked on "attempting to start..." and couldn't start the process)
I've also tried PowerShell script which used the start-service command, using the -Credential parameter, but it didn't work.
another idea - is there a way to verify this using Regedit?

Powershell remoting - cannot execute an exe as another user

I've a commandline program (c#) that encrypts config files based on machine key.
A powershell script copies the build to a Target Server, modifies configs accordingly and installs windows services.
All the windows services run as local system account (standard user, non-admin) - let's call this account "locuser".
The Target Server is a Win 2012 R2 Server. All of the above is achieved by PS remoting from the Build Server to this Target server.
Now, I need to run the encrypt commandline program as "locuser", so that the program can use the account specific key to do the encryption.
I know that this can be easily achieved by calling Start-Process cmdlet with -Credentials parameter. Well, here's the catch, the above works fine, if I remote in (RDP) to the Target Server and then run the Start-Process .... -Credential $cred from a Powershell Console.
However, I need this to be working while I remote-in (using my scripts) to the TargetServer whilst deploying. When I remote-in to the TargetServer I use credentials that has Admin privileges.
I've tried the following
I've granted "locuser" both "Full Control" and "Invoke (Execute)" permissions by using the Set-PSSessionConfiguration -Name Microsoft.PowerShell -ShowSecurityDescriptorUI command. I've run this command for both Microsoft.Powershell and Microsoft.Powershell32 - Still get Access Denied
I've edited the "Local Security Policy"->"Local Policies"->"User Rights Assignment"->Impersonate a client after authentication - and added both the Admin account (that I login with) and the "locuser" account - Still get Access Denied
I've also granted locuser admin rights - Still get Access Denied
I'm pretty sure, there is some configuration on the PS Remoting Side of things that I'm missing out but can't figure out what - because all Powershell throws me is a Access Denied error (see screenshot) with little to no useful information to troubleshoot further.
Also, checked Event logs for any traces but to no avail.
You've fallen prey to the dreaded Double Hop. Basically you're authenticating from computer A to computer B, then trying to authenticate again from computer B to computer C (which also happens to be B in this case).
If at all possible, you would be better off ending the session and starting a new one with the locuser credentials, then just calling Start-Process. Another, more messy approach is to use schtasks.
I can tell you how to do it in the same session but it's a bit messy and very complicated, and should only be a last resort:
On the originating server (Build Server):
Run the command Enable-WSManCredSSP -Role Client -Delegate [name] where [name] is an IP or DNS address / range including any target servers (eg "192.168.1.*")
Open GPEdit.msc, navigate to Computer Configuration\Administrative Templates\System\Credentials Delegation and check that the rules Allow delegating fresh credentials and Allow delegating fresh credentials with NTLM... are enabled and include [name]
On the Target Server:
Run the command Enable-WSManCredSSP -Role Server
Running the command:
Invoke-Command [targetserver] [-Credential $cred] -Scriptblock {
## do stuff
Invoke-Command . -Credential $locusercred -Authentication Credssp -ScriptBlock {
Start-Process -FilePath $sc #etc
}
}
Some things to be aware of:
Firstly I used this setup to create a local session, then remote from there (so A-A-B instead of A-B-B) so the Group Policy stuff might be in the wrong place but pretty sure it's right.
Secondly I found that credentials are a pain to get working in sessions (in this case $locusercred). I did get it going natively but weirdly it suddenly couldn't decrypt the securestring. I ended up saving a securestring with a defined key to the registry so it can always be decrypted from any account, you may need to come up with your own solution there.
All this stuff is explained in the free eBook "The Secrets of PowerShell Remoting", if you go for the double-hop approach I recommend giving it a read.

How to rejoin domain when trust relationship is lost

I have a number of virtual machines which have snapshots applied by using a PowerShell script. Occasionally, the virtual machines lose their "trust relationship" with the domain. This breaks the script as I can no longer use PowerShell remoting to get into the machines and configure them.
How can I remotely reset the trust relationship of these virtual machines? Perhaps there are possibilities for rejoining the domain that don't involve remoting?
Any alternate solutions to manually rejoining the domain require logging in to the computer and doing this locally. I haven't found anything that can do this otherwise.
So far, I've attempted to put together a script that simply remotes into the box as the local administrator:
$password = ConvertTo-SecureString "password" -AsPlainText -Force
$cred= New-Object System.Management.Automation.PSCredential ("Administrator", $password)
$sesh = new-pssession -computername "theMachine" -credential $cred
At this point, I was hoping to use PowerShell to reset the password or something like that to reset the domain trust relationship. However, this results in an error on the last line: Access is Denied.
I don't think you can use the local administrator account with PowerShell remoting. Is there any other way I can remotely get a virtual machine that has lost its domain trust relationship to rejoin the domain?
Interesting a problem. Would a combination of PSExec and netdom work? I don't have a VM with broken trust relationship, so I can't test the idea.
Anyway, PSExec has parameters -u and -p for username and password. Make sure you know a local administrator account. Passing its credentials to PSExec should provide a remote shell even with broken trust relationship. Netdom.exe or a Powershell script can be used to re-join the computer to the domain.
Another an option would be changing the policy for computer accounts. A GPO that sets "Computer Configuration\Windows Settings\Security Settings\Local Policies\Security Options\Domain member: Maximum machine account password age" to 0 would set the computer account password never to expire. This might rise some security issues, though.
Edit
Use psexec to open a shell session. Like so,
psexec -u computer\administrator -p password \\computer cmd
After you got the shell, try and experiment with netdom commands. Remove the computer from the domain and add it to the domain. Netdom join and netdom remove support credential passing, so supply valid domain account credentials. After you know the exact command syntax, save the values to a script file and launch it with psexec like so,
psexec -u computer\administrator -p password \\computer c:\myScript.cmd

Powershell: Discover default network credentials when launched from runas /netonly

I am looking for a way to capture the network credentials of the current session into a variable that I can pass later...
The point is to execute commands on a foreign domain that I have account access/privileges to, but there is not a trust between the source and target domains.
First, we run inside a powershell that was spawned using the runas command (runas /netonly /user:domian\account powershell
From here I can do pretty much everything I want to except create an event in the task scheduler without hardcoding the username/password into the command line
invoke-command -computer $destination -scriptblock {schtasks -ru domain\account -rp password}
What I am looking to do is something like
$username = Get Current Session Network Username ($(whoami) brings up the actual local longon account,not the runas account that spawned the powershell window)
$password = Get the Password that was entered when the RunAs command was executed
Once a security token has been created from credentials entered and validated against active directory, the password is no longer kept around. It is not available for retrieval and reuse elsewhere. Only the token remains. This is by design.
UPDATE:
I dug a little further to bolster my case, and it's not quite as above but the end result is the same. The password used with runas.exe does not appear to be available. The network credentials are not validated against AD, which makes sense in retrospect since you often use /netonly for working with a remote, untrusted domain: By definition, you cannot validate the remote credentials from the local system. From MSDN:
Here's information for the flag LOGON_NETCREDENTIALS_ONLY, used with CreateProcessWithLogonW.
Log on, but use the specified credentials on the network only. The new
process uses the same token as the caller, but the system creates a
new logon session within LSA, and the process uses the specified
credentials as the default credentials.
This value can be used to create a process that uses a different set
of credentials locally than it does remotely. This is useful in
inter-domain scenarios where there is no trust relationship.
The system does not validate the specified credentials. Therefore, the
process can start, but it may not have access to network resources.
Ok, so since it can't validate the credentials and get a token, then it must store the password somewhere in memory since it must pass them over the wire later for SSPI etc. So, can we get at them from the process launched from runas.exe ? Let's see:
PS> runas /netonly /user:foo\bar powershell.exe
Enter the password for foo\bar: ******
I literally used foo\bar for domain and user above. It is not validated, as mentioned already. I entered 12345 for a password. The above line will launch a new instance of powershell. So, from that new instance, let's look at the default network credentials:
PS> [System.Net.CredentialCache]::DefaultNetworkCredentials
UserName Domain
-------- ------
Oh well, out of luck: Nothing there. My guess is the credentials are guarded in some encrypted part of memory in the kernel, probably the LSA (local security authority) out of reach from prying processes.

Run Command as administrator in PowerShell script. UAC

OK here is my issue:
I am trying to run a script remotely on a server.
I am an administrator on both boxes, firewall exceptions are in place, remote admin is enabled, and everything else looks good that i can see.
invoke-command -ComputerName $ComputerName -ScriptBlock `
{
cd C:\Windows\System32\inetsrv\;
./appcmd.exe ADD vdir /app.name:<SiteName>/ /path:/<VDir Name> /physicalPath:<Path to files>
}
I keep getting the following error in return
ERROR ( hresult:80070005, message:Failed to commit configuration changes. Access is denied.
The server it is trying to run on is a server 2k8 R2 box and I am thinking the issue is a UAC problem. Is there anyway to get this to run as administrator without having to click yes on a UAC box?
This piece of code will eventually become a script that will have to be completely automated.
Any help would be greatly appreciated.
OK. After some research and testing I figured out the issue. After disabling UAC and the firewall and the script still not working I dug a little deeper and discovered that the main issue was the way invoke-command runs the commands. it uses the credentials of the person running the script to authenticate to the server then tries to use another account to run the permissions or lowers the privileges of the user so that certain commands cannot be run.
I added the -Credentials switch to the invoke command and everything is working great now. Corrected code sample below:
$user = New-Object Management.Automation.PSCredential("$UserName", $securePassword)
invoke-command -ComputerName $ComputerName -Credential $user -ScriptBlock `
{
cd C:\Windows\System32\inetsrv\;
./appcmd.exe ADD vdir /app.name:<SiteName>/ /path:/<VDir Name> /physicalPath:<Path to files>
}
This seems to indicate that you need to ensure you are a local admin on the remote machine (although admittedly this is for WMI specifically). According to this you can change a registry key to stop UAC applying to remote logons for administrators (search for LocalAccountTokenFilterPolicy). That shouldn't disable UAC just not filter the token if you use powershell/WMI remotely with an administrator account.
Set the option "EnableLUA" (DWORD value) found in HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System to 0 and reboot.
This will disable UAC without a problem, I would do it for all your users, whether with or without permission is up to you.
This trick works in Windows Vista and Windows 7 too.
Is there anyway to get this to run as administrator without having to click yes on a UAC box?
If this were possible it would entirely defeat the point of UAC.
Thus, it would appear your only real solution is to disable UAC on the box.