I'm not even sure if this is possible, but is it feasible to secure, end-to-end runtime data on an uncontrolled client?
Specifically, is there any functionality in Java to take in encrypted data, process it and send it back out encrypted, all without exposing the data in plaintext to a curious 3rd party that has full access to the client?
Also, I know that code obfuscation is merely an annoyance to a dedicated individual with a decompiler, so I'm assuming for this scenario that the attack party has full source/operating knowledge.
I'm interested in answers either way. If there is no existing functionality, would it be feasible given Java's architecture? If Java can't do it, is there another language/platform that could? I'm fearing this may require special hardware.
To have a chance at doing what you are talking about, you need special hardware. You can't have a secure layer "on top" of an insecure layer. For example, if the attacker has full control over the hardware, he can always compromise the OS running on that host.
The special hardware is called a "Trusted Platform Module," or TPM. This supports remote attestation, which would allow you to verify that a client has not been tampered with. Some parts of the TPM are available on many computers (my Dell laptop, for example). In fact, I think all computers purchased by the US federal government are required to have a TPM. However, most consumers do not enable the TPM, and there's a lot of hostility toward TPM from privacy advocates. I'm also unsure how many machines with a TPM include the remote attestation capability.
Anyway, the bottom line is that you can't give someone a secret, and the key to the secret, and expect it to remain a secret. You have to retain control over the whole stack, top-to-bottom. Trusted Treacherous Computing allows you do do that, even if you don't legally own the hardware in question.
It is fundamentally not possible to be completely secure if the client is not locked down. At some point the bytes will exist in memory, and that memory can be read by hostile applications.
If your goal isn't to make it completely secure but merely inconvenient for the casually curious, then just be sure to not write the data to temporary files or anywhere else that would be trivial to examine.
Not only "can't be done", but "easy to compromise".
Look at 'aspect-oriented programming' and byte-compiler classes. This is normally used for things like inserting database transactions, performance logging, logging statements (so you can drop the calls from the source code and make it a lot cleaner), access control (so you separate the implementation and authorization), etc. There are a lot of extremely useful things you can do if you can quietly wrap one class with another.
But that also means it's trivial to wrap your classes to capture all of the unencrypted messages within your application, encryption keys, etc. I think I can get in even if you do everything in a single long procedure, although it might take a little more effort.
Related
I'm trying to make sure that someone can't recompile my obfuscated application and then send malicious data to my server. I am doing an SSLed PHP_POST of my application's versionCode and packageName. These POSTED variables are all encrypted via asymmetrical encryption along with signature verification which will be changed per every version upgrade. I have thought of using checksums but those methods are not supported officially by Google and research has shown that they are not error-proof meaning that they could potentially disrupt legitimate users.
On top of all of this is a ban-on-site via IP/Mac Address/IMEI/Serial/Android_ID/etc when something is detected that is 100% not legit.
I understand that nothing could be 100% secured and the difference between a good security and a bad one is the time/money/effort it takes to break a security is valued higher than the item being protected by the security. With this in mind, are there any other methods I could use to protect my application or any ideas I should implement to add onto current security?
On a side-note, how easy is it to decompile/recompile an apk(jar) that's been obfuscated and would it be easier once its been done once? (aka, it doesn't matter how many times I change the key because the application is already compromised and the decompiler can simply look at the same spot where my last key was)
First thing, first, don't do your own crypto. If you are properly(!) doing SSL that is probably enough to protect data in transit against tampering, etc. What you need to do is authenticate your app somehow which is generally tricky, because you need to keep the credentials in the app. There are different ways around that, but currently the standard (and Google-endorsed way) is to use Google Play services to obtain a token and verify it in your server app. Details here: http://android-developers.blogspot.jp/2013/01/verifying-back-end-calls-from-android.html
This not perfect, but is probably better than most non-standard solutions you can come up with.
Decompiling is generally easy, and obfuscation doesn't change much, since it is trivial to find the places where you are calling system APIs (to get MAC addresses, hash, encrypt, etc.)
I want to implement encrypted communication between two JAVA servers, both are under my control. There are three architectures I have in mind and want to get your input on the pros and cons of them.
Architecture 1:
Whenever I invoke a remote method, I do not pass the parameters as plain text but as a serialized CipherText-Object. I will use the ESAPI-library for this, but the actual implementation does not matter. What's important is that the CipherText-Object contains arbitrary Data encrypted with a symmetric key including an MAC for authentication. The symmetric key is available as a pre-shared secret on both servers.
Architecture 2:
I don't care about the encryption on application level but delegate it to the transport layer. This could be a VPN-Tunnel or some sort of server-to-server encryption that is supported. I don't have too much information about what is available on modern application server at the moment. Input on this is welcome as well.
Architecture 3:
Using javax.rmi.ssl to use RMI over SSL.
It feels like architecture 1 is complicated and a pain to implement. Architecture 2 leaves the encryption to the application server. As an application developer I have no control over the configuration these features. That's bad because I want to ensure that the application cannot be used without proper encryption. Architecture 3 seems to be the best way but I have no experience with this technology.
How would you rate those three architectures? Did I miss an even better way to implement this? The main goal is to ensure secure encrypted communication, but the complexity of the resulting source code, performance issues and the like are of course a concern as well.
First of all, security solutions are not one-size-fits-all. You must evaluate threats(who would be interested in snoping/attacking), risks (what would you lose if an attacker succeeded) and cost of implementation and use.
Second, the security solutions usually are not exclusive. You could implement all 3 solutions at the same time (communication over VPN of RMI-SSL calls with encripted parameters). The issue would be cost of implementation and overhead.
Now to the question at hand:
1) I do not like it, because:
It allows someone snopping to know what metods are called, even if he does not know which data is passed.
As far as I know, MACs can be spoofed
You have to keep control of your servers now and in the future so the shared secret is not discovered. Maybe next month one of your servers is taken away to another location/branch/departament and more people starts having access to it. Or maybe they deploy your servers in another bussiness without changing the secret.
2 and 3) are more or less equivalent. With 2, though, you have to get sure that your servers only accept connections coming through the OpenVPN, and not from other NI. I do not know RMI over SSL well, but if it has not any hidden vulnerability it looks OK.
IMHO, I would go for 3 (standard, integrated in the server and more flexible). 2 is a good option too, easier to implement but requires you have a better control of the server. 1 is reinventing the wheel where there are already valid options, I would discard it.
Architecture 4: standard socket I/O over SSL.
I have developed a system using Digital Signatures
The program is written in Java
Provider = "BC"
SIGNATURE_ALGORITHM = "SHA256withRSA"
Keys
The Client holds the public key
The Server holds the private key
License Generation
Clients request a license from the server
Server decides if they should get a licenses
Creates a signed object and sends it back to the client
I am wondering about easy ways to hack a system like this and what I can do to prevent it.
How can I prevent a user from decompiling my code and inserting their own code? (I am aware of proguard but hear that it can be worked around). I am also a little worried about a user creating a false licensing server and somehow modifying the source code to point to their server (because I will be releasing the licensing and server code to the public).
When dealing with cryptography and security - if it's of any real importance to you - never use anything home-made.
Always use a proper library.
The margin for bugs and mistakes in this field are huge. Your applications security deserves better.
How can I prevent a user from decompiling my code and inserting their own code?
The short answer is that you can't. You can make it harder (e.g. obfuscation) but you simply cannot prevent it. The fact that most computer games are cracked within days of release is evidence of this.
Turning to the rest of your question: the design looks fine. It's hard to prevent a fake licensing server, but maybe it's not going to be a likely attack anyway. The attacker could just remove the license check from the client instead.
As #Yuval points out, rolling your own crypto is a Bad Idea, but you seem to be doing it the right way by using BouncyCastle. Just make sure you always "sign what you mean", that is sign the license itself rather than, say, encrypting the license and signing the encrypted version.
BouncyCastle's lightweight API provides tools for signing arbitrary blobs of data; I'd recommend you use that rather than Java's cumbersome "provider" interface.
You should also take care to ensure the physical security of the private key. If that gets compromised then you're in real trouble. It may be worth thinking about a mechanism for revoking compromised licences and replacing them with new ones.
What is the safest communication method between two applications on the same machine, both Java and C/C++ clients with a Java server.
Are SSL sockets safe enough or they can be broken by "man in the middle" attacks?
The main concern here is how the clients can trust the local server?
Would introducing a remote server improve the security of the local communication and how can this be achieved?
You need to elaborate your threat model. It's a general truism that anyone with physical access to your hardware, motivation and sufficient time will be able to subvert anything. This goes double if that attacker happens to be an admin on the server.
And yes, anything that is in your code is readable with admin access. You can try clever tricks like encrypting or obfuscating a password stored in binaries/JAR files, but this is a hindrance, not an absolute barrier.
Again, on the other side, there are no absolute barriers for confidentiality, merely more or less efficient obstructions. Whatever your measure, whatever the strength of your encryption and key management, with enough time and incentives, anything will yield. Which returns us to my first point: what is your threat model (what attacks do you wish to protect against); how much are your protected assets worth; and whom and what do you trust?
Safe from what? If an attacker has root, they can subvert system calls and spy on memory buffers before encryption and after decryption, and nothing you can do is safe.
If an attacker does not have root, they can't see this information even if you don't encrypt it.
So I don't see a point to this.
If your entire system, including it's secrets are running on the same machine, then unforutnately it is intrinsicly unsafe. A hacker can see all parts of the system, and with enough effort, can unravel any protection, or encryption scheme you put in place.
If the system must be 100% secure then part of the system needs to be remote, and so unavailable to a hacker to comprimise.
I'd have to say that memory-mapped files or shared memory regions are the safest method, which both Java and C++ (Win32, Unix) support for interprocess communication. It's more complex though as you have to deal with your own synchronisation. Bypass sockets completely.
A pipe should provide safe (and easy) communication. Yes, hackers would be able to retrieve a password if it is stored in a binary and the binary's permissions allow reading the file.
How can I retrieve the bytecode and make a hash to see if someone has manipulated my bytecode in-memory or on file?
EDIT:
Does signing the binaries protect the code from being modified and executed? As much as I want to protect my users from making sure they are running my software. I would also like to protect the program (server) from being used by a hacked client.
How do I detect from the server side if someone tampered with my client?
So you are trying to prevent some process with the same (or higher) privilege level than your application from manipulating your application?
That's a task that's doomed to fail. Because if you add your security checks, what would prevent the attacker from modifying your isSecure() method by replacing it with a simple return true;?
I think you need to clarify your requirements (at least I'm having trouble understanding what you are looking for).
In security-related areas, you always need to answer two questions, befor you can even start to tackle a problem:
What am I trying to protect?
What capabilities does an attacker have?
In your case, I believe you are trying to protect a Java client's class files from being modified. In that case the answer depends on what the (potential) attacker can do.
If the attacker actually has admin privileges on the machine the client is running on, then there is essentially nothing you can do. As saua above points out, if you cannot trust the the system you're running on, you're doomed.
If the attacker can only modify the class files before they reach the client maching, then signing your JAR files will let your clients detect the manipulation.
Maybe you want to sign your jar files instead?
What you want should be possible via Intrumentation, by adding custom Transformer. See http://java.sun.com/j2se/1.5.0/docs/api/java/lang/instrument/package-summary.html
Custom classloader also does the job, as it gets bytecode when class is defined.
How do i server side detect if someone tampered with my client?
You can not. On the internet nobody knows if you're a dog ;-)
Seriously: the only option server-side for making any assumptions about the client, is in the information sent back over the network. By encrypting the protocol and making it sufficiently hard to reverse-engineer, you can make it hard for an intruder to hack the client, but not impossible.
NGSCB (formerly known as Palladium) is designed to make this more secure, but this has its own set of issues.
You can create your own classloader and do the checking manually, or you can sign your code and let the java runtime do the job for you.
Signing the jars will protect the code from being modified. Signing involves creating a signature based on your private key. The public key is embedded in the jar with these signatures. Java will validate the signatures against your public key and refuse to load modified classes.
A hacked client will be a little harder to prevent. First an attacked would have to reverse engineer your protocol. You could take a step toward preventing this with a java obfuscator, but ultimately the attacker could just watch the wire and reverse engineer the protocol from the traffic. Even if you encrypt the client-server comms (this isn't exactly easy, considering using a protocol that already does it for you ... SSH or HTTPS) you will ultimately still be suceptible to a man-in-the-middle attack.
What exactly are you trying to protect against?
On the client, you can call getResourceAsStream with the path name to the class file in your jar.
That answers one part of your question ("How can i retrieve the bytecode"). Other answers cover the larger issues well.