Hi Satish,

Why recreateMountedPagesAfterExpiry influences encrypted URLs:

First, we must reemphasize that the home page is effectively a mounted page, mounted at "/".

When you have setRecreateMountedPagesAfterExpiry(true), then the IRequestListener URLs (eg, for a Link component) for the home page are rendered like this:

/?0-1.ILinkListener-link

Notice that the URL path (before query string) is still the mounted page path - "/".

When you have setRecreateMountedPagesAfterExpiry(false), the IRequestListener URLs look like this:

/wicket/page?0-1.ILinkListener-link

The CryptoMapper class (shipped with Wicket) makes a special effort NOT to encrypt URLs for the home page. IE, when the URL path before the query string is "/". So, with recreateMountedPagesAfterExpiry, the IRequestListener URLs have a path of "/", which is not encrypted.

Without recreateMountedPagesAfterExpiry, IRequestListener URLs have a path of "/wicket/page", which is then encrypted.

That is why this flag affects URL encryption.

Why does the CryptoMapper not encrypt URLs for the mounted path "/"?

Because CryptoMapper is designed to be used before mounting pages. When pages are mounted after the CryptoMapper is installed (best practice), the URLs for these pages are not modified by the CryptoMapper at all. Remembering that the home page is effectively a mounted page, we want to make the home page behave the same way as other mounted pages.

We want people to be able to pass custom query parameters to the home page, and have those query parameters preserved in URLs relating to the home page.

Also, if encrypting IRequestListener URLs for the home page (/?0-1.ILinkListener-link) protects against CSRF attacks, it does so only for the home page, not for any pages mounted after the CryptoMapper was installed.

A better solution would be to a different CryptoMapper that is mounted AFTER all other pages are mounted, that has the single job of encrypting IRequestListener URLs for mounted pages.

This is why I provided you with QueryParameterCryptoMapper - to do just that. You mount normal CryptoMapper to encrypt all non-mounted URLs. Then you mount all your pages, then you mount the QueryParameterCryptoMapper. (I not sure that you were using both, you should).

Normal CryptoMapper encrypts all parts of non-mounted URLs, but IRequestListener URLs for mounted pages and the home page are not encrypted. QueryParameterCryptoMapper encrypts these.

I see you have included the second one I provided, which only encrypts the PageAndComponentInfo query parameter (this one: 0-1.ILinkListener-link). This is fine.

Please use like this:

getSecuritySettings().setCryptFactory(new KeyInSessionSunJceCryptFactory());

setRootRequestMapper(new CryptoMapper(getRootRequestMapper(), this));

        mountPage("/path1", MyPage1.class);
        mountPage("/path2", MyPage2.class);

setRootRequestMapper(new QueryParameterCryptoMapper(getRootRequestMapper(), this));

How to get Page expired instead of 404 when session has expired?

Well, you can use the same error page if you want. In my last email I was just explaining what was happening, not criticizing your approach. Nothing wrong with what you had if that's what you want. It does, however, rob you of the opportunity to display a real 404 page for legitimate 404 errors.

In short, no, there is no setting in Wicket to throw PageExpiredException when a URL cannot be decrypted.

My approach to this would be, mark URLs as definitely encrypted, so that CryptoMapper knows it really should be decryptable. If it encounters a URL marked as definitely should be decryptable, but is not decryptable, throw PageExpiredException. This would require you to modify CryptoMapper and QueryParameterCryptoMapper.

CryptoMapper, to mark the URL as definitely should be decryptable by CryptoMapper, you could prepend "/wicket/crypt" to encrypted URLs. For QueryParameterCryptMapper, you could name the encrypted parameter "wicket_crypt", so that the mapper knows it should be able to decrypt this.

Regarding CSRF protection provided by CryptoMapper:

I dont know if you have been using the CryptoMapper and QueryParameterCryptoMapper together as I suggested above, but I assume here that you were.

In your last update to WICKET 5326 you say that with encrypted links you are still able to copy and paste the link to a new browser and execute the URL. I am able to reproduce the problem, but only by session fixation.

Lets go through the issues. CSRF, or at least the type I'm talking about, is when a attacker gets you to request a URL which performs some action that you did not intend to perform.

Lets say you have a home page with one link on it which, if clicked, launches some ICBM nukes and generally causes WW3. The URL for this link to be executed is something like "http://nukesite/?0-1.ILinkListener-link";. You know not to click on the link unless you really mean it. The attacker gets you to click on a link like "http://innocent/whatever";, which you dont realize redirects to "http://nukesite/?0-1.ILinkListener-link";. You click on the innocent link and suddenly there are fireworks like 1999.

This only works if the attacker gets the page id and render count correct. In the example above, the page id is 0 and the render count is 1. If either of these number are not correct, the page will just be rendered without the action having been taken, or is recreateMountedPageAfterExpiry is off, you will get page expired error.

Using the QueryParameterCryptoMapper class I attached to the ticket, these IRequestListener URL query parameters (like "?0-1.ILinkListener-link") are encrypted on the home page and mounted pages.

If you do not use a unique encryption key per session, this does not help much, since the encrypted URL will be the same for all sessions. If the attacker manages to get the URL for another session, he can redirect you to the same encrypted URL, and you are still vulnerable.

However, you are using KeyInSessionSunJceCryptFactory, so each session has its own decryption key. That means that encrypted URLs obtained from one session will not be decryptable in a different session, and so not work.

Like you said, you were able to copy the URL from one browser into a different browser and it worked. The only way I can reproduce this is by copying the URL with the jsessionid in it. Before the servlet container has verified that cookies are working in your session, the session id is encoded in URLs. If you copy a URL that has the session id in it into a different browser, then the second browser will be seen as part of the same session - it identifies itself with the same session id.

Because both browsers are using the same session, they both use the same decryption key, so URLs from one browser can be decrypted by the other.

This is session fixation, almost not really CSRF. What is important to note here, is that the attacker is the one who started the session. He needed to start the session in order to obtain a valid link to send to you. He then sends the link to you with HIS session id encoded in the URL. If he has the link, he could just as well execute it himself, without needing to employ CSRF to get you to execute it. In other words, you execute the CSRF link in his session, with his privileges. It would be easier for him to just click the link himself. Same result.

The only thing I can see an attacker could gain here is if he sends you a link generated from his unauthenticated (and hence unprivileged) session, which you execute. If you then authenticate the session as yourself, he can continue using the same session id on his side, but now he has all your privileges. This is proper session fixation, and would work just as well if the link was to the home page.

You can avoid this by calling Session.replaceSession() BEFORE marking the session as authenticated during authentication. Normal defense against session fixation.

Thanks,
Jesse


On 18/09/2014 22:54, sgu...@osc.state.ny.us wrote:
Hello Jesse,

Thanks for the update.

I have updated the quick start with the following changes and is attached.



1. Setting inorg.apache.wicket.protocol.http.WebApplication#init() method

*super*.init();

getSecuritySettings().setCryptFactory(*new*KeyInSessionSunJceCryptFactory());

setRootRequestMapper(*new*CryptoMapper(getRootRequestMapperAsCompound(), *this*));

getApplicationSettings().setPageExpiredErrorPage(PageExpired.*class*);

getPageSettings().setRecreateMountedPagesAfterExpiry(*false*);

2. Removed the 404 mount in org.apache.wicket.protocol.http.WebApplication#init()

3. Removed /404 error page config from web.xml

4. Commented configureResponsePageExpired.class which was configured to 404 status


With the above changes I have noticed the following.

1. Home page urls are encrypted and XSRF safe (tested by copy pasting urls from home page in different browser)

The setting you recommended belows is actually playing a role in encrypting home page urls.

getPageSettings().setRecreateMountedPagesAfterExpiry(*false*);

If you removed the above setting then your home page urls are exposed and XSRF vulnerable.

Please explain why this flag has a bearing on encrypting home page urls ?

2. On session expiry we click on any urls (home page/ non home page) we see a 404 NOT_FOUND. I understand from your pervious explanation that since urls are encrypted and session is unbound we get a 404.



But my question still remains how to handle the above scenario where is user is redirected to SessionExpired Page on session expiry ?

is there a explicit setting in wicket or some way where the user is redirected to SessionExpired Page on session expiry ?




/Thanks & Regards/
/Satish Gutta/




From: Jesse Long <j...@unknown.za.net>
To: users@wicket.apache.org
Date: 09/17/2014 04:35 PM
Subject: Re: on session expiry home page links behave differently than non home page links
------------------------------------------------------------------------



Hi Satish,

The problem here is that your quickstart uses the same page for page
expired error and error 404.

PageExpired.STATUS_CODE is 404.

Your web.xml sets the 404 error page to /404, and you mount the
PageExpired page as /404. You also set the PageExpiredErrorPage to
PageExpired.

When your session expires, the decryption key is no longer available in
the session, so the URL cannot be decrypted. This is because you are
using KeyInSessionSunJceCryptFactory, which stores a new unique random
decryption key in each session. When the session expires, a new session
is created which in turn gets a new random decryption key. The new
session's get cannot decrypt the encrypted URL which was encrypted with
the old, expired session's key.

Because the URL cannot be decrypted, no IRequestMapper can map the URL
to a IRequestHandler, and a 404 error results. So, you are not actually
getting a page expired error, you are getting a 404 error. It looks the
same to you because you are using the same page to display both errors.

The reason the home page links do not cause a 404 error is because the
URL is not encrypted on the home page, at least not in this quickstart.
(I know, I'll get back to you about the other issue you have). Because
there is no encryption on the home page link, the link remains usable to
wicket after the session has expired.

Wicket can see that you are trying to execute a callback link on the
home page, because the URL is /?1-1.ILinkListener...., but because the
session has expired, page id 1 is no longer retrievable from the page
store. However, because of the URL, wicket can tell that this was
something to do with the home page, and just recreates a new instance of
the home page and displays that to you.

You can control this behavior by calling
getPageSettings().setRecreateMountedPagesAfterExpiry(false);

Cheers,
Jesse


On 17/09/2014 17:23, sgu...@osc.state.ny.us wrote:
> Hello,
>
> I am having a problem in dealing with Session expiry specifically when
> you click on a link in home page after session expiry.
>
> The out come is you remain on home page, you are neither navigated to
> the link you clicked nor redirected to PageExpired page which is
> configured in
>
> _org.apache.wicket.protocol.http.WebApplication#_init() _method_ _as_
> _follows_
>
> getApplicationSettings().setPageExpiredErrorPage(PageExpired.*class*);
>         mountPage("/"+ PageExpired.STATUS_CODE, PageExpired.*class*);
>
> With that said, the behavior is different when links on other pages
> (link in First Navigation page from quick start)
> are clicked on session expiry, you actually hit PageExpired page.
>
> Why is the behavior different for home page links compared to links on
> other pages when it comes to session expiry ?
>
>
> I am attaching a quick start to support my explanation above.
> Quick Start Application flow:
> i. Hit root url http://localhost:8080 <http://localhost:8080/><http://localhost:8080/>, you
> will navigate to home page with a link to First Navigation page.
> ii. In First Navigation Page we have a link to Second Navigation Page.
> iii. In Second Navigation Page we have a link back to home page.
>
>
>
>
> /Thanks & Regards/
> /Satish Gutta/
>
>
>
>
> Notice: This communication, including any attachments, is intended
> solely for the use of the individual or entity to which it is
> addressed. This communication may contain information that is
> protected from disclosure under State and/or Federal law. Please
> notify the sender immediately if you have received this communication
> in error and delete this email from your system. If you are not the
> intended recipient, you are requested not to disclose, copy,
> distribute or take any action in reliance on the contents of this
> information.
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org
> For additional commands, e-mail: users-h...@wicket.apache.org






Notice: This communication, including any attachments, is intended solely for the use of the individual or entity to which it is addressed. This communication may contain information that is protected from disclosure under State and/or Federal law. Please notify the sender immediately if you have received this communication in error and delete this email from your system. If you are not the intended recipient, you are requested not to disclose, copy, distribute or take any action in reliance on the contents of this information.


---------------------------------------------------------------------
To unsubscribe, e-mail:users-unsubscr...@wicket.apache.org
For additional commands, e-mail:users-h...@wicket.apache.org

Reply via email to