Weblogic SQL Authenticator and salted hash passwords.

Last 2 weeks I have been wrestling with a problem on how to make weblogic sql authenticator work correctly for user authentication when user password field is in salted hash format generated externally. I have discussed this problem in OTN as well. Posts here and here.
Though I have not a found a solution yet for our situation other than discard SQL authenticator altogether , I would like to share my learnings here.

Problem
We are migrating a legacy application to weblogic. The legacy application maintains the user id store in its internal database. The passwords are stored in salted hash format. We are planning to migrate the user id store to an oracle database and setup sql authenticator to do the authentication.

From testing so far we are not able to authenticate the users using the salted hash passwords migrated from the legacy app. The legacy app admin says the salt is
stored within the hash (??) .

So the expected steps are:

1. SQL authenticator read the salted hash from the password field in the table.
2. SQL authenticator extracts the salt from the salted hash
3. gets the plain text password from the login
4. Generates a salted hash for the plain text password using the salt obtained in step (2)
5. Compares the generated salted hash with the salted hash field in the database.

However from our testing weblogic fails to authenticate and works only if the user is created via admin console and hence use the weblogic native salted hash formats.

Cause
Actually the issue was the algorithm used by the external system was slightly different than what weblogic has implemented to parse the salted hash passswords. Had to decompile the classes , especially com\bea\security\utils\authentication\PasswordHashUtility.class to confirm this.

SQL authenticator expects the salted hash to be generated in this format : {SSHA}+plain text salt+base64Encode(sha-1{salt+plain text password})

Legacy app was generating the salted hash in the format : {SSHA}+base64Encode(sha-1{plain text password+salt}+plaintextSalt)

Legacy is conforming to RFC 3112 section 3.2 http://tools.ietf.org/html/rfc3112. Not a clue what spec weblogic has implemented.

Conclusion
Its possible to use salted hash passwords generated by weblogic to be verified by external systems using non weblogic api’s and also weblogic to verify correctly salted hashes generated by external systems. The key here is to know the format of the salted hash password used by weblogic .

It is : {SSHA}+plain text salt+base64Encode(sha-1{salt+plain text password})

Note the random salt value is always stored within salted hash field, so the verifier can always extract the salt value from it.

As per this if an external user creation utility can generate salted hash in the above format it can be verified by weblogic sql authenticator.

The other way round when weblogic generates a salted hash , e.g. I got this value when using sql authenticator to change the password to a value ‘welcome1’ {SSHA}T+4MyqBh0+e8Y3k1eekNmTjePeayFXY=.

The string without the {SSHA} prefix is 32 chars . SHA-1 generates 160 bits or 20 byte hash. Base64 encoding 20 bytes increases the size to 28 bytes.
So the last 28 chars are the hash value , the first 4 after the {SSHA} prefix should be the salt
so salt is : T+4M

so if an user enters the password in an external system, the system can generate the same salted hash using non weblogic api’s
e.g. run the below php code http://writecodeonline.com/php4/

$password="welcome1";
$salt="T+4M";
$sha_hashed = sha1($salt.$password); 
$packed = pack("H*",$sha_hashed); 
 
$encoded = base64_encode($packed); 
echo "{SSHA}".$salt.$encoded;
 

It generates the same salted hash value as what sql authenticator has stored in the db table and hence the password verification will work.

{SSHA}T+4MyqBh0+e8Y3k1eekNmTjePeayFXY=

Advertisements

About atheek

I am a Weblogic consultant working in Middleware/Integration area.
This entry was posted in Security and tagged , , . Bookmark the permalink.

7 Responses to Weblogic SQL Authenticator and salted hash passwords.

  1. Matthias says:

    Hello, that’s a most insightful article. Thanks a lot!

    Generally, it appears to me that WebLogic 10 makes it very hard to *fully replace* the module that does the username/password checking. Please update your blog when you find a solution for this.

    Related, it’s a real challenge to bring WebLogic 10.x to accept user names with an apostrophe in them (“Sean O’Connell”). Apparently, WebLogic 10 rejects those without any further ado, and that check cannot be disabled (?). Would be great to see documentation on “weblogic.security.providers.authentication.shared.DBMSUtils.verifyInputCharactersName()”

    Great software that you have to disassemble to find out how it works, in the times of open source.
    M.

  2. atheek says:

    Hack it mate 🙂 unfortunately thats the only solution i have found.. Replace WL’s class with your own version ..however client won’t accept as it violates licensing terms with oracle. I am analysing whether i can use custom dbms authenticator instead of sql authenticator. I have a feeling it is not possible as the password check is done by the jaas login code of wls which is not offered for customization.. Still searching for a solution.

  3. Olov P says:

    Hi! Great post!

    I am working on a similar problem regarding weblogic password hashes. I wish to add wls users with generated passwords before starting the domain, in offline mode. If you have the password hash, it is just a matter of putting it in a ldift-file and the server imports it to the internal LDAP at startup. The problem is that I can’t figure out how weblogic hashes the passwords for DefaultAuthenticator. When I try the same ‘trick’ as you, generating a pw hash on the format {ssha}+salt+base64(sha1(salt+password)) it does not match the hash weblogic generates. For example, ‘welcome1’ gets encoded to:
    e3NzaGF9NXlHUzluR0dKRGg5UGpCSFBTMUR4bEJaOUd1bUs1VTU=
    in weblogic, which is
    {ssha}5yGS9nGGJDh9PjBHPS1DxlBZ9GumK5U5
    in base64.
    When i try generating the hash in a perl script i get
    {ssha}5yGSgB0hkVfZBVW6FOjDFEsLVETpsSc=
    where I assumed 5yGS is the salt, which is the same as your code generates.

    Not expecting you to solve my problems, but since you seem to have been working on this maybe you have som idea about what is happening.

    Regards
    Olov

    • atheek says:

      The best way to debug this to decompile the weblogic classes to see what is happening inside.. this is how I got the format for SQL authenticator.
      Start with the stack trace for password failure and drill down to the class where the password verification is happening for a particular provider..
      Most of the authentication classes are in cssWlSecurityProviders.jar ( under the package weblogic\security\providers\authentication) in WLS_HOME/server/lib/mbeantypes directory

      • Olov P says:

        The problem occured when weblogic tried to import the entry from the ldif file into the ldap, generating an error. Here I thought weblogic didn’t follow the spec, but apparently it just doesn’t accept comments in a “dn block” in the ldif file… Now it’s working beautifully and I can generate passwords with slappasswd, a script, or whatever I fancy, as long as it follows RFC 2307.
        I think EmbeddedLDAPATNDelegate is checking the password for the user connecting to the ldap, this password is encrypted with 3DES/AES and can be found in config.xml.

        Best regards
        Olov

    • atheek says:

      Also did some quick checking on the EmbeddedLDAPATNDelegate class in the above package which has this method, & looks like the password is stored in encrypted format.

      String getPasswordForUser(AuthenticatedSubject requestor, String userName)
      throws NotFoundException, InvalidParameterException
      {
      String password = getPasswordForUser(userName);
      if (password == null) {
      return null;
      }
      if (this.encryptionService == null) {
      this.encryptionService = new ClearOrEncryptedService(SerializedSystemIni.getEncryptionService());
      }

      if (!this.encryptionService.isEncrypted(password)) {
      return null;
      }

      return this.encryptionService.decrypt(password);
      }

    • atheek says:

      Great!! that you made it to work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s