Java embedded jetty is accepting HTTP TRACE method

11,511

Solution 1

On your Constraint object, you need to call setAuthenticate(true), and ensure that you don't call setRoles(String[]). This makes it the equivalent of a <security-constraint> with an empty <auth-constraint>, which forbids access.

The reason it works with the DefaultServlet and not the CXFServlet is because the DefaultServlet specifically denies access to the TRACE method.

Solution 2

Extending the Server class and overriding the handle() method worked best for me.

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.Server;

public class MyServer extends Server {

    @Override
    public void handle(HttpChannel<?> connection) throws IOException, ServletException {
        Request request=connection.getRequest();
        Response response=connection.getResponse();

        if ("TRACE".equals(request.getMethod())){
            request.setHandled(true);
            response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
        } else {
            super.handle(connection);
        }
    }
}

Solution 3

You can create a filter:

...
@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        if ("TRACE".equalsIgnoreCase(httpRequest.getMethod())) {
            httpResponse.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
            return;
        }
        chain.doFilter(request, response);
    }
....

Solution 4

Jan's answer works (of course). However, it will cause jetty to print a warning on startup.

WARNING ... SecurityHandler ... has uncovered http methods for path ...

To avoid this first add the constraint as in Jan's answer (disable TRACE) and then add another constraint (allow everything but TRACE). I invoke the following code for each ServletContextHandler:

private void disableTraceMethodForHandler(final ServletContextHandler servletContextHandler) {
    SecurityHandler securityHandler = servletContextHandler.getSecurityHandler();
    if (securityHandler == null) {
        securityHandler = new ConstraintSecurityHandler();
        servletContextHandler.setSecurityHandler(securityHandler);
    }
    if (securityHandler instanceof ConstraintSecurityHandler) {
        ConstraintSecurityHandler constraintSecurityHandler = (ConstraintSecurityHandler) securityHandler;

        ConstraintMapping disableTraceMapping = new ConstraintMapping();
        Constraint disableTraceConstraint = new Constraint();
        disableTraceConstraint.setName("Disable TRACE");
        disableTraceConstraint.setAuthenticate(true);
        disableTraceMapping.setConstraint(disableTraceConstraint);
        disableTraceMapping.setPathSpec("/");
        disableTraceMapping.setMethod("TRACE");
        constraintSecurityHandler.addConstraintMapping(disableTraceMapping);

        ConstraintMapping enableEverythingButTraceMapping = new ConstraintMapping();
        Constraint enableEverythingButTraceConstraint = new Constraint();
        enableEverythingButTraceConstraint.setName("Enable everything but TRACE");
        enableEverythingButTraceMapping.setConstraint(enableEverythingButTraceConstraint);
        enableEverythingButTraceMapping.setMethodOmissions(new String[] {"TRACE"});
        enableEverythingButTraceMapping.setPathSpec("/");
        constraintSecurityHandler.addConstraintMapping(enableEverythingButTraceMapping);
    }
}

I figured out this solution after I found this issue in Google's appengine-java-vm-runtime and the fix, both by Jan. The code above should do the same as the XML config there.

Share:
11,511
Admin
Author by

Admin

Updated on June 16, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm trying to disable HTTP TRACE method in embedded Jetty. In Jetty doc's is info that HTTP trace is disabled by default, but for embedded it is still enabled. I was trying to disable trace as a security constraint as is done in jetty.xml.

        ServletContextHandler servletHandler = new ServletContextHandler(ServletContextHandler.SESSIONS | ServletContextHandler.SECURITY);
        servletHandler.setClassLoader(Server.class.getClassLoader());
        servletHandler.setContextPath("/");
        servletHandler.addEventListener(new ContextLoaderListener());
        servletHandler.addServlet(new ServletHolder(new CXFServlet()), "/*");
        servletHandler.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
        servletHandler.setInitParameter("contextConfigLocation", BeansConfig.class.getName());
        servletHandler.setInitParameter("javax.ws.rs.Application", DispatcherConfig.class.getName());
    
         /*
         * <security-constraint>
         * <web-resource-collection>
         * <web-resource-name>Disable TRACE</web-resource-name>
         * <url-pattern>/</url-pattern>
         * <http-method>TRACE</http-method>
         * </web-resource-collection>
         * <auth-constraint/>
         * </security-constraint>
         */
         Constraint constraint = new Constraint();
         constraint.setName("Disable TRACE");
    
         ConstraintMapping mapping = new ConstraintMapping();
         mapping.setConstraint(constraint);
         mapping.setMethod("TRACE");
         mapping.setPathSpec("/"); // this did not work same this mapping.setPathSpec("/*");
    
         ConstraintSecurityHandler securityHandler = (ConstraintSecurityHandler) servletHandler.getSecurityHandler();
         securityHandler.addConstraintMapping(mapping);
    

    Example output from soapUI:

    HTTP/1.1 200 OK
    Content-Type: message/http
    Content-Length: 143
    Server: Jetty(9.0.6.v20130930)
    
    TRACE / HTTP/1.1
    Connection: keep-alive
    User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
    Host: 192.168.33.115
    Accept-Encoding: gzip,deflate