Tuesday 27 October 2009

Part II - Working with WLS 10.3.1 SQLAuthenticator password algorithms

In the previous post we looked at how to configure the SQLAuthenticator password encryption options. Among other encryption algorithms we discovered that on creating a user from the WLS console, WLS would create the associated user in a database table with password "password" encrypted to:

{SHA-1}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

...when the SHA-1 option was set.

As was mentioned in the previous post, as the database table with its users and passwords may be shared by non-WLS based applications, it's important that those systems can encrypt passwords and compare them to the WLS result. In other words, in the example above, given that WLS generated a SHA-1 encrypted password, if another system uses the same SHA-1 algorithm will it generate the same encrypted password allowing it to compare the database SHA-1 encrypted password against the SHA-1 encrypted password it has?

In order to check we can get the same encrypted results, we'll investigate generating a SHA-1 password using the Oracle database's encryption facilities (so in this case the database acts as the other subsystem), comparing the database's encrypted SHA-1 password to that of WLS.

The following solution owes thanks to Sean at Oracle Support who very patiently led me in the right direction with my findings.

dbms_crypto

Oracle database fans will be familiar with the dbms_crypto package that provides encryption support.

dbms_crypto allows us to generate an encrypted password that we can compare to the WLS result. From table 34-1 of the dbms_crypto link, we note that dbms_crypto supports the following one-way hash algorithms: SHA-1, MD4 and MD5. As WLS via the JCE extensions (see the previous post) supports SHA-1, MD2 and MD5, it's fortunate we picked SHA-1 for this example.

The following anonymous PL/SQL block shows an example using the dbms_crypto package hash function with SHA-1 to produce an encrypted result:

DECLARE
input_string VARCHAR2(8);
raw_input RAW(128);
encrypted_raw RAW(2048);
BEGIN
input_string := 'password';
raw_input := utl_raw.cast_to_raw(convert(input_string, 'AL32UTF8','US7ASCII'));

encrypted_raw := dbms_crypto.hash(src => raw_input, typ => dbms_crypto.hash_sh1);
dbms_output.put_line('Output: ' || encrypted_raw);
END;
/

Output: 5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8
Note the output, a hex value, and doesn't match our WLS output for the same plaintext password "password" encrypted with SHA-1.

The missing bit of information (that I haven't found documented) is that WLS after encrypting the plaintext password, as confirmed by Oracle Support, WLS then converts the output to base 64. In the case of the dbms_crypto hash function, it converts the encrypted result to Hex. In order to get the same result you need to convert the Hex output to base 64.

There's a number of different ways to do this. One is to use a Java routine in the database, converting the dbms_crypto Hex result to a byte array, then byte array to base 64. A suitable algorithm would be:

byte[] bytearray = hexStringToByteArray("5BAA61E4C9B93F3F0682250B6CF8331B7EE68FD8");
String base64encoded = new BASE64Encoder().encodeBuffer(bytearray);
...where the hexStringToByteArray function is borrowed from Dave L on StackOverflow.

The end result is: W6ph5Mm5Pz8GgiULbPgzG37mj9g= ... finally matching what WLS wrote to the database (missing the algorithm prefix of course).

Conclusion

Why the WebLogic Server's SQLAuthenticator can make use of different encryption algorithm when writing to the database, it's important to ensure that the results are expected and understood and can be used by other subsystems.

Saturday 10 October 2009

My OOW presentations

If you're heading to OOW and would love to hear my Aussie accent, my sessions are:

SOA Lite: A taste of SOA with a smidgen of Web Services

S312176 - Sunday 13:00 - 14:00 - Moscone West L3 Room 3000

Abstract: Attempting to gorge yourself on a five-course SOA meal may result in a stomachache and a bill you can least afford at the moment. Instead, a quick and easy recipe with some simple Web services ingredients will give your systems that little taste of SOA you so crave. This session describes why Web services may be a better fit for you than SOA, discusses qualities of contemporary Web services and what skills to focus on when starting out with Web services, and presents a few hints and tips from the Web service trenches.

Oracle JDeveloper 11g JAX-WS Web Services: As easy as 1-2-3: XSD, WSDL, Generate!

307476 - Tuesday 17:30 - 18:30 - Hilton Hotel - Golden Gate 8

Abstract: Web services used to be hard. Creating XML schemas, long-winded Web Services Description Language (WSDL) code, and back-end Java code took much effort. Today Oracle JDeveloper 11g enables developers to visually design both the schemas and WSDL code by drag and drop and generate Web services based on both of these with the latest Java EE JAX-WS/JAXB Web service standards with just a few clicks. Finally programmers can get back to thinking about the programming problem they need to solve without wasting time setting up the Web service artifacts, which can be tedious, error-prone, and very repetitive. Learn more in this session.


In addition we have three ADF Enterprise Methodology Group sessions, one an official session and the other two part of the Unconference:

Oracle ADF Enterprise Methodology Group

312516 - Sunday 10:30 - 11:30 - Moscone West L3 - Room 3014
+ double session Wednesday 13:00 - 15:00 - Moscone West Floor 3 Overlook 1

Abstract: Although Oracle provides leading-edge software to build enterprise applications, there’s more to creating productive teams and delivering successful projects than just the tools. The Oracle ADF Enterprise Methodology Group, formed by Oracle Application Development Framework (Oracle ADF) practitioners around the world to fill that gap, considers wider issues such as best practices, maximizing code reuse, optimizing teamwork, and more. In this session, Oracle JDeveloper and Oracle ADF experts, including Oracle staff and Oracle ACEs, talk about such high-level Oracle ADF considerations. The Oracle ADF Enterprise Methodology Group is meeting at Oracle OpenWorld under the banner of the ODTUG Fusion Middleware SIG for 2009.


I hope to see you at OOW!

Monday 5 October 2009

Part I - Working with WLS 10.3.1 SQLAuthenticator password algorithms

WebLogic Server 10.3.1 supports loading user credentials and roles from a number of different sources, such as LDAP or a database, through the concept of "Security Providers". In order to work with a database table structure a "SQL Authenticator" provider is required.

Edwin Biemond has a good example of setting up both the database table structures and configuring the WLS SQL Authenticator against these tables. To keep the example simple, for the password field in the JHS_USERS table Edwin's has set the SQL Authenticator to write raw plain text passwords to the table. This makes it really easy for demonstration purposes to see what's written to the database.

To extend Edwin's post, a common requirement will be that:

a) The password value is written in an encrypted form to the database
b) Other non-WLS applications can generate the same encrypted result such that the encrypted passwords can be compared

The need for point "a" is obvious, unencrypted password in the database is a security weakness. But what about "b", why would you want this?

For many organisations the list of users and roles will be stored in database tables, and that information will be sourced by many different subsystems implemented in different technologies. It's not uncommon for sites to have Oracle Forms, .Net, JEE (and ADF of course!) applications all relying on the database user tables for their authentication and authorisation information.

Each of these subsystems would require users to login. The subsystem would then encrypt the password, retrieve the corresponding password from the database for the identified user, and compare the results. If they compare, we have a valid user; if the encrypted passwords are different, ring the alarm bells, we have an imposter (or at least make them login again ;-)

All things would be well with this solution, until you throw in the fact that each subsystem may support different encryption algorithms that would produce different results, effectively failing the encrypted password comparison each time. It becomes essential therefore that WLS's SQL Authenticator supports different encryption algorithms in order to provide as much flexibility as possible.

Password Settings

On configuring a SQL Authenticator as per Edwin's example, on accessing the Provider Specific information (from the WLS console select Security Realms -> myrealm -> Providers tab -> your named SQL Authenticator -> Configuration tab -> Provider Specific tab), you'll note the following options that influence the generation of encrypted passwords:

* Plaintext Passwords Enabled – true/false – relates how passwords are read from the database table. If true when WLS retrieves the password from the database, and it encounters a non encrypted password, it will undertake a non encrypted comparison between the user's password who is attempting to login against the database retrieved password. If false, WLS will enforce the database password must be encrypted for it to undertake an encrypted password comparison.

The question arises, how does WLS know the database password is encrypted? The answer is derived from the next detailed property Password Style Retained, where WLS when writing a new encrypted password to the database prefixes the encrypted password with the encryption algorithm that was used to encrypt the password. If it's missing, WLS assumes a plaintext password.

If the Plaintext Passwords Enabled property is false, one other side effect is if you attempt to set the Password Style property to PLAINTEXT, then update a user's password in the database, WLS will throw an error stating it doesn't support PLAINTEXT passwords:

[Security:099063]Plaintext password usage was rejected.

Thanks to Ming at Oracle Support for clarifying this property.

* Password Style Retained – true/false – the following properties unlike the Plaintext Passwords Enabled property deal with when updating existing user passwords in the database table, not when the password is read. When WLS writes a password to the table's password field, along with the encrypted text, it prefixes the password with the password algorithm used wrapped in ellipses. For example if the SHA-1 algorithm is used, the password would look like:

{SHA-1}W6PH5MM5PZ8GGIULBPGZG37MJ9G=

If the Password Style Retained property is set to true, and the existing password has a different encryption algorithm to that specified in the Password Algorithm field, WLS will use the latter to update the password. If Password Style Retained is set to false, regardless, WLS will overwrite the password with that specified in the Password Algorithm field.

* Password Algorithm – text field – default SHA-1 – as per the WLS documentation this can be any Java Cryptography Extension (JCE). Questionably what are the allowable values derived from the JCE? These are listed in the JSE 6.0 Java Cryptography Architecture Standard Algorithm Name Documentation.

For password generation we want a hash (aka. message digest or 1-way encryption) algorithm. From the documentation we find that our options are limited to SHA-1 (the default Password Algorithm value), MD2 and MD5.

Note that the JSE documentation states the bit size of the produced message digest (SHA-1 = 160-bit, MD2 = 128-bit, MD5 = 128-bit), which will influence the size of your password field to store the encrypted database value.

The Password Algorithm can be ignored if the Password Style is PLAINTEXT, or, the Password Style Retained is set to true and the password to be updated does not match the current Password Algorithm's specified function.

* Password Style – PLAINTEXT, HASHED, SALTEDHASHED – as guessed the PLAINTEXT option will write the unencrypted password to the database. A value of HASHED implies the Password Algorithm will be used. SALTEDHASHED also produces encrypted passwords though different from HASHED. I'm currently unsure of the difference between HASHED and SALTEDHASHED, the WLS documentation doesn't differentiate between them, though it does result in a different encrypted value.

Testing

Assuming you've configured your SQL Authenticator correctly as per Edwin's post, let's test what the different settings of the properties do.

For our testing let's assume there's always an existing user ALPHA whose password we want to update, as well as new users BETA, CHARLIE and DELTA (and so on) who we want to create with a new password.

First test

Plaintext Passwords Enabled = true
Password Style Retained = true
Password Algorithm = SHA-1
Password Style = HASHED

For the existing user ALPHA the encrypted password doesn't include the algorithm prefix (ie. {SHA-1}), in fact it was created by some other system that doesn't include the prefix. The ALPHA's password will be updated to "password".

For a new user BETA the password will be set to "password".

First result

Updated user ALPHA password = "password"

For the ALPHA users this result occurs because WLS encounters the Plaintext Passwords Enabled set to true, and the original password stored for the ALPHA user is unencrypted (ie. it's missing the algorithm prefix). WLS therefore decides an update to the password must be a plaintext password update.

New user BETA password = {SHA-1}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

In this case the BETA user makes use of the SHA-1 algorithm.

Second test

Plaintext Passwords Enabled = true
Password Style Retained = false
Password Algorithm = SHA-1
Password Style = HASHED

Same as the last test, for the existing ALPHA user the encrypted password doesn't include the algorithm prefix (ie. {SHA-1}), in fact it was created by some other system that doesn't include the prefix. The ALPHA's password will be updated to "password".

For a new user CHARLIE the password will be set to "password".

Second result

Updated user ALPHA password = {SHA-1}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

New user CHARLIE password = {SHA-1}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

In this case the Password Style Retained has overwritten the updated user ALPHA's password style with the new SHA-1 algorithm equivalent as the Password Style Retained = false setting removes the original plaintext algorithm – in other words the SHA-1 algorithm takes precedence. As expected the CHARLIE user's passwords uses the SHA-1 algorithm by default.

Third test

In this test we'll use the existing SHA-1 user ALPHA SHA-1 password, while switching to the MD2 algorithm, while not retaining passwords styles:

Plaintext Passwords Enabled = true
Password Style Retained = false
Password Algorithm = MD2
Password Style = HASHED

Existing ALPHA password = {SHA-1}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

For a new user DELTA the password will be set to "password".

Third result

Existing ALPHA password = {MD2}8DiBqIxuORNfDsxg79YJuQ==

New user DELTA password = {MD2}8DiBqIxuORNfDsxg79YJuQ==

As can be seen WLS switches to the MD2 algorithm in both cases as the Password Style Retained = false property enforces this.

Fourth test

In the last test we'll switch back to the SHA-1 algorithm, and attempt to update the ALPHA user's MD2 password to the SHA-1 equivalent asking WLS not to retain the existing password style:

Plaintext Passwords Enabled = true
Password Style Retained = false
Password Algorithm = SHA-1
Password Style = HASHED

Existing ALPHA password = {MD2}8DiBqIxuORNfDsxg79YJuQ==

Fourth result

Existing ALPHA password = {SHA-1}W6ph5Mm5Pz8GgiULbPgzG37mj9g=

As expected the ALPHA user's password is changed from the MD2 to SHA-1 encrypted password, again as the Password Style Retained = false property takes affect.

Conclusion

At this point we've seen how WLS can generate encrypted passwords using different algorithms down to the database. From here it's important to check the encrypted results in the database are actually "standard". In other words if a competing technology uses the SHA-1 algorithm to encrypt a password for example, will it see the same encrypted result WLS produced. This will be addressed in a following post.