[ 
https://issues.apache.org/jira/browse/CXF-7931?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Petr Kadlec updated CXF-7931:
-----------------------------
    Description: 
Creating a WebTarget with a given URI instance (or anything else, see below) 
does not make the request use the given URI; before the real request is made, 
the query part of the URI (and possibly other parts) is re-encoded. For a 
specific example, colons in the query are replaced with their URI-encoded 
version, %3A (even though it is unnecessary, colons belong to the pchar class 
allowed in the query component, see 3.4 and 3.3 of RFC 3986; however, the point 
is not that the re-encoding is "too strict", the point is that the re-encoding 
takes place at all).

While it may look harmlessly at a first glance (%3A and : are just two variants 
how to encode the same text), it is in fact not harmless at all. Specifically, 
SAML2 requests using the HTTP-redirect binding are sensitive to the exact text 
of the request URI because of the request signatures. See the explicit remark 
in [SAMLBindings] 3.4.4.1:
{quote}Further, note that URL-encoding is not canonical; that is, there are 
multiple legal encodings for a given value. The relying party MUST therefore 
perform the verification step using the original URL-encoded values it received 
on the query string. It is not sufficient to re-encode the parameters after 
they have been processed by software because the resulting encoding may not 
match the signer's encoding.
{quote}
So if a SAML2 request is passed or proxied using CXF, it gets broken if it 
contains anything encoded in a different way than CXF's UriBuilderImpl choose 
to encode it.

Moreover, AFAICT, there is no way to override this behavior. Even implementing 
our own UriBuilder which strives to keep the URI intact, and passing it to the 
.target(UriBuilder) overload, its contents is retrieved via getCurrentURI(), 
the resulting (still-correct) URI is then (in resetCurrentUri()) passed to a 
new explicitly-constructed UriBuilderImpl, parsing to be re-encoded later.

 

Reproducible example:

{{ClientBuilder.newBuilder()}}
 {{    .build()}}
 {{    .target(new URI("http://localhost:5544/x?q=1:2";))}}
 {{    .request(MediaType.APPLICATION_JSON)}}
 {{    .get();}}

Expected: a HTTP request is made to {{/x?q=1:2}}.

Actual: a HTTP request is made to {{/x?q=1}}{{%3A}}{{2}}.

  was:
Creating a WebTarget with a given URI instance (or anything else, see below) 
does not make the request use the given URI; before the real request is made, 
the query part of the URI (and possibly other parts) is re-encoded. For a 
specific example, colons in the query are replaced with their URI-encoded 
version, %3A (even though it is unnecessary, colons belong to the pchar class 
allowed in the query component, see 3.4 and 3.3 of RFC 3986; however, the point 
is not that the re-encoding is "too strict", the point is that the re-encoding 
takes place at all).

While it may look harmlessly at a first glance (%3A and : are just two variants 
how to encode the same text), it is in fact not harmless at all. Specifically, 
SAML2 requests using the HTTP-redirect binding are sensitive to the exact text 
of the request URI because of the request signatures. See the explicit remark 
in [SAMLBindings] 3.4.4.1:
{quote}Further, note that URL-encoding is not canonical; that is, there are 
multiple legal encodings for a given value. The relying party MUST therefore 
perform the verification step using the original URL-encoded values it received 
on the query string. It is not sufficient to re-encode the parameters after 
they have been processed by software because the resulting encoding may not 
match the signer's encoding.
{quote}
So if a SAML2 request is passed or proxied using CXF, it gets broken if it 
contains anything encoded in a different way than CXF's UriBuilderImpl choose 
to encode it.

Moreover, AFAICT, there is no way to override this behavior. Even implementing 
our own UriBuilder which strives to keep the URI intact, and passing it to the 
.target(UriBuilder) overload, it's contents is retrieved via getCurrentURI(), 
the resulting (still-correct) URI is then (in resetCurrentUri()) passed to a 
new explicitly-constructed UriBuilderImpl, parsing to be re-encoded later.

 

Reproducible example:

{{ClientBuilder.newBuilder()}}
{{    .build()}}
{{    .target(new URI("http://localhost:5544/x?q=1:2";))}}
{{    .request(MediaType.APPLICATION_JSON)}}
{{    .get();}}

Expected: a HTTP request is made to {{/x?q=1:2}}.

Actual: a HTTP request is made to {{/x%3Aq=1:2}}.


> WebTarget re-encodes query in URI
> ---------------------------------
>
>                 Key: CXF-7931
>                 URL: https://issues.apache.org/jira/browse/CXF-7931
>             Project: CXF
>          Issue Type: Bug
>          Components: JAX-RS
>    Affects Versions: 3.1.8
>         Environment: Tested on Windows in TomEE-plus 7.0.2, which contains, 
> IIANM, CXF 3.1.8.
>            Reporter: Petr Kadlec
>            Priority: Major
>
> Creating a WebTarget with a given URI instance (or anything else, see below) 
> does not make the request use the given URI; before the real request is made, 
> the query part of the URI (and possibly other parts) is re-encoded. For a 
> specific example, colons in the query are replaced with their URI-encoded 
> version, %3A (even though it is unnecessary, colons belong to the pchar class 
> allowed in the query component, see 3.4 and 3.3 of RFC 3986; however, the 
> point is not that the re-encoding is "too strict", the point is that the 
> re-encoding takes place at all).
> While it may look harmlessly at a first glance (%3A and : are just two 
> variants how to encode the same text), it is in fact not harmless at all. 
> Specifically, SAML2 requests using the HTTP-redirect binding are sensitive to 
> the exact text of the request URI because of the request signatures. See the 
> explicit remark in [SAMLBindings] 3.4.4.1:
> {quote}Further, note that URL-encoding is not canonical; that is, there are 
> multiple legal encodings for a given value. The relying party MUST therefore 
> perform the verification step using the original URL-encoded values it 
> received on the query string. It is not sufficient to re-encode the 
> parameters after they have been processed by software because the resulting 
> encoding may not match the signer's encoding.
> {quote}
> So if a SAML2 request is passed or proxied using CXF, it gets broken if it 
> contains anything encoded in a different way than CXF's UriBuilderImpl choose 
> to encode it.
> Moreover, AFAICT, there is no way to override this behavior. Even 
> implementing our own UriBuilder which strives to keep the URI intact, and 
> passing it to the .target(UriBuilder) overload, its contents is retrieved via 
> getCurrentURI(), the resulting (still-correct) URI is then (in 
> resetCurrentUri()) passed to a new explicitly-constructed UriBuilderImpl, 
> parsing to be re-encoded later.
>  
> Reproducible example:
> {{ClientBuilder.newBuilder()}}
>  {{    .build()}}
>  {{    .target(new URI("http://localhost:5544/x?q=1:2";))}}
>  {{    .request(MediaType.APPLICATION_JSON)}}
>  {{    .get();}}
> Expected: a HTTP request is made to {{/x?q=1:2}}.
> Actual: a HTTP request is made to {{/x?q=1}}{{%3A}}{{2}}.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to