Configuration of secret key storage in WebSphere Application Server

Configuration of secret key storage in WebSphere Application Server

Hi all,

this time I want to introduce a more development related blog post. Anyway this is a very interesting topic for an IBM Connections / WebSphere Administrator!!!

We have a self-registration application for IBM Connections / WebSphere Portal that stores configuration data (e.g. password of a LDAP bind User) in a property file. This password should not be stored unencrypted! My colleague Konstantin thought about the possibilities how to encrypt those passwords.

There is either the possibility to do it the „WebSphere Way“:

WebSphere Application Server encodes passwords for e.g. JDBC resources only by „XORing“ them. You can find a lot of those passwords in the security.xml file in the cell-root:

Bildschirmfoto 2015-03-12 um 09.44.03

When you now goto:

http://www.sysman.nl/wasdecoder/

you can decode the password easily:

Bildschirmfoto 2015-03-12 um 09.45.23

So not really safe the whole thing…

But we are Administrators and Developers so we can find another smarter solution for this 😉

Konstantin had the great idea to encrypt and decrypt passwords and configuration data using a shared secret. The shared secret is stored in a WebSphere key store… Yep, where you normally store SSL Certificates you can also store other things. The big advantage using a WebSphere key store is that you do not need to take care about passwords (think about a p12 key store file – you need to have a password to read the content). WebSphere takes care of this and you do not need to provide passwords when reading such a key store.

Konstantin did change his code so that one can enter a plaintext password in the property file with the prefix „encrypt:“ … When starting the application, the password gets encrypted. This is a very similar procedure used by IBM when configuring the TDI AssemblyLine (profiles_tdi.properties):

Bildschirmfoto 2015-03-12 um 10.29.34

Here you enter “{protect}-“ in front of the property and enter a plaintext password. When running the assembly line the password gets encoded.

And here is how you need to setup the keystore:

1. generate a secret key and save it in a keystore

cd /ibm/WebSphere/AppServer/java/bin
./keytool -genseckey -alias mykey -keystore /ibm/config/myKeystore.jsk -storepass mypassword -storetype JCEKS

2. Go to the WebSphere administration console, “SSL certeficate and key management” -> “Key stores and certificates” , select “Key set keystores” in the dropdown and click “New…”.

key1

3. Enter the path to the keystore you have just created in the command line and the password you used when creating the keystore. The type should be “JCEKS” and the readonly checkbox checked.

key2

4. create new key set:
Enter “userManager” as the key set name.
Select the newly created keystore and uncheck the “Generates key pair” checkbox. Click “Apply”

key3

5. go to the “Active key history” and click the “Add key reference” button.
As “alias reference” enter the name of the key you have created in the command line. Enter the key password you entered when creating the key.

key4

6. “Ok” and “save”. The key is ready to use.

That`s it. You now need to recode your application to encrypt / decrypt values in the property file. Furthermore you need to read the shared secred from the keystore.

It is rather easy to get the keys from the key store using the WebSphere API:

com.ibm.websphere.crypto.KeySetHelper ksh = KeySetHelper.getInstance();
SecretKey key = (SecretKey) ksh.getLatestKeyForKeySet(keySetName);

If you are interested in some more details regarding how to use the crypt service, just use the comment function – I will post some more code examples.

Code example

We`re using a class that can retrieve the key:

 public SecretKey getKey() throws KeyException{
        KeySetHelper ksh = KeySetHelper.getInstance();

            Object key = ksh.getLatestKeyForKeySet(keySetName);
            if (key == null) {
                throw new RuntimeException(
                        "Error getting key from key set, check the configuration of the key store and the key set");
            }
            return (SecretKey) key;
    }

The class KeySetHelper is taken from the ws-runtime-xx.jar that is available in WebSphere and needs to be provided.
Then we`re using another mothod to encode / decode:

 public String encrypt(String input) throws NoSuchAlgorithmException, NoSuchPaddingException {
        Cipher cipher;
    
            cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");

            cipher.init(Cipher.ENCRYPT_MODE, keyProvider.getKey(), ivSpec);
            return new String(Base64.encodeBase64(cipher.doFinal(input.getBytes())));
       
    }

    public String decrypt(String input) throws NoSuchAlgorithmException, NoSuchPaddingException{
        Cipher cipher;
        
            cipher = Cipher.getInstance("DES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, keyProvider.getKey(), ivSpec);

            return new String(cipher.doFinal(Base64.decodeBase64(input.getBytes())));
        
    }

That`s all 😉

9 thoughts on “Configuration of secret key storage in WebSphere Application Server

    1. Hi,

      it is contained in the ws-runtime-xxx.jar file – available in WebSphere.

      Julius

  1. Hello,

    Very good useful information. Could you please share some sample code to use it in the Java application?

    1. Hi Boobalan,

      I added some code to initialize, encode and decode the keys. Hope this helps!

      Julius

      1. I am getting NullPointerException
        at com.ibm.ws.crypto.config.WSKeySet.getLatestKey(WSKeySet.java:262)
        at com.ibm.websphere.crypto.KeySetHelper.getLatestKeyForKeySet(KeySetHelper.java:389)
        when calling ksh.getLatestKeyForKeySet(keySetName); where ksh is defined as KeySetHelper ksh = KeySetHelper.getInstance();

        Can you please guide the reason. The same thing is working fine on my local machine but when I deploy it on upper Environment its breaking at this place.

  2. i have create a keyStore file in the websphere and i tried to access secret key from the java class i created and it showing it is not finding the keyname. can you suggest what should i do.

  3. DarkMatter was able to retrieve the configured password from the applications server xml configuration file and access to Oracle database. The password was found encrypted using weak algorithm (XOR) and easily reversed. This attack allowed DarkMatter to gain access to the Database layer and access the Oracle DB. The compromised Oracle instance belong to the Dashboard application; however, the Oracle database could be compromised due to several missing patches and an attacker can potentially move to another database schema and access potentially sensitive information. The oracle instance is place in the database zone and do represent a risk for the whole zone.

    How can i secure the resource.xml file. in which all the datasource configuraiton is saved

    1. Hi,

      decoding the xored passwords in WAS xml files is pretty easy, you re right!
      If you have access to those files you can definitly gain access to databases or other systems – even the WAS administrator credentials might be stored there (xored)…
      There is a good article describing the problem –> https://www.ibm.com/developerworks/library/mw-1611-lansche-trs/index.html

      IBM talks about a script called passmgr.sh to encrypt password – I do not know this tool…
      In my opinion the best way to prevent such attacks is to limit ssh login to the servers to only authorized users!
      Furthermore the files in WebSphere can be changed to be only read / writeable by the WebSphere runtime user…
      This presumes that you have a proper access management to your Linux (or Windows) Servers in place!

      hope this helps a bit

  4. I have generated a my AESKeyGenerator.jar and i have put it in KSET ->key generator class name. After i go to “Active key history” and click on “generate Key”.; so the websphere user exit call my generateKey method. Wow fantastic. Now i have a my secret key. So after same decrypt call using this key, automatically i log a new generateKey call .. so the secretKey is recreated and my privateKey crypted with old secretKey don’t run anymore. Why happen that? Who call generateKey from my AESKeyGenerator?

    Thank you for your support

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.