Okay, so pretty much I'm trying to add security to my Java class file. I don't want it to get decompiled. So what I've done is created a login system where the java app checks it through a web request. If the login information is correct then it will run the script. However, I want to further improve security and have the class file hosted online.
How can I make it download & run the online hosted file?
Also, when the app/script stops running or it's closed the .class file is deleted.
I'd prefer where it did not have to download the file, just get from an online server and compile/run.
Let's go through the things you have done, and the things you are proposing to do and see if they will really work:
Asking for a password. This is easily to defeat:
Capture the classfile.
Decompile it.
Identify the place where it makes the remote call does the login check, and checks the response.
Modify the bytecodes to remove all of that.
Rather than installing the class file, download it on demand and delete it when it finishes. Also easy to defeat.
Capture network request made to download the file.
Replay the request using (say) curl or wget and capture the downloaded class file.
Proceed as above.
And variations are relatively easy to defeat too:
Obfuscation can always ultimately be defeated by manual decompilation and/or running the bytecodes using a debugger.
Downloading using one-time key or something can be defeated by reverse engineering the procedure and extracting the one-time key ... before it is used.
Encrypting the bytecodes can defeated because the JVM has to have the bytecodes in decrypted form at some point. So the means of decryption of the bytecodes must be embedded in code ... that can be reverse engineered.
The bottom line is that it is impossible to prevent a skilled and determined person from defeating security schemes that depend on keeping things secret from a user who controls his / her own execution platform.
The best you can hope to do is stop low-skilled attackers, and slow down skilled ones. You need to ask yourself ... is it really worth the effort?
(Note: you have the same problem no matter what implementation language you use.)
Create a new URLClassLoader (the "default" Java classloader) and point it at wherever you saved the file:
// the directory where you're saving the .class file
File tmpDir = new File("/tmp/yadda/blah/");
ClassLoader cl = new URLClassLoader(new URL[] { tmpDir.toURI().toURL() }, Thread.currentThread().getContextClassLoader());
Class<?> cls = cl.loadClass("SuperSecretClass");
// use reflection to instantiate cls, call methods, etc.
(Passing in the parent class loader might not be necessary in a non-webapp, but I'm too lazy to test that detail. Using the thread's classloader explicitly will work one way or the other.
This assumes that your secret class is not in a package, if it is you'll have to create the appropriate directory structure inside the temporary directory and point the classloader at the root of the package tree, as usual.
Also: this sort of security-by-obscurity sounds like a bad idea. You're still downloading the file, if it's over an unsecured connection a determined attacker can sniff it, and there's still the period of time during which it's on disk. You could create a completely custom ClassLoader that directly reads the stream, but even the class file could probably be recovered with a little more effort. (Like pointing a debugger at your main app and intercepting stream reads.) The javadoc for ClassLoader provides an example of how to do this.
Related
I want my java application to be able to automatically keep itself up to date, i already made all the code to download the latest jar file and put it in the designated path but since my program has to be open to actually check if there are updates available and then update them it gives me this error:
Exception in thread "main" java.nio.file.FileSystemException: name.jar: The process cannot access the file because it is being used by another process
Now my question is not why i get this error since it is quite obvious why, the question is: how would i go about actually updating the .jar file succesfully since it has to be open to actually download the update? I'd rather not make another .jar to act like a standalone updater if there are other options.
Example of the code i'm using to test:
URL url = new URL("<working url to the .jar file>");
InputStream in = url.openStream();
Files.copy(in, Paths.get("app.jar"), StandardCopyOption.REPLACE_EXISTING);
in.close();
First of all: the other answer is correct, there are ways to silently update/restart JAR files. And downloading new JARs, with a full restart, that is fine.
But the question asks about updating a JAR "in use", and for that I have a distinct non-answer: you are going down the very wrong rabbit hole!
Even if you somehow hack your way into overriding the JAR file on the file system while one (or more!) JVMs that have (or have not) have loaded classes from that JAR are running, the result is not what you would expect it to be: replacing the JAR file content doesn't magically reload all classes into a running JVM. The classes are already loaded! Changing their "load origin" in the file system does not affect "running" classes.
If at all, you enable situations such as:
class A is loaded from Jar X (version N)
Jar X is updated
class B is loaded from Jar X (version N+m)
But snap, that class B expects class A to look differently. And all of a sudden you have a versioning conflict within that JVM instance. Because it loaded some classes from X (version N), and other classes from X (version N+1, or N+5 because that customer skipped downloads for 2 weeks). And it gets worse: the exact error scenario might totally depend on the workload that your JVM has seen so far, and how it is used after the update. One customer might not have any issues, and the other might crash within 5 minutes (crashing at some point is very likely though).
Long story short: don't do this. Instead:
either tell your users that they have to restart the application when updates came in
or look into the "real" JVM hotswapping mechanism. But honestly: this is more of a debug feature, you do that in a development environment, for example using a tool like JRebel. You do not want to use it in a production environment at your customer. Because as said, runtime versioning issues are bad.
First of all it is close to impossible to replace a running application, without restarting it, but there are techniques to transition fluidly. Here's a popular one (simplistic):
You launch application.exe, which checks version and finds that there's a new version.
application.exe launches updater.exe and closes itself (or waits, until updated version is downloaded and then closes itself.
updater.exe replaces the file and launches application.exe again.
So this part is a staple (replacing the core application), without some sort of hardcode memory hacks, to my knowledge.
If you don't need to update the actual core application and are willing to invest time into developing a dynamic library/asset management in your application, you can essentially unload a library or an asset, update it from application.exe and then reload it when it has finished updating, without needing to restart the application.
This might be the thing you are looking for, because if your application.exe is just a loader, and core logic of the application is 1 of the libraries, you can replace essentially any part of the application. You still have to "restart" that part of the application, but you can save and restore important data before restart and restore it after to make the transition somewhat fast and painless.
It's will most likely be time consuming to learn and implement.
Here's an answer with some insight into the second portion of the answer.
PS: I used ".exe" as a reference everywhere. Just imagine it's about jars, same principles apply.
I have a jnlp application that loads and executes a jar file ( client ) on a users computer. The user uses this jar to communicate with a server that provides a services. I've seen users using javassit and javasnoop to alter the functionality of the client. Is there any way I can remotelly detect changes created by the previously mentionted utilities ? For example, can I checksum the classes locally and send the result to the server ( who knows the correct checksum of each class ) ?
There is no way in general to prevent the client from running any code they wish to. The security of your system should never rely on assuming that clients are running specific code or are not aware of specific information contained in the jars you send them.
Furthermore, attempts to impose DRM tend to cause problems for legitimate users and alienate your customers while doing little to prevent people who actually do want to hack the system.
You can for example create a check sum of your java file and make your application to calculate the checksum at runtime and send it for verification to server. The simplest checksum is a hash code of whole jar.
The only question is why? And who is the super user that takes your jar and performs instrumentation on it? And why is he doing this? And even if he has reasons, who cares? If you are afraid that somebody is going to hack your server make it secure enough and do not care about client (IMHO).
You can open a classfile named p1.p2.ClName with Classloader.getResourceAsStream("/p1/p2/ClName.class"), read it, and compute its checksum.
But, as user can change the functionality, he can also remove that checksum checking.
I'm working in a project where we need to encrypt the .jar file so no one can access to the .class files which inside the jar file.... is there any java coding which can help me to encrypt the .jar file ?
Even if you encrypt the jar file, it must be decrypted before the JVM is able to run it, so you'll need another jar file containing classes that decrypt and loads in the JVM.
Since this second jar file cannot be itself encrypted, a malicious user wanting to see you class files, can simply look at classes in this second jar file, and then decrypt your super-secret jar file and have access to it.
Maybe you can increase security of your code using an obfuscator, but it will eventually protect (make it harder but not impossible) your class files from decompilation, not from being used.
If obfuscation is not enough, you could consider compiling your jar file to a DLL for windows or a SO for unix/linux, that will make it much harder to decompile, but it's not always possible to do that correctly and it's generally a PITA. GCJ is able to do this somehow, and there are other commercial products that will actually compile .class/.jar directly to machine code.
However please consider that it does not matter how much security you put in it, since the client computer MUST be able to execute it, it must be able to read it, so no matter what your code will be exposed, you can only make it harder.
If you really have an algorithm so secret you don't want to disclose no matter what, consider converting it to a web service, hosting it on your server, so that you don't have to send the actual code to the client machines and can also better prevent unauthorized copies of your application by checking access to that vital part of it.
I assume you are aware of the fact that any skilled java coder can reverse-engineer the Java tool you use (or write) and still decode the app's jars? Also writing custom classloaders which read your "encrypted" code can be decompiled and a tool could be written to bypass it.
Even with obfuscation and bytecode modification and custom classloaders, java is hackable/decompileable and the source can almost always be brought to a somewhat readable state.
You want to obfuscate, not encrypt, the jar file.
A popular choice for doing this in Java is ProGuard.
No. Since your program needs to be able to run the code it would be pointless anyway.
You can obfuscate your code though so decompiling the .class files results in less readable code (meaningless variable/class names etc).
As far as I know this is not supported by standard JVM. But you can do the following. Separate your application into 2 parts. First will not be encrypted. It will be a simple loader that will instantiate the rest using custom class loader. This class loader will get Classes as arrays of bytes, decrypt and load them.
if you don't want to provide an access to the class files inside the jar, why should you supply your jar with the application?
It feels like your question is kind of wrong conceptually...
If you need some custom way of loading the classes, consider to use custom classloader.
if you are packaging in jar -> just rename it to jarname.ABCD or any misleading extension or even take off the extension, and accordingly specify the jar name in your application.
i prefer jCrypt!
It is a simple tool where you can crypt the classes(and ressources)
I've been searching for days but I have not found a clear answer. How would I go about writing a small jar file to give to my users that simply gets a jar file from a URL (with multiple classes in it) and run it. It would be great if the end user never actually has the jar on his computer at anytime. I am doing this as a small security measure.
If the user is going to execute your code, it must exist on their computer. It's just the way it works.
If you wanted to re-write your code to perform most of the work on your servers, that'd be one mechanism to combat piracy, but it does mean that you need to duplicate all the input verification checks: perform them once on the client side, for reasonable response time, and again on your own servers, to ensure that your users aren't trying to use your services improperly.
Another mechanism would be to run a VNC server on your servers, and ask your users to VNC in. The software executes completely on your servers. It is a draconian step though, one your users will likely detest.
I am not sure how you'd go about it, but I know that using Maven allows you to access things without having the jar locally. You can just specify the URL. So maybe look into how they do their repositories.
Another option would be to encrypt your JAR file and write a custom class loader that decrypts it on the fly on client machines. This won't prevent a power user from attaching a debugger to the JVM and examining your byte code, but it prevents the typical user from having access to your code.
All,
I'm working on the design of a cloud-based service that will provide the option to execute some "plugin" code submitted by clients. In order to make this work it is essential that the plugins can't threaten system integrity or have any ability to access the data of other clients.
Ideally I'd like it to be possible for clients to submit a simple jar file (containing a class conforming to some pre-defined interface) which would then be run within a sandbox.
The client code should be allowed to:
Take as much CPU time as it needs on a single thread
Perform any calculations using standard java classes (e.g. java.lang.Math, java.util.Random etc.)
Call any libraries bundled in the jar (but which must be subject to the same restrictions)
But I would specifically need to disallow the following:
Spawning new threads (so that server resource can be fairly managed!)
Any access to the file system / IO / network
Any access to native code
Any access to data in the JVM other than that passed to / created by the client code
Any access to reflection on classes other than those in the .jar sandbox
Any ability to call methods on objects outside the sandbox, other than the standard Java libraries
Is it be possible to achieve this with a custom ClassLoader / SecurityManager setup? Or will I need to start looking for a more sophisticated solution (e.g. launching multiple JVMs?)
Managing resource and limiting resources is not possible in java. You can prevent malicious code to access system resources (disk/network and so) or the JVM itself but:
...
Spawning new threads (so that server resource can be fairly managed!)
If i wanna be malicious I am gonna do all my code in the finalizer thread and just block the VM. Same doing protected void finalize(synchronized(Thread.class) {for(;;) LockSupport.park();}} bye-bye new threads.
Eating all the memory, eating all direct memory and so on.
Accessing zip files in my own jar, and expect 'em getting moved away, so the JVM crashes (due to bug(s) in zlib)
If one purposely wants to deny resources, it is just not a feasible task to try and catch the hacker. You'd need to know what to search for and dynamically check/enhance the classes on run-time to disallow the behavior.
Any ability to call methods on objects outside the sandbox, other than the standard Java libraries
What are the standard libraries? Do you know if/when they must possibly execute some code in a privileged method.
Each customer - separate VM w/ full restrictions, process affinity/priority, incl max memory/stack and so on.
I think everything you want to achieve can be done through a custom SecurityManager. In fact it's pretty simple, you just create a class that extends SecurityManager, implement the two checkPermission(..) methods and in the first iteration just throw an SecurityException for everything that comes in (and log what you just denied). Then you allow specific operations until you find yourself in the situation that it's possible to create useful plugins and let your clients play with it. They will complain. Then you have to judge whether to allow them to do whatever they requested or if you want to stick with your rules. Here the difficult part begins...