“Is there any way to mask the passwords that my users enter when running my Windows Scripts?”
Password masking is a method of hiding a user’s keyboard input so that another person cannot see what’s being typed on screen. This security measure helps to ensure that “shoulder surfers” can’t gain passwords by simply looking over someone’s shoulder. There are two different ways that password masking can be implemented from within the Windows Script Host environment.
The first method of password masking makes use of the Standard Input stream provided by the command prompt window. Naturally, this method requires that your scripts are run using the Cscript.exe engine rather than from Wscript.exe. That’s not a problem. Starting your script off with the following snippet will ensure that your script runs in Cscript regardless of how it’s launched.
If LCase(Right(Wscript.FullName, 11)) <> "cscript.exe" Then strPath = Wscript.ScriptFullName strCommand = "%comspec% /k cscript " & Chr(34) & strPath & chr(34) Set WshShell = CreateObject("WScript.Shell") WshShell.Run(strCommand) Wscript.Quit End If
WScript’s FullName method returns the full path to the Windows Script Host engine that is running the current script. It’s a simple matter of checking whether cscript.exe was used and then running the script with cscript.exe if it wasn’t.
Most likely you’ll be wanting to recreate a type of login scenario. We’re going to focus on using the Standard Input and Standard Output streams. In other words, this is the keyboard input and screen output of the command window.
WScript.StdOut.Write "Enter Username: "
The WScript object provides access to both the StdIn and StdOut streams. In this line, I’m using the Write method to write text to the command window. The cursor will remain at the end of the text that I provide making this text appear as a text prompt.
strUser = WScript.StdIn.ReadLine
I can then accept user input by accessing the Standard Input stream. The ReadLine method that I’m using will return all text characters until it reaches a line break. In other words, it will fill the buffer with text from the standard input stream until the user presses the enter key. It will then return a text string containing the contents of the stream buffer. Because we’re reading an entire line, the cursor will automatically move to the next line in the command window.
Now we’re ready to do the same thing–this time to get the user’s password. However, we want to mask this password input so that it cannot be read on screen. As it turns out, there’s a very simple COM object available that provides that functionality.
Set ScriptPW = CreateObject("ScriptPW.Password") WScript.StdOut.Write "Enter password: " strPass = ScriptPW.GetPassword() WScript.StdOut.WriteLine ""
The first step in to create an instance of the ScriptPW.Password object. This is a scriptable COM interface for ScriptPW.dll which ships natively in most newer versions of Windows.
Once a reference to the ScriptPW object has been created, the StdOut stream is used to create a prompt as before. This time around, however, we won’t be using the StdIn stream to capture user input. Well, at least not directly! Instead we’ll use the only method exposed by the ScriptPW object, GetPassword. This method will return text from the StdIn stream without displaying it on screen. A variable is used to capture the text string returned by this method.
Since the GetPassword method doesn’t display the text it receives, the cursor will not move as a result of the user pressing the enter key. If you need to move the cursor to a new line, you can pass an empty string to the StdOut stream’s WriteLine method.
And there you have it. The strPass variable now contains the password that was provided by the user in a masked fashion. No need to pass passwords as script arguments or have them hard-coded into your scripts. The user instead has to pass them to the script at run time in a much more secure fashion.
The second method of masking a password makes use of HTML. You can either automate Internet Explorer to create a web form, or more appropriately you can embed this into an HTML Application. In any case, the syntax is pretty simple.
<html> <head> <meta http-equiv="Content-Type" content="text/html; charset=windows-1252" /> <title>Login Application</title> <hta :application applicationname="LoginBox" border="dialog" borderstyle="normal" caption="My HTML Application" contextmenu="no" maximizebutton="no" minimizebutton="yes" navigable="no" selection="no" showintaskbar="yes" singleinstance="yes" sysmenu="yes" version="1.0" windowstate="normal" /> </head> <body> </body> </html>
This code will create a basic HTML Application. Save it as a plain text file with a .hta extension.
<form id="LoginForm"> Enter Username: <input type="textbox" id="UserName"/><br /> Enter Password: <input type="password" id="Password"/><br /> <input type="submit" value="Login"/> </form>
In the body section, you’ll want to create a simple form. Notice that I’ve named each element using the ID attribute. This is true for the form element as well as each input element. You’ll need these IDs later in order to access the form controls with VBScript.
<script language="vbscript"> Function LoginForm_OnSubmit strUser = LoginForm.UserName.Value strPass = LoginForm.Password.Value End Function </script>
Finally, you’ll need to add this script to the head section of your HTA. This script responds to the OnSubmit event of the LoginForm element. Whenever the form is submitted, the values of the UserName and Password fields are assigned to strUser and strPassword, respectively. You can continue adding whatever code you need to this function.