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 > >