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
- deploy ProtectionViewSample.war to GlassFish
- 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".
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.