views:

81

answers:

4

I'm not a Java developer, but my client has hired one to update some JAR files on their site. Prior to doing so, we audited the existing code and found a number of security vulnerabilities. One of the solutions we employed to make the files more secure is to create a new database user with read-only access to the database, and only for those tables that the JAR files required to operate. I then found out that they are storing these credentials in plain text files alongside the JAR files, only an educated-guess away from the public at large. And finally today they are asking for much looser database privileges, but I don't think she understands that she really shouldn't need them for a properly written JAR file.

Anyway, I'm pretty sure this developer wouldn't know a security vulnerability if it bit her on the backside. And I don't know enough about Java/JAR files to properly advise her on what she should be doing, only enough about infosec to tell her what she shouldn't be doing.

So what are the typical security considerations when writing a distributed JAR file that connects to a remote MySQL database? Is there a standard way to encrypt the connection details (username and/or password)? IIRC, aren't .jar files just glorified ZIP archives, and couldn't anyone therefor unpack the file and view the connection details in the source code? Is there a way to encrypt the jar file content?


UPDATE: I received the following clarification from the developer. Does this sound right?

All the classes in the jar file are encrypoted. i have always encrypted all the class files before archiving them in a jar file. if you open any [redacted] jar, you will only see encrypted code. so there is no chance for a user to be able to view the source code by decompiling the classed. the classes do use jdbc to connect to the db, the search eangine needs to connect to the DB to run sqls. these sqls are in teh encrypted clasees in the jar file.

when i asked you about the encrypting the DB password, I meant what you say below. we will write an encryption/decription code in java and use it. Thecompiled class from this source code will again get encrypted as part of the reoutine class encryption procedure. We use a Java obfuscation tool called Retroguard to encrypt all the classes. we also embed a key in the html page to make sure that the application will work only if it has been downloaded form [redacted] website. if the user copies the jar to his local machine and tries to run it, it will fail.

+1  A: 

Yes, JARs are just ZIP files, so it's entirely possible to open one using WinZip and look at the contents. If you know what you're doing, you can find a plain text password inside.

It sounds like your JAR contains a client that connects directly to a database. You don't say whether this is done over the Internet or a VPN or a LAN. Is the database deployed remotely from the client?

This is one reason why client/server apps went away: it's hard to secure them over the Internet.

Your app sounds like classic client-server to me. Do I have that right?

A middle tier is usually introduced between the client and the database to check security, validate and bind inputs, and shuttle requests to the appropriate handler for fulfillment. Have users present credentials that your middle tier has to validate before passing them along to the database.

It can also give you a fighting chance against SQL injection attacks.

If you encrypt the JAR contents you'll have to write a custom class loader to decrypt them when loading. Not for the faint of heart.

If your client is a Swing app, with all the logic and database stuff built into the listeners and event handlers registered for each component, you'll have a serious rewrite on your hands. You'll be moving to more of a service oriented architecture, where all the work is done by services on the server side. The client only does what it's supposed to in classic MVC: pass events along to the server side and display results. Your client will be a lot lighter.

That's going to be the biggest shock to your development team and the business.

duffymo
The jar will be embedded on an HTML page and will make requests back to the MySQL database that the rest of the website uses. Honestly not sure why they went with Java on this. My guess is that some engineer knew it and didn't want to be bothered with learning PHP. Please see my update in the original message for more info.
Chrisbloom7
How would PHP be any better? I don't see that the update makes me feel much better. Do you charge for this product? Do you really have a MySQL database exposed to the entire Internet? Good luck with that. You have no idea who's hacking into that database. It's possible to do this with Java, but it sounds like your design is flawed from the get-go.
duffymo
No, the database is currently behind a firewall with a few IP exceptions. But now that you mention it, we would have to open it up entirely for this to work. Regarding PHP, it would be better because all of the database connections would happen behind the scene directly at the server, and only the end data would be transmitted (aka just like every other PHP/MySQL application on the internet)
Chrisbloom7
Just to clarify, this is not a jar file served via Tomcat or some other Java server. This is an applet embedded on an HTML page...
Chrisbloom7
Yes, I got that. People who have applets usually put a servlet between their HTML page and the database to do all the security and binding things that I'd recommend. An applet connecting to a database directly is so 1995.
duffymo
agree with duffymo, this does seem like a design flaw. if there is data needed by the applet at load time, prepare that data server side and pass it to your applet via parameters in the html. If the applet takes information and requires the DB to update something then put it in a form, ajax or something else to retrieve this information. Exposing your DB to an applet is not the right design here. Since your DB access will be read only, I would suggest some form of AJAX to feed the data. Keep the DB credentials server side
Sean
Thanks for all the feedback on this. I'm really surprised at not having considered the problem with the firewall before this. I've spoken to the client and the Java developer and informed them that we simply could not do it this way. Instead, I would expose a new set of API URLs that she could use to query data - all processing being done on the server itself and only transmitting the resulting data to the applet.
Chrisbloom7
A: 

To put it in plain text is (i think) serious vulnerable. Indeed, one can extract the jar and read what's written in that plain text.

If using a jar is a must, i will recommend to create a class (just a simple class) which contains the username, password, url, etc with final keyword. Even though this method is not really secure, at least a compiled class cannot be easily read. Another advantage (or perhaps disadvantage) is the 'hard-coded' connection properties cannot be easily modified. Even if you have the source code, you still need to re-compile it and re-jar it.

jancrot
Please see my update to the original question for more info on how the jar will be packaged.
Chrisbloom7
A: 

I think the convention for that kind of thing for most developers is to store a configuration file outside of the root of the web directory. Of course if this is a desktop application and not web that's not possible. Something I've done before in a SWING based MySQL driven app with limited number of users was instead of using a middle tier for authentication and presenting data as a service, using MySQL's built in authentication so that all of the security would be defined in the schema and then duplicating the permission settings for every user. Kind of a hackish but reliable approach.

Novikov
The jar file will use it's own separate MySQL user account with read-only access to the database. But it will run on a web page, and so my guess is that there's no way to store the resource file outside the webroot because then the jar file won't be able to access it either (since it runs as a local application on the client end)
Chrisbloom7
Ah, then for all intents and purposes it's broken by design, nothing your or the consultants do can fix it in my opinion.
Novikov
A: 

I'll begin my answer by stating something often stated: "any person can create a security scheme that he/she cannot break".

Now, taking note of the update where the mention of encryption and obfuscation is made in the same update, it would be wise to note that encryption is not the same as obfuscation. Technically, encryption involves the use of a key to transform some plaintext into ciphertext, with the plaintext recoverable only with knowledge of the original key. Obfuscation is nowhere close to encryption by definition - it involves the removal of information from executable source code, that renders the executable supposedly "difficult" to reverse-engineer. Usually, obfuscation involves replacement of symbols by smaller ones, and sometimes, reordering of source code that makes the reverse-engineered source code difficult to read, while retaining the execution profile of the original (obfuscated source code has the same code and data flow paths as the original).

Of importance here, is the fact that the password is coded into the source code. It is reasonable to assume that the obfuscated source code will also contain the hard coded password. This assumption is reasonable since most obfuscators have never attempted to mutate the constant pool within a class file - mutating a constant pool is dangerous for it can result in changes in runtime behavior. If the password has been hard-coded into the source code as a String, then the class file (obfuscated or not) will have the password in the String constant pool, which will be loaded into memory by the JVM (with no decryption or decoding process in between).

The best practice in this case is to get the end-users to specify the database user ID and password (if they're managing the application setup), to store these user provided credentials securely (this depends on the nature of the application; Java EE applications should attempt to have the container manage these credentials), and manage these credentials securely when they're retrieved from the secure store. You might want to take a look at the OWASP article on Insecure Storage for more pointers.

Given the use of an applet, it is not recommended to have the database user ID and password in the applet. This needs to be done for various reasons - good applications allow for changing the database user ID and password with mere configuration changes to the application. Hard coding the password in source code is bound to increase management overhead; you might have to get end-users to clear their Java applet cache every time the DBA chooses to change the password (and this is bound to happen occasionally in a sane data center). Moreover, you might also need to protect against database account lockouts, when the changes to the applet are being deployed. Like other recommendations posted, it would make a good deal of business sense to manage the database connections from within the middle tier.

Vineet Reynolds