Usman ur Rehman Ahmed's blog

Decrypt aspnetMembership Provider based DNN Passwords

The brief steps are as following,

1- Create a new website (I am using C# here) in Visual Studio

2- Inside the web.config file, add the machineKey tag and provide “validationKey” and “decryptionKey” as found from web.config file of your running DNN site using which passwords are stored. (The keys provided here will work with the password as given in step 5)

<machineKey validationKey="5D47DA8BBE8C9D02378BC3360FD6724A43C69016" decryptionKey="F5292CB499D6A71955A7B389BFBF3712D0A48D1971DEE889"

decryption="3DES" validation="SHA1" >

3- Create a new class and name it, “RecoverPassword.cs”

4- Copy paste the following code inside the above created class. This way we inherit our class from aspnet membership provider pattern class and thus will use its decryption procedure to decrypt the passwords. If you want to do that manually, do remember that Ctrl+K+M is a nice shortcut to implement base class methods which saves quite an effort from your end.

using System;
using System.Configuration.Provider;
using System.Text;
using System.Web.Security;

public class RecoverPassword : MembershipProvider {

    //Create a static instance of this class as a singelton  

    private static readonly RecoverPassword _instance = new RecoverPassword(); 

    public override MembershipPasswordFormat PasswordFormat {
        get {
            return MembershipPasswordFormat.Encrypted;
        }   
    }   

    public static string RecoverEncryptedString(string target)   
    {       
        try       
        {           
            // Decode the password in Base64           
            byte[] data = Convert.FromBase64String(target);
            //Get advantage of the DecryptPassword method
            byte[] decryptedPassword = _instance.DecryptPassword(data);
            string encodedPassword = Encoding.Unicode.GetString(decryptedPassword);
            // Remove the salt value prepended to the value
            // Salt value doesn''t do anything more than being appended to thte password string, just strip it out
            return encodedPassword.Substring(8);
        }
        catch (ProviderException ex)
        {
            throw ex;
        }
    }

    public override string ApplicationName
    {
        get
        {
            throw new NotImplementedException();
        }
        set
        {
            throw new NotImplementedException();
        }
    }

    public override bool ChangePassword(string username, string oldPassword, string newPassword) {
        throw new NotImplementedException();
    }

    public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string

newPasswordAnswer)
    {
        throw new NotImplementedException();
    }

    public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer,

bool isApproved, object providerUserKey, out MembershipCreateStatus status)
    {
        throw new NotImplementedException();
    }

    public override bool DeleteUser(string username, bool deleteAllRelatedData)
    {
        throw new NotImplementedException();
    }

    public override bool EnablePasswordReset
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override bool EnablePasswordRetrieval
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new NotImplementedException();
    }
   
    public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
    {
        throw new NotImplementedException();
    }

    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
    {
        throw new NotImplementedException();
    }

    public override int GetNumberOfUsersOnline()
    {
        throw new NotImplementedException();
    }

    public override string GetPassword(string username, string answer)
    {
        throw new NotImplementedException();
    }

    public override MembershipUser GetUser(string username, bool userIsOnline)
    {
        throw new NotImplementedException();
    }

    public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
    {
        throw new NotImplementedException();
    }

    public override string GetUserNameByEmail(string email)
    {
        throw new NotImplementedException();
    }

    public override int MaxInvalidPasswordAttempts
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override int MinRequiredNonAlphanumericCharacters
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override int MinRequiredPasswordLength
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override int PasswordAttemptWindow
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override string PasswordStrengthRegularExpression
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override bool RequiresQuestionAndAnswer
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override bool RequiresUniqueEmail
    {
        get
        {
            throw new NotImplementedException();
        }
    }

    public override string ResetPassword(string username, string answer)
    {
        throw new NotImplementedException();
    }

    public override bool UnlockUser(string userName)
    {
        throw new NotImplementedException();
    }

    public override void UpdateUser(MembershipUser user)
    {
        throw new NotImplementedException();
    }

    public override bool ValidateUser(string username, string password)
    {
        throw new NotImplementedException();
    }
}

5- Your default.ascx.cs file should look like this, (Optionally change the password in Page_Load to the encrypted password you want to decrypt).


using System;public partial class _Default : System.Web.UI.Page {

    protected void Page_Load(object sender, EventArgs e)        
    {
         //This password can be obtained from the DNN''s table aspnet_Membership column "Password"       
         //Or you can query ther datbase row and call decryption method for each user       
         string password = "vhicPWw3Eo/+z+mrKM5ZQCIcURj1O5Cq9Epw942lfpmsDPagupzLGw==";

        //Call our inherited class to get Decrypted Password       
        string recoveredPassword = RecoverPassword.RecoverEncryptedString(password);

        //Write down the decrypted password            
      Response.Write(recoveredPassword);   
    }
}

6- Right click > View in Browser and the password is decrypted on a fly. If you surf on this topic you will find that DNN uses password salt to encrypt values. What actually goes inside the encryption is not important.  What is important to understand is that, how password salt is used in the encryption process. If you would know that, you will easily be able to decrypt the password.

What happens is as following, we get the encrypted password. Normalize it to base 64 byte stream. We then convert this encoded byte stream into decrypted byte stream (using base class decryptPassowrd method). Then we convert this decrypted byte stream into Unicode string and strip out the first 8 characters which makes up the portion of password salt. The remainder is our decrypted password.

11
To Posterous, Love Metalab