Secure connection between client and server - java

I'm developing a server component that will serve requests for a embedded client, which is also under my control.
Right now everything is beta and the security works like this:
client sends username / password over https.
server returns access token.
client makes further requests over http with the access token in a custom header.
This is fine for a demo, but it has some problems that need to be fixed before releasing it:
Anyone can copy a login request, re-send it and get an access token back. As some users replied this is not an issue since it goes over https. My mistake.
Anyone can listen and get an access key just by inspecting the request headers.
I can think of a symmetric key encryption, with a timestamp so I can reject duplicate requests, but I was wondering if there are some well known good practices for this scenario (that seems a pretty common).
Thanks a lot for the insight.
PS: I'm using Java for the server and the client is coded in C++, just in case.

I don't get the first part, If the login request is https, how can anyone just copy it?
Regarding the second part, t This is a pretty standard session hijacking scenario. See this question. Of course you don't have the built-in browser options here, but the basic idea is the same - either send the token only over a secure connection when it matters, or in some way associate the token with the sending device.
In a browser, basically all you have is IP address (which isn't very good), but in your case you may be able to express something specific about your device that you validate against the request to ensure the same token isn't being used from somewhere else.
Edit: You could just be lucky here and be able to rule out the IP address changing behind proxies, and actually use it for this purpose.
But at the end of the day, it is much more secure to use https from a well-known and reviewed library rather than trying to roll your own here. I realize that https is an overhead, but rolling your own has big risks around missing obvious things that an attacker can exploit.

First question, just to get it out there: if you're concerned enough about nefarious client-impersonator accesses, why not carry out the entire conversation over HTTPS? Is the minimal performance hit significant enough for this application that it's not worth the added layer of security?
Second, how can someone replay the login request? If I'm not mistaken, that's taking place over HTTPS; if the connection is set up correctly, HTTPS prevents replay attacks using one-time nonces (see here).

One of the common recommendations is - use https
https man in the middle attack aside using https for the entire session should be reliable enough. You do not even need to worry about access tokens - https takes care of this for you.
Using http for further requests seems to introduce some vulnerabilities. Now anybody with a network sniffer can intercept your traffic steal the token and spoof your requests. you can build protection to prevent it - token encryption, use once tokens, etc. but in doing so you will be re-creating https.
Going back to the https man in the middle attack - it is based on somebody's ability to insert himself between your server and your client and funnel your requests through their code. It is all doable i.e. in case the attacker has access to the physical network. The problem such attacker will face is that he will not be able to give you a proper digital certificat - he does not have the private key you used to sign it. When https is accessed through a browser, the browser gives you a warning but still can let you through to the page.
In your case it is your client who will communicate with the server. And you can make sure that all proper validations of the certificate are in place. If you do that you should be fine
Edit
Seconding Yishai - yes some overhead is involved, primarily CPU, but if this additional overhead pushes your server over board, you have bigger problems with your app

Related

Securing every request of a session by challenge/response?

We need to design a secure web application. I would like to propose a session handling mechanism which does a challenge-response on every request, not only during login using a CRAM method.
The reason is to harden the web application against session hijacking (eg by CSRF) and replay or man-in-the-middle attacks.
Using a nonce is suggested in some places, but in our webapp it seems impractical, as asynchronous requests can go on, or the user could open new windows, hit the back button etc.
Idea: The client and the server have a shared secret (a previously established user password), every subsequent request does again a challenge/response based on that secret, e.g 'response = hash(challenge + hashedPassword)'. The server executes the request only if the response to the challenge matches. Much like during CRAM, but ongoing for every request.
The question: Is this a feasible idea? If so, it surely has been implemented or is even some standard? How would we use this in a java or php based webapp?
The question really comes down to what you want to achieve. If you want to fight CSRF-Attacks, a secret token in addition to the session key is your way to go. However, changing the token in every request will cause problems - not only will the back-button kill the session, but as one webpage usually contains a lot of asynchronously and parallel loaded data (images, css, javascript, etc.), your approach will not enable any additional data to be loaded afterwards, as each additional request will change the required token, thus killing the session.
You may get around this by embedding all resources into the page via BASE64 and other tricks, but that will seriously hinder your possibilities and may have compatibility issues with some browsers.
So, in the end, your approach will not add much security, but will most likely create a whole set of potential problems for your customers. I'd stick to one secret token per session in the URL to fight CSRF and concentrate on securing against other attacks like XSS and user-friendly security measures like two-factor authentication with a smartphone or something similar. After all, the user is the #1 attack vector nowadays.
Update (2012-06-14)
The token will not fight XSS-attacks, but it will defend against basic CSRF-attacks (e.g. by implanting a bogus url call in an image). I've actually had a situation at work today, where I needed to secure a get-request against user modification and worked up some code. The code may be also usable to secure static, session-timeout form- and link-tokens (right your problem).
The idea is to have a server-secret, which is used to generate a hash/AuthToken over data to secure. If a rogue javascript would try to change any of the given data, the AuthToken would not match. In my specific problem, I have one server authenticating a user and have to send his information over to a third party (username, mailaddress, name, etc.). This GET-Request might be easily changed by any user after authentication, so I have to authenticate the GET-Request-Parameters. By rerunning the AuthenticationToken-Process, the third party can compare the resulting AuthTokens, thus validating the incoming data. Without the shared secret, it is (near-to) impossible to forge the data.
On your problem: Having a static token on GET and POST-requests (or a dynamic one like the project of mine) will protect you against simple CSRF-attacks via e.g. links in forums, which a user has to click to get attacked. As the link will never contain the correct token, your webpage is secure. However, if an attacker manages to load a javascript into the webpage via XSS, you're screwed and no technique in the world will help against it, as the javascript can scan the whole DOM-tree of the page to find an capture any tokens whatsoever.
So, it comes down to this:
use tokens on GET and POST-requests to fight CSRF
secure your page against XSS-injections
I find the OWASP cheat sheets are a good resource for such design decisions:
CSRF Prevention Cheat Sheet
XSS Prevention Cheat Sheet
Your scheme sounds similar to the HTTP digest authentication without establishing any kind of session post authentication. Which is probably an improvement over HTTP Basic. And that is assuming both are over TLS!
I am not sure how feasible your scheme might be or how vulnerable to replay attacks or MITM it might be.
If it is an option you might consider the new <keygen> html5 tag which can help establish a two way TLS session. This would be the most secure option..

How to secure a REST web service in Java EE 6

I have made a web application using Java EE 6 (using reference implementations) and I want to expose it as a REST web service.
The background is that I want to be able to retrieve data from the web application to a iOS app I made. The question is how would I secure the application? I only want my application to use the web service. Is that possible and how would I do this? I only need to know what I should search for and read and not the actual code.
Unfortunately, your webservice will never be completely secure but here are few of the basic things you can do:
Use SSL
Wrap all your (app) outbound payloads in POST requests. This will prevent casual snooping to find out how your webservice works (in order to reverse engineer the protocol).
Somehow validate your app's users. Ideally this will involve OAUTH for example using Google credentials, but you get the idea.
Now I'm going to point out why this won't be completely secure:
If someone gets a hold of your app and reverse engineers it, everything you just did is out the window. The only thing that will hold is your user validation.
Embedding a client certificate (as other people have pointed out) does nothing to help you in this scenario. If I just reverse enginneered your app, I also have your client certificate.
What can you do?
Validate the accounts on your backend and monitor them for anomalous usage.
Of course this all goes out the window when someone comes along, reverse engineers your app, builds another one to mimic it, and you wouldn't (generally) know any better. These are all just points to keep in mind.
Edit: Also, if it wasn't already obvious, use POST (or GET) requests for all app queries (to your server). This, combined with the SSL should thwart your casual snoopers.
Edit2: Seems as if I'm wrong re: POST being more secure than GET. This answer was quite useful in pointing that out. So I suppose you can use GET or POST interchangeably here.
Depends on how secure you want to make it.
If you don't really care, just embed a secret word in your application and include in all the requests.
If you care a little more do the above and only expose the service via https.
If you want it to be secure, issue a client certificate to your app and require a
valid client certificate to be present when the service is accessed.
my suggestions are:
use https instead of http. there are free ssl certificate avaliable,
get one and install.
use a complex path such as 4324234AA_fdfsaf/ as the root end point.
due to the nature of http protocol, the path part is encrypted in the https request. therefore it's very safe. there are ways to decrypt the request through man-in-the-middle attack but it requires full control over the client device including install an ilegal ssl certificate. but, i'd spend more time on my app to make it successful.
Create a rule on the machine which hosts your Web Service to only allow your application to access it through some port. In Amazon EC2, this is done creating a rule in the instance Security Group.
We have used RestEasy as a part to securing our exposed RESTful webservices. There should be lot of example out there but here is the one which might get you started.
http://howtodoinjava.com/2013/06/26/jax-rs-resteasy-basic-authentication-and-authorization-tutorial/
You can also use OAUTH:
http://oltu.apache.org/index.html

The danger of disabling certificate validation in Java

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

Security matter: are parameters in url secure?

I have developed myself in the last few months about web development in java (servlets and jsp). I am developing a web server, which is mainly serving for an application. Actually it is running on google app engine. My concern is, although I am using SSL connections, sending parameters in the URL (e.g. https://www.xyz.com/server?password=1234&username=uname) may not be secure. Should I use another way or is it really secure? I don't know if this url is delivered as plaint text as whole (with the parameters)?
Any help would be appreciated!
Everything is encrypted, including the URL and its parameters. You might still avoid them because they might be stored in server-side logs and in the browser history, though.
Your problem seems to go further than Web Server and Google App Engine.
Sending a password through a web form to your server is a very common security issue. See this SO threads:
Is either GET or POST more secure than the other? (meaningly, POST will simply not display the parameter in the URL so this is not enough)
Are https URLs encrypted? (describes something similar to what you intend to do)
The complete HTTP request including the request line is encrypted inside SSL.
Example http request for the above URL which will all be contained within the SSL tunnel:
GET /server?password=1234&username=uname HTTP/1.1
Host: www.xyz.com
...
It is possible though that your application will log the requested URL, as this contains the users password this may not be OK.
Well, apart from the issues to do with logging and visibility of URLs (i.e., what happens before and after the secure communication) both GET and POST are equally secure; there is very little information that is exchanged before the encrypted channel is established, not even the first line of the HTTP protocol. But that doesn't mean you should use GET for this.
The issue is that logging in is changing the state of the server and should not be repeated without the user getting properly notified that this is happening (to prevent surprises with Javascript). The state that is being changed is of the user session information on the server, because what logging in does is associate a verified identity with that session. Because it is a (significant) change of state, the operation should not be done by GET; while you could do it by PUT technically, POST is better because of the non-idempotency assumptions associated with it (which in turn encourages browsers to pop up a warning dialog).

Authorized Flash Client to Java Server connection

I'm building a Flash-based Facebook game with a Java backend, and I'm planning to use a RESTful approach to connect the two of them (not a persistent socket connection). I'm using the AS3 library to connect the client to Facebook, so that's where I have my session information stored. However, how do I authorize client connections back to the server? I can't leave the callback URLs open since that'd let people manipulate game state without playing the game. I need to make sure that the calls are coming from a valid client and through a valid session.
At the moment, users have no direct login to the backend server -- it's all handled through the client frontend. Can I pass the Facebook OAuth2 access token to the backend in a way that the backend can verify its validity? Should that be enough to trust a valid frontend connection?
I could do a two legged OAuth signed request or just use a simple shared secret, but the keys would have to be packed in with the flash client, which makes that almost useless for this use case.
Somebody has to have solved this problem, but I can't find it.
If you are using Java as a backend, I would consider using BlazeDS. It is a great library for doing AMF connections (which are async so fit your non-persistent socket requirement). If you are using Spring on the backend at all, I'd highly recommend using Spring-Flex as well. It adds a bunch of goodies that make exposing AMF services a breeze. Also, it adds hooks to allow 'easy' integration of Spring Security.
For the oAuth stuff, I would move the oAuth portion to the web side instead of the flash client (which I think I understand is what you do now). This way you can authenticate the web session on the server side and secure the page that contains the .swf. Then when your user loads the .swf in your code (assuming you're using spring security integrated into BlazeDS) you can call cs.authenticated on your cs:mx.messaging.ChannelSet. This will work, but may be more reword than you want to do.
We had similar problem in one of our project. What we ended up doing was used the following token passing method:
1) Fresh client connects to the server and get a token that's valid for x amount of time.
2) The client has an obfuscated part of code that uses an algorithm to change the token (and this algorithm changes at some frequency in sync with the server). The client uses the algorithm to change the token and includes it in the next request to the server.
3) The server knows the original token and the algorithm so now it can check to see if the new token in valid and it's from a valid client.
4) The cycle continues.
This is no 100% secure, since someone can really spend time and analyze the communication and eventually understand the pattern, but you can play around with the algorithm so much and change it often enough to make it hard for someone to guess it.
Hope this helps.
P.S. The application that I'm talking about that uses this has been in production for past 5 years and gets ~300k unique users a day and no one has broken in yet.

Categories