Security considerations when hosting signed jars - java

What are the security implications for hosting signed jars on the internet?
As I understand jar signing, once a user choose to auto-accept a certificate, it doesn't matter if the signed jar came from your domain, linked from another domain or hosted on another domain. For example, Sun uses this method to give applets OpenGL support, by providing (hosted) signed jar that link to the driver. So are there any precautions I should make as the developer and certificate-signer of the java-code I make available?

Depending on the context, you are relying on the security manager and associated security policy to do the right thing. Generally unless you are doing your own classloader magic, you shouldn't need to do anything special. If you have control of the security policy, (for example in a java application rather than applet) you can grant permissions to call your jars only to certain other code. If you rely on codebase to distinguish code, a https URL is better. It is also no harm to limit access to the jars on the webserver if you know where/who the accesses should be coming from, but is probably more trouble than it is worth.
However, you should always bear in mind that the caller of your API may not be your code, and may be malicious. So in your threat modelling, you should think about what a malicious user may be able to do if they somehow had access to the functionality given by the API your code exposes. The security manager is supposed to check up the call stack to prevent this kind of thing. But if for example your signed jar has a method LaunchMissiles() ...you might want to ask the user if they are sure anyway. And you might want to authenticate the user too.
Nor should you necessarily rely on the user to click the right button on any security warning, especially if it refers to certificates and URLS etc - most users fall into one of two categories: those who click OK on any warning because they don't understand it, and those who click Cancel on any warning because they don't understand it.

Related

Supported, non-spoof-able way to determine current user in Java?

For various reasons, I have a Java application that needs to be able to detect which user is running it. I've seen a few suggestions that address the issue, but none are fully satisfactory.
Some suggest using the system property user.name, but this is not reliable as it can be spoofed in at least 2 ways (changing the value of the environment variable that the system looks to, or starting the program with an override value via a -Duser.name option).
Another option is to use the classes in the com.sun.security.auth.module package, but the Java Ruling Class is very clear on why this is not a good idea (see for example this web page).
This seems like it's a sufficiently valuable capability that there should be a way to do this in Java that is supported, but I haven't been able to find it. Any suggestions?
For various reasons, I have a Java application that needs to be able to detect which user is running it.
Bad luck, on modern, but especially on unix/posix systems, it's up to the user to define which libraries get loaded when your java gets loaded. This can include a library that intercepts call to the C runtime (libc) that checks user names.
Not to mention that user namespaces are a common feature on multiple OSes, which allow any unprivileged user to set arbitrary user names. This is by design.
In short: the system is the user's. You can't use whatever that system says to authenticate against any other system. This is a truth as old as authentication systems: you need an anchor of trust, and on a system that you don't control, such an anchor is not yours to get – unless you have things like TPM or FIDO/cryptographic smartcard readers.
You will have to find a fundamentally different security mechanism. You can never trust a user's system if you've got anything to hide from them. Think about this: your user might very well boot a virtual machine in which they control everything; they very much copy the original machine's hard drive byte for byte, but they change their user name in that VM to that of someone else. Game over for your system.
I feel like I need to repeat that: You cannot trust a user's system. If your security depends on your software doing actually what is expected of it (e.g. validating a password, or checking anything else, and if successful, sending a packet somewhere), then a simple debugger can just jump over any security measure and execute the code you didn't mean to be executed in a case of non-authentication. You, as a developer, know how to use a debugger. Any user could use a debugger, too.

User activation code in android app

I need to add something that generate an activation code in my android app so the app features should work only if the app is activated. what is the best way to do that ?
If I understand the question correctly, what you want to achieve is technically impossible.
Any functionality your app has is already there in the app, downloaded to the client. A user can use a debugger to disassemble the app file and change your source code to either not require an activation code or accept any code (whatever is easier, but both are possible). Anything you give to a client should be considered as being fully controlled by the client, any logic in there can be changed, secrets can be seen, etc.
This may not be straightforward, especially if you use some kind of an obfuscation, but it will always be possible. The question is only the effort needed.
And the effort is key here. In some scenarios, protecting low-value resources, it may be good enough to deter the lowest profile attackers. It's always about risk and the cost of protection. But you need to be aware of the above, that the logic in an app cannot be protected.
So if you want to protect your stuff, you have a few options for different scenarios:
Have two separate apps, one free without paid functionality included and one paid. Users can use the free one and then buy the other if they want.
Have paid functionality served by a server. If critical business logic is on the server side, you can really enforce access control rules and you can maintain control over who has access. This may have serious implications on your app architecture and functionality though.
If the value you are trying to protect is low, you can go for obfuscation and access control logic in the app as mentioned above, but you need to be aware that this can be cracked relatively easily, especially on Android by changing the apk.
I believe you cannot do this with just your app, you definitely need the help of server which would generate an activation code for you and match it with the logged in user. Once the generated activation code is passed on to the user via email or any other means, then you can match the activation code given by the user and then match with the one in the server and if they match, let them use the features.
I hope this is what you want. But I might even be dumb enough to misunderstand you. Let me know if this is what you want.

Checking password in java code (security concerns)

I am writing a small webserver for my house to play around with a few java API's I want to know better. This web server will eventually hold personal files and pictures.
I did not feel like setting up an LDAP server for authentication and was wondering how bad would it be if i just had the java code check it directly?
As long as you take proper precautions not to distribute or publish your source code, having a hardcoded password is most certainly safer than having a network service validate it. There are two problems, however:
Keeping your source code secret may not be too hard, but you can easily forget that you hardcoded the password in the future an become careless about the source. You may want to copy it to a friend, or publish it on github.
Having the password hardcoded means that someone that compromises your code may easily learn the password. A tried-and-true network authentication solution will not be ridden with vulnerabilities - your code almost certainly will.
A potential alternative you should consider is to keep a plain text file with the password, and read it as necessary. It mitigates (but doesn't eliminate) these two issues, and will also allow for a bit more security if your OS supports the proper file permissions and user privilege separation.
As always, avoid using a password repeatedly for different services. Since you'll have untested code facing the internet, remember to implement proper OS-level counter-measures.

How to achieve some measure of "privilege separation" with Java web-server?

I'm trying to be proactive around security on my Jetty web-server boxes -- especial with regards to storing SSL key information although I'd like a generic solution. Apache uses privilege separation so that it starts as root so it can read the protected SSL key files (and other secure configuration) and then switches to some common user to actually server HTTP requests. But Java has no mechanism for doing this.
Any recommendations around how to achieve the same level of security in a Java web application? My requires include:
Secret information should only be readable by root.
Any passwords which unlock keys and the like should not be configured into the code so that someone with the same user level permissions as the server can't get them easily.
I'm running under Amazon EC2 so I want the security to be as automatic as possible -- i.e. no interactive password entering by operators.
One possibility would be to use ~LDAP to separate the secret information from the application and only bake the LDAP access username/password into the application. But I'm looking for a better solution.
Thanks for any information.
Edit:
I'd hoped for solutions that covered SSL but took into account other secrets that I wanted to limit access to. I did not make that clear enough in my initial post.
The apache technique you described is provided by the optional jetty-setuid features.
See http://www.eclipse.org/jetty/documentation/current/setuid.html
As soon as you bake anything like a password into source (which is stored on disk), you've circumvented security. So, storing the information in LDAP isn't going to help.
I'm not convinced the setuid feature is going to help either, in that it is there purely for accessing ports in the networking code, and might not do the setuid at the correct time (after opening the SSL files). Of course, you could test that by protecting the files as root and see if it can open them...if so, you're golden and Joakim's answer is the best option.
What we do is set up a simple apache or nginx server to front the JVM through a proxy, then run jetty under it's own UID. Then you can take advantage of the setuid SSL security that is already well-tested in either of those servers. We also have some other requirements that this also helps solve, but I would probably choose to do it this way even if we didn't.
The nginx config is also pretty darn 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;
}
}
I would suspect that, because of the multi-platform nature of Java, there hasn't been much emphasis on Unix-based techniques like what exists in Apache Httpd, since these may not necessarily be applicable to all platforms on which Java can run.
In Java, privilege separation is in-built, by the means of the security manager. Whether this is as good as the root/non-root separation, I'm not sure (there can always be bugs). However, its policies are, in principle, capable of expressing more subtle access rules than just the distinction between a root and non-root users.
Jetty had this, but this was apparently dropped in Jetty 9 (you can still use a security manager, but you may have to write your own policies and do a bit more of the work to implement them in the container).
The Jetty Policy document also states:
Normally a user trusts the application they are developing or are trusting enough to deploy a webapp into an instance of jetty. If you don't know that you need to use the security manager setup, you probably don't.
I'm not sure I'd agree with that. Indeed, if there's a webapp I suspect to be malicious, I won't run it anyway, but using a security manager is also about containing potential security bugs. Anyone can write bugs, even good programmers. Having a mechanism that restrict possible actions by webapps is certainly a good thing.
A sensible policy would certainly prevent webapps from accessing the config files and the keystores.
I would also argue that this webapp separation is also at the core of the notion of "container" (although security is only one of the purposes of this separation, it seems to have been lost).
In fairness, it's not as straightforward as the separation offered by the root/forking mechanism in Apache Httpd. The power of Java security policies also brings complexity. I suppose these features are generally not well understood, and thus little used. Using Apache Httpd (or Nginx, or others) as a reverse proxy tends to be a simpler solution for the purpose of protecting the private keys.
Another way you could look into is using a PKCS#11 keystore. This is supported by the JRE. Hardware Security Modules would help prevent your private keys to be copied. (From a Java point of view, you get a PrivateKey instance that delegates the cryptographic operations to the PKCS#11 library, but from which you cannot extract the private data at all.)
Of course, this is a problem when you don't have access to the hardware, but there are software implementations of this (looking up "Software HSM" might seem odd, but it will bring a few results). Not all of them will let you have the separation you're after, but some should (effectively, by communicating with another entity holding the private key, which you could potentially run as another user). I haven't tried it, but this one might be of interest.
Although I appreciate both #Joakim and #Tony's answers, I was hoping for a more generic solution that covered general password protection without JNI/Jetty specific features and more generic than just SSL secret key protection.
The best solution I can come up with is a small C wrapper program that was setuid root. It would:
Starts up and read in a collection of secret information from root protected files on disk into memory. It should immediately encrypt the secret information in memory (see below).
Switches from root to the unprivileged user running the application.
Forks and exec's JVM with the appropriate application arguments.
Writes the encryption key and the encrypted passwords in via STDIN.
When the JVM boots, it immediately reads in the encrypted secret information from STDIN.
One they are read the wrapper application will terminate.
As an extension, the small C wrapper could stay running and provide access to the JVM to system resources by using a simple line based protocol over STDIN/STDOUT. This would give the JVM access to other protected resources on the system in a controlled manner.
Here are some other thoughts on possible solutions.
A service started at boot time by init.d script that runs as root and serves a collection of secret keys to the JVMs starting up by some web service or though some FIFO file or something. After the first request it would shutdown or after some number of seconds after boot.
LDAP is certainly better than having the secret foo on the box itself -- readable by the application user. As an alteration to the solution above, the setuid program could inject the LDAP password into application so it would not live in user readable space.
As always, both applications would need to protect the passwords in memory. Storing them in system sockets or splitting them up into noncontiguous memory blocks is always a good idea. You could also generate a secret key and encrypt them in memory as well.

Why should I sign my JAR files?

Why should I sign my JAR files?
I know that I need to sign my client-side JAR files (containing Applets) so that special things like filesystem access can be done, and so that the annoying bit at the bottom of windows doesn't show, but why else? And do I need to sign my server-side JAR files containing Servlets, etc.?
Some basic rules for when and when not to sign JARs would be appreciated - thanks!
The short answer - don't, unless your company policy forces you to.
The long answer
Signing jars is effectively telling your customer "I made this, and I guarantee it won't mess up your system. If it does, come to me for retribution". This is why signed jars in client-side solution deployed from remote servers (applets / webstart) enjoy higher privileges than non-signed solutions do.
On server-side solutions, where you don't have to to placate the JVM security demands, this guarantee is only for your customer peace of mind.
The bad thing about signed jars is that they load slower than unsigned jars. How much slower? it's CPU-bound, but I've noticed more than a 100% increase in loading time. Also, patches are harder (you have to re-sign the jar), class-patches are impossible (all classes in a single package must have the same signature source) and splitting jars becomes a chore. Not to mention your build process is longer, and that proper certificates cost money (self-signed is next to useless).
So, unless your company policy forces you to, don't sign jars on the server side, and keep common jars in signed and non-signed versions (signed go to the client-side deployment, non-signed go to server-side codebase).
Signing a jar file, just like using certificates in other contexts, is done so that people using it know where it came from. People may trust that Chris Carruthers isn't going to write malicious code, and so they're willing to allow your applet access to their file system. The signature gives them some guarantee that the jar really was created by you, and not by an impostor or someone they don't trust.
In the case of server-side or library jars, there's usually no need to provide that kind of guarantee to anybody. If it's your server, then you know what jars you're using and where they came from, and you probably trust your own code not to be malicious.
A good reason could be if you never wanted anybody to be able to sneak in modfied classes to be called by your code.
Unfortunately that includes yourself :-D So this is only to be done if you really need it. Check the "sealed jar" concept.
In terms of applets: From 6u10, the Sun JRE replace the warning banner with less obtrusive (from 6u12, IIRC) warning triangle (necessary to support shaped and transparent windows). 6u10 also allows controlled file access through the JNLP services API.
The principle of least privilege says that you should not sign the classes of your jar files. Security is not necessarily easy.
Simply showing a certificate dialog box should not be construed to mean that the entire contents of a web page is to be trusted.

Categories

Resources