Thanks for all the responses Mark!

Once I realized specifically what was happening, I started working backward
to see if I could preempt the necessity for the directory traversal in the
first place. I figured out that Struts 2 is building the provided url by
combining the 'location' attribute (url), with the 'location' param
(context) and so was passing 'WEB-INF/content/%{url}' up the chain.

Turns out I can override the default params by passing a params array to
my @Request annotation, and so I was able to avoid the necessity for
traversal by modifying my annotation to:

@Result(name = BaseAction.REDIRECT_TO_NON_STRUTS2, location = "%{url}",
params = {"location", "%{url}"})

Really appreciate all the info you provided. Definitely helped me track
down exactly what was going on.

Alex


On Tue, Feb 4, 2020 at 3:52 AM Mark Thomas <ma...@apache.org> wrote:

> On 03/02/2020 21:34, Alex Pritchard wrote:
> > I think I've narrowed the change down to this commit:
> >
> https://github.com/apache/tomcat/commit/fdd86cf2e0b851aced2f460c765fea5293a30940#diff-8b91a9296e19012bf6be4bdf975fab0d
> >
> >
> > *org.apache.catalina.core.ApplicationContext.java *
> > *getRequestDispatcher(path) *
> >
> > In 7.0.78, this creates a dispatcher to the path built using
> > context.getPath() + normalizedPath, whereas 7.0.79 creates a dispatcher
> to
> > the path of the provided URI, ignoring any changes made by
> > RequestUtil.normalize.  In both cases, the normalizedPath is used to
> > populate this uriCC, and then 7.0.78 creates an encoded URI from the
> uriCC,
> > but the 7.0.79 version populates uriCC and then creates a dispatcher
> using
> > the pre-normalized URI.
> >
> > So ApplicationDispatcher has a doForward that's passing forward the
> > 'web-inf/content/../../foo.jsp' uri, when it used to forward a '/foo.jsp'
> > uri.
> >
> > Not sure what I can do with that information though. The doesn't appear
> to
> > be any configurable behavior here.
>
> The behaviour is essentially required by the Servlet specification.
> HttpServletRequest.getRequestURI() has to return the original,
> unmodified (no decoding, no normalization) URI.
>
> While the bug report was related to async, it the impact of the root
> cause was wider.
>
> There might be something you can do with configuration. If this is a
> forwarded request and it is getting flagged by a filter in Spring
> Security you can tell that filter not to consider requests that have
> been forwarded or included. Whether that is safe to do for your
> application, I can't tell.
>
> Mark
>
>
> >
> > Alex
> >
> >
> > On Fri, Jan 31, 2020 at 10:28 AM Mark Thomas <ma...@apache.org> wrote:
> >
> >> On 30/01/2020 21:38, Alex Pritchard wrote:
> >>> Totally possible. I tried modifying \conf\context.xml, using both
> >>> useRelativeRedirects="true" and "false":
> >>>
> >>> <Context useRelativeRedirects="true">
> >>>     <WatchedResource>WEB-INF/web.xml</WatchedResource>
> >>> </Context>
> >>>
> >>> I also tried making the same changes in our
> >>> web-app/src/main/resources/meta-inf/context.xml in case that was
> >> overriding
> >>> somehow.
> >>
> >> That looks right to me. Odd. I thought I was on to something.
> >>
> >> Can we go back to my request for a step-by-step description of what is
> >> happening. I am particularly interested in the HTTP request/response
> >> headers for the requests between the client and the server. Comparing a
> >> set from a working version to a non-working version should be helpful.
> >>
> >> Mark
> >>
> >>
> >>>
> >>> Alex
> >>>
> >>>
> >>> On Thu, Jan 30, 2020 at 3:07 PM Mark Thomas <ma...@apache.org> wrote:
> >>>
> >>>> On 30/01/2020 19:53, Alex Pritchard wrote:
> >>>>> Thanks for the response!
> >>>>>
> >>>>> I think you're right about identifying the wrong cause. I searched my
> >>>>> way through the apache versions and isolated 7.0.79 as being the
> first
> >>>>> version that breaks the redirect.
> >>>>>
> >>>>> I have tried setting useRelativeRedirects to both explicitly true and
> >>>>> false, though it seemed to produce no effect on my outcome.
> >>>>
> >>>> How did you set it? It may be that the setting didn't take effect and
> >>>> you got the default both times.
> >>>>
> >>>> Mark
> >>>>
> >>>>
> >>>>
> >>>>>
> >>>>> If there's some other difference between 7.0.78 and 7.0.79 that I'm
> >>>>> missing, maybe that would help pin down the problem. Nothing in the
> >>>>> changelog jumped out at me and the only CVE listed for 7.0.79 was
> >>>>> CVE-2017-7674 Cache Poisoning, which didn't seem related to my issue.
> >>>>>
> >>>>>
> >>>>>
> >>>>> I think you have identified the wrong change as the root cause of the
> >>>>> problem. RequestUtil still normalizes, it just won't let you traverse
> >>>>> outside of the webapp root. The URL above would be fine.
> >>>>>
> >>>>> It isn't clear to me exactly what is going on here. A step-by-step
> >>>>> description of what happens may help us identitfy potential root
> >> causes.
> >>>>>
> >>>>> Given that the annotation uses location and that StrictHttpFirewall
> is
> >>>>> part of Spring Security, I'm wondering if a redirect is involved. If
> >> so,
> >>>>> maybe something to do with useRelativeRedirects on the Context
> >>>>> (introduced in 7.0.67)?
> >>>>>
> >>>>> Mark
> >>>>>
> >>>>>
> >>>>> On Thu, Jan 30, 2020 at 12:41 PM Alex Pritchard <
> >>>> pritchard.a...@gmail.com>
> >>>>> wrote:
> >>>>>
> >>>>>> Hi,
> >>>>>>
> >>>>>> Trying to drag a legacy app forward and running into a breaking
> change
> >>>>>> based on the fact that we're using struts2 to serve some JSPs from a
> >>>>>> directory outside our context root by taking advantage of the
> >>>> now-patched
> >>>>>> directory traversal exploit.
> >>>>>>
> >>>>>> Essentially the action class is returning
> >>>>>> @Result(location="../../foo.jsp"). Previously this would be
> flattened
> >>>>>> from appName/web-inf/content/../../foo.jsp into appName/foo.jsp (I
> >>>> think by
> >>>>>> RequestUtil ?) but now it is not, so the StrictHttpFirewall
> >> isNormalized
> >>>>>> check fails.
> >>>>>>
> >>>>>> My question is if there's any way to configure our installation in
> >> some
> >>>>>> way to either identify the alternate directory as a root for these
> >> other
> >>>>>> jsps (while still functioning for the jsps that are correctly in
> >>>>>> web-inf/content) or to allow a specific directory traversal in some
> >>>>>> context.
> >>>>>>
> >>>>>> Appreciate any input!
> >>>>>>
> >>>>>> Alex
> >>>>>>
> >>>>>
> >>>>
> >>>>
> >>>> ---------------------------------------------------------------------
> >>>> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> >>>> For additional commands, e-mail: users-h...@tomcat.apache.org
> >>>>
> >>>>
> >>>
> >>
> >>
> >> ---------------------------------------------------------------------
> >> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> >> For additional commands, e-mail: users-h...@tomcat.apache.org
> >>
> >>
> >
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org
> For additional commands, e-mail: users-h...@tomcat.apache.org
>
>

Reply via email to