I have a Java application running on Tomcat 6.0.29, with Apache 2.2.3 in front.
The login page uses HTTPS, while most pages use HTTP.
If a user tries to access a page (HTTP) that is login protected, he gets redirected to the login page (HTTPS), logs in, then gets redirected back to the originally requested page.
This works great, as the JSESSIONID cookie is set as non-secure, and used for both HTTP and HTTPS.
However, if the user starts at the login page (HTTPS), the JSESSIONID cookie is set as Secure, and thus the session is not available after login when redirecting to pages under HTTP, forcing a new session and redirect to login page again. This time it works though, because this time the JSESSIONID cookie is set as non-secure.
How can I avoid that users have to log in twice when they hit the login page first?
(Update: for clarity) Starting with the login Http get/post use https and use https through out the user's logged in session.
Use Http only when there is no logged in user.
There is a reason that cookies are not allow to cross protocol boundaries - it is an attack vector! (* see update below)
How to do this very bad idea
If you really insist, encode the jsessionId in the redirect to the http url ( or always encode the jsession id in the url). When Tomcat gets the http redirect, tomcat should find the session and continue.
Why you shouldn't do this
Seriously, any site that mixes https and http content on the same page is just opening themselves to all sorts of fun (and easy) attacks.
Going from https to keep the login "secure" is pointless if the rest of the session is in cleartext. So what that the username/password (probably just the password) is protected?
Using the ever-popular man-in-the-middle attack, the attacker just copies the session id and uses that to have fun. Since most sites don't expire sessions that stay active, the MIM effectively has full access as if they had the password.
If you think https is expensive in terms of performance look here, or just search. Easiest way to improve https performance to acceptable is to make sure the server is setting keep-alive on the connection.
update 1:
For more see Session Hijacking, or Http Cookie Theft
update 2:
See Firesheep Firefox plugin for how to do this quick and easy.
Related
I have an application that has both a backend and a frontend (in java). I need to have user authentication but I would prefer not to handle most of it myself. So I thought I could have users authenticate with their google accounts.
The backend part is mostly implemented, and it works fine from the browser:
I try to navigate to a URL of my server, and the browser is redirected to the google login page.
I login, and the browser is redirected back to my server, this time with auth info (some kind of token?) and I get a response.
But I'm having trouble figuring out how to set this up from a desktop app. I would like for the app to have a login button that when pressed, opens the google login page in the system browser for the user to login. If the login is successful, the desktop client can use the info from their google account (e.g. the email address) to identify itself with my server.
It's the first time I'm working on something like this, so I don't know if I'm looking in the right place. My research online leads me to OAuth2.0, but that seems more like authorization than authentication.
I looked at google's OpenID guide and it directed me to using OAuth2 for installed applications, is that the right solution for my use case? Or is that for applications that only have a frontend and all data is kept in the desktop app?
I am not completely sure whether it is secure, and whether it aligns with best practices, but I found a solution. I used the idea of the loopback redirect uri in my own way.
I start an http listener on the desktop app on a random available port, let's say it's port 54321.
I want to contact a url to my server. In that url I add the loopback port as a query argument. So the url would be something like https://myserver.org:8443/signin?loopback_port=54321
I start the system browser with this url. The server requires authentication, so the browser is redirected to google to login and provide authorization for the application to access my google account data.
Once the login in google is done, the browser is redirected back to the url of my server that it was first trying to reach. Now since the authentication is done, the request goes through.
I updated the /signin endpoint on my server to return redirects to /signin2 (again with the loopback_port param). The redirect from /signin will set the JSESSIONID in a cookie in the browser, and when we get the request in /signin2, we can read that JSESSIONID.
When we get the request in /signin2, we use the loopback port and the jsessionid to build a redirect url to the http listener on the desktop app. The jsessionid will be included as a query argument. So the browser is redirected to http://localhost:54321/?JSESSIONID=....
The http listener on the desktop app parses the request to get the JSESSIONID from the cookie, and it can use that in subsequent requests it sends to the server. Having this cookie, the server associates the desktop app's request with the authentication done earlier.
I have a web application which requires username and password authentication to enter.
What I am doing is, authenticate a user from a stand alone Java app, which would do so by making Http request to the server using username and password. Then I would retrieve JSESSIONID cookie from response of server.
Now what I want is to use this JSESSIONID to continue session on browser i.e. to let user navigate pages of my web app which would be opened by my stand alone java app which I use for authentication.
Is this possible? Or is there any other way to do so.
Cookie can be changed using below mentioned methods.
Cookie cookie = new Cookie("JSESSIONID", NEWSESSIONID);
response.addCookie(cookie);
From your application you can send JSESSIONID as parameter while opening browser first time and reset your cookie using above method either in filter or servlet. This will reset your cookie in client side once you send response back. Next request on wards you will be able to access the session created previously.
It's possible but it's not that simple.
Since web applications don't share sessions, what you're looking for is a Single Sign On (SSO) solution, which involves an "Identity Provider" (IdM) that authenticates users for one or more "Service Providers" (SP). In this case, your servlet is the IdM and your web app is an SP.
Depending on your deployment, the following are third-party, open-source SSO libraries that you may be able to use:
Kerberos
PicketLink (for JBOSS)
OpenAM (for Tomcat)
If you don't want to use a third-party library, you may also be able to modify your servlet to be the IdM. Either way, I suggest reading a little about Security Assertion Markup Language (SAML) before deciding on a solution. SAML is a popular method that the above libraries implement.
I have a simple webapp on Tomcat with form authentication, and notice that there is a "pre-login" JSESSIONID that's being set whenever a user just goes to the login page, before any login attempt even occurs.
Is this default behavior in Tomcat? Why does Tomcat generate a JSESSIONID just for loading a login page? Shouldn't it generate any session id's only after an actual login? (Not because someone just loads the login page!)
Note: I should mention that my entire webapp (login page and all) is hosted over https; no part of it is exposed via http. Also I am not using JSP. After login, Tomcat generates a second JSESSIONID, different from the first. And that's the one the user uses for the remainder of their session.
But why does it set a "pre-login" JSESSIONID in the first place?
If you use Tomcat means of form auth, it has to store the initial request somewhere to perform the stateless redirect for the auth. After that, it will re-evaluate the request. The SavedRequest is saved in the session. You should disable the changeSessionIdOnAuthentication flag.
I'm looking for a plain English, "for dummies" explanation of how does JSESSIONID work from security aspects
Can someone who merely knows my current JSESSIONID impersonate / hijack my session?
In what scenarios JSESSIONID will be part of the URL, and is this OWASP #2 security risk (scenario #1) still relevant for latest versions of Tomcat / Glassfish, and if so, what to "turn off/on" to prevent it?
Q: Can someone who merely knows my current JSESSIONID impersonate / hijack my session?
A: Yes.
That's why it is important that your site is careful with cookies. Indeed, if you are worried about packet sniffing, this means that you should only send the session cookie when the request was made over an HTTPS connection1. And setting the 'httpOnly' flag helps things by stopping client-side javascript, etc from using the cookie.
Q: In what scenarios JSESSIONID will be part of the URL
A: Typically, this happens when the webserver (at the container level) puts the session token into the URL:
as a workaround for the user's browser not setting cookies, or
to make the URL "suitable" for bookmarking or sending to someone else via an email.
Obviously, this is insecure and "bad practice" ... though a short session timeout does tend to mitigate this. (Alternatively, it is OK over HTTPS ... provided that the user doesn't share the URL with other people1.)
For Tomcat 6.x, I believe that the way to prevent the container from (ever) adding the session id to the URL is to add the disableURLRewriting="false" attribute to the context.
For Tomcat 7:
Context.disableURLRewriting: This has been removed. An equivalent effect can be obtained by configuring the session-config/tracking-mode elements in a web application or in the global CATALINA_BASE/conf/web.xml file.
1 - This assumes that you have patched (etc) your webserver to address the known SSL end-point vulnerabilities. If not, your HTTPS connections may be insecure.
I need to implement Sign Sign Out in Java using Spring Security. What CAS needs from my application is to access
https://www.home.com/cas/logout.cfm?service=myService&redirect=http://encoded.url.of.my.site
I put this URL to LogoutFilter's constructor parameter (as logoutSuccessUrl), so when I click logout URL on my site, Spring Security clears the session and redirects me to that URL, which is over HTTPS. It does what is supposed to do and the tries to redirect me back to my website's welcome address. However, this address is on HTTP protocol, not on HTTPS. So either because of sending some info in parameters when accessing that secure page, or because of redirecting back to non-secure, Firefox gives me a message:
Although this page is encrypted, the
information you have entered is to be
sent over an unencrypted connection
and could easily be read by a third
party.
OK, this is clear, but... How does logging using SSO work then? It essentially does the same thing. My website redirects to SSO's login page over https, which on success redirects back to my site, which is over plain http. How can I get rid of that message?
OK, after some research I got the answer. Firefox throws this message only if there is some post data in the redirect, which occurs from HTTPS to HTTP. This message can't be disabled, there is a corresponding comment in Firefox'es source code. The data that is posted (in form of XML) should allow to invalidate session. This also gives CAS an ability to invalidate session without any action from the user of the application (CAS posts data to that URL and application invalidates user's session).
Logging in didn't throw any messages because it was a simple redirect, without any data.