Local System Account and Windows Credential Manager - powershell

So, I have a powershell script that uses the Windows Credential Manager to store credentials. When I use my account I can access these credentials, but it seems like when I try to use the local system account (trying not to use my account to run scripts) it doesnt pull from the credential manager. What gives?
if (Get-Module -ListAvailable -Name CredentialManager) {
Import-Module CredentialManager
}
else {
Install-Module CredentialManager
}
$service_fqdn = '<SERVER-FQDN>'
$creds = Get-StoredCredential -Target '<SERVICE ACCOUNT>'
$oauth_client_id = $creds.UserName
$oauth_client_secret = $creds.GetNetworkCredential().Password
I get a null error when I try to get the password for $oauth_client_secret

The issue is that all credentials are stored and accessible for only the current logged in user.
i.e. If you create the credential logged in as user1, you can't access them as user2, or even with the Local System Account.
This makes sense, and can't be worked around. You don't want random
logged in people/users to be able to access other people's
credentials.
The "workaround" is to create a new user/service account with minimal permissions that is dedicated to running the service/script. You then can create the new credential as that new user/service account:
New-StoredCredential -Target "Server1" -Username "SA-Username" -Password "Password123"
Then running the script as that user, you will have access to the credential.
Note: you cannot use the Local System Account to run the script as you can't explicitly specify the Local System Account as a valid user to create the new stored credential.
Edit:
As #MrBungle correctly mentions. The Local System Account has god like powers, and it is recommended not to use it if possible. Instead use the unprivileged Local Service Account whenever possible.

Related

Powershell password error when creating a new SecretStore vault

When attempting to setup a new PS SecretStore vault, I get a prompt to enter a password. It is my understanding that the first time you setup a vault, you need to enter a new password in. However, upon typing a new password I get the following message:
Set-Secret : A valid password is required to access the Microsoft.PowerShell.SecretStore vault.
Use the Unlock-SecretStore cmdlet to provide the required password to access the store.
What could I potentially be doing wrong as every video and article is able to set this up in a few easy commands. I've also tried 2 different servers to ensure something was not messed up with my local PC.
Install-Module Microsoft.Powershell.SecretManagement, Microsoft.Powershell.SecretStore -Scope CurrentUser
Register-SecretVault -Name SecretStoreTest -ModuleName Microsoft.PowerShell.SecretStore -DefaultVault
get-secretvault
Set-Secret -Name Password1 -Secret "Pa55word"
It appears this has to do with not running in administrative mode. I had attempted to run in admin mode on my remote server, but it still failed. When attempting on my local it did indeed work though.

How to Run some scripts into Virtual Machines(username and password) created in Hyper-V through scripts, without prompts

Problem statement: I want to run some scripts into a Virtual machine created in Hyper-V. The virtual machine has a Username and a password.
The problem is Whenever I use invoke-command or enter-pssession, it prompts for username and password. I need to do it without Entering details manually every time and should be able to do it through scripts.
You will need to run the scripts as a Hyper-V admin (local admin on the host), but you can automate the process of providing the VM credentials by export a [pscredential] object to disk:
# Enter the credentials when prompted
$VMCredentials = Get-Credential
$VMCredentials |Export-CliXml path\to\credentials.xml
Export-CliXml will automatically use DPAPI to encrypt the password part using a key derived from the current security context - meaning only the same user on the same machine will be able to decrypt it again.
In order to use these stored credentials, simply call Import-CliXml:
$VMCredentials = Import-CliXml path\to\credentials.xml
Invoke-Command { ... } -VMName VM01 -Credentials $VMCredentials

Can I change my own password in Active Directory using Powershell

I am trying to change password for my own account in AD using powershell. My account is just a regular account (no domain admin rights)
I tried net user, dsquery and powershell cmdlets, but all of them errors out "Access is denied". I think all of those requires admin rights.
Is there a way to change my own password using powershell or cmd ?
Why I am doing that?
We have 8 different AD domains and I have an account in each. With different password expiration policies it is very difficult to remember all the passwords. So I want to do a script that connects to each domain with my user account in that domain and changes the password. I'll repeat that for all the domains.
If you have the Active Directory PowerShell Module installed, this is a pretty easy task using Set-ADAccountPassword.
You can use the -Server parameter to supply a different Domain Controller name from each Domain to set the password on that Domain.
$DomainControllers = "Domain1DC","Domain2DC","Domain3DC"
$MyName = "MyUserName"
ForEach ($DomainController In $DomainControllers) {
Set-AdAccountPassword -Identity $MyName -Server $DomainController
}
Set-ADUserAccountPassword used this way will prompt you for the old password then the new password for each domain controller.

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.

Get current user's credentials object in Powershell without prompting

I have a Powershell script that is going to be run through an automation tool against multiple servers.
It works fine on Windows machines, as the remote calls use the tool's service account without any need for prompting or exposing any credentials in code.
This script also runs against Linux machines via SSH using the SharpSSH package. SharpSSH does not automatically use the Powershell user's credentials but requires either a username and password, an RSA key file, or a PSCredential object.
I can't prompt for credentials using Get-Credential, because it's being run through the automation tool. I don't want to expose the username and password in code or have an RSA key sitting out there. I would like to construct a PSCredential object from the current Powershell user (the service account).
Trying [System.Net.CredentialCache]::DefaultNetworkCredentials shows a blank, and [System.Security.Principal.WindowsIdentity]::GetCurrent() doesn't provide the object or information I need.
Does anyone have a method for creating a PSCredential object from the current user? Or maybe a completely different alternative for this problem?
Many thanks!
The Windows API will not expose the information you need, which is why Powershell can't get to them. Its an intentional feature of the security subsystem. The only way for this to work is for the Linux machines to trust the calling machine, such as joining them to an Active Directory (or any kerberos setup really).
Aside from that, you'd need to store and pass this information somehow.
You could store the RSA key in the user's keystore and extract it at runtime (using the .NET Crypto/Keystore libs), so you aren't storing the key around with the code. That way the key itself would be protected by the OS and available only when the calling user was authenticated. You'd have one more thing to install, but may be the only way to achieve what you are aiming for.
"Trying [System.Net.CredentialCache]::DefaultNetworkCredentials shows a blank, and [System.Security.Principal.WindowsIdentity]::GetCurrent() doesn't provide the object or information I need."
You already have your answer. I use this to pass the currently logged in user's credentials along in several scripts:
$Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$Username = $Credentials.UserName
$Password = $Credentials.Password
If you try to dump them to any kind of readable output, those values are empty when you dump them (for obvious security reasons), however they do work where you need a PSCredential object.
How about encrypting the password using the service account's encryption key?
A quick example:
Run PowerShell as the service account, run the following and save the output to a text file (or embed it in the scheduled task call):
$String = '<PASSWORD>'
ConvertFrom-SecureString -SecureString (ConvertTo-SecureString -String $String -AsPlainText -Force)
Use the following in your scheduled task in order to decrypt and utilize the password:
$EncryptedString = '<ENCRYPTED PASSWORD FROM ABOVE>'
[Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR((ConvertTo-SecureString -String $EncryptedString)))
That should do the trick. You cannot reuse the encrypted password on a different computer, though, or if you for whatever reason destroy you local key store :)
Since you can get the password in plaintext from a credential object, I doubt you can get this without prompting.