I'm working on a closed source java app that analyzes JAR files.
Since java can be easily decompiled, and obfuscation really isn't a big deal,
I want to provide an online service that will execute the app on my server and
return it's result much like fernflower here: www.reversed-java.com/fernflower/.
Problem is, I fear that's a recipe for disaster having my app load any potentially
harmfull jars on the server, even though i'm never running the jars.
All i'm doing is load them using URLClassLoader and JarInputStream.
Can a jar I am loading override classes in my original app in order to execute malicious code,
or mess up my program?
What are the risks in dynamically loading jars?
What are the risks in dynamically loading jars?
There are no risks of dynamically loading per se. The risks are really the risks of running untrusted code. If you do that without taking the appropriate precautions, you risk having your machine totally compromised.
If you are going to do this kind of thing, at the very least you should run untrusted code in a sandbox that stops it from doing anything potentially harmful. For instance, you need to block reading and writing local files, running external processes, using reflection, accessing system properties, and so on. And you may want to stop it creating threads, creating sockets, and other things that consume system resources.
Finally, you need to consider the case where some untrusted JAR has a method that is an infinite loop. This is a problem that can't be dealt with using security sandboxes. Indeed, the only bomb-proof way to get rid of a looping thread is to exit the JVM and restart it.
Can a jar im loading override classes in my original app in order to execute malicious code, or mess up my program?
I don't think it can easily override your classes, but there are lots of other ways for untrusted code to "mess up" your world; see above. (And if the untrusted code can execute reflective code, then it possibly can override your classes by messing around with the classloader's private data structures.)
Related
I'm trying to add a java scripting option to my web application with the following requirements:
1-The user writes custom java code.
2-The user can compile/run this code.
3-The user can upload jars and use them in his code (without using a custom class loader/reflection).
By overriding the java class loader, I managed to achieve the first 2 requirements.
However, for the 3rd requirement, I am unsure how to proceed.
I was wondering if there was a way to use an existing api to handle this, or any offline java code compilers to execute this custom code:
input : java code+ dependent jars -> output : code execution
There is no way to dynamicly load additional JARs from the user without creating a new ClassLoader instance. But it doesn't necessarily need to be a custom subclass of ClassLoader.
The general idea is that you create a new instance of (say) URLClassLoader providing the URLs for (say) a local copy of the user's JARs. This new classloader would typically have your application's classloader as its parent classloader. Then you would use the new classloader to load the user's classes; i.e. the ones you wanted to user. You would need to reflection to create instances of those classes, and then you could cast them to an interface in your app's code-base and invoke methods on them as per a normal class.
Offline compilation won't help. The problem you need to solve is getting your application to >>load<< the user's code.
Warning: what you are proposing to do sounds rather dangerous. You have no real control over the code that the user is going to put into the Java source code or JAR. It could potentially do all sorts of malicious things: reading / writing your server's files, exfiltrating secrets or confidential data, mining bitcoins, causing your server to participate in a DDOS. Or just do something that is annoying and disruptive.
That potentially malicious coder is going to run within your webapp on your server.
I am trying to build an application that runs under JavaSE and Android. Most of the code is the same between the two, but there are some specific functions that need to be separated. I use Eclipse. So I decided to put the shared code in a separate project, and then build one more project for Android and one for Java, which reference the shared project. I put all Java and Android specific functions in one class residing in the Java and Android specific projects. These classes are called UtilsJ (for Java) and UtilsA (for Android). The code in the shared project uses a factory to determine at runtime which version it needs to pick, and then calls the class loader to load the right class. Essentially: if property java.vm.name equals Dalvik, load UtilsA, else load UtilsJ (and of course cast to the Utils interface before returning).
My question is simply if this is a good idea or is something going to eventually break? I've never used class loader before. Any other suggestions how to implement this sharing would also be appreciated.
Generating an interface implementation dynamically is certainly a valid technique. For instance, having a data access interface that has multiple implementations; one each for flat files, MySQL and WebDAV. The program can pick an implementation at run time based on system/platform properties.
But this feels different. If I saw that I had a Java app and an Android app that had a lot of common code, my goal would be to create an Eclipse project that generates a jar file that I could just drop into the libraries of both projects. In that case, the jar file wouldn't contain any code that was incompatible with one platform or the other. So there wouldn't be any reason to have a platform-specific implementation.
Let's take your example some code reading an initialization file. If it's common code, you have an input parameter which is a file. On Android, maybe it's "/data/data/com.whatever.blahblahblah" and on Java you're getting the "user.dir" system parameter for the top level directories. But one way or another, it's a File, and you hand it to your common setup method. That's okay. But if your initialization file read code e.g. needs a Context to get a Resource to read the file for Android, then it's not common code. And it doesn't belong in a library jar for a JVM-hosted app.
So I think that in your case the platform-specific implementation classes are overkill. If it's common code, it's the same code — period.
Let's talk about another example in your comment. If you are using desktop Java, then you are probably using Swing or AWT, so you still have the same issue of running some network task off the UI thread, notifying when it completes, maybe even updating some progress indicator UI while it's processing. Same function, same operation, but the code is so different that I can't see how having it in the same library next to an AsyncTask version could be of any benefit.
And testing might get tricky. Obviously JUnit will work for everything, but some tests would need to run on a device or emulator.
I stated that it was a valid technique, and of course you may have other compelling reasons to choose the multi-platform option. You asked the question; is anything going to break? My answer is: Probably not, but why risk dealing with some heartburn down the road? Speaking for myself, I wouldn't do it. If I had to support multiple MVC apps, my common library would have nothing but M.
I use Eclipse and have some project compiled and running. Then I decide to modify some class.
It seems that running project doesn't catch up changes, but if I run another instance of project then it does see changes.
The question, how does Eclipse rule this out?
Because I see that .class files are stored as single instance and later changes just overwrite previous. It maybe JVM who load classes in memory and don't touch them even if they changed. But I would like to hear complete story.
When a program runs, it reads the .class file into memory and uses that copy from then on.
If you change, it doesn't re-read the file and load/link it again, that would be more complicated. There are class loaders which do this automagically, but this is not default behaviour. (It is also very unreliable as you might change the class in an incompatible way e.g. modify a field, or method signature)
Generally speaking, software is implemented in the simplest way imaginable. It is more likely to work and be understood if it is simple. This should be your guiding principle when trying to understand how computers work.
I have a piece of software, contained in a single .jar that is doing its job but sometimes I need to quickly push a bug fix necessitating replacing the .jar file in a central location, unfortunately if there is a currently running execution of this jar file if I replace it then it crashes with "class not found" error. I thought that once a jar file is executed the JVM will cache it in memory and won't do any reads from the disk but apparently this is not the case, how can (if possible at all) this be remedied?
EDIT:
The application is not web-based. It's normal Java SE.
JAR files are not loaded into memory in bulk, as other shared object libraries are. Their classes are loaded into memory on a demand basis, so if you remove a JAR file and a class lookup needs to occur, the file handle the class loader will be invalid (because the open file it referenced is now gone) and you will get an error.
Operating systems manage the file handles, so replacing an open file with a new copy is not going to fool anyone. You need to close the file first, which often can only be done by garbage collecting the class loader. If you are using the system class loader, then that means shutting down the JVM.
People have written frameworks to create custom class loaders that can be disposed independently of the system class loader; however, this does complicate class loading. While it can accomplish what you are asking, it cannot do so without restructuring your existing program to accommodate the lookup of classes in the framework's class loaders (and accommodating the loss and gain of class loaders over time).
If you want to try such a framework, see Christian's post. If you want to learn a bit more about how one project uses class loaders to facilitate its needs, take a peek under the covers of Apache's Tomcat, which restricts web applications within their own class loaders.
Often you might find that the correct answer really is to stop the service prior to deployment, and start it after deployment.
The only two possibilities I can think of are using JRebel or OSGi.
At work, I use a Java application (I have located compiled/executable jars on the C-drive). I want to be able to grab some information from this application through code. The application itself probably does not store information, so it must communicate with legacy systems some way, I am not sure how, I have seen traces of a Servlet(?) Hence, I suspect the application also has built-in "encryption"(?)
I do not want to get involved in encryption and login procedures etc., so I am thinking I could just build a Java project around the current executable jars, and launch the application as I usually do (through the "main" entry point, "Start.jar", but then after execution call the functions that I want to (i.e. the application just runs as usual in the background)...
Would that be possible? Is there another way? Can one, for example, hook up to an already executed Java application and issue commands?
What I have tried so far
Downloaded Eclipse, and created a new project
Made Eclipse "reference" external jars (there was a wizard in Eclipse)
Created a new class in my new project, in which I launch the "main" entry point of the "main" executable jar (the structure of all the jars pops up with "IntelliSense"). I have also found out which argument I need to supply to the main procedure using JD-GUI (Java Decompiler)...
It seems that from inside the main procedure a call is made to another procedure, which resides in a different jar, in the debug window of Eclipse I just see an error, which made me doubt that my current approach is viable... Maybe the problem arises because the command is issued from a compiled jar? Could there be an issue with the "class path"? Does this at all seem like a solution? But then again, I have no experience with Java (mostly VBA and some C#).
You can start your JVM for the application with options, which enable remote debugging. Then you can connect the eclipse debugger to this JVM.
http://www.eclipsezone.com/eclipse/forums/t53459.html
Based on your question, I am going to guess that your application does not have a Java API you can code against. That would, of course, be the easiest way. So, if you have not checked, do that first.
Assuming you don't have an API to code against, I think your approach is correct. But it could be hard to do, since you are basically flying blind trying to figure out what the application is doing. Remote debugging might solve part of that problem.
There might be a slightly easier solution, if you are sure it is sending requests across the network. You can use a tool like Wireshark to see what it is creating. Then, you can have your application create requests that look like that and send them to that destination. This assumes of course that the requests aren't encrypted. In that case you are probably out of luck.