I am currently developing a spring boot web application. It is a REST api proxy that connects to another api using some very sensitive credentials. The credentials are hard-coded at the moment, but obviously they should not be. What is the proper way of hiding them?
I have considered using some library, like jasypt to encode them and put the encoded values in a properties file, with the key hidden somewhere, perhaps in system variable, (but it is just another layer of obfuscation, isn't it?)
How can I properly hide these sensitive credentials?
You can use your server environment to hide your properties. Just store on your production server application.properties with real credentials and protect access, so only your application will have access to the property file.
The fundamental problem is that if you ever need to hold security credentials in the clear in the memory of a computer program, AND there are people who have the equivalent of "root" access to the machine, then it is possible for one of those people to gain access to the credentials.
So you need to design your security so that that the credentials never need to be held in the server's memory.
If you are really serious about solving this, you need to investigate Hardware Security Modules. However, the HSM approach is going to be complicated and expensive, and may require you to rework your authentication protocols.
Related
Currently, my spring-boot application connects to a local MongoDB without credentials. To be able to install it at a customer I need to provide the capability to use username and password for the DB connection. I am using the application.properties file, which currently contains only these 3 lines related to the database:
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=myApp
There would be these two additional ones:
spring.data.mongodb.username
spring.data.mongodb.password
But of course, I don't want to have the password in plain text within this file, or even worse in our git. One option would be to provide them as a parameter with a start script but then again it would be readable as plain text in the process details.
I've seen some encryption in the properties file using Jasypt, but I don't understand how this approach would work in my case. I never explicitly use these properties as they are automatically taken by spring to do the connection.
What would be the safest approach?
TL; DR
It depends on your security/risk profile, which method is acceptable.
The longer read
Your question is: What would be the safest approach?
A simple answer to this question is not storing the password anywhere but letting an operator type it in. Obviously, that's not the answer you're looking for as with servers in data centers or even VM's in the cloud this approach isn't feasible.
To understand what method is safe enough and which one is acceptable, it's important to understand your organizational context, its willingness to accept risk and the resulting consequence which is the requirement for handling secrets. This evaluation can result that for one organization it may be fine storing credentials in plain text (because the environment is secured or there's a low threat associated on exposed secrets), others require encryption with proper key management and auditing.
You're already describing that storing credentials in Git isn't a proper option. So I assume that you're looking towards a method that protects the actual secret in some way. Protection can happen on different levels:
Storing secrets in a protected place with access control applied
An environment variable on a host that is access protected
An access-controlled file with protected by permissions
Storing secrets in the encrypted form
Encrypting the value and storing it in a file. Here you need to consider who has access to this file and what about key management. Introduces sort of chicken and egg problem
Encrypting the value and storing it in memory. Still, you need to solve the key management issue.
Retrieving the secret from a trusted source
Credentials are typed in by an ops person (Not really feasible)
Asking a service to provide you with the credential. The remote service protects the secret and allows you/your application to ask for the secret.
There are potentially more possibilities but let's stick with these for now. One aspect that is associated with the above-mentioned possibilities is the transport of the credential from the source to the target destination. Transport typically spans over one to many parties and each of these parties need to be trusted in some way (i.e. you must make sure a certain party does not divulge your credentials). This pattern is also known as chain of trust. If every hop in the chain of trust is known, to not expose your credentials, then you can react with a particular protection pattern to this context. If you find a weak link that elevates the risk of exposure (e.g. a public folder, Lookup by an operator), then you again need to increase the level of protection according to your needs.
Having all that said, let's take a look which possibilities you have with Spring Boot to apply protection of secrets:
Environment variables
You can store configuration using environment variables or system properties. The aspect of volatility distinguishes from a persistent (e.g., file-based) storage. Variables can be set before/upon application startup.
Example for environment variables:
export SPRING_DATA_MONGODB_USERNAME=…
export SPRING_DATA_MONGODB_PASSWORD=…
java -jar my-app.jar
Examples for system properties:
java -jar my-app.jar -Dspring.data.mongodb.username=… -Dspring.data.mongodb.password=…
java -jar my-app.jar --spring.data.mongodb.username=… --spring.data.mongodb.password=…
Please note that environment variables/command lines can be introspected by the /proc file system and tools like ps
See the reference documentation on Externalized Configuration for further details.
Encrypted Configuration Properties
Spring Cloud comes with crypto support for individual properties. You can encrypt selected properties with different keys and key types (symmetric, asymmetric). This approach allows you to select properties that should be encrypted without the need to encrypt the whole file.
Example for environment variables:
application.properties
spring.data.mongodb.password={cipher}FKSAJDFGYOS8F7GLHAKERGFHLSAJ
Please note this approach introduces the requirement of property key management.
See the reference documentation on Spring Cloud Config Encryption and Decryption for further details.
Application-controlled secrets
Configuration Properties in Spring Boot are obtained from the Environment and provided by PropertySources. You can contribute either properties or an entire PropertySource before spinning up Spring Boot.
Example of adding a PropertySource:
SpringApplication app = new SpringApplication(DemoApplication.class);
app.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
#Override
public void initialize(ConfigurableApplicationContext applicationContext) {
applicationContext.getEnvironment().getPropertySources().addFirst(…);
}
});
app.run(args);
Example of adding a property:
SpringApplication app = new SpringApplication(DemoApplication.class);
app.setDefaultProperties(Collections.singletonMap("spring.data.mongodb.password", "…"));
app.run(args);
Remote Configuration Properties
Spring Cloud Config allows you to centralize configuration that is served by Spring Cloud Config Server. Properties are no longer stored locally, but served from a config service that can be secured differently than your application protection level. To setup Spring Cloud Config Server, you need an additional service and integrate the client dependency in your application.
Please note that this approach does not solve the overall problem, but just moves it into someone else's responsibility.
See the reference documentation on Spring Cloud Config Server for further details.
Using Secrets Management
If you can afford a Secrets Management, such as HashiCorp Vault, CredHub, Azure KeyVault, Kubernetes Secrets, then you can leverage the features of your platform/Secrets Management system to apply protection to your credentials.
Secret Management systems typically handle encryption, auditing, and access control for you. These systems keep an encrypted copy of the credential. Once you request the credential (typically over TLS secured connections), the system checks whether you/your application is allowed to access that secret or not.
Some of these systems also provide dynamic secrets. Dynamic secrets are generated for a particular application instance upon demand. If your application wants to connect to MongoDB, the secrets management system is going to create a credentials pair and server these to your application. When your application stops, then the secrets management system is going to revoke the credentials.
See the reference documentation on Spring Cloud Vault for further details.
One addendum to the answer from #mp911de:
There is a second file option in Spring Boot: You are able to provide an additional file to overwrite the standard config, by providing either a ENV variable SPRING_CONFIG_ADDITIONAL_LOCATION to a file or adding it as a command property like spring.config.additional-location, see Application Property Files.
This could give you the opportunity to add the credentials via some file base secret deployment (eg. Kubernetes secrets used as a volumeMounts, Puppet/Chef/Ansible based secret deployment etc.).
I am working on a Java application that should be run in the background and was thinking of externalizing some sensitive info (DB credentials among others) in case it should change. These info is required in order for the application to start. However, I was wondering what is the proper way of doing this?
I was thinking of the following but needs advice from a security standpoint.
Encrypted passwords will be passed as Main arguments when starting the application. However, I noticed that any user can see the arguments when the list of processes in the OS will be viewed.
Generate an external file, i.e. java properties file (with encrypted credentials) with view restrictions, and pass the file path to the application
Put the encrypted credentials in the user's environment variables for the application to access it
Note: We already have an encryption tool that we use
Personally, I was leaning to the 2nd option but I would like to know suggestions, comments, or best practices for cases like this.
Thanks!
2 is the most sensible option. Problem with 1 and 3 is, once they have access to the "encrypted" string, all they have to figure out how are you decrypting it (You anyway have to do it, to make use of it).
Have you looked at Spring Cloud Config, I don't know whether this is an option for your or not.
Option 2 is most common.
Personally, I do not recommend Option 1 and 3.
There could be other options too.
As example you can look at PicketBox Vault.
It allows to make custom implementation more secured than default.
In fact it is extended option 2 - there is a Vault file protected by key stored in Keystore.
Still password to that Keystore(alias) must be secured, but only one(two). It is useful, when there are many properties need to be secured. It is also more manageable, since all properties secured same way and in one place.
I have a requirement to use property files to have some important information which should not be revealed to anyone.
My question is : regarding security concern, is using a property file a safe option or not ?
This depends on a larger context (security policy of the whole solution) and the nature of data you want to keep secure.
In most environments, a secure network is constructed by using firewalls etc., and inside, even sensitive information (like API keys) are stored in property files etc. as plain text. There are more sophisticated solutions that can keep these information encrypted, but it requires considerable setup.
Some people suggest embedding a encryption key in the source to encrypt the property files and then obfuscating the source to hide the encryption key, but this is security through obscurity and should be avoided.
If you are storing password information to authenticate users etc., then you should store salted hash of passwords.
EDIT:
Probably one of the best way would be to encrypt the property file and let operators type the encryption keys every time the app. starts (to avoid storing the encryption key in a persistent store). Note however, an attacker could still read the process memory to get the decrypted value.
This is why most solutions focus on securing the network, rather than protecting against an attacker who already has access to the servers.
You have at least two choices:
read properties value from system properties configured only in the operating system of the deployment server
read properties value by lookin up JNDI name, so your properties value are configured in the application server
With each of the above approaches security concerns can be addressed focusing on the deployment environment and not focusing on the application sources or binary.
Ask back. There are two options: a configuration inside the application, and outside the application, in the Java EE server. I think they meant to have the properties file outside the application. You should ask that.
Having it outside the application also allows deploying the app in different environments. And is more secure as even the developer does not need to store somewhere the production password.
How to access the file depends a bit on the server.
I have the ability to do password hashing in the Web-app layer of my system or in the DBMS (postgresql's pgcrypto). Is there any advantage to using either or?
For more context, I will be using Amazon's AWS (EC2 and RDS).
The system has various mobile clients which contact the back-end (through one Spring/Hibernate Web App). There is no direct access to the database through these mobile clients, they all must go through the java web app.
EDIT:
Other tidbits:
HTTP basic authenication over SSL, Stateless/RESTFUL (as much as possible), using the blowfish cipher for hashing with a randomly (well.. psuedo random) generated salt.
Will the password be synchronized? (used by more than one application) If it is that will be the largest guide. I generally recommend not handling unencrypted passwords any more than you must. On the other hand screwing up password hashes is real easy to do, and hard to fix so use a library that gets security updates. Above all be simple, clean well documented code is even more important when dealing with security.
I'm working on a project which involves writing web services on mainframe enviroment.We are going to be provided a test enviroment on which we can do development and see the inital results. That process is taking a lot of time and I wanted to see if I can simulate some of the parts that I've to do.
Finally I've to get web services talking with mainframes which would have webservice talking with DB2 and IMS segments. I've never worked with mainframes before and I wanted to know how can I create mocks for IMS segment which then my webservice can read and update to. I would appreciate any insights into this
I've done the mainframe side of POX and SOAP web services in CICS. (CICS can access both DB2 and IMS) The thing that seems to surprise the distributed folks is the tag names. They tend to be generated from language structures, so they look like (in our case) COBOL variable names.
Other than that, the SOAP looks like what the WSDL says it should, the POX looks like POX.
If you've got a schema, work from that. Don't worry about the fact that it's a mainframe or that the data is stored in IMS or DB2, write to the specification.
You might want to ask about authentication mechanisms, as this is another stumbling block regardless of platform. Generally people are nervous about unauthenticated access to their business systems, even if that access is coming from another part of the same organization. No one wants to have created an exploitable hole in their security.
In our case, using CICS, we required a logon ID and password for each transaction - http basic authentication as per RFC 2617. Depending on your policies and procedures, that password may be required to expire on a regular basis. Some organizations allow non-expiring IDs, some don't.
An option we looked at but did not implement was SSL certificates. CICS allows one to send a certificate along with a request and then CICS matches the certificate to a logon ID under whose auspices the rest of the transaction runs. The ID is authenticated by virtue of the certificate. This is done in the TCPIPSERVICE definition in CICS.
I realize I'm going on about CICS and you didn't even mention it in your question, but I have to believe you're going to run into similar concepts/issues. IMS also does web services, and I seem to remember there being a mechanism to expose a DB2 stored procedure as a web service. IMS, DB2, and CICS all use the same external security manager behind the scenes.