Skip to content

Commit

Permalink
Disable 'Server' HTTP header in REST responses
Browse files Browse the repository at this point in the history
Such header is attached automatically by Jetty and specifies it's
version, like 'Server: Jetty(9.4.8.v20171121)'.

This commit makes Jetty not attach the 'Server' header for security
reasons. Known server type and version allows to search for
known vulnerabilities and exploit them.
  • Loading branch information
lutovich committed May 16, 2018
1 parent f7f2f7d commit b3bf529
Show file tree
Hide file tree
Showing 4 changed files with 166 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ protected HttpConfiguration createHttpConfig()
HttpConfiguration httpConfig = new HttpConfiguration();
httpConfig.setRequestHeaderSize( configuration.get( ServerSettings.maximum_request_header_size) );
httpConfig.setResponseHeaderSize( configuration.get( ServerSettings.maximum_response_header_size) );
httpConfig.setSendServerVersion( false );
return httpConfig;
}

Expand Down
120 changes: 120 additions & 0 deletions community/server/src/test/java/org/neo4j/server/HttpHeadersIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
/*
* Copyright (c) 2002-2018 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.server;

import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
import com.sun.jersey.client.urlconnection.HTTPSProperties;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.net.URI;
import java.util.List;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.ws.rs.core.MultivaluedMap;

import org.neo4j.test.server.ExclusiveServerTestBase;
import org.neo4j.test.server.InsecureTrustManager;

import static com.sun.jersey.client.urlconnection.HTTPSProperties.PROPERTY_HTTPS_PROPERTIES;
import static org.eclipse.jetty.http.HttpHeader.SERVER;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.neo4j.server.helpers.CommunityServerBuilder.serverOnRandomPorts;

public class HttpHeadersIT extends ExclusiveServerTestBase
{
private CommunityNeoServer server;

@Before
public void setUp() throws Exception
{
server = serverOnRandomPorts().withHttpsEnabled()
.usingDataDir( folder.directory( name.getMethodName() ).getAbsolutePath() )
.build();

server.start();
}

@After
public void tearDown() throws Exception
{
if ( server != null )
{
server.stop();
}
}

@Test
public void shouldNotSendJettyVersionWithHttpResponseHeaders() throws Exception
{
URI httpUri = server.baseUri();
testNoJettyVersionInResponseHeaders( httpUri );
}

@Test
public void shouldNotSendJettyVersionWithHttpsResponseHeaders() throws Exception
{
URI httpsUri = server.httpsUri().orElseThrow( IllegalStateException::new );
testNoJettyVersionInResponseHeaders( httpsUri );
}

private static void testNoJettyVersionInResponseHeaders( URI baseUri ) throws Exception
{
URI uri = baseUri.resolve( "db/data/transaction/commit" );
ClientRequest request = createClientRequest( uri );

ClientResponse response = createClient().handle( request );

assertEquals( 200, response.getStatus() );

MultivaluedMap<String,String> headers = response.getHeaders();
assertNull( headers.get( SERVER.name() ) ); // no 'Server' header
for ( List<String> values : headers.values() )
{
assertFalse( values.stream().anyMatch( value -> value.toLowerCase().contains( "jetty" ) ) ); // no 'jetty' in other header values
}
}

private static ClientRequest createClientRequest( URI uri )
{
return ClientRequest.create()
.header( "Accept", "application/json" )
.build( uri, "POST" );
}

private static Client createClient() throws Exception
{
HostnameVerifier hostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
ClientConfig config = new DefaultClientConfig();
SSLContext ctx = SSLContext.getInstance( "TLS" );
ctx.init( null, new TrustManager[]{new InsecureTrustManager()}, null );
config.getProperties().put( PROPERTY_HTTPS_PROPERTIES, new HTTPSProperties( hostnameVerifier, ctx ) );
return Client.create( config );
}
}
23 changes: 2 additions & 21 deletions community/server/src/test/java/org/neo4j/server/HttpsAccessIT.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,13 @@
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.neo4j.test.server.ExclusiveServerTestBase;
import org.neo4j.test.server.HTTP;
import org.neo4j.test.server.InsecureTrustManager;

import static org.hamcrest.CoreMatchers.startsWith;
import static org.hamcrest.Matchers.is;
Expand Down Expand Up @@ -64,24 +62,7 @@ public void startServer() throws NoSuchAlgorithmException, KeyManagementExceptio

// Because we are generating a non-CA-signed certificate, we need to turn off verification in the client.
// This is ironic, since there is no proper verification on the CA side in the first place, but I digress.

TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager()
{
public void checkClientTrusted( X509Certificate[] arg0, String arg1 )
{
}

public void checkServerTrusted( X509Certificate[] arg0, String arg1 )
{
}

public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}
};
TrustManager[] trustAllCerts = {new InsecureTrustManager()};

// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance( "TLS" );
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright (c) 2002-2018 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.test.server;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.X509TrustManager;

public class InsecureTrustManager implements X509TrustManager
{
@Override
public void checkClientTrusted( X509Certificate[] x509Certificates, String s ) throws CertificateException
{
}

@Override
public void checkServerTrusted( X509Certificate[] x509Certificates, String s ) throws CertificateException
{
}

@Override
public X509Certificate[] getAcceptedIssuers()
{
return null;
}
}

0 comments on commit b3bf529

Please sign in to comment.