Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Springboot doesn't let through percentage and backslash in URL

We got a get request that sends string characters in url, so we use path variables to receive them. Apparently there is no way that the calling service would change its method of calling backend so we need to be able to accept a url with the following unencoded characters:

When percentage sign % is sent a http 400 is returned. It does go through if the two characters following % make up an UTF-encoded character

Backslash is converted into a forward slash. I need it to stay backslash.

I'm guessing these might be Tomcat or servlet configuration issues.

(spring boot version 1.5.14.RELEASE)

like image 601
Greg Hill Avatar asked Jun 29 '18 19:06

Greg Hill


3 Answers

Percent signs (%) should be no problem if you properly URL encode them (%25). However, slashes and backslashes will not work with Tomcat, even if you encode them (%2F and %5C).

You could set the following properties when running the application:

-Dorg.apache.tomcat.util.buf.UDecoder.ALLOW_ENCODED_SLASH=true
-Dorg.apache.catalina.connector.CoyoteAdapter.ALLOW_BACKSLASH=true

However, this won't fix the issue, because in this case, those encoded slashes will be recognized as real ones. So, let's say you have the following controller:

@ResponseBody
@RequestMapping("/api/{foo}")
public String getFoo(@PathVariable String foo) {
    return foo;
}

Well, then if you call /api/test%5Ctest, it won't be able to find the correct path. A solution to this problem is to use wildcard matchers and to parse the URL itself from the incoming HttpServletRequest:

@RequestMapping("/api/**")
public String getFoo(HttpServletRequest request) {
    // ...
}

Another solution is to use a completely different web container. For example, when using Jetty, this isn't a problem at all, and URL encoded slashes and backslashes will both work.

like image 74
g00glen00b Avatar answered Oct 12 '22 07:10

g00glen00b


Spring 5 now blocks encoded percent signs by default. To enable them, create a new Bean that calls setAllowUrlEncodedPercent()

@Bean
public HttpFirewall allowEncodedParamsFirewall() {
    StrictHttpFirewall firewall = new StrictHttpFirewall();
    firewall.setAllowUrlEncodedPercent(true);    
    return firewall;
}

There are similar method-calls for forward- and backwards-slash

like image 20
BlueRaja - Danny Pflughoeft Avatar answered Oct 12 '22 08:10

BlueRaja - Danny Pflughoeft


What you are experiencing is not specific to Spring Boot. Instead, it's a restriction of HTTP.

The HTTP standard requires that any URL containing the percent characters must be decoded by the web server (cf page 36):

If the Request-URI is encoded using the "% HEX HEX" encoding [42], the origin server MUST decode the Request-URI in order to properly interpret the request.

As a result, it's not possible to escape the slash character reliably.

Therefore, when the slash is used in a URL – with or without encoding – it will be treated as a path separator. So it cannot be used in a Spring Boot path variable. Similar problem exist for the percent sign and backslash.

Your best options are to use query parameters or a POST request.

In the following URL, the value test_with_/and_% is transmitted:

https://host/abc/def?text=test_with_%2F_and%25
like image 31
Codo Avatar answered Oct 12 '22 07:10

Codo