I have a web application which is accessible to users through proxy sevlet - part of bigger web application. Communication between browser and bigger application is encrypted by ssl. From my embedded application I would like to set a secure cookie which indicates users' session. Communication between proxy servlet and my web application is not encrypted, so when I set session id cookie it doesn't have secure flag. My application is running on tomcat and response from this tomcat is proxy'ied to client's browser by proxy servlet.
Will this cookie be secure and unable to hijacked by others, despite the fact that is not indicated as secure? Can browser send back cookie in not secured connection in that situation?
edit:
I will specify a little bit more architecture of that sollution to make it clear:
There are 2 web applications, each one has its own session:
1) one is accesible directly to users and communication between it and browser is encrypted by SSL. (application X)
2) second is not accesible to users, but is proxy'ied by servlet from application X (application Y) Servlet is also proxy'ing http headers.
Architecture looks like on this diagram:
client browser| <-SSL-> |Application X (proxy servlet) | <-internal network, no SSL -> |application Y
I would like to set cookie in client browser from application Y that indicates session. Cookie header is taken from application Y to X and set into the client's browser, but unfortunately this header doesn't have secure flag. I'm not sure wheter it will be send back by browser in secure connection or not.
This really isn't a good way to secure your web app because the most important area of communication (between the browser and however they get to your app) is not encrypted. That is the area most likely to be snooped on by others. Cookies are inherently insecure without SSL because without SSL there is no way to encrypt them. They're just part of the HTTP transaction (and thus are only as secure as the rest of it).
Sessions are pretty much inherently safe from tampering if the HTTP transactions happen over SSL because the cookie only contains a fairly unique ID code pointing to a storage compartment on the server for the user's information in the servlet container.The only way someone can hijack that is they can intercept the cookie and make their browser use that cookie. Again, SSL is your best bet there.
Now, you could use something like a nonce to add additional security on top of SSL. There are plenty of apps out there that use them if you want to look at live examples.
It seems like the user's web browser connects to your web proxy server remotely via HTTPS, and your web proxy server connects to your application locally via HTTP.
You may still be able to set the cookie as secure by manually setting the secure option for the cookie, or manually creating the cookie header. Generally, a web/application server ignores settings on outgoing cookies. Instead, it's generally up to the browser to enforce the rules.
It's important to send the cookie with the secure option to the browser, so the browser knows not to send the cookie back unless it's over HTTPS, thus preventing eavesdropping. You should also include the httponly option for the cookie.
Adding a nonce would not provide any additional protection here because if the victim can be convinced to send the request out unencrypted, the attacker will be able to capture both the cookie and the nonce.
This is not to say that nonce's aren't good on their own to prevent replay attacks, even over HTTPS, but it wont prevent session hijacking.
Related
I am trying to build a client / server servlet application with these general requisites:
both the client and the server are jetty embedded;
the server expose a servlet in order to receive json data via POST;
the connection must be secured via SSL (i.e. the connection will be done via Internet via https);
I want that only my Jetty client be able to send data to my server, all other tentative must be refused by the server;
the server and the client are unattended machines (i.e. not password via command line could be inserted by human);
no password in clear must be stored on the client device. In general I don't want someone could open the remote client device and stole the password and building a fake remote device capable to send data to my server too.
I have build a perfectly working client / server application via HTTP but I am confused about the security.
I have read that there is the possibility to use client / server mutual authentication and seems what I am looking for but I can't get the complete picture.
In this document client-certificate-authentication there is a more or less clear explanation about how to build a shared trusted CA but the password for accessing the TrustStore and the KeyStore are in clear in the code.
I think I am missing a tile in the puzzle.
Could someone point me in the right direction?
Thanks,
S.
I'm going with a simple answer (for now).
If you just want only your clients to talk to the server, then yes, Client SSL/TLS certificates are the way to go.
You'll want the server's SslContextFactory.Server.setNeedClientAuth(true) set to true. That will in turn cause Java's javax.net.ssl.SSLParameters.setNeedClientAuth(true) to be set on incoming connection establishment. If the client fails to provide the client certificate, the connection is closed, and no HTTP request is sent or processed.
As for securing the client certificate, that's up to you, you can do anything you want to do, as long as it results in a valid client SslContextFactory.Client that the Jetty client can access. This includes ...
Using plaintext passwords
Using obfuscated passwords (minimal effort, minimal security)
Encrypted keystore/truststore passwords elsewhere in your client, provided to the SslContextFactory.Client at the last minute. (modest security, wouldn't be that hard to figure out)
Creating the java.security.KeyStore object yourself and handing it to SslContextFactory.Client.setKeyStore(KeyStore) and SslContextFactory.Client.setTrustStore(KeyStore) methods prior to starting the Jetty Client. (a bit better security wise, puts more work on your behalf)
You might want to consider having the client certificates be short-lived (24 hours?) dynamically refreshed from the server, and have the client certificates be revokable (at the server/CA side) if you encounter abuse. (such as the same client certificate from multiple different client IPs)
I want to be able to accept both web browser clients and (automated) service clients to a single servlet running in my application. Some of the service clients will authenticate with TLS client certificates, but some will not. I do not want web browser clients to be prompted for a certificate ever, even if the user has some installed in their browser. The decision on whether to prompt for a client certificate is dynamic and based on policy according to the client, so cannot be statically configured in web.xml.
Is there a way to dynamically trigger TLS renegotiation to request a client certificate from within a servlet? If I had access to the raw SSLSocket then I could configure it to require a client certificate and then call startHandshake() to force renegotiation. As far as I can tell, there is no portable way to get hold of the SSLSocket associated with a servlet request/response though.
My application has to run in a variety of servlet containers, so I'd prefer to avoid container-specific solutions if possible. Ideally the solution would not involve a redirect, but I will accept that if it is the only way.
You wrote in comments above:
because that setting will cause a web browser to prompt the user to
choose a certificate if they have one installed that matches one of
the configured CAs. I never want that to happen for web browser
clients
Then I vote for this is impossible to achieve from server side. TLS takes first before any data sent through secure channel. You can't determine is it web browser or not knocking at your door not asking for client identity. From TLS point of view this is just yet another unnamed network client attempts to connect. After secure connection established, data is sent, and you can determine this is browser or not.
You may want to pipe browsers (1 way ssl) and server client (2 way ssl) through different endpoints.
Otherwise you may want to implement you own TLS protocol handshake procedure.
You may want to configure browsers not to answer to client certificate requests instead of configure server not to ask if (if it would be possible) to determine this is browser-based client. May be try to guess it through the cypher suit (list of supported crypto modes) but this is definitely not servlet level of interaction.
I am curious somebody know ho to solve you question.
In HTTPS (SSL) browser send the encrypted data which can be Decrypted by server only.
To confirm it, i did set up the burp proxy on my Firefox browser so that it intercepts the request sent to HTTPS server by browser .
When i receive it at burp, i see the data as entered by user though i was expecting browser must have encrypted that but did not.
So at what point of time browser encrypt data over HTTPS ?
Most pieces of software that do this (e.g. Anti-virus scanners) replace the https certificate with their own so the https traffic can be man-in-the-middled by the software.
While I'm not familiar with Burp, it looks like it does the same: https://portswigger.net/burp/help/proxy_using.html
So instead of
browser --(via https)--> server
Which only the server could read as only the server has the private key to decrypt the http so, it becomes:
browser --(via https)--> burp -- (via https)--> server
If you look at the https cert in your browser you'll probably notice it's been issued by Burp rather than being the real cert that the site shows when not using Burp.
This is the only real way of doing this, without majorly changing the browser to intercept it before the encryption happens, but can create its own problems: Should software really intercept traffic between you and your bank? What if that first connection can be compromised (see the Lenovo superfish incident for example). Many people (myself included) dislike MITM https services for this reason.
I've got backend running on the tomcat server and client running in the browser. Application is built on Spring 3 MVC + Spring security framework. How to secure the communication ? Is there other option than just to set the server to be accessed only via HTTPS ? I've got no experience with this so it might be a stupid question, but will this affect my application and do I have to set something up in my app, when the server shall communicate with client via GET/POST request via https ?
It depends somewhat what you mean by "secure." If you want privacy, you must use TLS (SSL) as a transport.
If you're only concerned with authentication, then you have another option: Digest Authentication.
Digest Authentication allows the client (browser, usually) and the server to exchange authentication credentials in a secure manner without securing the entire communication. If you use Digest Authentication, then third parties can still:
See what data the client and server exchange
Insert themselves between the client and server and alter the exchange
What third parties cannot do is spoof the authentication or steal username/passwords in transit.
If that's not secure enough, you need TLS. You do not necessarily have to purchase a certificate. You can use OpenSSL to generate your own. This certificate will not automatically be trusted by browsers, however, so you can't really use it for public sites.
You will need to consult your server documentation for how to set up HTTPS or Digest Authentication, depending on which fits your needs.
Your application should not be affected by switching from HTTP to HTTPS, Tomcat handles this or maybe an Apache in front. It's important to understand, that HTTPS is a server-thing, not an application topic, because the client makes a connection to the server (Tomcat), not to your application. Check out the Tomcat documentation, it's pretty clear about how things work.
And, like the others said: From what you've said it's best to use HTTPS (TLS/SSL). Certificates are a bit frightning at the beginning, but it's worth to invest the time.
HTTPS is the (S)ecure form of HTTP, since you have an HTTP client server application I would certainly used HTTPS. All you need is to create an SSL certicate for your website and restrict access to your website to HTTPS only, then you are 99.99% secure.
Your certicate can be either commercial from Versign or equivalent or some open source engine.
for the clients nothing needs to be done to support HTTPS
My objective is to set a cookie from within a servlet called from a java client, and get the cookie when a different servlet is called from the browser.
The java client has an authenticated session with the server.
The server runs locally.
I tried suggestions from a different question and rename put an alias domain name in my hosts file.
I manually set the domain of the cookie to the alias domain, but it still won't return on the server.
request.getRemoteHost() returns 127.0.0.1 in both servlets.
Any help would be appreciated.
A cookie is held in memory (or on disk, but at a specific place) by each client. A Java client and a browser don't share cookies. Two different browsers (IE and Firefox, for example) don't share cookies either. There is no way to do what you want.