securely storing passwords for reuse w/o exposing them

Hi. This is a topic that has been discussed many times in various places, but so far I haven’t found any satisfactory answer/solution.
What I need is to:

  • securely store passwords/credentials in a script
  • be able to distribute the script to other users and machines so that they can run the script, but never be able to extract the password in a manner that would allow them to use the credentials elsewhere

There are two reasons for this - automation and task delegation (without permission delegation). I need operators (humans) and automation systems (for example SC Orchestrator) to run scripts that perform action as privileged/elevated users, but these users themselves can never have the permissions of these privileged users.

There are several “solutions” to this that I’ve found:

  • use SecureStrings and encode the password with a key into a separate file - doesn’t solve a thing since in order to run the script the user needs access to the file with the key and therefore the user can then access the SecureString and decode it…
  • use EFS encryption … same problem as above
  • convert the PS script to an .EXE file (PS2EXE or PowerGUI) - both look nice, but they still expose the script in plain text. PS2EXE even includes a switch to extract the PS script from the EXE file, PowerGUI allows you to password protect the extraction, but from what I understand the script is still exposed as plaintext during runtime - so it can be read from the memory by the user?

Is there any solution to this? I assume (maybe incorrectly), there’s no direct solution to this in PowerShell itself. In my layman’s terms, I can’t imagine why it’d be so complicated to encrypt/hash a script and then convert it to an EXE without directly exposing the script content anywhere (extraction, runtime - memory) etc.

I hope I’m overlooking some solution since this must be pretty common problem for many organizations.

Thanks in advance

I don’t think what you’re describing is possible if everything runs locally on the non-privileged user’s computer. If the user is allowed to run a script, and the script is able to retrieve and use a stored password, then by definition the user has the ability to retrieve and use the same password. (And the instructions for doing so are right there in the script.) It doesn’t really matter whether this is a script or a compiled executable. Executables are still lists of instructions, and all you’ve done is make it harder to retrieve the password, but never impossible.

The only thing I can think of that might suit your needs is to have a custom server which acts as an intermediary. You grant users access to contact this server, and the server is responsible for storing, retrieving and using the credentials on behalf of the user. That way the stored credentials are never sent to the user’s computer. There are several ways this sort of solution could become a security vulnerability, though, if it’s poorly implemented or designed.

Dave, thanks for responding.
When you speak of the intermediary server, can you be more specific how this would work? Or would this have to be some specialized software?

It would be something custom developed, unless you find a similar solution that already meets your needs; I haven’t searched for one.

The general idea would be this: A user connects to a service (which could be just about anything; a RESTful API would probably be the current preference) and authenticates, selects a script to execute, and passes any necessary parameters to the server. The server side determines whether the user is authorized to run the script, and if so, loads up the credentials that have been stored for that particular script and executes it with the user’s parameters. Any output from the script would be passed back to the user (via XML or JSON in a REST API, most likely.)

Just subscribing for possible future updates. I’ve been wondering this as well.

I agree with Dave Wyatt that you really can’t store the passwords in the way you request. Either the script can get the password and then you also can get it (with more or less work involved, depending on how it is stored and made available), or it’s impossible for you to get to the password but then it will also be impossible for the script.

However, you should be able to achieve and solve the end-goal scenarios you describe without storing passwords yourself. You could do this by configuring custom remoting endpoints configured to allow execution of only the functionality you want them to be able to execute (e.g. only the specific powershell functions which you have created yourself for this purpose, or those which you allow the user to use) and not allow them to execute anything else using that endpoint.

So what I’d suggest you to do is read up the following help sections:

Get-Help about_session_configurations
Get-Help about_session_configuration_files

Also, you can get a list of relevant commands using:

Get-Command *sessionconfiguration*

Pay special notice to Register-PSSessionConfiguration and New-PSSessionConfigurationFile. For the given scenarios, you want very direct control of what can be achieved using the endpoints, so I would think you would want to configure the session to be in NoLanguage mode and also only allow execution of specially crafted functions which perform the things you want the user to be able to perform. When you register the endpoint using Register-PSSessionConfiguration, you can specify RunAsCredential making commands run on that endpoint run as another user, in this case a user with higher permissions (which is why I’d suggest restricting the endpoint as much as possible; to NoLanguage and only specific functions).

I’d forgotten about that -RunAsCredential parameter for remoting endpoints. That’s certainly easier to implement than a REST API on a web server, but be careful to properly hide all the commands you don’t want users to run, and don’t forget to set the language mode to ‘NoLanguage’. If you get that part wrong, people might be able to execute any code they like as your elevated account.

As luck would have it, Boe Prox is doing a series of Hey, Scripting Guy! blog posts this week on Remoting, and today’s article covers this exact topic: . (The only thing it doesn’t have, with regards to this thread, is the -RunAsCredential parameter when calling Register-PSSessionConfiguration , but you can easily add that.)

Dave & Robert, thanks both for responding. What a nice coincidence, I’ll go read up on session configurations and follow that blog series then.