Skip to content

Commit

Permalink
0002616: Tighten up default Jetty HTTP security settings
Browse files Browse the repository at this point in the history
  • Loading branch information
mmichalek committed Jun 2, 2016
1 parent 3136907 commit e3a2d9a
Show file tree
Hide file tree
Showing 3 changed files with 124 additions and 15 deletions.
Expand Up @@ -38,5 +38,9 @@ public class ServerConstants {

public final static String JMX_HTTP_ENABLE = "jmx.http.enable";
public final static String JMX_HTTP_PORT = "jmx.http.port";

public static final String SERVER_ALLOW_DIR_LISTING = "server.allow.dir.list";
public static final String SERVER_ALLOW_HTTP_METHODS = "server.allow.http.methods";
public static final String SERVER_DISALLOW_HTTP_METHODS = "server.disallow.http.methods";

}
Expand Up @@ -33,18 +33,17 @@
import java.io.Serializable;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.Enumeration;

import javax.management.Attribute;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.servlet.DispatcherType;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;

import mx4j.tools.adaptor.http.HttpAdaptor;
import mx4j.tools.adaptor.http.XSLTProcessor;

import org.apache.commons.lang.StringUtils;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.security.ConstraintMapping;
Expand All @@ -61,6 +60,7 @@
import org.eclipse.jetty.server.session.AbstractSession;
import org.eclipse.jetty.server.session.HashSessionManager;
import org.eclipse.jetty.server.session.HashedSession;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
import org.eclipse.jetty.util.ssl.SslContextFactory;
Expand All @@ -73,6 +73,7 @@
import org.jumpmind.symmetric.common.ServerConstants;
import org.jumpmind.symmetric.common.SystemConstants;
import org.jumpmind.symmetric.transport.TransportManagerFactory;
import org.jumpmind.symmetric.web.HttpMethodFilter;
import org.jumpmind.symmetric.web.ServletUtils;
import org.jumpmind.symmetric.web.SymmetricEngineHolder;
import org.jumpmind.symmetric.web.WebConstants;
Expand All @@ -83,6 +84,9 @@
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import mx4j.tools.adaptor.http.HttpAdaptor;
import mx4j.tools.adaptor.http.XSLTProcessor;

/**
* Start up SymmetricDS through an embedded Jetty instance.
*
Expand Down Expand Up @@ -149,6 +153,12 @@ public enum Mode {

protected String httpSslVerifiedServerNames = "all";

protected String allowDirListing = "false";

protected String disallowedMethods = "OPTIONS";

protected String allowedMethods = "";

protected boolean allowSelfSignedCerts = true;

public SymmetricWebServer() {
Expand Down Expand Up @@ -203,7 +213,9 @@ protected void initFromProperties() {
System.getProperty(ServerConstants.HTTPS_VERIFIED_SERVERS, httpSslVerifiedServerNames));
allowSelfSignedCerts = serverProperties.is(ServerConstants.HTTPS_ALLOW_SELF_SIGNED_CERTS,
Boolean.parseBoolean(System.getProperty(ServerConstants.HTTPS_ALLOW_SELF_SIGNED_CERTS, "" + allowSelfSignedCerts)));

allowDirListing = serverProperties.get(ServerConstants.SERVER_ALLOW_DIR_LISTING, "false");
allowedMethods = serverProperties.get(ServerConstants.SERVER_ALLOW_HTTP_METHODS, "");
disallowedMethods = serverProperties.get(ServerConstants.SERVER_DISALLOW_HTTP_METHODS, "OPTIONS");
}

public SymmetricWebServer start(int httpPort, int jmxPort, String propertiesUrl) throws Exception {
Expand Down Expand Up @@ -257,11 +269,17 @@ public SymmetricWebServer start(int httpPort, int securePort, int httpJmxPort, M
webapp.setContextPath(webHome);
webapp.setWar(webAppDir);
webapp.setResourceBase(webAppDir);
// webapp.addServlet(DefaultServlet.class, "/*");

webapp.setInitParameter("org.eclipse.jetty.servlet.Default.dirAllowed", allowDirListing);

SessionManager sm = new SessionManager();
webapp.getSessionHandler().setSessionManager(sm);

FilterHolder filterHolder = new FilterHolder(HttpMethodFilter.class);
filterHolder.setInitParameter("server.allow.http.methods", allowedMethods);
filterHolder.setInitParameter("server.disallow.http.methods", disallowedMethods);
webapp.addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));

webapp.getServletContext().getContextHandler()
.setMaxFormContentSize(Integer.parseInt(System.getProperty("org.eclipse.jetty.server.Request.maxFormContentSize", "800000")));
webapp.getServletContext().getContextHandler()
Expand Down Expand Up @@ -388,25 +406,25 @@ protected Connector[] getConnectors(Server server, int port, int securePort, Mod
/* Prevent POODLE attack */
String ignoredProtocols = System.getProperty(SecurityConstants.SYSPROP_SSL_IGNORE_PROTOCOLS);
if (ignoredProtocols != null && ignoredProtocols.length() > 0) {
String[] protocols = ignoredProtocols.split(",");
sslConnectorFactory.addExcludeProtocols(protocols);
String[] protocols = ignoredProtocols.split(",");
sslConnectorFactory.addExcludeProtocols(protocols);
}
else {
sslConnectorFactory.addExcludeProtocols("SSLv3");
sslConnectorFactory.addExcludeProtocols("SSLv3");
}

String ignoredCiphers = System.getProperty(SecurityConstants.SYSPROP_SSL_IGNORE_CIPHERS);
if (ignoredCiphers != null && ignoredCiphers.length() > 0) {
String[] ciphers = ignoredCiphers.split(",");
sslConnectorFactory.addExcludeCipherSuites(ciphers);
String[] ciphers = ignoredCiphers.split(",");
sslConnectorFactory.addExcludeCipherSuites(ciphers);
}

sslConnectorFactory.setCertAlias(System.getProperty(SecurityConstants.SYSPROP_KEYSTORE_CERT_ALIAS,
SecurityConstants.ALIAS_SYM_PRIVATE_KEY));
sslConnectorFactory.setKeyStore(securityService.getKeyStore());
sslConnectorFactory.setTrustStore(securityService.getTrustStore());



HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig);
httpsConfig.addCustomizer(new SecureRequestCustomizer());

Expand Down Expand Up @@ -593,9 +611,9 @@ public SessionManager() {
setLazyLoad(true);
setDeleteUnrestorableSessions(true);
setSessionCookie(getSessionCookie() + (httpPort > 0 ? httpPort
: httpsPort));
: httpsPort));
}

@Override
protected AbstractSession newSession(HttpServletRequest request) {
return new Session(this, request);
Expand Down
@@ -0,0 +1,87 @@
/**
* Licensed to JumpMind Inc under one or more contributor
* license agreements. See the NOTICE file distributed
* with this work for additional information regarding
* copyright ownership. JumpMind Inc licenses this file
* to you under the GNU General Public License, version 3.0 (GPLv3)
* (the "License"); you may not use this file except in compliance
* with the License.
*
* You should have received a copy of the GNU General Public License,
* version 3.0 (GPLv3) along with this library; if not, see
* <http://www.gnu.org/licenses/>.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jumpmind.symmetric.web;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;

public class HttpMethodFilter implements Filter {

private Set<String> allowedMethods = new HashSet<String>();
private Set<String> disallowedMethods = new HashSet<String>();

@Override
public void init(FilterConfig filterConfig) throws ServletException {
String allowMethodsConfig = filterConfig.getInitParameter("server.allow.http.methods");
loadMethods(allowMethodsConfig, allowedMethods);
String disallowMethodsConfig = filterConfig.getInitParameter("server.disallow.http.methods");
loadMethods(disallowMethodsConfig, disallowedMethods);
}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String method = httpRequest.getMethod().toUpperCase();

if (disallowedMethods.contains(method)) {
forbid(method, request, response);
} else if (!allowedMethods.isEmpty() && !allowedMethods.contains(method)) {
forbid(method, request, response);
} else {
filterChain.doFilter(request, response);
}
}

protected void forbid(String method, ServletRequest request, ServletResponse response) throws IOException {
HttpServletResponse httpResponse = (HttpServletResponse)response;
httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Method " + method + " is not allowed.");
}

protected void loadMethods(String configuredValue, Set<String> methods) {
if (!StringUtils.isEmpty(configuredValue)) {
String[] methodsSplit = configuredValue.split(",");
for (String method : methodsSplit) {
if (!StringUtils.isEmpty(method)) {
methods.add(method.toUpperCase());
}
}
}
}

@Override
public void destroy() {
// Empty.
}

}

0 comments on commit e3a2d9a

Please sign in to comment.