key in lock on pile of chains

Protecting Passwords in Tomcat Configurations Using the Java SDK in Machina Tools

Popular software applications underpin today’s internet. Database systems, web servers, and business applications have enabled the digital economy. These applications usually have associated configuration files, which enable secure interactions with each other and with customers. This configuration often contains plaintext passwords and login credentials. The protection of this sensitive data has become important, as software vulnerabilities have led to system compromises, exposing the data in these configuration files to attackers.

In this post, I’ll present two code samples that address this use case showing how you can protect sensitive values in the configuration files of the Apache Tomcat web container using SDKs from Machina Tools. A Tomcat extension point is employed to integrate the SDK allowing for recoverable encryption of the sensitive values. I’ll also look at other potential uses of the SDK and Machina engine. Both examples are available on GitHub, as noted below.

Apache Tomcat, TLS Keystores

The Apache Tomcat web container application includes support for TLS (SSL) client connections on one or more dedicated server network ports. To enable this feature, it is necessary to specify a TLS keystore for each port configured to service TLS connections. TLS keystores contain cryptography key material used by Tomcat to negotiate secure (encrypted) connections with web clients. Two common file formats used to store TLS keystores are PKCS12, which is independent of the software language in use, and JKS, which is a format specific to the Java software language.

TLS keystores are typically password-protected for security reasons. The keystore section of the Tomcat configuration includes this password. The password is used by Tomcat to unlock the keystore at startup, so that its key material may be used.

<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
    maxThreads="150" SSLEnabled="true"
    scheme="https" secure="true" keystoreFile="conf/server.pkcs12" sslProtocol="TLS"
    keystorePass="MyNotSoSecretPassword"
    />

When possible, it is desirable to secure this password to prevent its disclosure in the event of system compromise. There are a few general-purpose strategies for securely providing passwords to applications at startup:

  • Password is entered by hand in the process console at startup
  • Application configuration files contain password; files are secured via operating system file permissions

In the first case, manual intervention prevents the ability to automate process restarts. In the second case, exploitation of operating system vulnerabilities or misconfiguration can expose the content of secured files.

Java SDK

Machina can be used in situations like this to provide an additional layer of protection to passwords in configuration files. To demonstrate this, two code samples have been published to GitHub.

  • Code Integration Sample 1 describes a simple integration, leveraging the Tomcat PropertySource extension point (documented here). One of the Machina ChunkCipher encryption/encoding formats is used to create and protect an encrypted representation of the TLS keystore password.
  • Code Integration Sample 2 extends the first sample by protecting the Secure Enrollment Profile (SEP) on the filesystem using data derived from the Tomcat process environment.

In each sample, chunk ciphers are used to transform a passphrase to its encrypted representation, which can then be stored in the configuration file. Machina policy controls can then allow the release of the associated encryption key only to a Machina-enrolled device that is authorized to access the encrypted data.

Tomcat Configuration PropertySource

Tomcat includes an extension point that allows users to modify the default loading of configuration variables. The extension point is documented here. Its default behavior is to substitute marked configuration values with values from the Java Runtime Environment (JRE) system property set. The Ionic code samples augment this behavior, allowing for the use of Machina-protected values.

Code Integration Sample #1

The first code sample makes use of the Tomcat PropertySource extension point to allow for storage of arbitrary Machina-protected configuration values in the Tomcat configuration. The Ionic chunk cipher encrypted string for each protected value is stored in the Tomcat configuration file. The values are seamlessly decrypted on access by the Machina configuration accessor. The PropertySource also provides a mechanism for encryption of the original text.

Note that the PropertySource facility is a general-purpose Tomcat interface for accessing settings in the Tomcat configuration. The Tomcat documentation suggests that all XML configuration files are passed through the active PropertySource implementation. This means that any configuration value may be similarly protected using Machina.

Code Integration Sample #2

The second code sample builds on the first, adding protection of the Secure Enrollment Profile (SEP) that is used to interact with Machina. The SEP contains data pointing to the enrollment server to use, as well as data to identify the client making platform requests. While the first code sample uses a plaintext SEP to configure the SDK, the second sample protects the SEP configuration data using an encryption key derived from the Tomcat process environment.

The environment data can be any information that is available to the Java process. This might include (but is not limited to):

  • the Java Runtime Environment system property set
  • the process environment
  • the OS hostname
  • the OS network interfaces
  • information about files and folders on the OS filesystem.

The collected data may be organized logically into groups of environment settings. A threshold may also be optionally defined for each group of settings, allowing for some variance in the environment to be tolerated.

While the data defined in the sample implementation is relatively simple, arbitrarily complex data may be incorporated into a custom implementation of SecretShareData, in order to raise the bar guarding against unwanted exposure of the SEP data. It is recommended that you use low latency queries to generate the data, to minimize the amount of time needed to reconstitute the SEP secret.

Resources