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 11:47:41 -0500

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
Blog http://blogs.steeplesoft.com