How to achieve some degree of “privilege sharing” with a Java web server?

I am trying to be active in security on my Jetty web server mailboxes - especially with regard to storing SSL key information, although I would like to get a general solution. Apache uses privilege sharing , so it starts with root privileges, so it can read protected SSL key files (and other secure configurations), and then switches to some common user actually HTTP server requests. But Java has no mechanism for this.

Any recommendations for ensuring the same level of security in a Java web application? My requirements include:

  • Secret information should be read-only.

  • Any passwords that unlock keys, etc., should not be configured into code so that someone with the same user level rights as the server cannot easily get them.

  • I work under Amazon EC2, so I want security to be as automatic as possible, i.e. no interactive passwords entered by operators.

One possibility would be to use ~ LDAP to branch sensitive information from the application and only bake the LDAP username / password for the application. But I'm looking for a better solution.

Thanks for any info.

Edit:

I was hoping for solutions that covered SSL, but took into account other secrets that I wanted to restrict access to. I did not make this clear enough in my initial post.

+6
source share
4 answers

Although I appreciate the answers of @Joakim and @Tony, I was hoping for a more general solution that covered general password protection without specific JNI / Jetty functions and more general than SSL secret key protection.

The best solution I can come up with is a small C wrapper program that was setuid root. It would be:

  • Launching and reading in the collection of classified information from files protected by root files on disk to memory. It should immediately encrypt sensitive information in memory (see below).
  • Switches from root to the unprivileged user running the application.
  • Forks and exec JVM with corresponding application arguments.
  • Writes the encryption key and encrypted passwords through STDIN.
  • When the JVM boots, it immediately reads the encrypted secret information from STDIN.
  • One of them will be read, the shell application will be completed.

As an extension, a small C-shell can work and provide JVM access to system resources using a simple protocol based on STDIN / STDOUT. This would provide the JVM with access to other secure resources in the system in a controlled manner.

Here are some other thoughts on possible solutions.

  • The service was started at boot time using the init.d script, which is run as root and serves to collect secret keys for JVMs launched by some web service or at least some FIFO file or something else. After the first request, it will be disconnected or after a few seconds after loading.
  • LDAP is certainly better than the secret foo on the window itself - a user readable application. As a change to the above solution, setuid can enter an LDAP password into the application, so it will not live in a user-readable space.

As always, both applications will need to protect passwords in memory. Storing them in system sockets or dividing them into non-contiguous blocks of memory is always a good idea. You can also create a secret key and encrypt them in memory.

0
source

The apache method you described is provided by additional Jetty-setuid functions .

See http://www.eclipse.org/jetty/documentation/current/setuid.html

+3
source

As soon as you bake something like a password into the source code (which is stored on disk), you circumvent security. Thus, storing information in LDAP will not help.

I am not sure that the setuid function will also help, since it exists solely to access ports in the network code and may not do setuid at the right time (after opening SSL files). Of course, you can verify this by protecting the files as root and see if it can open them ... if so, you are golden, and Joakim's answer is the best option.

What we do is configure a simple apache or nginx server to start the JVM through a proxy server, and then launch the pier under its own UID. Then you can take advantage of the security of the setuid SSL server, which is already well tested on any of these servers. We also have some other requirements that this also helps to solve, but I would probably decide to do it this way even if we didn’t.

The nginx configuration is also quite simple:

server { listen 192.168.1.1:443; server_name www.mydomain.com; index index.html index.htm; root /usr/share/nginx/html; ssl on; ssl_certificate /etc/nginx/conf.d/ssl/server.crt; ssl_certificate_key /etc/nginx/conf.d/ssl/server.key; access_log /var/log/nginx/ssl.access.log main; ssl_session_timeout 5m; ssl_protocols SSLv2 SSLv3 TLSv1; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; location /AppPath { proxy_pass http://jettyhost:8080/AppPath; } } 
+1
source

I would suspect that due to the multi-platform nature of Java, there is not much attention paid to Unix-based methods, such as what exists in Apache Httpd, as they may not necessarily apply to all platforms on which Java can run.

In Java, privilege separation is built in using the security manager. Whether this is as good as root / non-root separation, I'm not sure (there can always be errors). However, its policy is in principle capable of expressing more subtle access rules than simply distinguishing between root and non-root users.

Jetty had this, but it seems to have fallen in Jetty 9 (you can still use the security manager, but you may have to write your own policies and a bit more work to implement them in the container).

The Jetty Policy Document also says:

Typically, the user trusts the application that they are developing, or trusts enough to deploy the webapp to a berth instance. If you do not know what you need to use the security manager setting, probably not.

I'm not sure I agree with that. In fact, if there is a webapp that I suspect is malicious, I won’t start it anyway, but using the security manager is also associated with potential security errors. Anyone can write errors, even good programmers. Having a mechanism that limits what’s possible with webapps is definitely good.

A reasonable policy will certainly not allow web clients to access configuration files and keystores.

I would also like to argue that this separation of webapp also underlies the concept of “container” (although security is only one of the goals of this separation, it seems to have been lost).

In fairness, this is not as simple as the separation suggested by the root / forking mechanism in Apache Httpd. The strength of the Java security policy also brings complexity. I believe that these functions, as a rule, are not completely understood and, therefore, are used little. Using Apache Httpd (or Nginx or others) as a reverse proxy tends to be a simpler solution for protecting private keys.

Another way you could peek is to use the PKCS # 11 keystore. This is supported by the JRE. Hardware security modules help prevent your private keys from being copied. (From a Java perspective, you get a PrivateKey instance that delegates cryptographic operations to the PKCS # 11 library, but from which you cannot extract personal data at all.)

Of course, this is a problem when you do not have access to hardware, but there are software implementations of this (searching for "Software HSM" may seem strange, but it will bring several results). Not all of them will allow you to separate you, but some of them should (in fact, by communicating with another object containing a private key that you could run as another user). I have not tried, but this one might be of interest.

+1
source

All Articles