|
@@ -1,5 +1,5 @@
|
|
/*
|
|
/*
|
|
- * Copyright 2012-2017 the original author or authors.
|
|
|
|
|
|
+ * Copyright 2012-2020 the original author or authors.
|
|
*
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* you may not use this file except in compliance with the License.
|
|
@@ -16,14 +16,14 @@
|
|
|
|
|
|
package org.springframework.security.web.firewall;
|
|
package org.springframework.security.web.firewall;
|
|
|
|
|
|
-import javax.servlet.http.HttpServletRequest;
|
|
|
|
-import javax.servlet.http.HttpServletResponse;
|
|
|
|
import java.util.Arrays;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.Collections;
|
|
import java.util.HashSet;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.Set;
|
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
|
+import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
|
/**
|
|
/**
|
|
* <p>
|
|
* <p>
|
|
@@ -59,10 +59,15 @@ import java.util.Set;
|
|
* Rejects URLs that contain a URL encoded percent. See
|
|
* Rejects URLs that contain a URL encoded percent. See
|
|
* {@link #setAllowUrlEncodedPercent(boolean)}
|
|
* {@link #setAllowUrlEncodedPercent(boolean)}
|
|
* </li>
|
|
* </li>
|
|
|
|
+ * <li>
|
|
|
|
+ * Rejects hosts that are not allowed. See
|
|
|
|
+ * {@link #setAllowedHostnames(Collection)}
|
|
|
|
+ * </li>
|
|
* </ul>
|
|
* </ul>
|
|
*
|
|
*
|
|
* @see DefaultHttpFirewall
|
|
* @see DefaultHttpFirewall
|
|
* @author Rob Winch
|
|
* @author Rob Winch
|
|
|
|
+ * @author Eddú Meléndez
|
|
* @since 4.2.4
|
|
* @since 4.2.4
|
|
*/
|
|
*/
|
|
public class StrictHttpFirewall implements HttpFirewall {
|
|
public class StrictHttpFirewall implements HttpFirewall {
|
|
@@ -82,6 +87,8 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|
|
|
|
|
private Set<String> decodedUrlBlacklist = new HashSet<String>();
|
|
private Set<String> decodedUrlBlacklist = new HashSet<String>();
|
|
|
|
|
|
|
|
+ private Collection<String> allowedHostnames;
|
|
|
|
+
|
|
public StrictHttpFirewall() {
|
|
public StrictHttpFirewall() {
|
|
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
|
urlBlacklistsAddAll(FORBIDDEN_SEMICOLON);
|
|
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
|
urlBlacklistsAddAll(FORBIDDEN_FORWARDSLASH);
|
|
@@ -230,6 +237,13 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ public void setAllowedHostnames(Collection<String> allowedHostnames) {
|
|
|
|
+ if (allowedHostnames == null) {
|
|
|
|
+ throw new IllegalArgumentException("allowedHostnames cannot be null");
|
|
|
|
+ }
|
|
|
|
+ this.allowedHostnames = allowedHostnames;
|
|
|
|
+ }
|
|
|
|
+
|
|
private void urlBlacklistsAddAll(Collection<String> values) {
|
|
private void urlBlacklistsAddAll(Collection<String> values) {
|
|
this.encodedUrlBlacklist.addAll(values);
|
|
this.encodedUrlBlacklist.addAll(values);
|
|
this.decodedUrlBlacklist.addAll(values);
|
|
this.decodedUrlBlacklist.addAll(values);
|
|
@@ -243,6 +257,7 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|
@Override
|
|
@Override
|
|
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
|
|
public FirewalledRequest getFirewalledRequest(HttpServletRequest request) throws RequestRejectedException {
|
|
rejectedBlacklistedUrls(request);
|
|
rejectedBlacklistedUrls(request);
|
|
|
|
+ rejectedUntrustedHosts(request);
|
|
|
|
|
|
if (!isNormalized(request)) {
|
|
if (!isNormalized(request)) {
|
|
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
|
|
throw new RequestRejectedException("The request was rejected because the URL was not normalized.");
|
|
@@ -272,6 +287,19 @@ public class StrictHttpFirewall implements HttpFirewall {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ private void rejectedUntrustedHosts(HttpServletRequest request) {
|
|
|
|
+ String serverName = request.getServerName();
|
|
|
|
+ if (serverName == null) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (this.allowedHostnames == null) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ if (!this.allowedHostnames.contains(serverName)) {
|
|
|
|
+ throw new RequestRejectedException("The request was rejected because the domain " + serverName + " is untrusted.");
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
@Override
|
|
@Override
|
|
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
|
|
public HttpServletResponse getFirewalledResponse(HttpServletResponse response) {
|
|
return new FirewalledResponse(response);
|
|
return new FirewalledResponse(response);
|