dev@glassfish.java.net

Re: REST API and slashes in resource names

From: Abhijit Kumar <abhijit.kumar_at_oracle.com>
Date: Wed, 02 Jun 2010 09:59:02 -0700

I have to jump in here. The vulnerability is around being able to
traverse outside of the so called "document root" of the server. Using
an encoded URL to get to a file under "document root" is not a
vulnerability.

IMHO, the answer is fairly simple (and sorry if this was already
discussed). Grizzly should implement a feature to allow configuration of
this feature per connector. Admin connector (port 4848) should be
configured to allow %2F and all the applications running there should
make sure that combination of encoded ".." and "/" can not be used to
get to unauthorized areas of the server.

On 6/2/10 9:47 AM, Jason Lee wrote:
> Shing Wai (and Amy) tell me that the web container suffers from the
> same vulnerability that the Tomcat changelog warns of. Ken and I have
> both confirmed this via testing (curl
> http://localhost:8080/foo%2Fbar.html returns the contents of
> foo/bar.html when it shouldn't).
>
> That being said, do we proceed with the double encoding, or press for
> a fix from the web container, which may not be very straightforward.
> The web container doesn't follow the same code path in handling
> requests, but here is how things work with the GrizzlyAdapters that
> the console and REST API use. In ContainerMapper.java, at line 193ff,
> we see:
>
> String uriEncoding = (String)
> grizzlyEmbeddedHttp.getProperty("uriEncoding");
> HttpRequestURIDecoder.decode(decodedURI, urlDecoder,
> uriEncoding, null);
> adapter = map(req, decodedURI, mappingData);
>
> Grizzly is asked, via HttpRequestURIDecoder, to decode the requested
> URL, which is where we're seeing our security check/failure, and THEN
> the adapter is requested.
>
> This may be the path of madness, but I disabled the call to
> HttpRequestURIDecoder, which lets the processing proceed. The request
> then does make it to GrizzlyAdapter.service(Request,Response), but
> fails again for similar reasons. This time, though, it should not.
> The call to HttpRequestURIDecoder is passed a UDecoder pulled from the
> request, which, in the case of RestAdapter, has allowEncodedSlash set
> to true in my local tree. It seems, though, there's a bug in
> Grizzly's UDecoder where the ivar allowEncodedSlash is hidden by a
> method parameter of the same name, whose value has been set to false.
> I've filed an issue with the Grizzly team
> (https://grizzly.dev.java.net/issues/show_bug.cgi?id=828) and am
> waiting for feedback on that.
>
> While I wait for their analysis, what are the downsides to disabling
> the call to HttpRequestURIDecoder.decode() in ContainerMapper? I'll
> kick off QL now and see if that turns up anything...
>
> On 6/2/10 4:16 AM, Paul Sandoz wrote:
>> Hi Ken,
>>
>> For a RESTful system the client should not be constructing URIs
>> unless informed how to do so by representations from the server (e.g.
>> HTML forms) otherwise it unduly couples the client and service. So
>> the construction of such URIs, and the placement in representations,
>> is a server-side issue not a client-side issue.
>>
>> IIRC i think the RESTful admin service is in accordance with that.
>>
>> Paul.
>>
>> On Jun 2, 2010, at 12:03 AM, Ken Paulsen wrote:
>>
>>>
>>> In an attempt to summarize our options and the requirements (as I
>>> understand them):
>>>
>>>
>>> Requirements:
>>>
>>> * Path
>>> element must be URL safe
>>> * Path
>>> element must not be ambiguous
>>> * Path
>>> element must not restrict the URL namespace further
>>> * Solution
>>> must be generic so it may be applied to any other use-case
>>> with invalid
>>> URL characters
>>> * Solution
>>> should be as natural & simple as possible to REST developers.
>>>
>>>
>>> Options
>>> for '/' within REST path element:
>>>
>>> * .../management/domain/resource/admin-object-resource/jndi/foo/property
>>> o Security
>>> Concerns:
>>> ??
>>> o Client
>>> Coding issues:
>>> None.
>>> o Readability:
>>> OK (JNDI name may be confused for part of the path)
>>> o Ambiguous:
>>> Yes (JNDI slashes are not distinguishable from the path
>>> elements)
>>> o Other
>>> Issues:
>>> Just the ambiguity.
>>> * .../management/domain/resource/admin-object-resource/jndi%2Ffoo/property
>>> o Security
>>> Concerns:
>>> ??
>>> o Client
>>> Coding issues:
>>> Must call urlencode on JNDI name (simple & expected)
>>> o Readability:
>>> Good
>>> o Ambiguous:
>>> No
>>> o Other
>>> Issues:
>>> Grizzly may not allow %2F???
>>> * .../management/domain/resource/admin-object-resource/(jndi/foo)/property
>>> o Security
>>> Concerns:
>>> ??
>>> o Client
>>> Coding issues:
>>> Must know to put parenthesis "()" around JNDI name and
>>> to NOT urlencode
>>> it.
>>> o Readability:
>>>
>>> OK. This is not a typical solution so it looks funny.
>>> '/' inside ()'s
>>>
>>> may be confusing (looks like 2 tokens: "(jndi" and "foo)".
>>> o Ambiguous:
>>>
>>> No. However, you need to know the special rules to read
>>> it correctly
>>>
>>> (i.e. ()'s have higher precendence than '/'). This is
>>> not a standard
>>>
>>> and will be confusing.
>>> o Other
>>> Issues:
>>> None.
>>> * .../management/domain/resource/admin-object-resource/jndi%252Ffoo/property
>>> o Security
>>> Concerns:
>>> Nothing known.
>>> o Client
>>> Coding issues:
>>>
>>> Must call urlencode on JNDI name 2x. This may be
>>> confusing as to why it
>>>
>>> must be called 2x. However, it is simple to implement
>>> since it uses a
>>>
>>> standard encoding.
>>> o Readability:
>>> OK. Will be confusing that it is encoded 2x instead of
>>> the standard of
>>> 1x.
>>> o Ambiguous:
>>> No
>>> o Other
>>> Issues:
>>> None.
>>> * .../management/domain/resource/admin-object-resource/property?jndiName=jndi_at_
>>> o Security
>>> Concerns:
>>> Nothing known.
>>> o Client
>>> Coding issues:
>>> Must call urlencode on JNDI name (simple & expected);
>>> must add a
>>> Query String parameter.
>>> o Readability:
>>> OK (see other issues)
>>> o Ambiguous:
>>> Yes (see other issues)
>>> o Other
>>> Issues:
>>>
>>> Query String parameters are not ordered in Java and
>>> cannot be related
>>>
>>> to a particular path element easily. This does not
>>> provide good a
>>>
>>> general solution to allowing '/' characters in path
>>> elements. It makes
>>>
>>> it difficult to read the path as a relative path
>>> identifying a single
>>>
>>> object. It also may be ambiguous if more than 1 path
>>> element needs to
>>>
>>> allow '/' in its name.
>>>
>>>
>>>
>>> I look forward to discussing this at the admin iteam...
>>>
>>>
>>>
>>> Ken
>>>
>>>
>>> On 06/01/2010 12:00 PM, Bruno Harbulot wrote:
>>>>
>>>> On 01/06/10 17:23, Paul Sandoz wrote:
>>>>
>>>>>> On 01/06/10 11:47, Andreas Loew wrote:
>>>>>>> Hi Paul,
>>>>>>>
>>>>>>> Paul Sandoz schrieb:
>>>>>>>
>>>>>>>>> Not quite: '{' and '}' are just "unsafe" characters,
>>>>>>>>
>>>>>>>> They are disallowed in the URI syntax:
>>>>>>>>
>>>>>>>> http://greenbytes.de/tech/webdav/rfc2396.html#rfc.section.2.4.3
>>>>>>>
>>>>>>> while I don't want to argue with you about the subtleties of the
>>>>>>> fact
>>>>>>> that curly brackets are *not* part of *neither* "reserved" *nor*
>>>>>>> "unreserved" characters, it seems to me that the following would be
>>>>>>> fully sanctioned by the spec:
>>>>>>>
>>>>>>> .../management/domain/resources/admin-object-resource/(jndi/foo)
>>>>>>>
>>>>>>> because "normal" brackets are "unreserved" characters: "Data
>>>>>>> characters
>>>>>>> that are allowed in a URI but do not have a reserved purpose are
>>>>>>> called
>>>>>>> unreserved."
>>>>>>>
>>>>>>> So how about wrapping resource values that contain "reserved"
>>>>>>> characters
>>>>>>> by a pair of (unreserved) "normal" brackets '(' and ')'?
>>>>>>
>>>>>> I'm not sure whether you want to take more recent RFCs into
>>>>>> consideration, but in RFC 3986, which obsoletes RFC 2389,
>>>>>
>>>>> Good point. I was using the URI spec that is referenced by HTTP 1.1
>>>>> (maybe the work on tidying up the HTTP spec will update the
>>>>> reference?)
>>>>>
>>>>>
>>>>>> parentheses are reserved characters:
>>>>>>
>>>>>> http://tools.ietf.org/html/rfc3986#section-2.2
>>>>>>
>>>>>> Section 2.4 is probably relevant to this discussion too (especially
>>>>>> its last sentence).
>>>>>>
>>>>>
>>>>> I am not sure what the last sentence actually means in terms of
>>>>> parsing
>>>>> a URI :-) but i strongly suspect for HTTP schemes and the path
>>>>> component
>>>>> that '(' and ')' are OK. Jersey does not encode such characters
>>>>> when URI
>>>>> building path components e.g.:
>>>>>
>>>>> URI u = UriBuilder.fromPath("/(xxx/yyy)/zzz").build();
>>>>>
>>>>> BTW IIRC Microsoft's Astoria uses '[' and ']' for delimitation and
>>>>> those
>>>>> are percent encoded.
>>>>>
>>>>> It would be so much easier if we could use %2F !
>>>>
>>>> I guess Jersey might not follow the newer RFC.
>>>> What I meant with the relevance of the last sentence of section
>>>> 2.4, is that it more or less implies that, once the path components
>>>> (separated with '/' have been split) and %2F decoded, further tools
>>>> in the dispatch chain shouldn't split them further.
>>>>
>>>> I wasn't aware of the security issue with %2F and proxy servers,
>>>> but it sounds more like a case of fixing the way the server behind
>>>> the proxy interprets them when it shouldn't.
>>>>
>>>>
>>>> Coming back to the original problem... To be honest, I don't use
>>>> Glassfish every day so I'm not sure whether I'm going to go off
>>>> topic here, but from a REST point of view, there's no such thing as
>>>> a RESTful URI (and I think no one had used that expression in the
>>>> thread so far, so no problem here ;-) ).
>>>>
>>>> This is a question that often comes back on the rest-discuss list,
>>>> but the important point in REST is how you can link and get the
>>>> resources.
>>>> Considering that the query part is an integral part of the URI
>>>> (although some implementations don't necessarily view it this way),
>>>> these two elements are more or less equivalent in terms of "URI
>>>> RESTfulness":
>>>> <a href="http://myblog.example/pages/1">First page</a>
>>>> <a href="http://myblog.example/?page=1">First page</a>
>>>>
>>>> People often think that RESTful systems must have "RESTful URIs"
>>>> that are query-free. That's not strictly true as far as the REST
>>>> constraint are concerned from a theoretical point of view.
>>>> It's mostly an aesthetic matter, which is frankly barely relevant
>>>> if you follow the hypermedia constraints of REST. Having a query in
>>>> the URI is often a bad sign when the parameters symbolise actions
>>>> (e.g. "?action=delete"), so that's probably why they're often
>>>> discouraged.
>>>>
>>>> Whilst
>>>> <http://localhost:4848/management/domain/resources/admin-object-resource/jndi-foo?convertDash=true>
>>>> could be considered as symbolising an action (arguable, since it
>>>> clearly wasn't the intent),
>>>> it sounds like
>>>> <http://localhost:4848/management/domain/resources/admin-object-resource/?resource=jndi%2Ffoo>
>>>> would be just fine.
>>>>
>>>> Where having a query part or not matters is in terms of
>>>> implementation, regarding how the query is dispatched to whatever
>>>> needs to process that query. That's of course where the problem is
>>>> here. I think the two main downsides of using a query are that not
>>>> all proxy cache the requests with queries and that it also makes it
>>>> harder to use another query on that resource or to build a
>>>> sub-hierarchy (I'm not sure if it would be the case here).
>>>>
>>>>
>>>> Best wishes,
>>>>
>>>> Bruno.
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe_at_glassfish.dev.java.net
>>>> For additional commands, e-mail: dev-help_at_glassfish.dev.java.net
>>>>
>>
>
>
> --
> Jason Lee
> Senior Member of Technical Staff
> GlassFish Administration Console
>
> Oracle Corporation
> Phone x31197/+1 405-343-1964
> Bloghttp://blogs.steeplesoft.com