dev@glassfish.java.net

Re: REST API and slashes in resource names

From: Jason Lee <jason.d.lee_at_oracle.com>
Date: Wed, 02 Jun 2010 12:02:57 -0500

Ultimately, that's where I'd like to drive this. I think the mechanism
is there already, though it appears to be buggy (thus my report). It
may also be more appropriate to change ContainerMapper to allow %2F than
to remove the decoding there and handle the %2F issue per adapter. I'll
defer to Bill and Jerome on that, as they're likely more familiar with
that code than I am.

On 6/2/10 11:59 AM, Abhijit Kumar wrote:
> 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


-- 
Jason Lee
Senior Member of Technical Staff
GlassFish Administration Console
Oracle Corporation
Phone x31197/+1 405-343-1964
Blog http://blogs.steeplesoft.com