Tuesday, June 4, 2013

LoadRunner Password Encoder and lr_decrypt()

If you ever need to disguise a password in a VuGen script, you will no doubt have used the lr_decrypt() function. If you have stopped to think for a second or two, you will have realised “encrypting” the password in your script doesn’t make it more secure in any meaningful way. Anyone with access to the script can decode the password with a single line of code:

// As a security measure, LoadRunner password encryption is about as effective as rot13.
lr_output_message("The secret password is: %s", lr_decrypt("50de7ec44d2ff7033c2fcb9e5cf7307799d7"))
So, if this feature doesn’t really make anything more secure, why was it included in LoadRunner? This is a classic example of a “pre-sales feature” – during the sales process, you just know that a potential customer is going to have an attack of “due dilligence” and say that everyone knows that passwords should not be stored in plaintext and they couldn’t possibly buy the product because it is so insecure. As a pre-sales engineer, you can say “it’s okay, all the passwords in the script are encrypted”, and the barrier to sale suddently disappears.

Encoding Passwords


There are several ways that a password string can be encrypted/encoded:
During recording, if the VuGen recording engine sees that you have made an HTTP POST request with a name/value pair called “password”, it will replace the password value with a call to lr_decrypt() when the script is generated.
When editing your script in VuGen, you can right-click any string constant function argument and 

By using the Password Encoder, located under Start > Programs > HP > LoadRunner > Tools > Password Encoder
There is also a command line version of the Password Encoder, that can be found under LoadRunner\bin\PasswordEncoderConsole.exe. Note that the command line program can also be called from a LoadRunner script using popen() or invoked from a batch file if you need to encode a large number of passwords.

Decoding Passwords

An encoded password can be translated to plaintext in two ways:


  • By calling lr_decrypt() and using the plaintext string that is returned by the function. 
  • Recently added to VuGen (with the release of LoadRunner 11.50), is the ability to right-click on a call to lr_decrypt() in your script and select “Restore Encrypted String” from the context menu. 

Source Code Examples

If you want to have a play with with the LoadRunner encrypt/decrypt function directly (without using lr_decrypt()), you can do this by calling the vugen_crypt_encrypt() and vugen_crypt_decrypt() functions in VuGenCallback.dll.

// C example
Action()
{
    char* plaintext = "my secret password";
    char encryptedBuf[100];
    char decryptedBuf[100];
 
    lr_load_dll("C:\\Program Files\\HP\\LoadRunner\\bin\\VuGenCallback.dll");
 
    lr_output_message("plaintext: %s", plaintext);
    vugen_crypt_encrypt(plaintext, -1, encryptedBuf);
    lr_output_message("encrypted: %s", encryptedBuf);
    vugen_crypt_decrypt(encryptedBuf, decryptedBuf);
    lr_output_message("decrypted 1: %s", decryptedBuf);
    lr_output_message("decrypted 2: %s", lr_decrypt(encryptedBuf));
 
    return 0;
}
// C# example. Use the .NET vuser type to run this code.
namespace Script
{
    using System.Runtime.InteropServices; // DllImport
    using System.Text; // StringBuilder
 
    public partial class VuserClass
    {
        // Note: this program uses VuGenCallback.dll, which is also used by 
        // DecryptAddin (which gives the context menu encrypt/decrypt options in VuGen).
        // The PasswordEncoderConsole.exe and PasswordEncoder.exe programs use 
        // PwdEncoder.dll instead.
        // Note: do not add a reference to this DLL in the Runtime Settings, as it will
        // give a compilation error (due to a missing manifest).
        [DllImport(@"C:\Program Files\HP\LoadRunner\bin\VuGenCallback.dll")]
        private extern static int vugen_crypt_encrypt(string currentString, int miLen, [MarshalAs(UnmanagedType.LPStr), In, Out] StringBuilder encodedString);
        [DllImport(@"C:\Program Files\HP\LoadRunner\bin\VuGenCallback.dll")]
        private extern static int vugen_crypt_decrypt(string encodedString, [MarshalAs(UnmanagedType.LPStr), In, Out] StringBuilder decodedString);
 
        public int Action()
        {
            string plaintext = "my secret password";
            var encrypted = new StringBuilder();
            var decrypted = new StringBuilder();
 
            lr.output_message("plaintext: " + plaintext);
            VuserClass.vugen_crypt_encrypt(plaintext, -1, encrypted);
            lr.output_message("encrypted: " + encrypted);
            VuserClass.vugen_crypt_decrypt(encrypted.ToString(), decrypted);
            lr.output_message("decrypted 1: " + decrypted.ToString());
            lr.output_message("decrypted 2: " + lr.decrypt(encrypted.ToString()));
 
            return 0;
        }
    }
}