1

I'm writing a PowerShell script that, every few months, a third-party app will automatically call to do the following among other things:

  1. Use [System.Web.Security.Membership]::GeneratePassword() to randomly-generate a password then use that password with Export-PfxCertificate and OpenSSL's passin.
  2. Use a static password to authenticate via COM API to a third-party system that doesn't support API keys or anything.

What's the best way to do this securely?

As far as I'm aware, there's nothing wrong with #1 but everything I've read online regarding #2 advises:

  • Requiring that the user supply the credentials when the script is executed but that defeats the point of automating the process.
  • Using PSCredential but that's not possible here.
  • Using an encrypted key / password file but, as far as I'm aware, there isn't really any point in that as you're effectively still storing the password alongside the script file - if the server gets compromised then they could either read the password from the script or decrypt the password in the keyfile. Unless you use a custom encryption key which isn't stored on the server but, again, that defeats the automation.
mythofechelon
  • 3,692
  • 11
  • 37
  • 48
  • 1
    It is possible to encrypt the password to file such that it can only be recovered on the same server by the same user, so the file is effectively useless to anyone else. Not 100% secure, but possibly good enough for your situation. Check out my previous answer to a similar question: [What is the best way to store account credentials ...](https://stackoverflow.com/questions/50917375/what-is-the-best-way-to-store-account-credentials-especially-password-for-an-a/50918111#50918111) – boxdog Apr 29 '19 at 12:40

2 Answers2

2

For # 2, there are lots of resources/articles covering securing credentials when using PowerShell.

Starting with Windows Credential Manager ...

Install-Module -Name "CredentialManager"

Get-Command -Module "CredentialManager"

$Target = "YourServerName"
$UserName = "Administrator"
$Secure = Read-host -AsSecureString
New-StoredCredential -Target $Target -UserName $UserName -SecurePassword $Secure -Persist LocalMachine -Type Generic

Get-StoredCredential -Target "servername" –AsCredentialObject

Remove-StoredCredential -Target "servername"

... then looking at other methods. See this Q&A for additional approaches. Passwords in powershell logging

As for...

if the server gets compromised

... if a nefarious one is this far into your system, to be able to do this, then this kicks in: Ten Immutable Laws Of Security (Version 2.0)

postanote
  • 15,138
  • 2
  • 14
  • 25
  • This led me to https://mcpmag.com/articles/2017/07/20/save-and-read-sensitive-data-with-powershell.aspx | "Credentials" which uses `Get-Credential | Export-CliXml`, `$Credential = Import-CliXml`, and `$Credential.GetNetworkCredential().Password` which is what I went with. – mythofechelon Aug 02 '19 at 13:26
  • Follow-up question: What's the best way to approach my ideal scenario where the user performs the setup to enter the config (including credentials) but the system executes the script - surely the system won't be able to decrypt the credentials because it's a different security context and, therefore, *-CliXml uses different keys? – mythofechelon Aug 05 '19 at 08:50
  • I used this method instead: https://getsysadminblog.com/2017/03/16/create-aes-secure-passwords-for-use-in-powershell-scripting/ – mythofechelon Aug 05 '19 at 14:32
1

Have you checked out Azure Key Vault or something similar?

If you go that route, take a look at the Az module (Windows PowerShell 5.1 or PowerShell Core). The Az.KeyVault sub module has lots of functions for working with the vault.

EDIT: To address security, we don't know much about the system. However, these are the things I would look into:

  1. Least privilege: make sure that this service account can only do what it is supposed to do.
  2. Time of use restrictions: if the schedule that this should execute is known, configure the system to only allow the account to successfully authenticate during that time and even JIT permissions, if possible.
  3. Location based restrictions: Only allow the account to authenticate from the location. Best result, being able to restrict to the specific server(s) from which it should be executed (could require a dedicated egress IP(s)).
  4. Auditing: monitor and alert for changes to these settings.

If these are in place, your exposure is that the actual system is compromised and an attacker could make unintended changes within the allowed scope during the permitted window. It is a fairly low risk, at that point, which is much better than not implementing such controls.

These could be implemented potentially within the application, or through a 3rd party trusted authentication source if it could be integrated with the application.

Dustin
  • 326
  • 1
  • 7