Block URL Encoded "/" in DefaultHttpFirewall

Fixes gh-4169
This commit is contained in:
Rob Winch
2016-12-07 14:32:41 -06:00
parent fc516b55a6
commit 666e356ebc
2 changed files with 126 additions and 33 deletions

View File

@@ -15,39 +15,93 @@
*/
package org.springframework.security.web.firewall;
import static org.assertj.core.api.Assertions.fail;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import static org.assertj.core.api.Assertions.fail;
/**
* @author Luke Taylor
*/
public class DefaultHttpFirewallTests {
public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.",
"/path/path//.", "./path/../path//.", "./path", ".//path", "." };
public String[] unnormalizedPaths = { "/..", "/./path/", "/path/path/.", "/path/path//.", "./path/../path//.",
"./path", ".//path", "." };
@Test
public void unnormalizedPathsAreRejected() throws Exception {
DefaultHttpFirewall fw = new DefaultHttpFirewall();
MockHttpServletRequest request;
for (String path : unnormalizedPaths) {
for (String path : this.unnormalizedPaths) {
request = new MockHttpServletRequest();
request.setServletPath(path);
try {
fw.getFirewalledRequest(request);
fail(path + " is un-normalized");
}
catch (RequestRejectedException expected) {
} catch (RequestRejectedException expected) {
}
request.setPathInfo(path);
try {
fw.getFirewalledRequest(request);
fail(path + " is un-normalized");
}
catch (RequestRejectedException expected) {
} catch (RequestRejectedException expected) {
}
}
}
/**
* On WebSphere 8.5 a URL like /context-root/a/b;%2f1/c can bypass a rule on
* /a/b/c because the pathInfo is /a/b;/1/c which ends up being /a/b/1/c
* while Spring MVC will strip the ; content from requestURI before the path
* is URL decoded.
*/
@Test(expected = RequestRejectedException.class)
public void getFirewalledRequestWhenLowercaseEncodedPathThenException() {
DefaultHttpFirewall fw = new DefaultHttpFirewall();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/context-root/a/b;%2f1/c");
request.setContextPath("/context-root");
request.setServletPath("");
request.setPathInfo("/a/b;/1/c"); // URL decoded requestURI
fw.getFirewalledRequest(request);
}
@Test(expected = RequestRejectedException.class)
public void getFirewalledRequestWhenUppercaseEncodedPathThenException() {
DefaultHttpFirewall fw = new DefaultHttpFirewall();
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/context-root/a/b;%2f1/c");
request.setContextPath("/context-root");
request.setServletPath("");
request.setPathInfo("/a/b;/1/c"); // URL decoded requestURI
fw.getFirewalledRequest(request);
}
@Test
public void getFirewalledRequestWhenAllowUrlEncodedSlashAndLowercaseEncodedPathThenNoException() {
DefaultHttpFirewall fw = new DefaultHttpFirewall();
fw.setAllowUrlEncodedSlash(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/context-root/a/b;%2f1/c");
request.setContextPath("/context-root");
request.setServletPath("");
request.setPathInfo("/a/b;/1/c"); // URL decoded requestURI
fw.getFirewalledRequest(request);
}
@Test
public void getFirewalledRequestWhenAllowUrlEncodedSlashAndUppercaseEncodedPathThenNoException() {
DefaultHttpFirewall fw = new DefaultHttpFirewall();
fw.setAllowUrlEncodedSlash(true);
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/context-root/a/b;%2f1/c");
request.setContextPath("/context-root");
request.setServletPath("");
request.setPathInfo("/a/b;/1/c"); // URL decoded requestURI
fw.getFirewalledRequest(request);
}
}