1. add customization support for double forwardslash in StrickHttpFirewall
2. add getEncodedUrlBlacklist() and getDecodedUrlBlacklist() method in StrickHttpFirewall Fixes gh-6292
This commit is contained in:
parent
d099a62a6f
commit
c0e66a9ba1
|
@ -88,6 +88,8 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||||
|
|
||||||
private static final List<String> FORBIDDEN_FORWARDSLASH = Collections.unmodifiableList(Arrays.asList("%2f", "%2F"));
|
private static final List<String> FORBIDDEN_FORWARDSLASH = Collections.unmodifiableList(Arrays.asList("%2f", "%2F"));
|
||||||
|
|
||||||
|
private static final List<String> FORBIDDEN_DOUBLE_FORWARDSLASH = Collections.unmodifiableList(Arrays.asList("//", "%2f%2f", "%2f%2F", "%2F%2f", "%2F%2F"));
|
||||||
|
|
||||||
private static final List<String> FORBIDDEN_BACKSLASH = Collections.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));
|
private static final List<String> FORBIDDEN_BACKSLASH = Collections.unmodifiableList(Arrays.asList("\\", "%5c", "%5C"));
|
||||||
|
|
||||||
private Set<String> encodedUrlBlacklist = new HashSet<String>();
|
private Set<String> encodedUrlBlacklist = new HashSet<String>();
|
||||||
|
@ -99,6 +101,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||||
public StrictHttpFirewall() {
|
public StrictHttpFirewall() {
|
||||||
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
||||||
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
||||||
|
urlBlacklistsAddAll(FORBIDDEN_DOUBLE_FORWARDSLASH);
|
||||||
urlBlacklistsAddAll(FORBIDDEN_BACKSLASH);
|
urlBlacklistsAddAll(FORBIDDEN_BACKSLASH);
|
||||||
|
|
||||||
this.encodedUrlBlacklist.add(ENCODED_PERCENT);
|
this.encodedUrlBlacklist.add(ENCODED_PERCENT);
|
||||||
|
@ -203,6 +206,23 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Determines if double slash "//" that is URL encoded "%2F%2F" should be allowed in the path or
|
||||||
|
* not. The default is to not allow.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param allowUrlEncodedDoubleSlash should a slash "//" that is URL encoded "%2F%2F" be allowed
|
||||||
|
* in the path or not. Default is false.
|
||||||
|
*/
|
||||||
|
public void setAllowUrlEncodedDoubleSlash(boolean allowUrlEncodedDoubleSlash) {
|
||||||
|
if (allowUrlEncodedDoubleSlash) {
|
||||||
|
urlBlacklistsRemoveAll(FORBIDDEN_DOUBLE_FORWARDSLASH);
|
||||||
|
} else {
|
||||||
|
urlBlacklistsAddAll(FORBIDDEN_DOUBLE_FORWARDSLASH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
* Determines if a period "." that is URL encoded "%2E" should be allowed in the path
|
* Determines if a period "." that is URL encoded "%2E" should be allowed in the path
|
||||||
|
@ -412,10 +432,6 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.indexOf("//") > -1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = path.length(); j > 0;) {
|
for (int j = path.length(); j > 0;) {
|
||||||
int i = path.lastIndexOf('/', j - 1);
|
int i = path.lastIndexOf('/', j - 1);
|
||||||
int gap = j - i;
|
int gap = j - i;
|
||||||
|
@ -433,4 +449,21 @@ public class StrictHttpFirewall implements HttpFirewall {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the existing encoded url blacklist which can add/remove entries from
|
||||||
|
*
|
||||||
|
* @return the existing encoded url blacklist, never null
|
||||||
|
*/
|
||||||
|
public Set<String> getEncodedUrlBlacklist() {
|
||||||
|
return encodedUrlBlacklist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the existing decoded url blacklist which can add/remove entries from
|
||||||
|
*
|
||||||
|
* @return the existing decoded url blacklist, never null
|
||||||
|
*/
|
||||||
|
public Set<String> getDecodedUrlBlacklist() {
|
||||||
|
return decodedUrlBlacklist;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -428,4 +428,100 @@ public class StrictHttpFirewallTests {
|
||||||
|
|
||||||
this.firewall.getFirewalledRequest(request);
|
this.firewall.getFirewalledRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenAllowUrlLowerCaseEncodedDoubleSlashThenNoException() throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
this.firewall.setAllowUrlEncodedDoubleSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2f%2fc");
|
||||||
|
request.setContextPath("/context-root");
|
||||||
|
request.setServletPath("");
|
||||||
|
request.setPathInfo("/a/b//c");
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenAllowUrlUpperCaseEncodedDoubleSlashThenNoException() throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
this.firewall.setAllowUrlEncodedDoubleSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2F%2Fc");
|
||||||
|
request.setContextPath("/context-root");
|
||||||
|
request.setServletPath("");
|
||||||
|
request.setPathInfo("/a/b//c");
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenAllowUrlLowerCaseAndUpperCaseEncodedDoubleSlashThenNoException()
|
||||||
|
throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
this.firewall.setAllowUrlEncodedDoubleSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2f%2Fc");
|
||||||
|
request.setContextPath("/context-root");
|
||||||
|
request.setServletPath("");
|
||||||
|
request.setPathInfo("/a/b//c");
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenAllowUrlUpperCaseAndLowerCaseEncodedDoubleSlashThenNoException()
|
||||||
|
throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
this.firewall.setAllowUrlEncodedDoubleSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2F%2fc");
|
||||||
|
request.setContextPath("/context-root");
|
||||||
|
request.setServletPath("");
|
||||||
|
request.setPathInfo("/a/b//c");
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenRemoveFromUpperCaseEncodedUrlBlacklistThenNoException() throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2F%2Fc");
|
||||||
|
this.firewall.getEncodedUrlBlacklist().removeAll(Arrays.asList("%2F%2F"));
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenRemoveFromLowerCaseEncodedUrlBlacklistThenNoException() throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2f%2fc");
|
||||||
|
this.firewall.getEncodedUrlBlacklist().removeAll(Arrays.asList("%2f%2f"));
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenRemoveFromLowerCaseAndUpperCaseEncodedUrlBlacklistThenNoException()
|
||||||
|
throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2f%2Fc");
|
||||||
|
this.firewall.getEncodedUrlBlacklist().removeAll(Arrays.asList("%2f%2F"));
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenRemoveFromUpperCaseAndLowerCaseEncodedUrlBlacklistThenNoException()
|
||||||
|
throws Exception {
|
||||||
|
this.firewall.setAllowUrlEncodedSlash(true);
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setRequestURI("/context-root/a/b%2F%2fc");
|
||||||
|
this.firewall.getEncodedUrlBlacklist().removeAll(Arrays.asList("%2F%2f"));
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getFirewalledRequestWhenRemoveFromDecodedUrlBlacklistThenNoException() throws Exception {
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "");
|
||||||
|
request.setPathInfo("/a/b//c");
|
||||||
|
this.firewall.getDecodedUrlBlacklist().removeAll(Arrays.asList("//"));
|
||||||
|
assertThatCode(() -> this.firewall.getFirewalledRequest(request)).doesNotThrowAnyException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue