dev@glassfish.java.net

Re: REST API and slashes in resource names

From: Ken Paulsen <ken.paulsen_at_oracle.com>
Date: Wed, 02 Jun 2010 10:28:01 -0700

On 06/02/2010 09: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.
Yes, we realize this. But w/o setting up a complicated scenario,
showing that %2F is being interpreted as "/' suggests that a
"%2F..%2FunauthorizedPath" vulnerability may exist. In addition to your
solution below (which I like), refusing to urldecode %2F to "/" before
resolving paths also fixes this vulnerability *AND* works in all web
container cases, I believe. Unless of course the preferred behavior is
to have the vulnerability. ;) It would not prevent paths that are
interpreted by user-defined applications from receiving %2F's, though,
which may or may not be desired by the user-defined application (I would
argue they would like to receive it in most cases... but that's just an
opinion). Perhaps Abhijit's solution below is the best case since we've
already gone down the (wrong) road of disallowing valid URL
characters... hard to undo that at this point.

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