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.
Related
I've been struggling with a simple problem for hours now. I am working on a desktop application (a wallet) which needs a seed phrase to operate.
Naturally, the seed needs to be encrypted with a password and stored into a config file. I've found Jasypt which enables me to encrypt a String easily but apparently Jaspyt's PBEStringencryptor is supposed to be unsafe/deprecated. Since there's only one password, salting it wouldn't make any sense (would it?).
I've found many other methods on stackoverflock but I keep saying experts showing up and claiming how unsecure method x is.
To sum up my question: since I am only dealing with a single seed phrase, would using Jasypt's Stringencryptor be sufficient or should I use a different method?
The reason you are struggling to find a secure solution is probably that there is no secure solution that works in general.
Let me restate the problem that I think you are trying to solve:
Your application needs a "secret" to operate.
You cannot trust the user. (If you could, then you could in theory get the user to supply the secret each time they use the system.)
You cannot rely on operating system access control to keep the "secret" safe, because of one or more of the following:
the operating system is inadequate or buggy
you don't trust the operators / administrators
you can't be sure that the system hasn't been hacked, or
the system is not physically secured. (If someone can get undetected physical access to the hardware for long enough, they can circumvent OS security.)
Given the above assumptions, there is no secure solution. No matter what your application code does, it is possible for someone with sufficient OS-level privilege (assigned properly, or acquired nefariously) to watch what your code is doing and intercept the secret.
So what is the solution?
If you can assume that the platform is secure and the operators are trusted, there are technical ways to keep the secret secure ... from a non-privileged user.
There are mitigations for some kinds of security attacks. For example, you could use a Hardware Security Module to hold the secret so that it doesn't need to be stored in the file system.
Otherwise ... run the software on your (secure) infrastructure rather than the user's PC or your customer's servers.
seed needs to be encrypted with a password and stored into a config file..
Seems you are correct, the most reasonable way to encrypt the seed would be using some sort of password based encryption (PBE..).
Since there's only one password, salting it wouldn't make any sense (would it?).
you are storing the encrypted seed value itself, so in this case you may be ok with some application-wide static salt
PBEStringencryptor is supposed to be unsafe/deprecated.
would using Jasypt's Stringencryptor be sufficient
I am not aware of Jasyp being unsecure, it depends more on used parameters (any reference?). I usually use pure Java with standard PBKDF2 a few examples. However, Jasyp makes encryption done properly without deeper knowledge. The problem with cryptography is that it's easy to completely break security just using wrong set of parameters or using it wrong way. If you are just starting, using PBEStringencryptor may be safer option.
Someone mentioned using a hardware module (e. g. smartcard, TPM,.. ), could be safer, but less portable
I'am not an Java developer but as per described, what I would do in your case is to use asymmetric encryption of your seed with the desired password before storing it into a config file.
You could use Rivest Shamir Adleman (RSA), Elliptic Curve Cryptography (ECC) to name a few algorithms.
Cheers
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.
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.
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.