1

I have the below powershell myscript.ps1 which I use to ask for username and password and depending on it it copies a file to a certain destination. I wanted to make this myscript.ps1 protected so no one can edit it and see the username and password and I found the solution found here which converts the powershell script to an .exe file. When I originally run the script using powershell the below credentials form appears allowing me to enter the username and password. But after the .exe is generated and when I run it the credentials form no longer appears, instead the cosole appears saying "Credential:" I don't know why? I want the credentials form to still appear when running the exe. Anythoughts please?

$credentials = Get-Credential
if ($credentials.Username -eq "user1" -And $credentials.GetNetworkCredential().password -eq "pass1") 
{ Copy-Item "test1.pdf" "\test\test1.pdf"; } 
else 
{ Copy-Item "test2.pdf" "\test\test2.pdf"; }

Output when running the script through powershell: enter image description here

Output when running the generated exe file:

enter image description here

1

Keeping passwords secret within source code

First, I'll try to address your direct question:

I wanted to make this myscript.ps1 protected so no one can edit it and see the username and password

I assume you don't really care about people actually editing/changing the script, but only want to keep the password secure. As Ben said, transforming it into an exe really doesn't do much to prevent extraction because you are still embedding the password in it.

What you really want is a password hash, which is a one-way function that transforms a password into a hash you can embed. Given only the hash, an attacker cannot reverse the process, but you can verify a password attempt by hashing the entered password and comparing it with the known hash of the correct password.

For example, pseudocode:

$authorisedHash = 'thehashedpassword';
$password = (Get-Credential).Password;
if ((Get-Hash $password) -eq $authorisedHash)
{
    echo 'Password correct';
}

Where $authorisedHash is the precalculated result of (pseudocode) Get-Hash that you store for later comparison.

Ideally, you'd use an algorithm such as Bcrypt or PBKDF2, with a high work factor (i.e. slow it down) so brute force attacks (guessing by trying every possible password) take too long to be feasible.

By this method, the only string you ever store in your code is the original output of whichever "Get-Hash" (pseudocode) function you happen to use, which makes it very difficult if not impossible to get the original password out of your source code.


Protecting a file with a password

However, while this keeps the password secret, it really doesn't offer any security advantage. As Ben said, there's really nothing stopping the user from manually running the Copy-Item, or even just copying the file themselves with Windows Explorer.

For this kind of security, you'd need to use Windows' Access Control Lists and a separate user account that's actually authenticated elsewhere (e.g. via Windows OS login/runas commands). You need an external service or account to perform the copy, because you need to make sure the user doesn't have direct access to bypass the script.

If this isn't possible for you (e.g. because you distribute the files along with the script, but you are not an admin of the machine), then what you should be doing is encrypting the file. By encrypting the file with the password, you make sure the file is useless without the password (and therefore copying the file is useless because it remains unreadable until decrypted).

Now, this could be done via PowerShell, but there are other, easier, ways. An easy generic method is to store the file within an encrypted archive, such as ZIP1, RAR, 7z, etc., where the user must provide the password to extract. Alternatively, PDFs themselves include support for encryption, requiring a password before they can be read.


1 Note that Windows' built-in crypto support for ZIP in XP to 7, possibly 8 and 10, does not support AES. It only supports the insecure legacy ZIP encryption. So you'll need third-party tools to extract, or a self-extracting archive (exe).

| improve this answer | |
0

If a user can execute a script, they can read its contents. (You can only execute a script if you know what is says, otherwise you wouldn't know what to run.) Therefore, it is not possible to have a user simultaneously able to use your script and unable to read the password out of it. You could include the password as a cryptographic hash, but if that script runs as a normal user, the user could just bypass the script and copy test1.pdf to the destination without running your script at all.

Instead, you should apply file access controls to the destination files/folders to require the privileged operation run as an authenticated user. Then, you could supply the user-provided credential as Start-Job's -Credential parameter.

| improve this answer | |
  • Thanks for your answer. I actually find a solution where the script can be converted to an exe as shown here: gallery.technet.microsoft.com/… but after I convert my script and run the resulted .exe file instead of the credentials appearing, the console appear saying "credintial:" not sure why the credentials form no longer appears? I'll updated my question – Tak Oct 24 '16 at 1:12
  • @Tak That converter hosts the script in a lightweight PowerShell host, which has fewer features than the real one. Also note that the resulting assembly "contains the source script encoded in Base64", which can be easily reversed to obtain any secrets therein. – Ben N Oct 24 '16 at 2:09
  • So it can't be edited to make it runs the real one? – Tak Oct 24 '16 at 2:11
  • @Tak It looks like the -noConsole switch for the generator script might enable a fancier credential prompt, but you still won't get all the features of the real PowerShell host. And, of course, the password will still be recoverable if it is usable by your script, no matter how obfuscated it is. – Ben N Oct 24 '16 at 2:15
  • > Therefore, it is not possible to have a user simultaneously able to use your script and unable to read the password out of it. -- it is possible, by means of a one-way hash (bcrypt, PBKDF2, etc.) instead of the direct string comparison currently used. But that would be rather meaningless as you say in your next sentence - without external authentication/access control, the user could simply copy the file directly. Actually, a better solution might be to encrypt the file using the password as the key. Which can be done within the PDF itself, too. – Bob Oct 24 '16 at 2:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.