Security configuration for Myfaces Core 1.1.8, 1.2.9, 2.0.1 and later

The updated web config param list used by myfaces core could be found here:

http://myfaces.apache.org/core12/myfaces-impl/webconfig.html http://myfaces.apache.org/core20/myfaces-impl/webconfig.html

First of all, to enable/disable encryption of view state you can use this param:

    <!-- To enable encryption -->
    <context-param>
        <param-name>org.apache.myfaces.USE_ENCRYPTION</param-name>
        <param-value>true</param-value>
     </context-param>

    <!-- To disable encryption -->
    <context-param>
        <param-name>org.apache.myfaces.USE_ENCRYPTION</param-name>
        <param-value>false</param-value>
     </context-param>

Encryption is enabled by default. Note that encription must be used in production environments and disable it could only be valid on testing/development environments.

With myfaces you can configure the algorithm used for encription of view state using this params:

    <!-- Indicate the encryption algorithm used for encrypt the view state. -->
    <context-param>
        <param-name>org.apache.myfaces.ALGORITHM</param-name>
        <!-- See http://java.sun.com/j2se/1.4.2/docs/guide/security/jce/JCERefGuide.html for details -->
        <param-value>AES</param-value>
    </context-param>

    <!-- Defines the default mode and padding used for the encryption algorithm -->
    <context-param>
        <param-name>org.apache.myfaces.ALGORITHM.PARAMETERS</param-name>
        <param-value>CBC/PKCS5Padding</param-value>
    </context-param>

    <!-- Defines the initialization vector (Base64 encoded) used for the 
         encryption algorithm. Note its usage depends on the algorithm config used,
         that means it must be defined if CBC mode is used and could not if ECB mode is used -->
    <context-param>
        <param-name>org.apache.myfaces.ALGORITHM.IV</param-name>
        <param-value>NzY1NDMyMTA3NjU0MzIxMA==</param-value>
    </context-param>

    <!-- Indicate the algorithm used to calculate the Message Authentication Code that is added to the view state. -->
    <context-param>
        <param-name>org.apache.myfaces.MAC_ALGORITHM</param-name>
        <param-value>HmacSHA1</param-value>
     </context-param>

Additionally, you can define the secret upon the encription/mac calculation is done using this params:

    <!-- Defines the secret (Base64 encoded) used to initialize the secret key
         for encryption algorithm. The size of it depends on the algorithm used for encryption -->
    <context-param>
        <param-name>org.apache.myfaces.SECRET</param-name>
        <param-value>MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz</param-value>
    </context-param>

    <!-- Define the initialization code (Bas64 encoded) that are used to initialize the secret key used
         on the Message Authentication Code algorithm. The size of it depends on the algorithm used for mac calculation -->
    <context-param>
        <param-name>org.apache.myfaces.MAC_SECRET</param-name>
        <param-value>YWJjZDEyMzQ=</param-value>
    </context-param>

If no secret is provided a random one is generated for encription algorithm, and if no mac secret is provided a random one is generated too. Note if you web server is restarted a ViewExpiredException will be thrown, because the secret is initialized at application startup.

An example command line below shows how you can obtain the base 64 encoded value of any String, using as example the binary distribution of myfaces core available in download page. The lenght of the key (in the example abcd1234, that means size 8) depends on the algorithm used for encoding:

cd myfaces-core-1.2.9-bin
cd lib
java -cp .\myfaces-api-1.2.9.jar;.\myfaces-impl-1.2.9.jar;.\commons-logging-1.1.1.jar;commons-codec-1.3.jar org.apache.myfaces.shared_impl.util.StateUtils abcd1234

In the rare case of your JCA provider lacking a thread safe javax.crypto.spec.SecretKeySpec, it is advised that you disable SecretKey caching by specifying the following context parameter in the deployment descriptor.

    <context-param>
        <param-name>org.apache.myfaces.SECRET.CACHE</param-name>
        <param-value>false</param-value>
    </context-param>

    <context-param>
        <param-name>org.apache.myfaces.MAC_SECRET.CACHE</param-name>
        <param-value>false</param-value>
    </context-param>

If by some reason it is necessary to do something additional you can define a custom serial factory class that implements org.apache.myfaces.shared_impl.util.serial.SerialFactory and wrap the streams used for serialize/deserialize the view state.

    <context-param>
        <param-name>org.apache.myfaces.SERIAL_FACTORY</param-name>
        <param-value>to.my.custom.class.that.implements.serial.factory.interface.CustomSerialFactory</param-value>
    </context-param>

Security configuration for Myfaces Core 1.1.7, 1.2.8, 2.0.0 and earlier

When using client side state saving, the UI object model is serialized and rendered with the response. This is behavior controlled by the following context parameter.

    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
     </context-param>

One consequence of client side state saving is that anyone with a decoder and some time to kill can reconstruct the UI object model on the client side. This can be a problem for those of us who make use of the excellent t:saveState tag.

Users of myfaces core version 1.1.7, 1.2.8, 2.0.0 and earlier MUST use server side state saving instead to prevent padding oracle attack on view state.

Enabling encryption is as easy as putting the following context parameter in your deployment descriptor. There are two things to note here. First, this uses the default encryption algorithm, DES, so the secret must have a size of eight. Second, although the secret is actually "76543210", we do not put this directly in the deployment descriptor. Instead, we place it's base 64 encoded value. This annoying extra step in the process is required so that secrets are not limited to printable character values.

    <context-param>
        <param-name>org.apache.myfaces.secret</param-name>
        <param-value>NzY1NDMyMTA=</param-value>
    </context-param>

An example command line shows how you can obtain the base 64 encoded value of any String.

    java -cp .\myfaces-all.jar;.\commons-logging.jar;commons-codec.jar org.apache.myfaces.util.StateUtils abcd1234

There are stronger forms of encryption. Below is an example of how one would use the BlowFish algorithm with a secret of size 16.

    <context-param>
        <param-name>org.apache.myfaces.secret</param-name>
        <param-value>NzY1NDMyMTA3NjU0MzIxMA</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.algorithm</param-name>
        <param-value>Blowfish</param-value>
    </context-param>

When using stronger forms of encryption, you may get the following exception on the second HTTP request after placing this in your deployment descriptor

 InvalidKeyException: Illegal key size or default parameters

or the following exception on your first HTTP request

 java.lang.SecurityException: Unsupported keysize or algorithm parameters

This most likely means that you must go to a place like http://java.sun.com/j2se/1.4.2/download.html or http://java.sun.com/javase/downloads/index.jsp (JCE) and get the unlimited jursidiction policy files. You will basically need to replace a few jars under <JAVA_HOME>jre\lib\security . All of the following examples require unlimited jurisdiction policy files.

Here is an example of using 3DES with a secret of size 24.

    <context-param>
        <param-name>org.apache.myfaces.secret</param-name>
        <param-value>MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.algorithm</param-name>
        <param-value>DESede</param-value>
    </context-param>

All Three examples shown so far use the default encryption mode, ECB. CBC mode is generally regarded as a better. CBC mode encryption however requires what is known as an initialization vector (VI). You do not need to be familiar with these concepts. Just keep in mind that using CBC in combination with a VI is stronger then plain ECB when inputs (in our case, serialized streams of UIComponent values) have patterns (not design patterns!).

Below is an example of using AES encryption with a secret of size 24. There are two new context parameters. First, the org.apache.myfaces.algorithm.parameters context parameter is being used to override the default mode. Second, because the mode is now CBC, we MUST supply an IV as well using the org.apache.myfaces.algorithm.iv context parameter. The IV, like the secret, is base 64 encoded (and for the same reason). The real value of the IV in this example is "7654321076543210" .

    <context-param>
        <param-name>org.apache.myfaces.SECRET</param-name>
        <param-value>MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIz</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.ALGORITHM</param-name>
        <param-value>AES</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.ALGORITHM.PARAMETERS</param-name>
        <param-value>CBC/PKCS5Padding</param-value>
    </context-param>
    <context-param>
        <param-name>org.apache.myfaces.ALGORITHM.IV</param-name>
        <param-value>NzY1NDMyMTA3NjU0MzIxMA==</param-value>
    </context-param>

If you are using log4j, the following line in log4j.properties can be used to debug encryption at runtime.

    log4j.logger.org.apache.myfaces.shared_impl.util=debug

This feature was added after the MyFaces 1.1.1 release.

In the rare case of your JCA provider lacking a thread safe javax.crypto.spec.SecretKeySpec, it is advised that you disable SecretKey caching by specifying the following context parameter in the deployment descriptor.

    <context-param>
        <param-name>org.apache.myfaces.secret.cache</param-name>
        <param-value>false</param-value>
    </context-param>
  • No labels