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.
Related
What I am using:
Java EE
So, essentially I am making a web application that is free to use and open source, however I worry there will be users who are not familiar with java, I want these users to be able to configure DATABASE information without editing the code, would this be possible?
Things I want to try but don't know enough about:
- A installation page, kind of like the one WHMCS and Xenforo have, however I am not sure how to make this stick, for instance, if the user restarts there web server would the information be reset.
One way is,
You can make a way to read database details(hostname, port etc) from system environment variables. Users can set environment variables to add their DB details.
OR
You can create a docker image of your db and application and make a docker-compose file with details. then you can ask users to edit username/password in that file and then user will run 1 or 2 docker commands and application is up and ready.
Ex: fider is similar application and they provided through docker. for your reference https://getfider.com/docs/hosting-instance/
Note: this approach requires docker environment.
Since your deliverable is a war you expect the consumer to know their app container. The typical way for a JEE app to configure persistence layer is using persistence.xml file located in META-INF/ folder. You can tell the user to prepend class path with their own persistence configuration. I understand it may sound difficult but a typical system admin should know what you're asking. This is what war deliverable really means.
If you want to make it easy for lay people, build a docker image with a database of your choice and package with your app connected to this database. People who will want more will need handholding anyway. Hopefully in the form of their own developers.
I have an encryption program and I was looking for a way in so that only the encryption program have access to they keys folder. But setting it to the owner or anyone in the users aren't a good idea. I was thinking maybe something like Steam did with its folder. It restricted access even to the owner/admin of the computer and only the Steam app can communicate/edit/access the folder. I was wondering how to do it in Java.
The code that I currently have right now is this.
Path file = Paths.get("F:\\keys\\pic.datakey");
UserPrincipal owner = file.GetFileSystem().getUserPrincipalLookupService()
.lookupPrincipalByName("username");
Files.setOwner(file, owner);
with keys being the folder name and pic.datakey is the key that I'm trying to prevent anyone except the program to have access with.
How to set the folder owner to the encryption program's?
The encryption program is not a principal. It cannot own things. What you need is to run the program as some special principal1.
Problems:
What principal should you use? There won't be a platform-independent answer to that. Indeed, there isn't an obvious platform-specific answer, at least for Linux.
How do you ensure that the encryption program runs as the designated principal. This is not solvable in Java. (Long story ... but mechanisms like UNIX setuid will require a non-Java (non-shell) launcher to implement them securely for a Java program.)
But once you have done those things, it will be unnecessary to change the owner of the file (as per your code). The owner will default to the principal under which the program is currently being run.
But here's the real question. What do you think you will achieve by hiding the encryption keys from the user who has encrypted the file?
If we assume that the user has full "root" access (or equivalent) then they can access any file stored locally on the system, either directly (i.e. as root) or with some extra effort. Certainly on a typical operating system.
And the flip-side is that if the user doesn't have "root" (or equivalent) access, you can stop him / her from seeing files by setting the owner / permissions of the files. Adding encryption doesn't achieve a lot more.
Yes it's a security measure.
Security against what? The user who owns the machine? Even assuming that it is technically feasible, is it a reasonable thing to do?
(These are rhetorical questions. I am posing them for you to think about, not because I either agree or disagree with what you are doing. And not because I want to debate this.)
1 - Suppose that the program runs as the user. First of all a user cannot transfer ownership of his files to another user. That would provide an easy way to "cheat" file usage accounting. Your encryption program running as the user couldn't do that either. (The OS cannot determine the intent of an operation.) Second, assuming an ordinary user could change the owner of a file, then after the change of ownership the user would not be able to read it. Moreover, neither could the encryption program.
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.
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.
I have a typical web application deployed in Tomcat. The requirement is to provide incremental update way instead of full-package delivery (a war file) when update the application.
For example, once I finish a bug fix which changed a jar file, an XML file and jpg file. I call these 3 files as a patch. I am supposed to deliver the patch file. Even when customers want to rollback to original version, I have to provider a way to rollback the patch.
All the process is supposed to automatically.
From my perspective, the requirement doesn’t make sense. full-package delivery is easy and reliable way to update a web application, I don’t want to introduce complex and error-prone way to update.
Do you have idea to implement incremental update requirement? Thanks!
When you deploy the .war or .ear, the application server usually unpack it into an internal directory. You can change files in this directory directly, with a finer granularity. However, for changes to take effect consistently, you will need to restart the server.
Your perspective is indeed fully correct. Nowadays, sizes of files don't play a significant role, I don't see the problem with whole updates. Why isn't the customer happy with whole updates?
Note: If what he wants is dynamic updates, i.e. without restarting the server, then this is anyway a complete different problem, and mostly impossible for production systems in java (but doable during development, with solutions like JRebel).
You can create a Java Program that uses Delta-Sync protocol i.e. Only those files need to uploaded which are updated. If you have used Dropbox then you will understand pretty well.
Dropbox uses Delta-Sync protocol to update file and sync data.
Either way for time being you can use Dropbox by installing on your client (mapping to server's WAR folder) and your local machine and share that folder. Then whenever you change the files in your local machine it will automatically upload and sync those CHANGED (PATCH) files to your client's machine.