I'm writing on a Java EE project which will have everything from 3-6 different clients. The project is open source, and I wonder what security mechanisms one could/should use. The problem is: Because it is open source, I would believe that it is possible for anyone with a user to write their own client (maybe not realistic, but truly possible) and make contact with the server/database. I've tried to go through all the scenarios of reading/writing different data to the database as different roles, and I conclude with that I have to have some security mechanism on a higher level than that (it is not enough to check if that account type is allowed to persist that entity with that ID and so on...). In some way I have to know that the client making contact is the correct client I wrote. Could signing the Jar files solve this entire problem, or is there other ways to do it?
-Yngve
I really think that if restricting the available activities on the server side (based on role) is not sufficient, than you've got a bigger problem. Even if a user doesn't write their own client, whatever mechanism you are using for your remote calls is likely to be vulnerable to being intercepted and manipulated. The bottom line is that you should limit the possible calls that can be made against the server, and should treat each call to the server as potentially malicious.
Can you think of an example scenario in which there's a server action that a particular authenticated user would be allowed to take that would be fine if they're using your client but dangerous if they're not using your client? If so I'd argue that you're relying too strongly on your client.
However, rather than just criticize I'd like to try to also offer some actual answers to your question as well. I don't think signing your jar file will be sufficient if you're imagining a malicious user; in general, public-key cryptography may not help you much since the hypothetical malicious user who is reverse-engineering your source will have access to your public key and so can spoof whatever authentication you build in.
Ultimately there has to be someone in the system you trust, and so you have to figure out who that is and base your security around them. For example, let's imagine that there may be many users at a particular company who you don't necessarily trust, and one admin who oversees them, who you do trust. In that scenario you could set up your client so that the admin has to enter a special code at startup, and have that code be kept in memory and passed along with any request. This way, even if the user reverse-engineers your code they won't have the admin code. Of course, the calls from your client to your server will still be vulnerable to being intercepted and manipulated (not to mention that this requirement would be a royal pain in the neck to your users).
Bottom line: if your user's machine is calling your server, than your user is calling your server. Don't trust your user. Limit what they can do, no matter what client they're using.
Well the source may be available for anyone, but the configuration of the deployment and the database certainly isn't. When you deploy the application you can add users with roles. The easiest thing to do is to persist them in a database. Of course the contents of the table will only be accessible to the database administrator. The database administrator will configure the application so that it can access the required tables. When a user tries to log in, he/she must supply a username and password. The application will read the table to authenticate/authorize the user.
This type of security is the most common one. To be really secure you must pass the credentials over a secure path (HTTPS). For a greater degree of security you can use HTTPS client authentication. You do this by generating a public key for every client and signing this with the private key of the server. Then the client needs to send this signed key with every request.
EDIT: A user being able to write his/her own client doesn't make the application less secure. He/she will still not be able to access the application, if it is required to log in first. If the log in is successful, then a session (cookie) will be created and it would be passed with every request. Have a look at Spring security. It does have a rather steep learning curve, but if you do it once, then you can add security in any application at a number of minutes.
Related
I'm trying to build a soap service based on JAX-WS (using JBoss AS 7.1.1) and I need to implement security as well. The data is going to be sensitive, so it will be over HTTPS. However, I need to identify the client, and make sure that only they can perform operations for their organization.
From the looks of it, all I have seen on the JBoss documentation (and other JAX-WS providers documentation) indicates that multiple .xml files need to be edited (some at the app server layer).
I'm really looking for a way that I could just have a class in my service called with the SOAP headers, and I could perform the validation/authentication/authorization there. Would really appreciate someone being able to point me in the right direction.
You can always send authentication data explicitly along with the request (user and password, for example, in addition to the normal arguments). You have to make sure that the connection is encrypted.
You can refine this by using public/private keys: So first the server sends its public key, the client encrypts the user/password with that public key, and the server can decrypt it using its private key. As this might be too expensive on a request basis, the server could issue a token for a certain time which the client can send in the following requests (so a token is a means to establish a session).
That being said, and I know how cumbersome JBoss security setup is sometimes, you have to implement and test it very carefully, otherwise you might open some security holes (tokens may leak, sessions might be captured, token invalidation, SSL connection is terminated in web server, clear text passsword remains in RAM and is paged out on the disk etc.).
Currently I take part in developing a system based on Java EE (WebLogic server, to be more precise) and I am wondering how to protect some private data from administrators. For example, some parts of a system stores credentials for legacy systems in a deployment descriptors as plain text and this is bad because a deployer can read application configuration file (ejb-jar.xml, for example) and steal username and password for powerfull account. I want to close this security hole, but don't know how.
Now I am interested in protecting this kind of data:
Login
Password
Private key for symmetric encryption
From here I've discovered that I can use a JCEKS keystore to protect this type of information, but I can not understand how to use it. My application still should contain the kestore password and the key password to access it. So, a depoyer can steal passwords for keystores and keys, find my secure storage and steal credetials. Obviously, I can revoke read privileges from the deployer account, but then he can decompile my appliaction and develop his own similar app (or edit my one), that simply prints secure data to some file or send it by email... And now I am stuck...
Can anybody give me some links that can explain how to protect a system from administrators? Weblogic related links will be preferable. I totally understand that it is not possible to protect from all administrators and there should be some security administrator that will be responsible for keystore management and so forth, but I want to secure all sensitive data from everybody else.
RESULTS
Both jtahlborn's and slim's answers are correct, but slims's answer in more interesting. I think that in my case it will be appropriate to accept only signed applications for installation on the server. This decidion can solve problem with applicatoin modifications done by a administrator. Administrators will have password from keystore and all keys, but they will not have access to keystore file at all. Access to keystore file will have only special security administrators ('rw') and server ('r'). So, everybody will have the key, but nobody (except security administrators) will have access to the box.
There is no solution to this problem unless you enter login credentials at application startup (assuming the admin cannot access the application memory, which may not be a safe assumption). any solution which involves the keys sitting in the same place as the application will result in an administrator (with application filesystem access) being able to access any sensitive data accessible by the application. this is similar to the DRM problem (you can't give someone a locked box and the keys and expect that they can't open the box).
I think the meat of this question is in the definition of "admin".
You've said that you're comfortable with a "security admin" who does have access to key stores.
Traditionally, UNIX types think of "admin" as being the "root" user - someone with access to everything on the machine. Root can do literally anything, right down to peeking and poking at application memory, or reading/writing to raw disk addresses. If the server can get a private key, so can root.
If you want to define an "admin" role with more limited access, then yes, you could set up something where such users existed. They would need to have fewer privileges than the server application itself, since there is at least one thing the app can do (get a private key) that the "admin" cannot.
Such a user probably wouldn't be able to install the app either (since, if they could, they could create and install a version of the app which exposes the private key). Your "admin" couldn't therefore deploy the component that works with the private key. They could, however, potentially deploy a module that runs within that container (as long as the container cannot supply the private key to the module).
However, it's not just the key you want to protect. The real "secret" is the data encrypted using the key. So we still have a problem with the approach above. If the module can read the encrypted data, then so can an "admin" with the same privileges as the module. And that includes anyone who can install the module.
You could investigate ways to sign the module, so that an "admin" could not create their own version.
There comes a point, though, where the measures required to enable untrustworthy admins, become more expensive (in terms of time and effort) than simply using trustworthy admins.
So, you need to make a list of things your so called "admin" can do. Depending on what those things are, it may well be possible to allow a non-root user to do those things. On UNIX, you might use a tool like sudo to allow a non-root user to do things like start/stop the server, read logs, clean logs, etc.
It might be possible to separate the authentication from the rest of the application.
For example, if you communicate with the legacy systems via a TLS-secured socket, you could write a small separate application that accepts unencrypted connections from the application, then makes a secure, authenticated, connection to the legacy system, and pumps data between the application and the legacy system. Essentially, it's an authenticating proxy. Then, the application wouldn't need these keys. You could install and operate the application as a user who didn't have permission to read the files containing the key, but the application could still communicate with the legacy systems.
Of course, now you have the problem of how to authenticate the application to the proxy. You might feel that the machine is secure enough that you don't need to do that at all - as long as the proxy only listens on the loopback interface. If not, if you could use a unix domain socket instead, then you could control access using filesystem permissions: you could run the application as some user in some particular group, then restrict access to the socket to members of that group. Java doesn't have unix domain socket support in the standard library, but you can add it with junixsocket or JUDS.
I am making app, which would send value to php script. Then php script would conncect to Mysql database and return JSON array. And then the app would read it. How to ensure safety? For now I am not using any safety measures.
It depends, this is such a huge topic that a true answer would take a books worth of material.
What 'safety measures' are you asking about?
If you're talking about involving a web server, then you first need to secure your web server and build an API that is smart enough to protect against most common methods of attack. You need to make sure that other people - just by entering something in URL - cannot do the same thing your intended user can do. This means that you need to validate the user before giving them access to API.
Most common method of doing this is sharing a 'secret key' that only the server and client knows. So your user, with a phone, has a specific key and server has a key. Now user sends data to the server and also sends a validation hash (like sha1(KEY+DATA)). Server then receives data and makes sure that the hash is the same. Never send the key itself together with the request.
Another thing you need to test for are replay attacks. If someone listens in on the communication, then you have to limit the damage. This is usually done by you also sending a timestamp with the request and the server checking if the timestamp is within accepted range, so if someone sends that same request again later, it would fail due to timestamp being different. Server checks for this since timestamp is also taken into account for input data validation.
Then you have to make sure that the data returned from server is correct. So server will ALSO build a validation hash that your phone will check, making sure that someone didn't change the data while it was sent back to your phone.
As an added layer, you can also encrypt data that is sent (and received from API) with a heavy cryptography algorithm like AES/Rijndael 256bit encryption. This will encrypt data with a key that is required to open the data. If phone and server know the key and no one else does, then data can be sent securely.
Then the connection should be HTTPS/SSL, which helps protect communication from being listened in. But this does not help if someone already has access to your phone, so it is recommended to use the other mentioned methods as well.
As for your phone, it is pretty secure by itself as long as you don't have apps installed on it that might compromise that security. Also, if you think you can secure your web server less, thinking that since only phones communicate with it that it is safe, then a hacker can easily listen in on communication on their own phone and figure out the basics of your web service API and then open all the doors. So make sure your security layers go from biggest to smallest: web server is by far the biggest entity in your system.
As you can see, this is a MASSIVE topic that can take a long time to learn. But without knowing what exactly you were asking about, I cannot really help you any further.
This question may seem like a novice, and perhaps 'stupid' question but please bear with me...
I'm still struggling to find a way to get my Java application to use a keystore located inside the JAR file, and I'm very tempted just to disable certificate validation all together using the method here. However, before I do so, I just wanted to confirm why you should not do this and whether those reasons actually apply to me.
I've heard that no certificate validation can make your application liable to "Man In The Middle" attacks (I think), but even if I am correct, I am unsure as to what these actually are so please could somebody explain. Though, if they are what I think they could be, I'm not sure whether my application ever be subject to them because, my application only uses an SSL connection to obtain data from my website, so users do not tell the application which URLs to visit - if that makes sense...
Here's, an attack scenario. Other's might want to contribute some more.
Your application accesses a URL. At some point along the way (any intermediate network hop), an attacker could position himself as a "man-in-the-middle", that is, he would pretend to be a "proxy" for your communication, being able to read everything that goes through, and even modifying it on the way: the attacker could act on behalf of the user, mislead him as to what information he gets, and basically access al data being transferred.
Enter SSL: your client receives a certificate from the server, with a valid key (Signed by a known certification authority, or present in your keystore). The server will then sign and encrypt all it sends using that key. If an attacker where to place himself in the middle, he would not be able to read the data (it's encrypted) or modify it (it's signed, and modification would break the signature). He could still block communications altogether, but that's another story.
So that's that... if you ignore your keystore, you can't verify any server side certificate, and you open the door to man-in-the-middle attacks.
Though, if they are what I think they could be, I'm not sure whether
my application ever be subject to them because, my application only
uses an SSL connection to obtain data from my website, so users do not
tell the application which URLs to visit - if that makes sense...
If you connect to a server via SSL and you don't do any authentication, effectively you are have no security.
You have no idea who is the endpoint you are talking to.
The fact that the user does not type in a URL, but the URL is a hardcoded URL to your site is irrelevant. A simple proxy that forwards the data from your client to the server can steal all your client's data since there is no kind of authentication (this is the Man in the Middle Attack).
I would suggest you put the code you are using to load the keystore so that you get help on that.
Otherwise, if you don't have any requirements on security and you don't have any sensitive data you should go for plain connection (i.e. non-SSL) so that your performance does not deteriorate due to the unecessary (in your case) SSL overhead
My program needs to download object definitions (basically xml files, maybe binary files) on demand via the net. The program will request objects from my server during runtime. The only thing the program has to send the server is a string that identifies the object it needs (e.g. RedCubeIn3DSpace23). So a basic Key, Value system. My app also has to have some basic authentication mechanism to make sure only legitimate programs access my server’s info. Maybe send the license number and a password.
What is the best way to go about implementing this? I have 0 web knowledge so I'm not sure exactly what technologies I need. I have implemented socket programs in college so maybe that is what I need? Are there frameworks for this type of thing? There could be thousands of users/clients simultaneously; maybe more but I don’t know.
One super important requirement is that I need security to be flawless on the server side. That is, I can't have some hacker replacing object definitions with malicious one that clients download. That would be disastrous.
My first thoughts:
-Set up an ftp server and have each xml file will be named by the key value. Program logs in with its product_id and fixed password and just does downloads. If I use a good ftp server, that is pretty impervious to a hacker modifying definitions. Drawback is that it's very non expandable nor flexible.
-RESTful type system. I just learned about this when searching stackoverflow. I can make categories of objects using URL but how do I do authentication and other actions. Might be hard to program but is this a better approach? Is there a prebuilt library for this?
-Sockets using Java/C#. Java/C# would protect me from overflow attacks and then it is just a matter of spawning a thread on each connection and setting up simple messaging protocol and file transfers.
-SOAP. Just learned about it while searching. Don't know much.
-EC2. I think it (and other?) cloud services add a db layer over it.
That's what I can come up with, what do you think given my requirements? I just need a little guidance.
HTTP seems a better fit than ftp, since you only want to download stuff. That is, you would set up a web server (e.g. Apache), configure it for whatever authentication scheme you need, and have it serve that content.
SOAP is clearly overkill for this, and using raw sockets would be reinventing the wheel (i.e. a web server).
I'd do security on the socket level, using HTTPS. That way, the client will verify the identity of the server prior when establishing the connection, and nobody can intercept the password sent to the server. Again, a decent webserver will support this out-of-the-box, you just need to configure it properly.