Skip to content

View Protection is not working as expected since mojarra 2.3

Basic information

Project name: Eclipse Mojarra

Project id: ee4j.mojarra

What are the affected versions?

mojarra 2.3 or later

Details of the issue

Note: This bug affects a security feature, but I'm not sure whether it is a bug should be handled as a "security vulnerability". so I'm reporting it here just to be safe.

Summary

Protected view setting, which is a function added in JSF 2.2 as a CSRF countermeasure, may not take effect under certain conditions in mojarra 2.3 or later. This is an incompatibility between mojarra 2.2 and 2.3.

Details

According to the JSF specification, by listing viewIds (or url patterns) in faces-config.xml with protected-views tag, access to matching views is protected with a token.

<?xml version="1.0" encoding="UTF-8"?>
<faces-config
    xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" 
    version="2.2">
    <protected-views>
        <url-pattern>/protected.jsf</url-pattern>
    </protected-views>
</faces-config>

On the other hand, some JSF applications map the extension jsf to the Faces Servlet. Like this:

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

By defining it this way, if the actual view file included in the application is protected.xhtml, there are three access URL patterns to that view:

  • [a] /protected (*self forward only)
  • [b] /protected.jsf
  • [c] /protected.xhtml

In fact, no matter which pattern is used in the request, the JSF container will correctly resolve protected.xhtml.

However, since mojarra 2.3, protected-views does not protect as expected unless we specify the xhtml URL pattern [c].

Steps to reproduce

  1. deploy ProtectionViewSample.war to GlassFish
  2. curl http://host:port/ProtectionViewSample/protected.jsf

expects ProtectedViewException, but the target view appears.

  • app: ProtectionViewSample.war
  • src: ProtectionViewSample.zip

Do you know any mitigations of the issue?

We can protect the target views by replacing the URL pattern extension with the xhtml in protected-views. (Even if the request URL is /protected.jsf, it is protected.)

  <?xml version="1.0" encoding="UTF-8"?>
  <faces-config
      xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" 
      version="2.2">
      <protected-views>
-         <url-pattern>/protected.jsf</url-pattern>
+         <url-pattern>/protected.xhtml</url-pattern>
      </protected-views>
  </faces-config>
  • app: ProtectionViewSample_Mitigation.war

probably...

It is caused by passing the "logical viewId" as an argument to the following method instead of the raw "viewId".

https://github.com/eclipse-ee4j/mojarra/blob/b8a0530af4144c6c15b7010df9e0e50fcc4d90fc/impl/src/main/java/com/sun/faces/lifecycle/RestoreViewPhase.java#L182

                maybeTakeProtectedViewAction(facesContext, viewHandler, vdl, logicalViewId);

This "logical viewId" is necessary to create the view, but should not be used to determine if it is a protected view.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information