PowerShell Credentials and SecureStrings, Part II
In my first blog post on using secure passwords in PowerShell scripts, I discussed methods in PowerShell to keep passwords and other secure strings secure in memory and protect against memory dump attacks and the like. I showed how to use those secure strings to run commands either an alternate username and password if the commands ask for those or by building and using PSCredential objects for those commands that expect a full credential object. At the end of the blog I showed how to convert that secure string to a regular encrypted string using the Windows Data Protection API (DPAPI). While highly secure, that method of encrypting the string is limited to that one user account on that one computer by the way it uses the Windows DPAPI.
In this blog post, I will present some of the security considerations we want to be aware of when configuring security for scripts, especially automating their execution.
Defense-in-Depth
Let me first take a moment to comment on security in general. There is a term that’s used, “security by obscurity”, and that security by obscurity is insecure. There is sometimes confusion about what this means. Every security system relies on obscurity in some way. Even, for example, the very good (but not perfect!) Kerberos authentication system. For example: to log on to a Windows domain, you have to supply a username and a password. The whole system relies on that password be “obscure”, known only by the human responsible for the password. You could also use a smart card and certificates as part of the authentication process. This generally more secure as the obscurity of the authentication is even higher. You have to have a smartcard or a physical copy of the smartcard with the appropriate certificates and a PIN.
This obscurity is not what the “security by obscurity” refers to. The bad form of obscurity is when the obscurity that is required is that of the implementation itself, and to break the security one only needs to know the details of how it was implemented. For example: Storing a password in plaintext somewhere. Having your scripts read the password from the file is only secure as long as the location of the file is obscure (secret).
No security system is perfect, and they all have their flaws and situations where they are effective and not effective. Defense-in-depth is a design methodology that in principal attempts to increase security by using multiple security systems. This prevents breaking the security by exploiting the weakness of just a single system. In the previous blog post, I showed you how to encrypt the password in memory (SecureString) and write an encrypted form of the password to a file. Knowing where the file is doesnot help as the password is encrypted. The encryption acts as a second security system. If the encryption is good enough, it will be easier for an attacker to break the security by doing other things like cracking the password using various attacks, social engineering, physical espionage (e.g. hiding cameras to capture you typing the password), or rubber-hose cryptanalysis to force you to provide the password or keys.
What are we trying to protect against?
Let’s narrow the discussion back to securing strings. You might have various things you need to protect and secure strings for, but the most common and obvious are passwords. These are passwords to accounts that have privileges to perform actions on our computer systems that we want to limit access to because those or similar actions done at the wrong time or at all could be damaging to the system or your organization. A highly secure method then would always prompt a real human for a password. Unfortunatelythere are systems, interfaces, and situations where we want or need the computer to run a script automatically on a schedule or in response to some event. The end result we are looking for then is to prevent both someone gaining access to the actual password or someone using an intermediate to execute their own scripts without evening knowing the password.
Protecting Stored Passwords
We have seen how to protect passwords in memory using SecureStrings. Using ConvertFrom-SecureString with no parameters uses the Windows DPAPI to secure a password for one account on one computer. We have a few options for securing passwords for multiple people to use or on multiple computers. They all have their drawbacks. The other two options to theConvertFrom-SecureString either will not allow for automation or involves a loss of security protecting the password. It’s still better than nothing at all. In the next blog post, I will go into detail on those options and other choices we can still use with just Microsoft tools.
Password security is not an easy thing and trying to create your own system is likely to end in false security. Thinking you have a secure solution, but not having one in reality, is the real risk. Perhaps the best option is to look into 3rd party solutions such has password or key storage databases (open source PowerShell functions from Microsoft ScriptCenter that uses the Windows Credential Manager), script encryption programs like PShellExec, or custom schedulers with built in support for this, such as JAMS Enterprise Scheduler. Open source can be a real solution for this as well. Cryptography and security are computing areas where open source and open methods and algorithms have been used for decades. If everyone can see the methodology and after years of it being open, chances are the solution is good.