Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

View declared in <protected-views> still accessible after manipulating CSRF token

I'm exploring the new features in JSF 2.2 (pretty cool so far) but I still don't understand how Protected Views works, I created a facelet1 with a link to facelet2, like this:

<h:link styleClass="link" value="Go to protected page" id="link1"
    outcome="/protected/facelet2.xhtml"></h:link>

and in my faces-config.xml I added this:

<protected-views>
    <url-pattern>/protected/facelet2.xhtml</url-pattern>
</protected-views>

Now when I run the page a token is added in the url:

http://localhost:8080/<project>/protected/facelet2.faces?javax.faces.Token=1426608965211

According to the documentation, if the token does not match with the one in the server, the GET request is not processed (is my understanding correct?).

But if I modify the token (using Firebug or the dev tools included in the browser) the request is still processed, even if the token was modified.

Am I doing something wrong?

like image 759
CIOC Avatar asked Mar 17 '15 16:03

CIOC


1 Answers

This is caused because your FacesServlet is apparently mapped on JSF 1.0-style URL pattern of *.faces instead of JSF 2.0-style URL pattern of *.xhtml. The <protected-views><url-pattern> must match the actual URL pattern as you see in browser's address bar.

So, given an actual URL of /protected/facelet2.faces, you need to configure it as below:

<protected-views>
    <url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>

However, while at it, I discovered some nasty issues in current Mojarra 2.2.10 implementation:

  1. It does actually not do a prefix/suffix match as per Servlet 12.1 specification (there's even a vague comment in source code indicating that!). It does merely an exact match. This means, you can't use wildcard URL patterns like /protected/*.

  2. When generating the <h:link>, it does not compare the protected view URL pattern to the resolved URL, but to the JSF view ID. And, when checking an incoming request, it does not compare the request URL to the JSF view ID (like as during link generation), but to the <url-pattern>. This thus never matches, totally explaining why you could simply access it without a valid token.

Basically, you need the following configuration if you need to keep the JSF 1.0-style URL pattern of *.faces.

<protected-views>
    <url-pattern>/protected/facelet2.xhtml</url-pattern>
    <url-pattern>/protected/facelet2.faces</url-pattern>
</protected-views>

It'll then properly throw javax.faces.application.ProtectedViewException when being accessed without a valid token. Much better is to just map the FacesServlet explicitly on *.xhtml in web.xml.

<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

This way you never need to deal with virtual URLs.

I've reported this to Mojarra guys as issue 3837.

See also:

  • Sometimes I see JSF URL is *.jsf, sometimes *.xhtml and sometimes /faces/*. Why?
like image 90
BalusC Avatar answered Sep 21 '22 01:09

BalusC