I have a need to preserve session id after login. My session id cookie is marked as HttpOnly. Is such setup absolutely secure? Is there any possibility for an attacker to to perform session fixation attack if my session cookie is HttpOnly?
TLDR: Yes, in PHP and Firefox it is possible to add a second session cookie which, due to the order in the header, is preferred over the original one.
Also Yes, if there is other functionality which allows to set session IDs on the server. This depends on the application specific functionality.
Full explanation
Depends on what other functionality you have on your website to manipulate sessions. In some rare occasions, the application allows a user to set a session via a HTTP request. For example, via a GET parameter.
I believe you want to know if it is possible to fixate a session ID if the original session ID is set in a cookie with the HttpOnly flag. Therefore, I did a small test on a PHP application I was conducting a pentest on. Surprisingly, you can set a new PHPSESSID via a JavaScript injected as XSS. If there already was an existing PHPSESSID cookie with the HttpOnly flag, it simply puts this one next to the other one. In my case, in Firefox, it sent the following Cookies to the server after my attempt to set PHPSESSID via document.cookie = "PHPSESSID=FIXATEDSESSIONID":
Cookie: PHPSESSID=FIXATEDSESSIONID; __utma=139474299.465096418.1547461023.1548839033.1548851774.5; __utmz=139474299.1547461023.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); acceptCookies=true;
So there are now two session IDs in the request. In my setup, with PHP 5.6.25, the server takes the first cookie to bind a session. So in the case with Firefox and PHP 5.6.25, I was able to fixate my session ID (FIXATEDSESSIONID) via a JavaScript. The original session ID is still in the request but it is ignored by the server. Note that FIXATEDSESSIONID is literally the session ID I injected. So it was not necessary to get a legitimate session ID from the PHP server.
It's better to have session cookie as HttpOnly, because it obviously makes session more secure.
The right way to avoid session fixation vulnerability is to make new session for user on authentication.
Check OWASP article about session fixation. It has information about techniques to execute this kind of attack.
Related
So I'm implementing integration with API that uses OAuth 2, which state: Recommend to use httpOnly Cookies to store the tokens (access, refresh).
I've used sessions for long time and I was not sure if there is any difference between using httponly cookie or session
Any pros vs cons?
HttpOnly cookies serve same security as session cookies
Except the extra work involved with session cookies (storing and clearing data)
Oauth 2 recommends the usage of HttpOnly cookies, but I wasn't sure why!
Thanks in advance
Cookies and Sessions are used to store information. Cookies are only stored on the client-side machine, while sessions get stored on the client as well as a server. A session creates a file in a temporary directory on the server where registered session variables and their values are stored.
So...
The main difference between a session and a cookie is that session data is stored on the server, whereas cookies store data in the visitor's browser. Sessions are more secure than cookies as it is stored in server. Cookie can be turned off from browser.
Background: I have a javaee webapp deployed on tomcat which uses form based authentication. When the web server receives a login request, it sends the request to a dedicated authentication service which validates user login (User id and password). After successful authentication user's session is maintained in the web server.
Problem: I have written a simple webpp source code here, to simulate the scenario. On successful login the current HttpSession instance is invalidated and new instance is created. For each request for a post login page, the session is validated. A new JSESSIONID cookie is set which is used to identify the user during the session until session is expired or user logs out. This cookie can easily viewed in browser's dev tools. If I copy the cookie and set this in a different browser via JavaScript (document.cookie="JSESSIONID=xyzz") and then try to access a post login page, the server identifies it as a valid request and session is validated successfully. The post login page is served without user being challenged for user Id and password.
POC: User opens chrome and enter the URL http://localhost:8080/mywebapp/ and logs in with admin and pass1234. On successful log in the home page http://localhost:8080/mywebapp/home is shown. Now the JSESSIONID cookie is copied and set in FireFox. User enters http://localhost:8080/mywebapp/home in Firefox and is shown the home page without being challenged for userId and password.
Question: How can this be prevented wherein same session is getting replicated over multiple browsers?
You can't prevent this specific case of simply copying the cookie from your own browser (or by copying the cookie value from a HTTP payload copypaste/screenshot posted by an ignorant somewhere on the Internet). You can at most prevent the cookie getting hijacked by XSS or man-in-middle attacks.
This all is elaborated in Wikipedia page on the subject Session Hijacking of which I snipped away irrelevant parts (either already enforced by Servlet API, or are simply not applicable here).
Prevention
Methods to prevent session hijacking include:
Encryption of the data traffic passed between the parties by using SSL/TLS; in particular the session key (though ideally all traffic for the entire session[11]). This technique is widely relied-upon by web-based banks and other e-commerce services, because it completely prevents sniffing-style attacks. However, it could still be possible to perform some other kind of session hijack. In response, scientists from the Radboud University Nijmegen proposed in 2013 a way to prevent session hijacking by correlating the application session with the SSL/TLS credentials[12]
(snip, not relevant)
(snip, not relevant)
Some services make secondary checks against the identity of the user. For example, a web server could check with each request made that the IP address of the user matched the one last used during that session. This does not prevent attacks by somebody who shares the same IP address, however, and could be frustrating for users whose IP address is liable to change during a browsing session.
Alternatively, some services will change the value of the cookie with each and every request. This dramatically reduces the window in which an attacker can operate and makes it easy to identify whether an attack has taken place, but can cause other technical problems (for example, two legitimate, closely timed requests from the same client can lead to a token check error on the server).
(snip, not relevant)
In other words:
Use HTTPS instead of HTTP to prevent man-in-middle attacks.
Add a checkbox "Lock my IP" to login form and reject requests from different IP associated with same session in a servlet filter. This only works on users who know themselves they have a fixed IP.
Change session cookie on every request. Interesting at first sight, but breaks when user has same website open in multiple browser tabs/windows in same "session".
Not mentioned, but make sure you don't have a XSS hole anywhere, else it's very easy stealing cookies.
Last but not least, I'd like to make clear that this problem is absolutely not specifically related to Servlet API and the JSESSIONID cookie. All other stateful server side languages/frameworks such as PHP (PHPSESSID) and ASP (ASPSESSIONID) also expose exactly the same security problem. The JSESSIONID was previously (decade ago orso) only a bit more in news because by default it was possible to pass the session identifier along in the URL (which was done to support HTTP session in clients who have cookies disabled). Trouble started when ignorant endusers copypasted the full URL with JSESSIONID inside to share links with others. Since Servlet 3.0 you can turn off JSESSIONID in URLs by enforcing a cookie-only policy.
<session-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
See also:
How do servlets work? Instantiation, sessions, shared variables and multithreading
How to prevent adding jsessionid at the end of redirected url
remove jsessionid in url rewrite in spring mvc
What you have stated is called session hijacking. There are many good answers on how to prevent it.
Using same Jsession ID to login into other machine
we can use Encryption or hide JSESSIONID using Browser control.
Thanks
How does one implement maintaining sessions securely. Suppose just the login page uses SSL. So the user enters his usernamepassword and the http server verifies it is in the database and now what?
Does it set some cookie? If so then what should the cookie be set to so that security is maintained (encrypted, what kind of encryption)? Looking for a low level detailed answer. I hear there are various cookie hijacking concerns. If I only use SSL for the login but thereafter don't use SSL will the cookie be vulnerable?
Then after the browser is closed and the user comes back how does the cookie identify the username. How is this done securely without the cookie being stolen?
You definitely expose your clients to session theft if your connection is not encrypted at all times.
HTTP is a stateless protocol, so the only way to fake a stateful interaction is for client and server to send a session identifier with every transaction. If this isn't protected, it can trivially be stolen. Since the session identifier is the only authentication token during the open session, this is catastrophic.
The usual way to make a "remember me" feature would be to set a cookie whose lifetime is not limited to the browser's program lifetime (i.e. by setting an explicit expiration date), and storing some unique data in the cookie which you match against some remembering data (including the IP perhaps) in your database. But that does not absolve you from the need to encrypt all communication!
Whenever you authenticate, your application should change the session identifier it uses. This helps to prevent someone from setting up a session, copying the session identifier, and then tricking a user into using the session. Because the attacker already knows the session identifier, they can use it to access the session after the user logs in, giving them full access. This attack has been called "session fixation" among other things. How can i change the session id once the user login to the system ?
You're still on the server while you invalidate the session.
//get stuff out of session you want before invalidating it.
currentSession = request.getSession(true);
UserProfile userProfile = (UserProfile) currentSession.getAttribute("userProfile");
//now invalidate it
currentSession.invalidate();
//get new session and stuff the data back in
HttpSession newSession = request.getSession(true);
newSession.setAttribute("userProfile", userProfile);
Get the existing; invalidate it; create a new one ...
1) Get the current Session with HttpServletRequest.getSession();
2) Clear the Session: HttpSession.invalidate();
3) Create a new one: HttpServletRequest.getSession(true);
Talking generally (because this isn't a Java problem at all, it's a general web problem) session fixation arises when session IDs are easy to discover or guess. The main method of attack is when the session ID is in the URL of a page, for example http://example.com/index?sessionId=123. An attacker could setup capture a session and then embed the link in their page, tricking a user into visiting it and becoming part of their session. Then when the user authenticates the session is authenticated. The mitigation for this is to not use URL based session IDs, but instead use cookies
Some web applications will use a cookie session based but set it from the initial URL, for example visiting http://example.com/index?sessionId=123 would see the session id in the url and then create a session cookie from it, setting the id in the session cookie to 123. The mitigation for this is to generate random session ids on the server without using any user input as a seed into the generator.
There's also browser based exploits where a poorly coded browser will accept cookie creation for domains which are not the originating domain, but there's not much you can do about that. And Cross Site Scripting attacks where you can send a script command into the attacked site to set the session cookie, which can be mitigated by setting the session cookie to be HTTP_ONLY (although Safari does not honour this flag)
For Java the general recommendation is
session.invalidate();
session=request.getSession(true);
However at one point on JBoss this didn't work - so you need to check this works as expected within your chosen framework.
Invalidate the current session and the get a new session:
//invalidate the current session
request.getSession().invalidate();
/*
get another session and get the ID (getSession()) will create a session if one does not exist
*/
request.getSession().getId();
What's an elegant way in Classic ASP to check if session cookies are enabled in a user's browser using server side code (because javascript might be disabled as well).
I have a solution of my own but it looks ugly as hell.
#James - that doesn't differentiate between setting a session cookie and a general purpose cookie though (IE lets you differentiate between First Party, Session Cookies and Third Party, but I see with Firefox they only differentiate between First Party and Third Party)? I'm setting a session value in a login page then doing a Response.Redirect kinda thing and checking to see if the session value is still valid.
Unless you specify an expiry on the cookie it will be a session cookie. The term session is a bit overloaded in HTTP. When the IE dialog refers to a session cookie it means any cookie that is only stored in process memory and not persisted to disk, therefore only lives for the duration of the process (the session). Start another IExplore.exe process and you have another session which will not have the values of any previous or extant session cookies.
You are correct though that you can test whether even session level cookies are being blocked by just storing a value in the session object and testing for its presence on a redirect.
Well, the "ugly as hell" method we used, was to set a cookie and redirect to a new page. In the code for the new page, see if the cookie was set. Since the only way to get to the second page is to be redirected there when the cookie is set, it's presence or absence should tell the state of the browser.