Currently I take part in developing a system based on Java EE (WebLogic server, to be more precise) and I am wondering how to protect some private data from administrators. For example, some parts of a system stores credentials for legacy systems in a deployment descriptors as plain text and this is bad because a deployer can read application configuration file (ejb-jar.xml, for example) and steal username and password for powerfull account. I want to close this security hole, but don't know how.
Now I am interested in protecting this kind of data:
Login
Password
Private key for symmetric encryption
From here I've discovered that I can use a JCEKS keystore to protect this type of information, but I can not understand how to use it. My application still should contain the kestore password and the key password to access it. So, a depoyer can steal passwords for keystores and keys, find my secure storage and steal credetials. Obviously, I can revoke read privileges from the deployer account, but then he can decompile my appliaction and develop his own similar app (or edit my one), that simply prints secure data to some file or send it by email... And now I am stuck...
Can anybody give me some links that can explain how to protect a system from administrators? Weblogic related links will be preferable. I totally understand that it is not possible to protect from all administrators and there should be some security administrator that will be responsible for keystore management and so forth, but I want to secure all sensitive data from everybody else.
RESULTS
Both jtahlborn's and slim's answers are correct, but slims's answer in more interesting. I think that in my case it will be appropriate to accept only signed applications for installation on the server. This decidion can solve problem with applicatoin modifications done by a administrator. Administrators will have password from keystore and all keys, but they will not have access to keystore file at all. Access to keystore file will have only special security administrators ('rw') and server ('r'). So, everybody will have the key, but nobody (except security administrators) will have access to the box.
There is no solution to this problem unless you enter login credentials at application startup (assuming the admin cannot access the application memory, which may not be a safe assumption). any solution which involves the keys sitting in the same place as the application will result in an administrator (with application filesystem access) being able to access any sensitive data accessible by the application. this is similar to the DRM problem (you can't give someone a locked box and the keys and expect that they can't open the box).
I think the meat of this question is in the definition of "admin".
You've said that you're comfortable with a "security admin" who does have access to key stores.
Traditionally, UNIX types think of "admin" as being the "root" user - someone with access to everything on the machine. Root can do literally anything, right down to peeking and poking at application memory, or reading/writing to raw disk addresses. If the server can get a private key, so can root.
If you want to define an "admin" role with more limited access, then yes, you could set up something where such users existed. They would need to have fewer privileges than the server application itself, since there is at least one thing the app can do (get a private key) that the "admin" cannot.
Such a user probably wouldn't be able to install the app either (since, if they could, they could create and install a version of the app which exposes the private key). Your "admin" couldn't therefore deploy the component that works with the private key. They could, however, potentially deploy a module that runs within that container (as long as the container cannot supply the private key to the module).
However, it's not just the key you want to protect. The real "secret" is the data encrypted using the key. So we still have a problem with the approach above. If the module can read the encrypted data, then so can an "admin" with the same privileges as the module. And that includes anyone who can install the module.
You could investigate ways to sign the module, so that an "admin" could not create their own version.
There comes a point, though, where the measures required to enable untrustworthy admins, become more expensive (in terms of time and effort) than simply using trustworthy admins.
So, you need to make a list of things your so called "admin" can do. Depending on what those things are, it may well be possible to allow a non-root user to do those things. On UNIX, you might use a tool like sudo to allow a non-root user to do things like start/stop the server, read logs, clean logs, etc.
It might be possible to separate the authentication from the rest of the application.
For example, if you communicate with the legacy systems via a TLS-secured socket, you could write a small separate application that accepts unencrypted connections from the application, then makes a secure, authenticated, connection to the legacy system, and pumps data between the application and the legacy system. Essentially, it's an authenticating proxy. Then, the application wouldn't need these keys. You could install and operate the application as a user who didn't have permission to read the files containing the key, but the application could still communicate with the legacy systems.
Of course, now you have the problem of how to authenticate the application to the proxy. You might feel that the machine is secure enough that you don't need to do that at all - as long as the proxy only listens on the loopback interface. If not, if you could use a unix domain socket instead, then you could control access using filesystem permissions: you could run the application as some user in some particular group, then restrict access to the socket to members of that group. Java doesn't have unix domain socket support in the standard library, but you can add it with junixsocket or JUDS.
Related
One of my java class will connect to a another server and do some operation using rest services. Java class requires - username and password to connect to remote server. On other machines we used to store the credentials using oracle cwallet.sso but this is not an option for current machine. I am thinking to store the encrypted password in properties file adding some salt. I also need to store the key and salt string to some secure place. do we have any alternative in RHEL for password management like cwallet or any suggestions what to should be the best way to achieve this?
Please note that I will invoke this class using shell script.
Thanks
This is tricky, because if someone gets access to your server is already game over. So the solution is not just to encrypt the data, as it won't do much, but you need security in depth.
To put this in context, you can have the password encrypted, salted whatever... When an attacker gets access to the server, he won't be able to read any of those files (even with the encrypted password) unless he is able to become the user running the app. If he manages to do that, he only needs to do a memory dump and then fish for passwords (which is not hard).
So a real world solution is:
Only allow a restricted number of people to log on the server.
Only allow an even smaller number to become the user which runs the application server.
This group of people are the ones who can read/update the properties file
Disable any kind of backups on the files that contain secrets.
Again, encrypting passwords on the files might give you a sense of security, but again, if you follow the steps above, anyone who can read the file, will also be able to read the memory contents of the app. And even if someone does things right and stores that password in an bit of offheap memory, some linux tools can read the whole memory map of a process, so again, game over.
Using encryption in this case just adds obscurity and no real protection.
I have a flat java file that's querying two databases and currently has the credentials hardcoded. The plan is to convert this to spring batch but in the mean time I would like to encrypt them within a config/properties file externally and call them. I'm looking for any specific examples, best practice / solution. I appreciate any time and effort. Thank you!
If you decide to encrypt the credentials, then you have the problem of secure storing the encryption key. The best you can do it to not store it at all and require it to be given manually whenever your application starts up. Your application should use the key to decrypt credentials, connect to any services. Finally it must throw away the key and credentials after use, in order to prevent getting them from memory.
If manual intervention during application startup is unacceptable, then a typical solution is storing the key in a file with appropriately restrictive permissions on an encrypted partition, but if the system gets compromised, e.g. an attacker somehow gets root privileges or privileges of your application, he will be able to recover the database credentials.
I am building a java web application that will automatically grant users Administrative Rights to their Windows PC's when a manager approves their request.
In order to accomplish this, I am going to write a script to automatically remote into the users computer and add them to the computer's administrative group. I figured in order to do this though, I will need to have an Administrative Service Account to access all computers.
My question would be, how can I go about securely storing the Administrative Service Account information? The application will need the credentials every time it needs to go and give a user admin-rights, so how can I go about letting the application use the Service Account without human interaction? Obviously I cant just put admin credentials in a plain-text properties file. The credentials shouldn't be open for any developers to see who might go in and change the application later.
Could there be a better way to do this? Someone mentioned to me once maybe having an account in Active Directory to impersonate, but I wasn't able to follow up for more details on that.
There is one method of protecting service account passwords that is occasionally used for services that use databases is based on the concept of inversion of control.
Here the service can call a stored procedure, which has anonymous access, that prompts the database to generate, set, and send the password to the service, whose address it knows, via a separate call.
While the anon call is normally IP limited to prevent DoS attacks, it doesn't matter if some other process calls it, because the stored procedure will only send the password to the service regardless of who calls it.
I'm in the process of writing a server application that mainly allows people to submit jobs to a DRM system (e.g. TORQUE) over RMI. The application needs to run as root so that it can submit proxy jobs (where a job is run as a user other than the user who submits it), however this obviously isn't secure - the user name is simply a string parameter in the RMI. Anyone could pass any user name in and have a job run as that user.
What's the best way to get Java to authenticate this user name against authorised users of the system (with the aid of a password that would also be passed in)? I've had a look at JAAS and Apache Shiro, but they seem to be all about creating your own authentication methods. I want to use the system's existing authentication methods (Unix-like system), whatever they happen to be. Essentially if the user can SSH in, they're all right.
If your backend uses LDAP (which is possible if you have to manage a relatively large number of users for which a local /etc/passwd might be tedious), you can use JAAS and the existing LdapLoginModule.
If you want to authenticate against you local system (assuming Linux server) without this, it looks like JAAS-PAM might be able to help, although I've never tried it.
I'm writing on a Java EE project which will have everything from 3-6 different clients. The project is open source, and I wonder what security mechanisms one could/should use. The problem is: Because it is open source, I would believe that it is possible for anyone with a user to write their own client (maybe not realistic, but truly possible) and make contact with the server/database. I've tried to go through all the scenarios of reading/writing different data to the database as different roles, and I conclude with that I have to have some security mechanism on a higher level than that (it is not enough to check if that account type is allowed to persist that entity with that ID and so on...). In some way I have to know that the client making contact is the correct client I wrote. Could signing the Jar files solve this entire problem, or is there other ways to do it?
-Yngve
I really think that if restricting the available activities on the server side (based on role) is not sufficient, than you've got a bigger problem. Even if a user doesn't write their own client, whatever mechanism you are using for your remote calls is likely to be vulnerable to being intercepted and manipulated. The bottom line is that you should limit the possible calls that can be made against the server, and should treat each call to the server as potentially malicious.
Can you think of an example scenario in which there's a server action that a particular authenticated user would be allowed to take that would be fine if they're using your client but dangerous if they're not using your client? If so I'd argue that you're relying too strongly on your client.
However, rather than just criticize I'd like to try to also offer some actual answers to your question as well. I don't think signing your jar file will be sufficient if you're imagining a malicious user; in general, public-key cryptography may not help you much since the hypothetical malicious user who is reverse-engineering your source will have access to your public key and so can spoof whatever authentication you build in.
Ultimately there has to be someone in the system you trust, and so you have to figure out who that is and base your security around them. For example, let's imagine that there may be many users at a particular company who you don't necessarily trust, and one admin who oversees them, who you do trust. In that scenario you could set up your client so that the admin has to enter a special code at startup, and have that code be kept in memory and passed along with any request. This way, even if the user reverse-engineers your code they won't have the admin code. Of course, the calls from your client to your server will still be vulnerable to being intercepted and manipulated (not to mention that this requirement would be a royal pain in the neck to your users).
Bottom line: if your user's machine is calling your server, than your user is calling your server. Don't trust your user. Limit what they can do, no matter what client they're using.
Well the source may be available for anyone, but the configuration of the deployment and the database certainly isn't. When you deploy the application you can add users with roles. The easiest thing to do is to persist them in a database. Of course the contents of the table will only be accessible to the database administrator. The database administrator will configure the application so that it can access the required tables. When a user tries to log in, he/she must supply a username and password. The application will read the table to authenticate/authorize the user.
This type of security is the most common one. To be really secure you must pass the credentials over a secure path (HTTPS). For a greater degree of security you can use HTTPS client authentication. You do this by generating a public key for every client and signing this with the private key of the server. Then the client needs to send this signed key with every request.
EDIT: A user being able to write his/her own client doesn't make the application less secure. He/she will still not be able to access the application, if it is required to log in first. If the log in is successful, then a session (cookie) will be created and it would be passed with every request. Have a look at Spring security. It does have a rather steep learning curve, but if you do it once, then you can add security in any application at a number of minutes.