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