From d93d39a9c6cab31b308b3652f920c683b7fd75ca Mon Sep 17 00:00:00 2001 From: ghidra1 Date: Fri, 10 Sep 2021 16:29:00 -0400 Subject: [PATCH] GP-1287 Improved client/server TLS version restrictions. TLSv1.2 and TLSv1.3 enabled by default. --- .../ghidra/server/remote/GhidraServer.java | 25 ++++++++++-- .../ghidra/net/SSLContextInitializer.java | 39 ++++++------------- .../RuntimeScripts/Common/server/server.conf | 30 +++++++------- .../Common/support/launch.properties | 32 +++++---------- 4 files changed, 60 insertions(+), 66 deletions(-) diff --git a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java index 9fc5458dee..088c970198 100644 --- a/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java +++ b/Ghidra/Features/GhidraServer/src/main/java/ghidra/server/remote/GhidraServer.java @@ -66,6 +66,8 @@ import utility.application.ApplicationLayout; */ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHandle { + private final static String TLS_SERVER_PROTOCOLS_PROPERTY = "ghidra.tls.server.protocols"; + private static SslRMIServerSocketFactory serverSocketFactory; private static SslRMIClientSocketFactory clientSocketFactory; private static InetAddress bindAddress; @@ -786,17 +788,19 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan log.info( " Anonymous server access: " + (allowAnonymousAccess ? "enabled" : "disabled")); - log.info(SystemUtilities.getUserName() + " starting Ghidra Server..."); - - serverSocketFactory = new SslRMIServerSocketFactory(null, null, authMode == PKI_LOGIN) { + serverSocketFactory = new SslRMIServerSocketFactory(null, getEnabledTlsProtocols(), + authMode == PKI_LOGIN) { @Override public ServerSocket createServerSocket(int port) throws IOException { return new GhidraSSLServerSocket(port, bindAddress, getEnabledCipherSuites(), getEnabledProtocols(), getNeedClientAuth()); } + }; clientSocketFactory = new SslRMIClientSocketFactory(); + log.info(SystemUtilities.getUserName() + " starting Ghidra Server..."); + GhidraServer svr = new GhidraServer(serverRoot, authMode, loginDomain, nameCallbackAllowed, altSSHLoginAllowed, defaultPasswordExpiration, allowAnonymousAccess, autoProvision, jaasConfigFile); @@ -821,6 +825,21 @@ public class GhidraServer extends UnicastRemoteObject implements GhidraServerHan } } + private static String[] getEnabledTlsProtocols() { + String protocolList = System.getProperty(TLS_SERVER_PROTOCOLS_PROPERTY); + if (protocolList != null) { + + log.info(" Enabled protocols: " + protocolList); + + String[] protocols = protocolList.split(";"); + for (int i = 0; i < protocols.length; i++) { + protocols[i] = protocols[i].trim(); + } + return protocols; + } + return null; + } + static synchronized void stop() { if (server == null) { throw new IllegalStateException("Invalid Stop request, Server is not running"); diff --git a/Ghidra/Framework/Generic/src/main/java/ghidra/net/SSLContextInitializer.java b/Ghidra/Framework/Generic/src/main/java/ghidra/net/SSLContextInitializer.java index 3708f05ed4..fd74f17fa2 100644 --- a/Ghidra/Framework/Generic/src/main/java/ghidra/net/SSLContextInitializer.java +++ b/Ghidra/Framework/Generic/src/main/java/ghidra/net/SSLContextInitializer.java @@ -24,31 +24,25 @@ import ghidra.framework.ModuleInitializer; import ghidra.util.Msg; /** - * Initialize the default SSLContext for use by SSL connections (e.g., https). + * Initialize the default SSLContext for use by all SSL connections (e.g., https). * It is the responsibility of the Application to properly invoke this initializer - * so that the default SSLContext may be established. While HTTPS URL connections + * to ensure that the default SSLContext is properly established. While HTTPS URL connections * will make use of this default SSLContext, other SSL connections may need to * specify the {@link ApplicationSSLSocketFactory} to leverage the applications * default SSLContext. + *

+ * The property jdk.tls.client.protocols should be set to restrict secure + * client connections to a specific set of enabled TLS protocols (e.g., TLSv1.2,TLSv1.3). + * See JDK and JRE Cryptographic Algorithms + * for details. + * * @see ApplicationTrustManagerFactory * @see ApplicationKeyManagerFactory * @see ApplicationKeyManagerUtils */ public class SSLContextInitializer implements ModuleInitializer { - // NOTE: specifying a default protocol of "TLS" will defer the default - // protocol selection to the underlying protocol implementation. - // The protocol may be specified as a comma-separated list of protocol - // versions where the leftmost takes precendence during the initial - // negotiation. The Java security policy may be modified to disable - // the use of specific protocols via the jdk.tls.disabledAlgorithms - // property. The security property file is located within the - // java installation at jre/lib/security/java.security - - // Default list of allowed TLS protocols for outbound connections - private static final String DEFAULT_TLS_PROTOCOL = "TLS"; - - private static final String PROTOCOL_PROPERTY = "ghidra.net.ssl.protocol"; + private static final String DEFAULT_SSL_PROTOCOL = "TLS"; private static SSLContext sslContext; @@ -68,17 +62,6 @@ public class SSLContextInitializer implements ModuleInitializer { return initialize(); } - private static String getSSLProtocol() { - String value = System.getProperty(PROTOCOL_PROPERTY); - if (value != null) { - value = value.trim(); - if (value.length() != 0) { - return value; - } - } - return DEFAULT_TLS_PROTOCOL; - } - /** * Initialize default SSLContext * @return true if successful, else false (see logged error) @@ -95,8 +78,8 @@ public class SSLContextInitializer implements ModuleInitializer { KeyManager[] keyManagers = ApplicationKeyManagerFactory.getInstance().getKeyManagers(); try { - - sslContext = SSLContext.getInstance(getSSLProtocol()); + // Use new instance of SSLContext to avoid adopting CA certs provided with Java + sslContext = SSLContext.getInstance(DEFAULT_SSL_PROTOCOL); SecureRandom random = SecureRandomFactory.getSecureRandom(); sslContext.init(keyManagers, ApplicationTrustManagerFactory.getTrustManagers(), random); SSLContext.setDefault(sslContext); diff --git a/Ghidra/RuntimeScripts/Common/server/server.conf b/Ghidra/RuntimeScripts/Common/server/server.conf index 780da9a0c8..d93760510c 100644 --- a/Ghidra/RuntimeScripts/Common/server/server.conf +++ b/Ghidra/RuntimeScripts/Common/server/server.conf @@ -29,33 +29,37 @@ wrapper.java.additional.2=-DApplicationRollingFileAppender.maxBackupIndex=10 # Ensure that classpath_frag is defined for service startup wrapper.java.additional.3=-Dclasspath_frag=${classpath_frag} +# Limit server to specific TLS protocols for all secure connections. +# NOTE: multiple protocols must be separated with a semi-colon (e.g., TLSv1.2;TLSv1.3). +wrapper.java.additional.4=-Dghidra.tls.server.protocols=TLSv1.2;TLSv1.3 + # A suitable cacerts file must be installed when using PKI authentication -#wrapper.java.additional.4=-Dghidra.cacerts=./Ghidra/cacerts +#wrapper.java.additional.5=-Dghidra.cacerts=./Ghidra/cacerts # If Ghidra clients must authenticate the server, the server will need to install # a server key/certificate in a secure location (e.g., /etc/pki/...) # and specify the location and password via the properties below. # Be sure to properly set permissions on the Ghidra installation and this file # if using these settings. -#wrapper.java.additional.5=-Dghidra.keystore= -#wrapper.java.additional.6=-Dghidra.password= +#wrapper.java.additional.6=-Dghidra.keystore= +#wrapper.java.additional.7=-Dghidra.password= # Temporary Directory Setting - uncomment the following setting to override the Java default. # This may be necessary on certain Windows platforms when installing as a service. -#wrapper.java.additional.7=-Djava.io.tmpdir=C:\\Windows\\Temp +#wrapper.java.additional.8=-Djava.io.tmpdir=C:\\Windows\\Temp # Enable/Disable use of compression for DataBuffer serialization and Block Streams -wrapper.java.additional.8=-Ddb.buffers.DataBuffer.compressedOutput=true +wrapper.java.additional.9=-Ddb.buffers.DataBuffer.compressedOutput=true # Uncomment to enable remote debug support # The debug address will listen on all network interfaces, if desired the '*' may be # set to a specific interface IP address (e.g., 127.0.0.1) if you wish to restrict. # During debug it may be necessary to increase timeout values to prevent the wrapper # from restarting the server due to unresponsiveness. -#wrapper.java.additional.9=-Xdebug -#wrapper.java.additional.10=-Xnoagent -#wrapper.java.additional.11=-Djava.compiler=NONE -#wrapper.java.additional.12=-Xrunjdwp:transport=dt_socket\,server=y\,suspend=n\,address=*:18200 +#wrapper.java.additional.10=-Xdebug +#wrapper.java.additional.11=-Xnoagent +#wrapper.java.additional.12=-Djava.compiler=NONE +#wrapper.java.additional.13=-Xrunjdwp:transport=dt_socket\,server=y\,suspend=n\,address=*:18200 #wrapper.startup.timeout=0 #wrapper.ping.timeout=0 @@ -66,10 +70,10 @@ wrapper.java.additional.8=-Ddb.buffers.DataBuffer.compressedOutput=true # Uncomment to enable remote use of jvisualvm for profiling # See JMX documentation for more information: http://docs.oracle.com/javase/8/docs/technotes/guides/management/agent.html -#wrapper.java.additional.13=-Dcom.sun.management.jmxremote.port=9010 -#wrapper.java.additional.14=-Dcom.sun.management.jmxremote.local.only=false -#wrapper.java.additional.15=-Dcom.sun.management.jmxremote.authenticate=false -#wrapper.java.additional.16=-Dcom.sun.management.jmxremote.ssl=false +#wrapper.java.additional.14=-Dcom.sun.management.jmxremote.port=9010 +#wrapper.java.additional.15=-Dcom.sun.management.jmxremote.local.only=false +#wrapper.java.additional.16=-Dcom.sun.management.jmxremote.authenticate=false +#wrapper.java.additional.17=-Dcom.sun.management.jmxremote.ssl=false # YAJSW will by default assume a POSIX spawn for Linux and Mac OS X systems, unfortunately it has # not yet been implemented for Mac OS X. The default process support within YAJSW for Mac OS X is diff --git a/Ghidra/RuntimeScripts/Common/support/launch.properties b/Ghidra/RuntimeScripts/Common/support/launch.properties index 914085dbe6..b427d091b0 100644 --- a/Ghidra/RuntimeScripts/Common/support/launch.properties +++ b/Ghidra/RuntimeScripts/Common/support/launch.properties @@ -24,29 +24,17 @@ VMARGS_LINUX=-Dsun.java2d.uiScale=1 VMARGS_LINUX=-Dawt.useSystemAAFontSettings=on VMARGS_WINDOWS=-Dsun.java2d.d3d=false -# Set acceptable TLS protocol version(s) for outbound client SSL connections. -# The Ghidra application establishes the default SSLContext based upon -# this list of acceptable protocols. Omiting this property setting or -# simply specifying TLS without a version will defer to the underlying TLS -# protocol implementation and its preferred defaults. During the connection -# handshake both sides will agree upon a preferred protocol. The default -# SSLContext established within Ghidra is intended to support all -# Ghidra Servers client connections and other SSL-based -# network connections such as https, although it is possible for a -# connection-specific SSLContext to be established which bypasses this -# setting (e.g., log4j, bndlib). -#VMARGS=-Dghidra.net.ssl.protocol=TLSv1.3,TLSv1.2 +# The Ghidra application establishes the default SSLContext for all +# secure client connections based upon Java's default TLS protocol enablement. +# Setting this property will restrict the enabled TLS protocol versions for +# all secure network connections. Specifying multiple protocols must be +# comma-separated (e.g., TLSv1.2,TLSv1.3). See https://java.com/en/configure_crypto.html +# for details on configuring Java's cryptographic algorithms. +VMARGS=-Djdk.tls.client.protocols=TLSv1.2,TLSv1.3 -# Set acceptable HTTPS protocols for outbound HTTPS client connections for those -# cases which do not use the default SSLContext and associated socket factory -# (e.g., Apache HttpClientBuilder). Specifying TLS without a version will defer -# to the underlying TLS protocol implementation. -#VMARGS=-Dhttps.protocols=TLSv1.3,TLSv1.2 -VMARGS=-Dhttps.protocols=TLS - -# Force PKI authentication of all HTTPS and Ghidra Server connections (i.e., -# server authentication) -VMARGS=-Dghidra.cacerts= +# Force PKI server authentication of all HTTPS and Ghidra Server connections by +# specifying path to installed CA certificates file. +# VMARGS=-Dghidra.cacerts= # The following property will limit the number of processor cores that Ghidra # will use for thread pools. If not specified, it will use the default number