I saw a question get posted to an internal discussion group
that went something like this:
I
have a console application which uses CredUICmdLinePromptForCredentials. How can I add
support to allow a user to pipe a password from a file into my tool? For example:
type
password.txt | myTool.exe /user:user1
Answer: You
don't.
The Long Answer:
The whole purpose for CredUICmdLinePromptForCredentials, its entire reason for existence, is to
provide users a slightly more secure mechanism for supplying private authorization
information.
- If a password is stored in clear text on your hard-drive, then it is not secure.
- If a password is sent in clear text via the command shell's pipe/redirection mechanisms, then it is not secure.
- If a password is cached somewhere (clear or obfuscated) that can inherently be used by an un-authorized person (replay attack), then it is not secure.
If you aren't
attempting to be secure with a user's password, then there is no reason to use
CredUICmdLinePromptForCredentials, just read the file or input stream yourself
and be done with it.
Public Service Announcement: If you use one of the
CredUI*PromptFor*Credential APIs, be sure to either nuke the password (SecureZeroMemory)
or encrypt it (CryptProtectMemory)
as soon as possible (i.e. immediately
after the call and/or after any verification that needs to happen).
Now, the better question revolves around how one should
secure credentials such that they can still be used in an automated process.
Unfortunately this quickly degenerates into a philosophical question as
computers are inherently insecure, especially if you have physical access to it
(debuggers, physical analysis of hardware, etc. can expose your secrets). The
issue becomes even more philosophical considering that the objective of the
tool hasn't been scoped or discussed (and wasn't in the original post).
For the purpose of this (now philosophical) exercise, we
assume that we are not on a single computer - as we are dealing with automation
and want to distribute the credentials in a file. If we were on a single
computer we might utilize the Credential Manager
to help store this information locally.
To secure some chunk of data, we need to encode it. In order
to decode the information we need a key. Unfortunately we now need to store the
private key in a secure manner. Do we encode the key to secure it? If we
fast-forward a bit, you can easily see that this quickly turns into a
"which came first, the chicken or the egg" type of problem.
Since computers are insecure, the best place to store private
information is not in a computer. The
typical place is in a human. Now we've come full circle. In order to secure the
file that contains a password, we need someone to remember a password (and
people wonder why security is tricky). Now you can see that our philosophical
exercise is flawed, so really the question is not "how do we secure the
file", but "how secure is good enough?"