You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by Martin Grigorov <mg...@apache.org> on 2012/07/27 10:10:13 UTC

Re: Redirect to buffer strategy may not work properly on Tomcat 7.0.29

Hi Pedro,

I've CC-ed Tomcat's team, so they can explain better what Tomcat does.

On Fri, Jul 27, 2012 at 3:24 AM, Pedro Henrique Oliveira dos Santos
<pe...@gmail.com> wrote:
> Hi Martin,
>
> I don't see how to wrap the request or the response can be useful here. Even if we decorate the container request to return its URI based on the page being rendered address it will not be enough because Servlet API does not allow us to change the composition of a response. i.e. we are not able to set on which request URI the encode method of the response will work on (Tomcat API allows such thing but I'd rather not use to it).

I don't quite understand what you mean with the above.
As far as I understood Mark he suggests to use
HttpServletRequestWrapper which should return the proper base url when
asked (#getRequestURI, #getPath, etc.)

Thinking more about it now I don't see how this will help actually
because this wrapper will be reachable only by Wicket code. To encode
an URL Wicket calls HttpServletResponse#encodeURL(), note this is the
*response*, and it has no reference from the response to the wrapped
request, so Tomcat will be able to find and use only the original
request.
Wrapping the response and link it to it the wrapped request wont help
because Tomcat wont be able to cast to our custom wrappers.

>
> I simply don't get why Tomcat added such validation in the encode method. To redirect the request to a buffered response is a very common strategy that has being saving tons of applications from double form submissions for instance rather than a weird web framework implementation like I read in the ticket.

Do you know of another bigger web framework that uses this approach ?
If you know please mention it in the ticket. This will be a stronger
argument for Tomcat to not ignore this solution.

It all started with a ticket by me in Tomcat's Bugzilla to normalize
the absolute urls which are send in "Location" response header. This
is the redirect url. Before the ticket Tomcat was sending urls like
'http://www.example.com/a/b/../c/d.html' and '..' in this url caused
some problems in some cases, e.g. JMeter complained about it, and
Chris Colman reported an issue with IE when using Tomcat virtual
hosts.
So now Tomcat normalizes the url to
'http://www.example.com/a/c/d.html' before sending it to the client.
All good so far.

The new problem is that Tomcat uses the normalization even in
#encodeURL(), this method just encodes jsessionid if needed, even for
relative urls. To decide whether the relative url is part of the
current application Tomcat makes the url absolute and normalizes it.
When Wicket starts rendering the rendering for PageB (from my first
mail) it produces relative urls to PageB, but later Tomcat normalizes
them against PageA and url like
'http://www.example.com/a/b/../../../../c/d.html' fails because there
are too many '..'s.

I hope the problem is more clear now.

>
> It looks like the response will not encode the session id to links and callbacks in the buffered pages in a deeper path from Tomcat 7.0.29 on. I'm OK with the way the Tomcat team worked around this issue. Who knows if they aren't only doing some good by preventing some session fixation attacks.

They didn't workaround it yet. For now we discuss possible solutions
for the next version.

>
> Pedro Santos
>
> Em 25/07/2012, às 16:42, Martin Grigorov escreveu:
>
>> Hi,
>>
>> Please take a look at https://issues.apache.org/bugzilla/show_bug.cgi?id=53469.
>> This issue describes a problem which prevents Wicket's default
>> RenderStrategy - REDIRECT_TO_BUFFER.
>>
>> Basically the problem is:
>> - PageA mounted at /mount/pageA is requested
>> - the code uses setResponsePage(PageB.class) which is mounted at
>> /deeper/mount/path/pageB
>> - Wicket starts to render PageB (in the same request cycle) and for
>> each url in the page it asks the web container to encode it
>> (HttpServletResponse#encodeURL())
>> - here Tomcat 7.0.29+ tries to find whether the url to encode is part
>> of the web app. To do this it makes the relative url passed by Wicket
>> to absolute by using the HttpServletRequest's requestURI (i.e.
>> /mount/pageA). This may get wrong because Wicket actually generates
>> the urls against /deeper/mount/path/pageB
>>
>> Mark Thomas (Tomcat dev) suggests that Wicket could use
>> HttpServletRequestWrapper which should return the correct requestURI
>> depending on the current request cycle baseUrl.
>>
>> Any ideas and comments are welcome!
>>
>> --
>> Martin Grigorov
>> jWeekend
>> Training, Consulting, Development
>> http://jWeekend.com
>



-- 
Martin Grigorov
jWeekend
Training, Consulting, Development
http://jWeekend.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Re: Redirect to buffer strategy may not work properly on Tomcat 7.0.29

Posted by Martin Grigorov <mg...@apache.org>.
On Mon, Aug 27, 2012 at 2:54 PM, Emond Papegaaij
<em...@topicus.nl> wrote:
> I think encoding an absolute url and then re-relativize them, seems like a
> good idea. We do need 'full'-relative urls, because otherwise rewriting
> proxies will break.

I'm working on this.
But I still have problems with Url.isAbsolute() that returns 'true'
for 'http://host:9090/something' and just '/something'.

>
> Emond
>
> On Monday 27 August 2012 13:50:05 Martin Grigorov wrote:
>> Hi,
>>
>> I think I found a solution for this problem
>> (https://issues.apache.org/jira/browse/WICKET-4645 /
>> https://issues.apache.org/bugzilla/show_bug.cgi?id=53469) :
>>
>> org.apache.wicket.protocol.http.servlet.ServletWebResponse.java:
>>
>> @Override
>>       public String encodeURL(CharSequence url)
>>       {
>>               Args.notNull(url, "url");
>>
>>               UrlRenderer urlRenderer = RequestCycle.get().getUrlRenderer();
>>               Url _url = Url.parse(url);
>>               String fullUrl = urlRenderer.renderFullUrl(_url);
>>               String encodedFullUrl = httpServletResponse.encodeURL(fullUrl);
>>               Url _encoded = Url.parse(encodedFullUrl);
>>               String encodedRelativeUrl = urlRenderer.renderRelativeUrl(_encoded);
>>               return encodedRelativeUrl;
>>       }
>>
>> I.e. now Wicket makes the url absolute, pass it to the container for
>> encoding and then Wicket makes it relative again.
>> The only thing that bothers me is that "relative" in the previous
>> sentence is not really relative.
>> The produced urls look like:
>> "/contextPath/filterPath/a/b;jsessionid=qwerty?someParam=value"
>> As you see this is much longer than
>> "../../a/b;jsessionid=qwerty?someParam=value" in the case when the
>> context path is not ROOT and the filter path is not "/*".
>> Should I try to re-relativize it again by improving
>> org.apache.wicket.request.UrlRenderer#renderRelativeUrl() or this is
>> good enough ?
>>
>> On Sat, Jul 28, 2012 at 2:01 AM, Mark Thomas <ma...@apache.org> wrote:
>> > On 27/07/2012 09:10, Martin Grigorov wrote:
>> >> On Fri, Jul 27, 2012 at 3:24 AM, Pedro Henrique Oliveira dos Santos
>> >>
>> >> <pe...@gmail.com> wrote:
>> >>> Hi Martin,
>> >>>
>> >>> I don't see how to wrap the request or the response can be useful
>> >>> here. Even if we decorate the container request to return its URI
>> >>> based on the page being rendered address it will not be enough
>> >>> because Servlet API does not allow us to change the composition of
>> >>> a response. i.e. we are not able to set on which request URI the
>> >>> encode method of the response will work on (Tomcat API allows such
>> >>> thing but I'd rather not use to it).
>> >
>> > My bad. I was thinking of using some methods that were added early in
>> > the Servlet 3.0 development cycle that were later removed. Wrapping
>> > isn't going to help here unless Wicket implements its own encode methods
>> > in the wrapper (which instinctively I don't like as a solution).
>> >
>> >>> I simply don't get why Tomcat added such validation in the encode
>> >>> method.
>> >
>> > The validation (that any URL must part of the web application for the
>> > session ID to be added) has been present as far back as I can remember.
>> > That it didn't work correctly for relative URLs was a bug that only
>> > recently surfaced. In short, Tomcat should not be exposing the session
>> > ID to URLs outside of the web application.
>> >
>> >> The new problem is that Tomcat uses the normalization even in
>> >> #encodeURL(), this method just encodes jsessionid if needed, even
>> >> for relative urls. To decide whether the relative url is part of the
>> >> current application Tomcat makes the url absolute and normalizes it.
>> >> When Wicket starts rendering the rendering for PageB (from my first
>> >> mail) it produces relative urls to PageB, but later Tomcat
>> >> normalizes them against PageA and url like
>> >> 'http://www.example.com/a/b/../../../../c/d.html' fails because
>> >> there are too many '..'s.
>> >>
>> >> I hope the problem is more clear now.
>> >>
>> >>> It looks like the response will not encode the session id to links
>> >>> and callbacks in the buffered pages in a deeper path from Tomcat
>> >>> 7.0.29 on. I'm OK with the way the Tomcat team worked around this
>> >>> issue. Who knows if they aren't only doing some good by preventing
>> >>> some session fixation attacks.
>> >>
>> >> They didn't workaround it yet. For now we discuss possible solutions
>> >> for the next version.
>> >
>> > At the moment, I don't see a way for Tomcat to:
>> > - retain the check that a URL is part of the web application before
>> > adding the session ID; and
>> > - correctly support the passing of relative URLs to encodeURL() that are
>> > relative to something other than the currently processing request.
>> >
>> > I am open to suggestions.
>> >
>> > On a separate note, I intend to request some clarification on the
>> > handling of relative URLs and encodeURL() from the EG.
>> >
>> > Mark



-- 
Martin Grigorov
jWeekend
Training, Consulting, Development
http://jWeekend.com

Re: Redirect to buffer strategy may not work properly on Tomcat 7.0.29

Posted by Emond Papegaaij <em...@topicus.nl>.
I think encoding an absolute url and then re-relativize them, seems like a 
good idea. We do need 'full'-relative urls, because otherwise rewriting 
proxies will break.

Emond

On Monday 27 August 2012 13:50:05 Martin Grigorov wrote:
> Hi,
> 
> I think I found a solution for this problem
> (https://issues.apache.org/jira/browse/WICKET-4645 /
> https://issues.apache.org/bugzilla/show_bug.cgi?id=53469) :
> 
> org.apache.wicket.protocol.http.servlet.ServletWebResponse.java:
> 
> @Override
> 	public String encodeURL(CharSequence url)
> 	{
> 		Args.notNull(url, "url");
> 
> 		UrlRenderer urlRenderer = RequestCycle.get().getUrlRenderer();
> 		Url _url = Url.parse(url);
> 		String fullUrl = urlRenderer.renderFullUrl(_url);
> 		String encodedFullUrl = httpServletResponse.encodeURL(fullUrl);
> 		Url _encoded = Url.parse(encodedFullUrl);
> 		String encodedRelativeUrl = urlRenderer.renderRelativeUrl(_encoded);
> 		return encodedRelativeUrl;
> 	}
> 
> I.e. now Wicket makes the url absolute, pass it to the container for
> encoding and then Wicket makes it relative again.
> The only thing that bothers me is that "relative" in the previous
> sentence is not really relative.
> The produced urls look like:
> "/contextPath/filterPath/a/b;jsessionid=qwerty?someParam=value"
> As you see this is much longer than
> "../../a/b;jsessionid=qwerty?someParam=value" in the case when the
> context path is not ROOT and the filter path is not "/*".
> Should I try to re-relativize it again by improving
> org.apache.wicket.request.UrlRenderer#renderRelativeUrl() or this is
> good enough ?
> 
> On Sat, Jul 28, 2012 at 2:01 AM, Mark Thomas <ma...@apache.org> wrote:
> > On 27/07/2012 09:10, Martin Grigorov wrote:
> >> On Fri, Jul 27, 2012 at 3:24 AM, Pedro Henrique Oliveira dos Santos
> >> 
> >> <pe...@gmail.com> wrote:
> >>> Hi Martin,
> >>> 
> >>> I don't see how to wrap the request or the response can be useful
> >>> here. Even if we decorate the container request to return its URI
> >>> based on the page being rendered address it will not be enough
> >>> because Servlet API does not allow us to change the composition of
> >>> a response. i.e. we are not able to set on which request URI the
> >>> encode method of the response will work on (Tomcat API allows such
> >>> thing but I'd rather not use to it).
> > 
> > My bad. I was thinking of using some methods that were added early in
> > the Servlet 3.0 development cycle that were later removed. Wrapping
> > isn't going to help here unless Wicket implements its own encode methods
> > in the wrapper (which instinctively I don't like as a solution).
> > 
> >>> I simply don't get why Tomcat added such validation in the encode
> >>> method.
> > 
> > The validation (that any URL must part of the web application for the
> > session ID to be added) has been present as far back as I can remember.
> > That it didn't work correctly for relative URLs was a bug that only
> > recently surfaced. In short, Tomcat should not be exposing the session
> > ID to URLs outside of the web application.
> > 
> >> The new problem is that Tomcat uses the normalization even in
> >> #encodeURL(), this method just encodes jsessionid if needed, even
> >> for relative urls. To decide whether the relative url is part of the
> >> current application Tomcat makes the url absolute and normalizes it.
> >> When Wicket starts rendering the rendering for PageB (from my first
> >> mail) it produces relative urls to PageB, but later Tomcat
> >> normalizes them against PageA and url like
> >> 'http://www.example.com/a/b/../../../../c/d.html' fails because
> >> there are too many '..'s.
> >> 
> >> I hope the problem is more clear now.
> >> 
> >>> It looks like the response will not encode the session id to links
> >>> and callbacks in the buffered pages in a deeper path from Tomcat
> >>> 7.0.29 on. I'm OK with the way the Tomcat team worked around this
> >>> issue. Who knows if they aren't only doing some good by preventing
> >>> some session fixation attacks.
> >> 
> >> They didn't workaround it yet. For now we discuss possible solutions
> >> for the next version.
> > 
> > At the moment, I don't see a way for Tomcat to:
> > - retain the check that a URL is part of the web application before
> > adding the session ID; and
> > - correctly support the passing of relative URLs to encodeURL() that are
> > relative to something other than the currently processing request.
> > 
> > I am open to suggestions.
> > 
> > On a separate note, I intend to request some clarification on the
> > handling of relative URLs and encodeURL() from the EG.
> > 
> > Mark

Re: Redirect to buffer strategy may not work properly on Tomcat 7.0.29

Posted by Martin Grigorov <mg...@apache.org>.
Hi,

I think I found a solution for this problem
(https://issues.apache.org/jira/browse/WICKET-4645 /
https://issues.apache.org/bugzilla/show_bug.cgi?id=53469) :

org.apache.wicket.protocol.http.servlet.ServletWebResponse.java:

@Override
	public String encodeURL(CharSequence url)
	{
		Args.notNull(url, "url");

		UrlRenderer urlRenderer = RequestCycle.get().getUrlRenderer();
		Url _url = Url.parse(url);
		String fullUrl = urlRenderer.renderFullUrl(_url);
		String encodedFullUrl = httpServletResponse.encodeURL(fullUrl);
		Url _encoded = Url.parse(encodedFullUrl);
		String encodedRelativeUrl = urlRenderer.renderRelativeUrl(_encoded);
		return encodedRelativeUrl;
	}

I.e. now Wicket makes the url absolute, pass it to the container for
encoding and then Wicket makes it relative again.
The only thing that bothers me is that "relative" in the previous
sentence is not really relative.
The produced urls look like:
"/contextPath/filterPath/a/b;jsessionid=qwerty?someParam=value"
As you see this is much longer than
"../../a/b;jsessionid=qwerty?someParam=value" in the case when the
context path is not ROOT and the filter path is not "/*".
Should I try to re-relativize it again by improving
org.apache.wicket.request.UrlRenderer#renderRelativeUrl() or this is
good enough ?

On Sat, Jul 28, 2012 at 2:01 AM, Mark Thomas <ma...@apache.org> wrote:
> On 27/07/2012 09:10, Martin Grigorov wrote:
>> On Fri, Jul 27, 2012 at 3:24 AM, Pedro Henrique Oliveira dos Santos
>> <pe...@gmail.com> wrote:
>>> Hi Martin,
>>>
>>> I don't see how to wrap the request or the response can be useful
>>> here. Even if we decorate the container request to return its URI
>>> based on the page being rendered address it will not be enough
>>> because Servlet API does not allow us to change the composition of
>>> a response. i.e. we are not able to set on which request URI the
>>> encode method of the response will work on (Tomcat API allows such
>>> thing but I'd rather not use to it).
>
> My bad. I was thinking of using some methods that were added early in
> the Servlet 3.0 development cycle that were later removed. Wrapping
> isn't going to help here unless Wicket implements its own encode methods
> in the wrapper (which instinctively I don't like as a solution).
>
>>> I simply don't get why Tomcat added such validation in the encode
>>> method.
>
> The validation (that any URL must part of the web application for the
> session ID to be added) has been present as far back as I can remember.
> That it didn't work correctly for relative URLs was a bug that only
> recently surfaced. In short, Tomcat should not be exposing the session
> ID to URLs outside of the web application.
>
>> The new problem is that Tomcat uses the normalization even in
>> #encodeURL(), this method just encodes jsessionid if needed, even
>> for relative urls. To decide whether the relative url is part of the
>> current application Tomcat makes the url absolute and normalizes it.
>> When Wicket starts rendering the rendering for PageB (from my first
>> mail) it produces relative urls to PageB, but later Tomcat
>> normalizes them against PageA and url like
>> 'http://www.example.com/a/b/../../../../c/d.html' fails because
>> there are too many '..'s.
>>
>> I hope the problem is more clear now.
>>
>>>
>>> It looks like the response will not encode the session id to links
>>> and callbacks in the buffered pages in a deeper path from Tomcat
>>> 7.0.29 on. I'm OK with the way the Tomcat team worked around this
>>> issue. Who knows if they aren't only doing some good by preventing
>>> some session fixation attacks.
>>
>> They didn't workaround it yet. For now we discuss possible solutions
>> for the next version.
>
> At the moment, I don't see a way for Tomcat to:
> - retain the check that a URL is part of the web application before
> adding the session ID; and
> - correctly support the passing of relative URLs to encodeURL() that are
> relative to something other than the currently processing request.
>
> I am open to suggestions.
>
> On a separate note, I intend to request some clarification on the
> handling of relative URLs and encodeURL() from the EG.
>
> Mark



-- 
Martin Grigorov
jWeekend
Training, Consulting, Development
http://jWeekend.com

Re: Redirect to buffer strategy may not work properly on Tomcat 7.0.29

Posted by Mark Thomas <ma...@apache.org>.
On 27/07/2012 09:10, Martin Grigorov wrote:
> On Fri, Jul 27, 2012 at 3:24 AM, Pedro Henrique Oliveira dos Santos 
> <pe...@gmail.com> wrote:
>> Hi Martin,
>> 
>> I don't see how to wrap the request or the response can be useful
>> here. Even if we decorate the container request to return its URI
>> based on the page being rendered address it will not be enough
>> because Servlet API does not allow us to change the composition of
>> a response. i.e. we are not able to set on which request URI the
>> encode method of the response will work on (Tomcat API allows such
>> thing but I'd rather not use to it).

My bad. I was thinking of using some methods that were added early in
the Servlet 3.0 development cycle that were later removed. Wrapping
isn't going to help here unless Wicket implements its own encode methods
in the wrapper (which instinctively I don't like as a solution).

>> I simply don't get why Tomcat added such validation in the encode
>> method.

The validation (that any URL must part of the web application for the
session ID to be added) has been present as far back as I can remember.
That it didn't work correctly for relative URLs was a bug that only
recently surfaced. In short, Tomcat should not be exposing the session
ID to URLs outside of the web application.

> The new problem is that Tomcat uses the normalization even in 
> #encodeURL(), this method just encodes jsessionid if needed, even
> for relative urls. To decide whether the relative url is part of the 
> current application Tomcat makes the url absolute and normalizes it. 
> When Wicket starts rendering the rendering for PageB (from my first 
> mail) it produces relative urls to PageB, but later Tomcat
> normalizes them against PageA and url like 
> 'http://www.example.com/a/b/../../../../c/d.html' fails because
> there are too many '..'s.
> 
> I hope the problem is more clear now.
> 
>> 
>> It looks like the response will not encode the session id to links
>> and callbacks in the buffered pages in a deeper path from Tomcat
>> 7.0.29 on. I'm OK with the way the Tomcat team worked around this
>> issue. Who knows if they aren't only doing some good by preventing
>> some session fixation attacks.
> 
> They didn't workaround it yet. For now we discuss possible solutions 
> for the next version.

At the moment, I don't see a way for Tomcat to:
- retain the check that a URL is part of the web application before
adding the session ID; and
- correctly support the passing of relative URLs to encodeURL() that are
relative to something other than the currently processing request.

I am open to suggestions.

On a separate note, I intend to request some clarification on the
handling of relative URLs and encodeURL() from the EG.

Mark

Re: Redirect to buffer strategy may not work properly on Tomcat 7.0.29

Posted by Mark Thomas <ma...@apache.org>.
On 27/07/2012 09:10, Martin Grigorov wrote:
> On Fri, Jul 27, 2012 at 3:24 AM, Pedro Henrique Oliveira dos Santos 
> <pe...@gmail.com> wrote:
>> Hi Martin,
>> 
>> I don't see how to wrap the request or the response can be useful
>> here. Even if we decorate the container request to return its URI
>> based on the page being rendered address it will not be enough
>> because Servlet API does not allow us to change the composition of
>> a response. i.e. we are not able to set on which request URI the
>> encode method of the response will work on (Tomcat API allows such
>> thing but I'd rather not use to it).

My bad. I was thinking of using some methods that were added early in
the Servlet 3.0 development cycle that were later removed. Wrapping
isn't going to help here unless Wicket implements its own encode methods
in the wrapper (which instinctively I don't like as a solution).

>> I simply don't get why Tomcat added such validation in the encode
>> method.

The validation (that any URL must part of the web application for the
session ID to be added) has been present as far back as I can remember.
That it didn't work correctly for relative URLs was a bug that only
recently surfaced. In short, Tomcat should not be exposing the session
ID to URLs outside of the web application.

> The new problem is that Tomcat uses the normalization even in 
> #encodeURL(), this method just encodes jsessionid if needed, even
> for relative urls. To decide whether the relative url is part of the 
> current application Tomcat makes the url absolute and normalizes it. 
> When Wicket starts rendering the rendering for PageB (from my first 
> mail) it produces relative urls to PageB, but later Tomcat
> normalizes them against PageA and url like 
> 'http://www.example.com/a/b/../../../../c/d.html' fails because
> there are too many '..'s.
> 
> I hope the problem is more clear now.
> 
>> 
>> It looks like the response will not encode the session id to links
>> and callbacks in the buffered pages in a deeper path from Tomcat
>> 7.0.29 on. I'm OK with the way the Tomcat team worked around this
>> issue. Who knows if they aren't only doing some good by preventing
>> some session fixation attacks.
> 
> They didn't workaround it yet. For now we discuss possible solutions 
> for the next version.

At the moment, I don't see a way for Tomcat to:
- retain the check that a URL is part of the web application before
adding the session ID; and
- correctly support the passing of relative URLs to encodeURL() that are
relative to something other than the currently processing request.

I am open to suggestions.

On a separate note, I intend to request some clarification on the
handling of relative URLs and encodeURL() from the EG.

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org