Re: Tomcat 8.0.30 Session lost
Am 12.01.16 um 13:24 schrieb Mark Thomas: On 12/01/2016 11:06, Thomas Scheffler wrote: Am 11.01.16 um 22:05 schrieb Mark Thomas: Found on http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection the description how to switch the "feature" off. I will file two bugs soon describing the issues I had. Hopefully they will be fixed. 1.) if using HttpServetRequest.login(String, String) further request in the session are loosing the users Principal. 2.) After changing sessionId, old sessionIds should still be valid for a short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. Hi Mark, if you choose to use login() and this modifies the session ID. Further calls to login() should either: 1.) are not required as every request belonging to the same session are already authenticated. After login() other request of the same session will not return 'null' on getRemoteUser() or getUserPrincipal() 2.) are not required, as authenticate() use the information provided by the first login() call. 3.) do not modify the session ID as the same user was authenticated before and the session is therefor safe to session fixation attacks Those 3 all boil down to essentially the same requirement. Requests are populated with cached authentication information from the session at the start of the request (if the authenticator is configured to do so - all but DIGEST are by default). Hi, "all but DIGEST are by default" was my case. As I walked through the code I found most of the features I requested are already in place. There is already the tracking of the Principal in the session. To use the values of login() later in authenticate() in Tomcat 8.0.30 I had to insert "/foo" as my login page and "/bar" as my login-error-page. I think any value will do here ;-) FORM Restricted /foo /bar This activates the FormAuthenticator which correctly does, what I was hoping for. I think every authenticator can/should use the information stored by login() if it is available. kind regards Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Thomas, On 1/13/16 1:04 PM, Thomas Scheffler wrote: > Am 13.01.16 um 15:48 schrieb Christopher Schultz: >> Thomas, >> >> On 1/13/16 8:31 AM, Thomas Scheffler wrote: >>> Am 12.01.16 um 13:24 schrieb Mark Thomas: On 12/01/2016 11:06, Thomas Scheffler wrote: > Am 11.01.16 um 22:05 schrieb Mark Thomas: >>> >>> >> className="org.apache.catalina.authenticator.BasicAuthenticator" >>> changeSessionIdOnAuthentication="false" /> >>> >>> Found on >>> http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection >>> >>> >>> the description how to switch the "feature" off. >>> >>> I will file two bugs soon describing the issues I had. Hopefully >>> they >>> will be fixed. >>> >>> 1.) if using HttpServetRequest.login(String, String) further >>> request in >>> the session are loosing the users Principal. >>> >>> 2.) After changing sessionId, old sessionIds should still be valid >>> for a >>> short period of time of to the same client. >> >> The second request will get closed as INVALID on security grounds. If >> the old ID is valid for any period of time it makes a session >> fixation >> attack possible. You might as well disable changing the session ID on >> authentication. >> >> For the first the description above isn't clear enough to be sure >> exactly what you are asking for. However, based on the second request >> and what I have read of this thread I suspect that request will get >> closed as INVALID or WONTFIX. > > Hi Mark, > > if you choose to use login() and this modifies the session ID. Further > calls to login() should either: > > 1.) are not required as every request belonging to the same session > are > already authenticated. After login() other request of the same session > will not return 'null' on getRemoteUser() or getUserPrincipal() > > 2.) are not required, as authenticate() use the information > provided by > the first login() call. > > 3.) do not modify the session ID as the same user was authenticated > before and the session is therefor safe to session fixation attacks Those 3 all boil down to essentially the same requirement. Requests are populated with cached authentication information from the session at the start of the request (if the authenticator is configured to do so - all but DIGEST are by default). >>> >>> Hi, >>> >>> "all but DIGEST are by default" was my case. >>> >>> As I walked through the code I found most of the features I requested >>> are already in place. There is already the tracking of the Principal in >>> the session. To use the values of login() later in authenticate() in >>> Tomcat 8.0.30 I had to insert "/foo" as my login page and "/bar" as my >>> login-error-page. I think any value will do here ;-) >>> >>> >>> FORM >>> Restricted >>> >>> /foo >>> /bar >>> >>> >>> >>> This activates the FormAuthenticator which correctly does, what I was >>> hoping for. >>> >>> I think every authenticator can/should use the information stored by >>> login() if it is available. >> >> Which argument to login() carries the server-generated nonce used for >> login? Which argument includes the realm name? >> >> https://en.wikipedia.org/wiki/Digest_access_authentication > > Hi Chris, > > the login() method gets the username and the password. It has nothing to > do with configured auth-method in the web.xml. I'm familiar with this method and how it works. > Tomcat uses a generic > method[1] located in a super class do perform the login. The Principal > is stored in the session, if caching is enabled and a session is present > or created. > Depending on the configured auth-method the Principal is used later, if > found or not. My suggestion was to always use it, when it is stored in > the session. Tomcat can't verify that the incoming credentials match those credentials that were used in a previous login. How could Tomcat decide if new credentials were being used if Tomcat doesn't actually try to use them? Then, if Tomcat uses the credentials and they are valid, the session id must be changed for session-fixation prevention. If there is a difference between the BasicAuthenticator and the DigestAuthenticator, then that gap should probably be closed. -chris - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Thomas, On 1/13/16 8:31 AM, Thomas Scheffler wrote: > Am 12.01.16 um 13:24 schrieb Mark Thomas: >> On 12/01/2016 11:06, Thomas Scheffler wrote: >>> Am 11.01.16 um 22:05 schrieb Mark Thomas: > > className="org.apache.catalina.authenticator.BasicAuthenticator" > changeSessionIdOnAuthentication="false" /> > > Found on > http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection > > the description how to switch the "feature" off. > > I will file two bugs soon describing the issues I had. Hopefully they > will be fixed. > > 1.) if using HttpServetRequest.login(String, String) further > request in > the session are loosing the users Principal. > > 2.) After changing sessionId, old sessionIds should still be valid > for a > short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. >>> >>> Hi Mark, >>> >>> if you choose to use login() and this modifies the session ID. Further >>> calls to login() should either: >>> >>> 1.) are not required as every request belonging to the same session are >>> already authenticated. After login() other request of the same session >>> will not return 'null' on getRemoteUser() or getUserPrincipal() >>> >>> 2.) are not required, as authenticate() use the information provided by >>> the first login() call. >>> >>> 3.) do not modify the session ID as the same user was authenticated >>> before and the session is therefor safe to session fixation attacks >> >> Those 3 all boil down to essentially the same requirement. >> >> Requests are populated with cached authentication information from the >> session at the start of the request (if the authenticator is configured >> to do so - all but DIGEST are by default). > > Hi, > > "all but DIGEST are by default" was my case. > > As I walked through the code I found most of the features I requested > are already in place. There is already the tracking of the Principal in > the session. To use the values of login() later in authenticate() in > Tomcat 8.0.30 I had to insert "/foo" as my login page and "/bar" as my > login-error-page. I think any value will do here ;-) > > > FORM > Restricted > > /foo > /bar > > > > This activates the FormAuthenticator which correctly does, what I was > hoping for. > > I think every authenticator can/should use the information stored by > login() if it is available. Which argument to login() carries the server-generated nonce used for login? Which argument includes the realm name? https://en.wikipedia.org/wiki/Digest_access_authentication -chris - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Am 13.01.16 um 15:48 schrieb Christopher Schultz: Thomas, On 1/13/16 8:31 AM, Thomas Scheffler wrote: Am 12.01.16 um 13:24 schrieb Mark Thomas: On 12/01/2016 11:06, Thomas Scheffler wrote: Am 11.01.16 um 22:05 schrieb Mark Thomas: Found on http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection the description how to switch the "feature" off. I will file two bugs soon describing the issues I had. Hopefully they will be fixed. 1.) if using HttpServetRequest.login(String, String) further request in the session are loosing the users Principal. 2.) After changing sessionId, old sessionIds should still be valid for a short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. Hi Mark, if you choose to use login() and this modifies the session ID. Further calls to login() should either: 1.) are not required as every request belonging to the same session are already authenticated. After login() other request of the same session will not return 'null' on getRemoteUser() or getUserPrincipal() 2.) are not required, as authenticate() use the information provided by the first login() call. 3.) do not modify the session ID as the same user was authenticated before and the session is therefor safe to session fixation attacks Those 3 all boil down to essentially the same requirement. Requests are populated with cached authentication information from the session at the start of the request (if the authenticator is configured to do so - all but DIGEST are by default). Hi, "all but DIGEST are by default" was my case. As I walked through the code I found most of the features I requested are already in place. There is already the tracking of the Principal in the session. To use the values of login() later in authenticate() in Tomcat 8.0.30 I had to insert "/foo" as my login page and "/bar" as my login-error-page. I think any value will do here ;-) FORM Restricted /foo /bar This activates the FormAuthenticator which correctly does, what I was hoping for. I think every authenticator can/should use the information stored by login() if it is available. Which argument to login() carries the server-generated nonce used for login? Which argument includes the realm name? https://en.wikipedia.org/wiki/Digest_access_authentication Hi Chris, the login() method gets the username and the password. It has nothing to do with configured auth-method in the web.xml. Tomcat uses a generic method[1] located in a super class do perform the login. The Principal is stored in the session, if caching is enabled and a session is present or created. Depending on the configured auth-method the Principal is used later, if found or not. My suggestion was to always use it, when it is stored in the session. Hope this clarifies my summary. Thomas [1] org.apache.catalina.authenticator.AuthenticatorBase.doLogin(Request, String, String) - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Thomas, On 1/12/16 8:03 AM, Thomas Scheffler wrote: > Am 12.01.16 um 13:24 schrieb Mark Thomas: >> On 12/01/2016 11:06, Thomas Scheffler wrote: >>> Am 11.01.16 um 22:05 schrieb Mark Thomas: > > className="org.apache.catalina.authenticator.BasicAuthenticator" > changeSessionIdOnAuthentication="false" /> > > Found on > http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection > > the description how to switch the "feature" off. > > I will file two bugs soon describing the issues I had. Hopefully they > will be fixed. > > 1.) if using HttpServetRequest.login(String, String) further > request in > the session are loosing the users Principal. > > 2.) After changing sessionId, old sessionIds should still be valid > for a > short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. >>> >>> Hi Mark, >>> >>> if you choose to use login() and this modifies the session ID. Further >>> calls to login() should either: >>> >>> 1.) are not required as every request belonging to the same session are >>> already authenticated. After login() other request of the same session >>> will not return 'null' on getRemoteUser() or getUserPrincipal() >>> >>> 2.) are not required, as authenticate() use the information provided by >>> the first login() call. >>> >>> 3.) do not modify the session ID as the same user was authenticated >>> before and the session is therefor safe to session fixation attacks >> >> Those 3 all boil down to essentially the same requirement. > > Sorry, I do not see this leed to the same requirement. > > 1.) The Servlet-Spec notes: > > 13.6.3: > "The login method of the HttpServletRequest interface provides an > alternative means for an application to control the look and feel of > it’s login screens." > > 13.6.3.1: > "If the user is authenticated using form login and has created an HTTP > session, the timeout or invalidation of that session leads > to the user being logged out in the sense that subsequent requests must > cause the user to be re-authenticated." > > This defines a call to login() should be handled like Form-Login and not > as Basic-Authentication - like Tomcat currently does. It further states > the the user is logged-out on session timeout and not with every new > request. > >> Requests are populated with cached authentication information from the >> session at the start of the request (if the authenticator is configured >> to do so - all but DIGEST are by default). > > As stated above, if I use the authenticate() method. The user get a > Basic Authentication window asking for a login. At latest there should > be a usage of the already known credentials used by login(). > >> This request is asking that any method call on the request relating to >> authentication checks the session if the authenticator is configured to >> cache authentication information in the session. >> >> While this is possible, it won't solve the problem. There will still be >> a race condition in the application. Consider the following: >> Request1 - getRemoteUser() == null; >> Request2 - getRemoteUser() == null; >> Request2 - login() - OK >> Request1 - login() - ServletException as user is already logged in >> >> Given that the requested change will add complexity without actually >> solving the problem any enhancement request opened asking for such a >> change will be resolved as WONTFIX. > > Oh come on. It's the same case with the logout() method. No problem > there. Tomcat could handle this gracefully without any problems. > >> Therefore, I come back to my earlier point that the correct solution is >> for the application accesses authenticated resources in a sane way and >> then these issues simply won't be possible. In the specific example for >> this thread, the page that generates the list of thumbnails needs to >> require authentication as well as (some of) the thumbnails. > > It boils down to this problem: > > It's the servlet containers duty to do the session tracking. I showed, > that there is a racing condition and *Tomcat* currently fails to do so. > The client (every browser on the market) are not the problem here, they > behave like they should (Tomcat tells to value of the session cookie!) > > I file the bug, that's all a user can do. The race condition is with the application's behavior. Tomcat cannot protect against the use-case you present here in any sane way. The problem is that you are issuing many
RE: Tomcat 8.0.30 Session lost
Thomas > -Original Message- > From: Olaf Kock [mailto:tom...@olafkock.de] > Sent: Monday, January 11, 2016 4:12 PM > To: Tomcat Users List > Subject: Re: Tomcat 8.0.30 Session lost > > Well, at least you do a bit of protection instead of just disabling the > session fixation security filter. However, be aware that potentially many > people might come from the same IP address - either because it's a NATing > home router or a big company's proxy server. Especially if you want to attack > someone who's in the same network as yourself, this IP-based protection is > quite useless. > > I think I'm seeing the problems, and as long as you know what you're doing > and you accept the unavoidable consequences of this lower grade protection, > everything is fine. > > It still sounds funny that the session is not available with the next > requests... Might be worth to try different browsers for their timing on the > receipt of the cookie +1 Have you tried different browsers, say Internet Explorer, Chrome, and Firefox to see if the behavior is the same for all? This is kind of a long shot, but I'll mention it anyway. I had a similar kind of problem, where every resource request on a page was trying to create a new session. It turns out IE had a bug processing URL's with special chars in them, in my case an underscore "_". Using a different browser other than IE, or accessing the server by IP address instead of DNS name, hid the problem. After researching, experimentation, and pulling my hair out, I finally realized the underscore was the issue. Renaming the server solved the problem. Use keyword "weirdness" to search for old posts on this topic. Perhaps another long shot, and please forgive me if you have already made this clear, have you verified the timing and concurrency of your authentication and loading of page resources? IOW, are they the same, or different use-case events? > Also, as you call HttpServletRequest.login manually, double check that you're > doing this before the response is committed to the client, specifically > before any other (old) session id cookie is already in the response stream. > It sounds weird, but might help you debug further (note that I'm not looking > at tomcat's code. Apologies if I'm not making sense) > > Olaf > > Am 11.01.2016 um 21:52 schrieb Thomas Scheffler: > > > > I will file two bugs soon describing the issues I had. Hopefully they > > will be fixed. > > > > 1.) if using HttpServetRequest.login(String, String) further request > > in the session are loosing the users Principal. > > > > 2.) After changing sessionId, old sessionIds should still be valid for > > a short period of time of to the same client. > > > > Fixing one of these would cause the bug to disappear. > > > > To prevent session fixation attacks, I use IP address checking so that > > sessions are bound to the same IP address. > > > > Thanks to all the responses. Without you help it would have not been > > possible to get this fixed after two month of searching! > > > > kind regards, > > > > Thomas > > -- Cris Berneburg, Lead Software Engineer, CACI
Re: Tomcat 8.0.30 Session lost
On 12/01/2016 13:03, Thomas Scheffler wrote: > Am 12.01.16 um 13:24 schrieb Mark Thomas: >> On 12/01/2016 11:06, Thomas Scheffler wrote: >>> Am 11.01.16 um 22:05 schrieb Mark Thomas: For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. >>> >>> Hi Mark, >>> >>> if you choose to use login() and this modifies the session ID. Further >>> calls to login() should either: >>> >>> 1.) are not required as every request belonging to the same session are >>> already authenticated. After login() other request of the same session >>> will not return 'null' on getRemoteUser() or getUserPrincipal() >>> >>> 2.) are not required, as authenticate() use the information provided by >>> the first login() call. >>> >>> 3.) do not modify the session ID as the same user was authenticated >>> before and the session is therefor safe to session fixation attacks >> >> Those 3 all boil down to essentially the same requirement. > > Sorry, I do not see this leed to the same requirement. > > 1.) The Servlet-Spec notes: > > 13.6.3: > "The login method of the HttpServletRequest interface provides an > alternative means for an application to control the look and feel of > it’s login screens." > > 13.6.3.1: > "If the user is authenticated using form login and has created an HTTP > session, the timeout or invalidation of that session leads > to the user being logged out in the sense that subsequent requests must > cause the user to be re-authenticated." > > This defines a call to login() should be handled like Form-Login and not > as Basic-Authentication - like Tomcat currently does. It further states > the the user is logged-out on session timeout and not with every new > request. No it doesn't. You are reading more into the specification than is actually there. The final sentence of 13.6.3 is there to make the reader aware that the login() method exists as an alternative to using FORM authentication. Nothing more. >> Requests are populated with cached authentication information from the >> session at the start of the request (if the authenticator is configured >> to do so - all but DIGEST are by default). > > As stated above, if I use the authenticate() method. The user get a > Basic Authentication window asking for a login. At latest there should > be a usage of the already known credentials used by login(). As per the specification, calling that method is required to trigger the same authentication process and that is exactly what happens. The authentication process does check for cached credentials but, as with the other authentication related calls on the request, it checks the request not the session and the request is populated from the session at the start of the request processing. >> This request is asking that any method call on the request relating to >> authentication checks the session if the authenticator is configured to >> cache authentication information in the session. >> >> While this is possible, it won't solve the problem. There will still be >> a race condition in the application. Consider the following: >> Request1 - getRemoteUser() == null; >> Request2 - getRemoteUser() == null; >> Request2 - login() - OK >> Request1 - login() - ServletException as user is already logged in >> >> Given that the requested change will add complexity without actually >> solving the problem any enhancement request opened asking for such a >> change will be resolved as WONTFIX. > > Oh come on. Taking that sort of attitude is going to do nothing to help your case or encourage anyone here to spend their time helping you. > It's the same case with the logout() method. No problem > there. Tomcat could handle this gracefully without any problems. As I explained above, this can't be handled gracefully even with the changes you are requesting to Tomcat. Tomcat is required by the Servlet spec to throw a ServletException if a call to login() is made after a user has already been authenticated. The Servlet API does not provide the hooks necessary for an application to handle the race condition of parallel requests that require authentication and prevent this exception. Yes, the application could simply catch the exception and carry on but such a design is a large warning that that API is not being used correctly. >> Therefore, I come back to my earlier point that the correct solution is >> for the application accesses authenticated resources in a sane way and >> then these issues simply won't be possible. In the specific example for >> this thread, the page that generates the list of thumbnails needs to >> require authentication as well as (some of) the thumbnails. > > It boils down to this problem: > > It's the servlet containers duty to do the session tracking. Not correct. Responsibility for correct session tracking is split
Re: Tomcat 8.0.30 Session lost
Am 12.01.16 um 13:24 schrieb Mark Thomas: On 12/01/2016 11:06, Thomas Scheffler wrote: Am 11.01.16 um 22:05 schrieb Mark Thomas: Found on http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection the description how to switch the "feature" off. I will file two bugs soon describing the issues I had. Hopefully they will be fixed. 1.) if using HttpServetRequest.login(String, String) further request in the session are loosing the users Principal. 2.) After changing sessionId, old sessionIds should still be valid for a short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. Hi Mark, if you choose to use login() and this modifies the session ID. Further calls to login() should either: 1.) are not required as every request belonging to the same session are already authenticated. After login() other request of the same session will not return 'null' on getRemoteUser() or getUserPrincipal() 2.) are not required, as authenticate() use the information provided by the first login() call. 3.) do not modify the session ID as the same user was authenticated before and the session is therefor safe to session fixation attacks Those 3 all boil down to essentially the same requirement. Sorry, I do not see this leed to the same requirement. 1.) The Servlet-Spec notes: 13.6.3: "The login method of the HttpServletRequest interface provides an alternative means for an application to control the look and feel of it’s login screens." 13.6.3.1: "If the user is authenticated using form login and has created an HTTP session, the timeout or invalidation of that session leads to the user being logged out in the sense that subsequent requests must cause the user to be re-authenticated." This defines a call to login() should be handled like Form-Login and not as Basic-Authentication - like Tomcat currently does. It further states the the user is logged-out on session timeout and not with every new request. Requests are populated with cached authentication information from the session at the start of the request (if the authenticator is configured to do so - all but DIGEST are by default). As stated above, if I use the authenticate() method. The user get a Basic Authentication window asking for a login. At latest there should be a usage of the already known credentials used by login(). This request is asking that any method call on the request relating to authentication checks the session if the authenticator is configured to cache authentication information in the session. While this is possible, it won't solve the problem. There will still be a race condition in the application. Consider the following: Request1 - getRemoteUser() == null; Request2 - getRemoteUser() == null; Request2 - login() - OK Request1 - login() - ServletException as user is already logged in Given that the requested change will add complexity without actually solving the problem any enhancement request opened asking for such a change will be resolved as WONTFIX. Oh come on. It's the same case with the logout() method. No problem there. Tomcat could handle this gracefully without any problems. Therefore, I come back to my earlier point that the correct solution is for the application accesses authenticated resources in a sane way and then these issues simply won't be possible. In the specific example for this thread, the page that generates the list of thumbnails needs to require authentication as well as (some of) the thumbnails. It boils down to this problem: It's the servlet containers duty to do the session tracking. I showed, that there is a racing condition and *Tomcat* currently fails to do so. The client (every browser on the market) are not the problem here, they behave like they should (Tomcat tells to value of the session cookie!) I file the bug, that's all a user can do. Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Am 11.01.16 um 22:05 schrieb Mark Thomas: Found on http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection the description how to switch the "feature" off. I will file two bugs soon describing the issues I had. Hopefully they will be fixed. 1.) if using HttpServetRequest.login(String, String) further request in the session are loosing the users Principal. 2.) After changing sessionId, old sessionIds should still be valid for a short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. Hi Mark, if you choose to use login() and this modifies the session ID. Further calls to login() should either: 1.) are not required as every request belonging to the same session are already authenticated. After login() other request of the same session will not return 'null' on getRemoteUser() or getUserPrincipal() 2.) are not required, as authenticate() use the information provided by the first login() call. 3.) do not modify the session ID as the same user was authenticated before and the session is therefor safe to session fixation attacks If login() modifies the session and the session does not track the authentication information, session tracking is not deterministic due to side effects for multiple requests at a time. Fixing either #1, #2 or #3 does not harm security at all but will fix this bug in Tomcat. I also tried to use authenticate() on the request, but instead of using the last login() credentials it forced the use of Basic Authentication. So really I do not see a option left on the developer side, how to use login() in a reliable manner. kind regards Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
On 12/01/2016 11:06, Thomas Scheffler wrote: > Am 11.01.16 um 22:05 schrieb Mark Thomas: >>> >>> >>changeSessionIdOnAuthentication="false" /> >>> >>> Found on >>> http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection >>> the description how to switch the "feature" off. >>> >>> I will file two bugs soon describing the issues I had. Hopefully they >>> will be fixed. >>> >>> 1.) if using HttpServetRequest.login(String, String) further request in >>> the session are loosing the users Principal. >>> >>> 2.) After changing sessionId, old sessionIds should still be valid for a >>> short period of time of to the same client. >> >> The second request will get closed as INVALID on security grounds. If >> the old ID is valid for any period of time it makes a session fixation >> attack possible. You might as well disable changing the session ID on >> authentication. >> >> For the first the description above isn't clear enough to be sure >> exactly what you are asking for. However, based on the second request >> and what I have read of this thread I suspect that request will get >> closed as INVALID or WONTFIX. > > Hi Mark, > > if you choose to use login() and this modifies the session ID. Further > calls to login() should either: > > 1.) are not required as every request belonging to the same session are > already authenticated. After login() other request of the same session > will not return 'null' on getRemoteUser() or getUserPrincipal() > > 2.) are not required, as authenticate() use the information provided by > the first login() call. > > 3.) do not modify the session ID as the same user was authenticated > before and the session is therefor safe to session fixation attacks Those 3 all boil down to essentially the same requirement. Requests are populated with cached authentication information from the session at the start of the request (if the authenticator is configured to do so - all but DIGEST are by default). This request is asking that any method call on the request relating to authentication checks the session if the authenticator is configured to cache authentication information in the session. While this is possible, it won't solve the problem. There will still be a race condition in the application. Consider the following: Request1 - getRemoteUser() == null; Request2 - getRemoteUser() == null; Request2 - login() - OK Request1 - login() - ServletException as user is already logged in Given that the requested change will add complexity without actually solving the problem any enhancement request opened asking for such a change will be resolved as WONTFIX. Therefore, I come back to my earlier point that the correct solution is for the application accesses authenticated resources in a sane way and then these issues simply won't be possible. In the specific example for this thread, the page that generates the list of thumbnails needs to require authentication as well as (some of) the thumbnails. Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
On 12/01/2016 15:57, Thomas Scheffler wrote: > What I read in the specification is that a *fix* could be implemented > that would a allow the bug to disappear. The third point above, changing > the sessionId only if the user is "new" to the session, would fix the > problem, could be integrated easily and would help me and possibly > others. Does it open a new security risk? No. I'm not (yet) convinced that that is the case. I'd need to think through the various corner cases. But, as explained below, even if there were no additional security risks, I remain unconvinced about this approach. > You are right. Again there is nothing that prevents you to help to fix > that issue, neither spec nor anything. Yes there is. Read section 13.10 of the servlet spec. I was looking for something else but found section 13.10 and it is explicit that the behaviour you are asking for is not specification compliant. On top of that, the issue can't be fully fixed. And if it can't be fully fixed then all a partial fix would do is make the issue more difficult to reproduce and harder to track down. Even with the fix above, it doesn't solve the following (more involved than my previous example) race condition: UA sends sends request1 on connection 1 Request1 creates session1 with sessionid1 Request1 returns response1 to the UA UA sends request2 with sessionid1 on connection1 UA sends request3 with sessionid1 on connection2 request2 uses session1 reuqest2 returns response2 to the UA request3 authenticates and sessionid1 changes to sessionid1001 UA sends request4 with sessionid1 on connection1 request fails because sessionid1 no longer exists Fundamentally, if you want to use Tomcat's session fixation protection then you have to ensure that authentication can not happen concurrently with any request for the same session. Similar issues will occur if you have two parallel requests that both create a session. > You don't see the frustration you brought to me but you could read it. I > am sorry for that. In a world of asynchronous request handling and > protocol upgrading you are forcing users to deliver responses > sequentially. Sorry. This is so disappointing. There is no way around the fact the a request that does any of the following (and probably other actions as well) can not be concurrent with any other request from the same user else something is likely to break: - create a session - authenticate the user if session fixation protection is enabled Once you have done those things, you can use all the concurrency you like. > The spec just states that the user information on the request does not > change if one does not call login(), logout() or authenticate(). It says > nothing on the initial state, neither. But when I call authenticate() on > a request and used login() on an other request object, why can't > authenticate() not use that credentials? Why does the user have to > re-login again (basic auth)? See reference to servlet 13.10 above. > You are right. But I have no code to alter the session handling. It is a > standard webpage with restricted information that refers to restricted > images on the same fast server. A rather simple use case. I use the > login() method that was introduced in Servlet 3. There is no standard > conform way to have login() work for me. I cannot modify the browser to > load the images one by one. I could do by using JavaScript to load the > images and waiting for each response. Is that what you are suggesting? I don't know how your application is written so I can't give you specific advice. What I can say is any web application has to conform to the constraints I explained above else it will likely break. > It is just like a homepage that give a tiny information, who is logged > in. And depending on the user returns some information not readable by > "guests". No way to force a user to enter his credentials. You can visit > twitter without being asked for your login. You decide when you log in > and you never loose a session. One URL returns different results > depending on the user being logged in. Because Twitter is careful not to do parallel requests that might require authentication. > Of cause, if I require authentication, I can force Tomcat to not use > BasicAuthentication but FormAuthentication. That isn't going to solve the parallel request problem. > But during the page > generation I used the login() method to get the user information and > check for roles. Where is the user information coming from? > The page is delivered to the user At this point the UA should have the new session ID since it is after authentication takes place. > referencing thumbnails that are itself protected OK. So requests to those should use the new session ID which should pick up the authenticated user. > and lack of authenticate() to work as expected, The key question is why are these failing. > calling login() with the same credentials all over again > for every thumbnail.
Re: Tomcat 8.0.30 Session lost
Olaf, On 1/11/16 4:12 PM, Olaf Kock wrote: > Well, at least you do a bit of protection instead of just disabling the > session fixation security filter. However, be aware that potentially > many people might come from the same IP address - either because it's a > NATing home router or a big company's proxy server. Especially if you > want to attack someone who's in the same network as yourself, this > IP-based protection is quite useless. The primary example of this not working is America Online (which really does still exist). I haven't checked recently, but for quite a long time, they would proxy everybody through a small set of servers -- millions of users all appearing to have the same IP address. Restricting a login to a single IP address (e.g. like Bugzilla can do)? That does actually make some sense since it doesn't harm anyone and merely fails to add protection to AOL users and others users in a similar situation. But making IP address ~= session id? That will never work properly. -chris - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Am 12.01.16 um 14:41 schrieb Mark Thomas: 1.) are not required as every request belonging to the same session are already authenticated. After login() other request of the same session will not return 'null' on getRemoteUser() or getUserPrincipal() 2.) are not required, as authenticate() use the information provided by the first login() call. 3.) do not modify the session ID as the same user was authenticated before and the session is therefor safe to session fixation attacks Those 3 all boil down to essentially the same requirement. Sorry, I do not see this leed to the same requirement. 1.) The Servlet-Spec notes: 13.6.3: "The login method of the HttpServletRequest interface provides an alternative means for an application to control the look and feel of it’s login screens." 13.6.3.1: "If the user is authenticated using form login and has created an HTTP session, the timeout or invalidation of that session leads to the user being logged out in the sense that subsequent requests must cause the user to be re-authenticated." This defines a call to login() should be handled like Form-Login and not as Basic-Authentication - like Tomcat currently does. It further states the the user is logged-out on session timeout and not with every new request. No it doesn't. You are reading more into the specification than is actually there. The final sentence of 13.6.3 is there to make the reader aware that the login() method exists as an alternative to using FORM authentication. Nothing more. What I read in the specification is that a *fix* could be implemented that would a allow the bug to disappear. The third point above, changing the sessionId only if the user is "new" to the session, would fix the problem, could be integrated easily and would help me and possibly others. Does it open a new security risk? No. Tracking the user information in a session is also explicitly allowed by spec. Requests are populated with cached authentication information from the session at the start of the request (if the authenticator is configured to do so - all but DIGEST are by default). As stated above, if I use the authenticate() method. The user get a Basic Authentication window asking for a login. At latest there should be a usage of the already known credentials used by login(). As per the specification, calling that method is required to trigger the same authentication process and that is exactly what happens. The authentication process does check for cached credentials but, as with the other authentication related calls on the request, it checks the request not the session and the request is populated from the session at the start of the request processing. You are right. Again there is nothing that prevents you to help to fix that issue, neither spec nor anything. If one uses login() on request and during the request a session is created or already exist use the FormAuthenticator or create a LoginAuthenticator class instead of BasicAuthenticator on other request, when authenticate() is executed. authenticate() could get the Authenticator from an AtomicReference in the session (if available). Given that the requested change will add complexity without actually solving the problem any enhancement request opened asking for such a change will be resolved as WONTFIX. Oh come on. Taking that sort of attitude is going to do nothing to help your case or encourage anyone here to spend their time helping you. You don't see the frustration you brought to me but you could read it. I am sorry for that. In a world of asynchronous request handling and protocol upgrading you are forcing users to deliver responses sequentially. Sorry. This is so disappointing. It's the same case with the logout() method. No problem there. Tomcat could handle this gracefully without any problems. As I explained above, this can't be handled gracefully even with the changes you are requesting to Tomcat. Tomcat is required by the Servlet spec to throw a ServletException if a call to login() is made after a user has already been authenticated. The Servlet API does not provide the hooks necessary for an application to handle the race condition of parallel requests that require authentication and prevent this exception. Yes, the application could simply catch the exception and carry on but such a design is a large warning that that API is not being used correctly. The spec just states that the user information on the request does not change if one does not call login(), logout() or authenticate(). It says nothing on the initial state, neither. But when I call authenticate() on a request and used login() on an other request object, why can't authenticate() not use that credentials? Why does the user have to re-login again (basic auth)? Therefore, I come back to my earlier point that the correct solution is for the application accesses authenticated resources in a sane way and then these issues simply won't
Re: Tomcat 8.0.30 Session lost
Hi Christopher, Thanks for reminding me of my extra doubt that I missed writing of in the first post: Picking up on AOL: If I'm on proxy1 now, with many other users - will I stay on that proxy for a long time? Or will I be loadbalanced to many other proxies during my visit on the site? There's nothing that enforces me to come from the same IP every time. It's still common that home routers might get new addresses at least every 24h, and many mobile providers don't give out public IP addresses - I'm not sure if I keep my IP-address if I'm roaming to another network cell. Conclusion: Protection by IP-address-fixation calls for random problems that are hard to reproduce. Olaf Am 12.01.2016 um 16:51 schrieb Christopher Schultz: > Olaf, > > On 1/11/16 4:12 PM, Olaf Kock wrote: >> Well, at least you do a bit of protection instead of just disabling the >> session fixation security filter. However, be aware that potentially >> many people might come from the same IP address - either because it's a >> NATing home router or a big company's proxy server. Especially if you >> want to attack someone who's in the same network as yourself, this >> IP-based protection is quite useless. > The primary example of this not working is America Online (which really > does still exist). I haven't checked recently, but for quite a long > time, they would proxy everybody through a small set of servers -- > millions of users all appearing to have the same IP address. > > Restricting a login to a single IP address (e.g. like Bugzilla can do)? > That does actually make some sense since it doesn't harm anyone and > merely fails to add protection to AOL users and others users in a > similar situation. > > But making IP address ~= session id? That will never work properly. > > -chris > > - > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > For additional commands, e-mail: users-h...@tomcat.apache.org > - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
On 12.01.2016 12:06, Thomas Scheffler wrote: Am 11.01.16 um 22:05 schrieb Mark Thomas: Found on http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection the description how to switch the "feature" off. I will file two bugs soon describing the issues I had. Hopefully they will be fixed. 1.) if using HttpServetRequest.login(String, String) further request in the session are loosing the users Principal. 2.) After changing sessionId, old sessionIds should still be valid for a short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. Hi Mark, if you choose to use login() and this modifies the session ID. Further calls to login() should either: 1.) are not required as every request belonging to the same session are already authenticated. After login() other request of the same session will not return 'null' on getRemoteUser() or getUserPrincipal() 2.) are not required, as authenticate() use the information provided by the first login() call. 3.) do not modify the session ID as the same user was authenticated before and the session is therefor safe to session fixation attacks If login() modifies the session and the session does not track the authentication information, session tracking is not deterministic due to side effects for multiple requests at a time. Fixing either #1, #2 or #3 does not harm security at all but will fix this bug in Tomcat. I also tried to use authenticate() on the request, but instead of using the last login() credentials it forced the use of Basic Authentication. So really I do not see a option left on the developer side, how to use login() in a reliable manner. Thomas, what I was trying to explain to you previously, is this : Any "serious" webserver software is written so that it conforms to the rules defined in the HTTP protocol specification (RFC 2616/2617 and related). That is the case for Tomcat, for Apache httpd, and all other webservers. In addition, Tomcat being a java servlet engine, also adheres to the rules defined in the Java Servlet Specification. The HTTP specification and the Java Servlet Specification (https://java.net/downloads/servlet-spec/Final/servlet-3_1-final.pdf) have things to say about /some/ authentication schemes. When they do, the corresponding webservers / servlet engines respect these things, and applications should do the same. When the specs do not say anything about a particular aspect of user authentication e.g., then the webserver and the applications are free to do what they want, as long as what they do does not violate another aspect of the specs. There is no specification which dictates exactly what should happen in terms of authentication, for multiple simultaneous requests by a client, for webserver resources that require authentication. There is also no specification which dictates exactly in what order such simultaneous requests should be processed, nor exactly how long the processing of each individual request should take. That is because, at the very basic level, HTTP 1.1 is such that multiple requests, even if they originate from the same client over a short period of time, are still seen as individual, separate requests, from the webserver point of view; and according to the protocol specs, the webserver could even "delegate" each of these requests to separate distinct processes in the background (think of a front-end proxy with a load-balancer for example), and each of these background processes would know nothing about any other parallel process handling one of these requests for the same client at the same time. (For example, one of these processes would never know that some other related process is "just about" at the point of issuing a new session-id to that same client). That is just the way it is, and you are not going to be able to get every producer of webserver code, and of browser code, to change this in a way that suits your own idea of how things should happen. (It is not forbidden to try, but it will be a long process, much longer than changing your application). So, if you want your HTTP-based application to be portable across different webservers and configurations, it is /you/ who must make sure, in the design and logic of your application, that a case such as the one you encounter, cannot happen. One way of doing this would be to design your application in such a way as to /force/ a client to always go through a first call to a page which triggers the authentication and returns a result to the
Re: Tomcat 8.0.30 Session lost
On 1/12/2016 10:57 AM, Thomas Scheffler wrote: Am 12.01.16 um 14:41 schrieb Mark Thomas: 1.) are not required as every request belonging to the same session are already authenticated. After login() other request of the same session will not return 'null' on getRemoteUser() or getUserPrincipal() 2.) are not required, as authenticate() use the information provided by the first login() call. 3.) do not modify the session ID as the same user was authenticated before and the session is therefor safe to session fixation attacks Those 3 all boil down to essentially the same requirement. Sorry, I do not see this leed to the same requirement. 1.) The Servlet-Spec notes: 13.6.3: "The login method of the HttpServletRequest interface provides an alternative means for an application to control the look and feel of it’s login screens." 13.6.3.1: "If the user is authenticated using form login and has created an HTTP session, the timeout or invalidation of that session leads to the user being logged out in the sense that subsequent requests must cause the user to be re-authenticated." This defines a call to login() should be handled like Form-Login and not as Basic-Authentication - like Tomcat currently does. It further states the the user is logged-out on session timeout and not with every new request. No it doesn't. You are reading more into the specification than is actually there. The final sentence of 13.6.3 is there to make the reader aware that the login() method exists as an alternative to using FORM authentication. Nothing more. What I read in the specification is that a *fix* could be implemented that would a allow the bug to disappear. The third point above, changing the sessionId only if the user is "new" to the session, would fix the problem, could be integrated easily and would help me and possibly others. Does it open a new security risk? No. Tracking the user information in a session is also explicitly allowed by spec. Requests are populated with cached authentication information from the session at the start of the request (if the authenticator is configured to do so - all but DIGEST are by default). As stated above, if I use the authenticate() method. The user get a Basic Authentication window asking for a login. At latest there should be a usage of the already known credentials used by login(). As per the specification, calling that method is required to trigger the same authentication process and that is exactly what happens. The authentication process does check for cached credentials but, as with the other authentication related calls on the request, it checks the request not the session and the request is populated from the session at the start of the request processing. You are right. Again there is nothing that prevents you to help to fix that issue, neither spec nor anything. If one uses login() on request and during the request a session is created or already exist use the FormAuthenticator or create a LoginAuthenticator class instead of BasicAuthenticator on other request, when authenticate() is executed. authenticate() could get the Authenticator from an AtomicReference in the session (if available). Given that the requested change will add complexity without actually solving the problem any enhancement request opened asking for such a change will be resolved as WONTFIX. Oh come on. Taking that sort of attitude is going to do nothing to help your case or encourage anyone here to spend their time helping you. You don't see the frustration you brought to me but you could read it. I am sorry for that. In a world of asynchronous request handling and protocol upgrading you are forcing users to deliver responses sequentially. Sorry. This is so disappointing. Not really. If you ensure that the authentication is done first, before requesting any protected resources, you will then be able to deliver things in parallel. It's just the initial request that is messing you up, from what I understand of your description. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Am 08.01.16 um 17:02 schrieb Christopher Schultz: Tomcat will change the session identifier when the user authenticates. If you are creating a session before login, you'll see that the session id changes when authentication is successful. This is to protect against session-fixation attacks. I re-login the user, if tomcat returns "null" on HttpRequest.getUserPrincipal(). I noticed that the sessionId changes. But if I am required to re-login the user on parallel requests, it depends on magic what sessionId is given after all responses are delivered to the browser. You can see in the logs, that requested sessions are suddenly invalid. I would not require an other call to the login method if servlet container returns a user once it is authenticated in a session. Can you explain why the changing session id breaks your application? Are you storing session ids somewhere and just not updating the session id list when the session id changes? It should be possibly to listen for that event and update your session id list. Or maybe there's a better way to accomplish your goal rather than keeping your own session id list. (I'm guessing you have a session id list because it would best explain the behavior you are describing here.) I do not save the http session id anywhere. The browser saves it in a cookie. The cookie is changing rapidly because the UserPrincipaö is not returned from the request. Here is something I would prefer: 1. Every request that belongs to a given session returns a non null object when calling getUserPrincipal() after the login() method returns successfully. 2. As you have no control over the net and do not know in which order the browser receives its packets, you can not invalidate a sessionId in a snap. Tomcat has to gracefully invalidate it somehow. An example: 1. Client logs in 2. Server responds with SID=SID1 3. Client request 2 resources in parallel 4. Server receives first request and handles it, returning SID=SID2 5. Server receives second request (with SID=SID2), which belongs to invalid session. Code is creating a new session than. Server response with SID=SID3 6. Client will use SID3 in future requests which belongs to the new session and not the original session where the user is logged in. IMHO it would be also secure to lock the sessionId to the IP address instead of changing the id but less error-prone. You can even combine it and allow old sessionIds only from the original IP address. If the servlet container would just use the session information for HTML pages parallel request are rare. But when serving cachable thumbnails it often like checking headers and return 304. kind regards, Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
On 11/01/2016 20:52, Thomas Scheffler wrote: > Am 11.01.16 um 12:21 schrieb André Warnier (tomcat): >> So the solution in your case, is to make sure, in your application >> logic, that the first unauthenticated request would be totally processed >> by the server, and the response processed by the client, before the >> client sends a second request. >> If you do this, then the second client request /will/ contain the /same/ >> authentication token as the first request, and you will not have this >> problem. >> >> How to achieve this, is left as an exercise for the reader. > > This means changing all browsers to submit only one concurrent request > if the server is Apache Tomcat? Really? No, it simply means you have to construct your application in a sane manner so the client won't issue parallel requests for protected resources. > >changeSessionIdOnAuthentication="false" /> > > Found on > http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection > the description how to switch the "feature" off. > > I will file two bugs soon describing the issues I had. Hopefully they > will be fixed. > > 1.) if using HttpServetRequest.login(String, String) further request in > the session are loosing the users Principal. > > 2.) After changing sessionId, old sessionIds should still be valid for a > short period of time of to the same client. The second request will get closed as INVALID on security grounds. If the old ID is valid for any period of time it makes a session fixation attack possible. You might as well disable changing the session ID on authentication. For the first the description above isn't clear enough to be sure exactly what you are asking for. However, based on the second request and what I have read of this thread I suspect that request will get closed as INVALID or WONTFIX. Mark - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Well, at least you do a bit of protection instead of just disabling the session fixation security filter. However, be aware that potentially many people might come from the same IP address - either because it's a NATing home router or a big company's proxy server. Especially if you want to attack someone who's in the same network as yourself, this IP-based protection is quite useless. I think I'm seeing the problems, and as long as you know what you're doing and you accept the unavoidable consequences of this lower grade protection, everything is fine. It still sounds funny that the session is not available with the next requests... Might be worth to try different browsers for their timing on the receipt of the cookie Also, as you call HttpServletRequest.login manually, double check that you're doing this before the response is committed to the client, specifically before any other (old) session id cookie is already in the response stream. It sounds weird, but might help you debug further (note that I'm not looking at tomcat's code. Apologies if I'm not making sense) Olaf Am 11.01.2016 um 21:52 schrieb Thomas Scheffler: > > I will file two bugs soon describing the issues I had. Hopefully they > will be fixed. > > 1.) if using HttpServetRequest.login(String, String) further request > in the session are loosing the users Principal. > > 2.) After changing sessionId, old sessionIds should still be valid for > a short period of time of to the same client. > > Fixing one of these would cause the bug to disappear. > > To prevent session fixation attacks, I use IP address checking so that > sessions are bound to the same IP address. > > Thanks to all the responses. Without you help it would have not been > possible to get this fixed after two month of searching! > > kind regards, > > Thomas > > - > To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org > For additional commands, e-mail: users-h...@tomcat.apache.org > - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Am 11.01.16 um 12:21 schrieb André Warnier (tomcat): So the solution in your case, is to make sure, in your application logic, that the first unauthenticated request would be totally processed by the server, and the response processed by the client, before the client sends a second request. If you do this, then the second client request /will/ contain the /same/ authentication token as the first request, and you will not have this problem. How to achieve this, is left as an exercise for the reader. This means changing all browsers to submit only one concurrent request if the server is Apache Tomcat? Really? Found on http://www.tomcatexpert.com/blog/2011/04/25/session-fixation-protection the description how to switch the "feature" off. I will file two bugs soon describing the issues I had. Hopefully they will be fixed. 1.) if using HttpServetRequest.login(String, String) further request in the session are loosing the users Principal. 2.) After changing sessionId, old sessionIds should still be valid for a short period of time of to the same client. Fixing one of these would cause the bug to disappear. To prevent session fixation attacks, I use IP address checking so that sessions are bound to the same IP address. Thanks to all the responses. Without you help it would have not been possible to get this fixed after two month of searching! kind regards, Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Thomas, On 11.01.2016 11:30, Thomas Scheffler wrote: Am 08.01.16 um 17:02 schrieb Christopher Schultz: Tomcat will change the session identifier when the user authenticates. If you are creating a session before login, you'll see that the session id changes when authentication is successful. This is to protect against session-fixation attacks. I re-login the user, if tomcat returns "null" on HttpRequest.getUserPrincipal(). I noticed that the sessionId changes. But if I am required to re-login the user on parallel requests, it depends on magic what sessionId is given after all responses are delivered to the browser. You can see in the logs, that requested sessions are suddenly invalid. I would not require an other call to the login method if servlet container returns a user once it is authenticated in a session. Can you explain why the changing session id breaks your application? Are you storing session ids somewhere and just not updating the session id list when the session id changes? It should be possibly to listen for that event and update your session id list. Or maybe there's a better way to accomplish your goal rather than keeping your own session id list. (I'm guessing you have a session id list because it would best explain the behavior you are describing here.) I do not save the http session id anywhere. The browser saves it in a cookie. The cookie is changing rapidly because the UserPrincipaö is not returned from the request. Here is something I would prefer: 1. Every request that belongs to a given session returns a non null object when calling getUserPrincipal() after the login() method returns successfully. 2. As you have no control over the net and do not know in which order the browser receives its packets, you can not invalidate a sessionId in a snap. Tomcat has to gracefully invalidate it somehow. An example: 1. Client logs in 2. Server responds with SID=SID1 3. Client request 2 resources in parallel 4. Server receives first request and handles it, returning SID=SID2 5. Server receives second request (with SID=SID2), which belongs to invalid session. Code is creating a new session than. Server response with SID=SID3 6. Client will use SID3 in future requests which belongs to the new session and not the original session where the user is logged in. I think that the crux of the issue, is a proper understanding of how the HTTP protocol's Basic Authentication works, in its basic form. Remember, HTTP is old, and at the beginning, it did not envision "sessions", nor "simultaneous" requests. The basic idea was : - client connects to, and sends one request to the server - server processes request, and sends response to the client - server closes connection, and forgets everything about the request just processed Then the next request from a client comes in, etc.. Everything else aftwerward, was built on the basic schema above, as "patches", to allow for authentication, "sessions" composed of multiple requests/responses, "persistent connections", "cookies" etc.. But the basic logic remains the same to this day. For Basic authentication, the basic schema is as follows : 1) client establishes a connection to the server 2) client sends a request on that connection, for some server "resource" 3) the server checks if that resource is submitted to some form of authentication/authorization/access control. 3.1) if not, the server returns the resource to the client, and the request/response cycle is finished. 3.2) if yes (AAA required), the server checks if the request contains some form of authentication/authorization. 3.2.1) if yes (auth provided), the server checks if this authentication/authorization matches the requirements for this resource. 3.2.1.1) if yes, the server returns the resource, and the request/response is finished. 3.2.1.2) if not, the server returns a "forbidden" response, and the request/response is finished. 3.2.2) if not (no auth provided), the server returns a response "authorization required" to the client, and the request/response is finished. In a case like 3.2.2, the client must repeat the request, this time /with/ an authentication as required by 3.2 above. Whenever the server returns a response to the client, it can include a "set cookie" in that response. The next time that the client sends a request to that same server, it will then include this cookie, and maybe seeing this cookie will allow the server to respond "yes" to the question at 3.2 above. The above is the basic schema, as included in the HTTP protocol. There are many other schemes that work, but you have to know that if you differ from the schema above, then you are no longer within the strict HTTP protocol, and the responsibility of making sure that your alternative scheme works in all circumstances, is yours. In particular, the above scheme will fail in the following scenario : 1) the client sends a request to the server, for a protected
Re: Tomcat 8.0.30 Session lost
2016-01-08 19:02 GMT+03:00 Christopher Schultz: > Thomas, > > On 1/8/16 8:00 AM, Thomas Scheffler wrote: >> Am 08.01.16 um 11:43 schrieb Olaf Kock: >>> Is there any chance that the first and correctly authenticated cookies >>> (despite the debug output "secure=false") are https-only cookies and >>> won't get transmitted in http, thus triggering new sessions? E.g. any >>> chance they get rewritten at another level (Apache httpd, ServletFilter, >>> others) to be secure only - or that the debug output is slightly >>> incorrect because it omits the secure flag? >> >> This is from a test installation on the productive server where it can >> only be observed. For simplicity I use the maven cargo plugin to setup >> the tomcat here. It shows the same behavior on the productive server, >> where it uses HTTPS in combination with Apache HTTPD. >> >> I use BeanUtil.describe() to produce the cookie String. So this should >> all be correct. >> >> This error comes up on every browser with at least a certain number of >> request to that servlet. It has something to do with a race condition or >> side effect I'm not aware off. >> >> If I do not use container authentication, HTTP sessions won't get lost. >> >> Hunting this bugs for so many weeks now and ran out of ideas. > > Tomcat will change the session identifier when the user authenticates. > If you are creating a session before login, you'll see that the session > id changes when authentication is successful. This is to protect against > session-fixation attacks. > > Can you explain why the changing session id breaks your application? Are > you storing session ids somewhere and just not updating the session id > list when the session id changes? It should be possibly to listen for > that event and update your session id list. Or maybe there's a better > way to accomplish your goal rather than keeping your own session id > list. (I'm guessing you have a session id list because it would best > explain the behavior you are describing here.) FYI, http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpSessionIdListener.html - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Is there any chance that the first and correctly authenticated cookies (despite the debug output "secure=false") are https-only cookies and won't get transmitted in http, thus triggering new sessions? E.g. any chance they get rewritten at another level (Apache httpd, ServletFilter, others) to be secure only - or that the debug output is slightly incorrect because it omits the secure flag? Olaf Am 08.01.2016 um 10:07 schrieb Thomas Scheffler: > Hi, > > I have a very rare problem regarding session handling. It is > reproducible only on a single server environment. Of cause this is the > productive server. > > I use container authentication and for simplicity 'tomcat-user.xml'. > > Login is done via HttpServletRequest.login() method, whenever I need > to access user and role information. The HttpServletRequest is saved > in a ThreadLocal during request processing. > > While that normally does the job. There is one servlet that produces > simple thumbnails that triggers a problem. Session handling is done > via Cookies. > > A search result page lists several thumbnail images and the browser > tries to load them (of cause) in parallel. > > After the first thumbnail is loaded, the sessionId suddenly changes. > As the browser now submitting the "false" sessionId, new sessions are > created and the browser gets that new sessionId in the response. The > session from the first request is lost at that point and so are the > login credentials. > > Why are sessionIds changing during the request? > > > Here are the logs I produce via a Servlet Filter: > > - REQUEST - > > [dev-mir] DEBUG MCRRequestDebugFilter: REQUEST URI: > /mir/img/pdfthumb/Document_derivate_0049/2015-05-06_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf > > Cookies: > {path=null, maxAge=-1, domain=null, name=JSESSIONID, comment=null, > httpOnly=false, secure=false, class=class javax.servlet.http.Cookie, > value=BD12BA0ED4546B5BC119727DAF97086B, version=0} > COOKIES END > > REQUEST PARAMETERS: > centerThumb: no, > REQUEST PARAMETERS END > > Session is requested by cookie. > Session is not requested by URL. > Session is valid. > SESSION BD12BA0ED4546B5BC119727DAF97086B created at: > 2016-01-07T15:18:51.068 > SESSION ATTRIBUTES: > mycore.session: {} > SESSION ATTRIBUTES END > > Header: > accept: image/png,image/*;q=0.8,*/*;q=0.5 > accept-encoding: gzip, deflate > accept-language: en-US,en;q=0.5 > cache-control: max-age=0 > connection: keep-alive > cookie: JSESSIONID=BD12BA0ED4546B5BC119727DAF97086B > host: cms.example.com:8291 > if-modified-since: Wed, 06 Jan 2016 14:40:00 GMT > if-none-match: "4e0daa3453247bcfd985ee28de9616de" > referer: > http://cms.example.com:8291/mir/servlets/solr/select?q=objectType:mods%20AND%20createdby:protokoll=mods.dateIssued%20desc > user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 > Firefox/38.0 > HEADERS END > > - RESPONSE - > > [dev-mir] DEBUG MCRRequestDebugFilter: RESPONSE URI: > /mir/img/pdfthumb/Document_derivate_0049/2015-05-06_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf > > Status: 304 > Header: > Cache-Control: max-age=31536000 > ETag: "4e0daa3453247bcfd985ee28de9616de" > Expires: Sun, 24 Jan 2016 15:30:02 GMT > Set-Cookie: JSESSIONID=0A88AABC33D336900279B2378CD510B1; Path=/mir/; > HttpOnly > HEADERS END > > > - NEXT REQUEST - > > [dev-mir] DEBUG MCRRequestDebugFilter: REQUEST URI: > /mir/img/pdfthumb/Document_derivate_0047/2015-03-25_Protokoll%20der%20Sitzung%20des%20Fakult%C3%A4tsrates_%C3%B6ffentlich.pdf > > Cookies: > {path=null, maxAge=-1, domain=null, name=JSESSIONID, comment=null, > httpOnly=false, secure=false, class=class javax.servlet.http.Cookie, > value=BD12BA0ED4546B5BC119727DAF97086B, version=0} > COOKIES END > > REQUEST PARAMETERS: > centerThumb: no, > REQUEST PARAMETERS END > > Session is requested by cookie. > Session is not requested by URL. > Session is not valid. > Header: > accept: image/png,image/*;q=0.8,*/*;q=0.5 > accept-encoding: gzip, deflate > accept-language: en-US,en;q=0.5 > cache-control: max-age=0 > connection: keep-alive > cookie: JSESSIONID=BD12BA0ED4546B5BC119727DAF97086B > host: cms.example.com:8291 > if-modified-since: Wed, 06 Jan 2016 14:40:02 GMT > if-none-match: "9e485dcd85a2b2ee373717a67c282873" > referer: > http://cms.example.com:8291/mir/servlets/solr/select?q=objectType:mods%20AND%20createdby:protokoll=mods.dateIssued%20desc > user-agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 > Firefox/38.0 > HEADERS END > > > > > [dev-mir] DEBUG MCRServlet: Setting ReqCharEncoding to: UTF-8 > [dev-mir] DEBUG MCRHttpSessionListener: HttpSession > 20934FB3493889B9EE0FB425A002BB28 is beeing created by: > org.apache.catalina.session.StandardSessionFacade@6a75756b > > - RESPONSE - > > [dev-mir] DEBUG MCRRequestDebugFilter: RESPONSE URI: >
Re: Tomcat 8.0.30 Session lost
Am 08.01.16 um 11:43 schrieb Olaf Kock: Is there any chance that the first and correctly authenticated cookies (despite the debug output "secure=false") are https-only cookies and won't get transmitted in http, thus triggering new sessions? E.g. any chance they get rewritten at another level (Apache httpd, ServletFilter, others) to be secure only - or that the debug output is slightly incorrect because it omits the secure flag? This is from a test installation on the productive server where it can only be observed. For simplicity I use the maven cargo plugin to setup the tomcat here. It shows the same behavior on the productive server, where it uses HTTPS in combination with Apache HTTPD. I use BeanUtil.describe() to produce the cookie String. So this should all be correct. This error comes up on every browser with at least a certain number of request to that servlet. It has something to do with a race condition or side effect I'm not aware off. If I do not use container authentication, HTTP sessions won't get lost. Hunting this bugs for so many weeks now and ran out of ideas. regards, Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Am 08.01.16 um 14:03 schrieb André Warnier (tomcat): Hi Thomas. It is a bit difficult to figure out where the problem really is, without having the full picture of what is going on (your web.xml configuration, the order and precise timing in which requests really happen etc.). But one thing I would really focus on, is the general overall logic of the application, to see if the order in which things happen is really consistent with the authentication method that you are using. For example, if the initial call to the first page (the one which contains the document links) does not immediately trigger a session authentication, and in the meantime the browser starts making multiple quasi-simultaneous requests for the links present in that page, then things would get out of sync, since when the authentication does happen, the session-id /will/ change (check Wikipedia for "web session fixation"). That would overwrite the session-id cookie, perhaps in the middle of the calls still being made to retrieve the document links mentioned in the page. Hi André, I would like to give some insight information on how authentication is handled. As the application can run in command line or as a web application we have a custom session handling (refer to it as 'core session'). Within the core session there is a UserInformation implementation attached. UserInformation can have different implementations and allows to ask for the user id and if the user in in a specific role. In the HttpSession we only store the sessionId of our core session. When the http session is destroyed we also close the core session. So there is only this one property "mycore.session" in the httpsession. When using servlet container authentication (error happens only with it). I need to access the request object which is stored in a ThreadLocal and released at end of the request. Here are the most important methods private void loginIfNeeded() { //getCurrentRequest() returns Optional getCurrentRequest().ifPresent(currentRequest -> { if (currentRequest.getUserPrincipal() == null) { try { currentRequest.login(user, pwd); LOGGER.debug("Re-Logged in: " + user); } catch (ServletException e) { throw new RuntimeException(e); } } }); } public String getUserID() { loginIfNeeded(); lastUser = getCurrentRequest() .flatMap(r -> Optional.ofNullable(r.getUserPrincipal())) .map(Principal::getName) .orElseGet(() -> Optional.ofNullable(lastUser) .orElseGet("guest"); return lastUser; } public boolean isUserInRole(String role) { loginIfNeeded(); return getCurrentRequest().map(r -> r.isUserInRole(role)).orElse(Boolean.FALSE); } When the user first authenticated with his login credentials we put the servlet container user information to the core session. As the HTTP session is linked to it, we just need the http session to keep track of it. The error happens to be later, (possibly) many requests after the login form that put UserInformation to the core session. So there is no racing condition at that position. You can see in the code that I need to re-login from time to time, as the request object does not always return the remote user. Why does that change the sessionId? How can I track the user than? IMHO if HttpServletRequest.login() should only be called once in a http session than getUserPrincipal() should always return a user after login() is called on one request regarding to the same session, or? But if calling login() always invalidates the old session we have a problem here. As long as request are coming in sequentially this would be OK, as the browser gets a new cookie value with every response. But browsers are out of control and want to give cpu cores a good time. Anyway. I hope you are not lost in the details and are still willing to help me. regards, Thomas - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
On 08.01.2016 10:07, Thomas Scheffler wrote: Hi, I have a very rare problem regarding session handling. It is reproducible only on a single server environment. Of cause this is the productive server. I use container authentication and for simplicity 'tomcat-user.xml'. Login is done via HttpServletRequest.login() method, whenever I need to access user and role information. The HttpServletRequest is saved in a ThreadLocal during request processing. While that normally does the job. There is one servlet that produces simple thumbnails that triggers a problem. Session handling is done via Cookies. A search result page lists several thumbnail images and the browser tries to load them (of cause) in parallel. After the first thumbnail is loaded, the sessionId suddenly changes. As the browser now submitting the "false" sessionId, new sessions are created and the browser gets that new sessionId in the response. The session from the first request is lost at that point and so are the login credentials. Why are sessionIds changing during the request? Here are the logs I produce via a Servlet Filter: [snip] Hi Thomas. It is a bit difficult to figure out where the problem really is, without having the full picture of what is going on (your web.xml configuration, the order and precise timing in which requests really happen etc.). But one thing I would really focus on, is the general overall logic of the application, to see if the order in which things happen is really consistent with the authentication method that you are using. For example, if the initial call to the first page (the one which contains the document links) does not immediately trigger a session authentication, and in the meantime the browser starts making multiple quasi-simultaneous requests for the links present in that page, then things would get out of sync, since when the authentication does happen, the session-id /will/ change (check Wikipedia for "web session fixation"). That would overwrite the session-id cookie, perhaps in the middle of the calls still being made to retrieve the document links mentioned in the page. - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org
Re: Tomcat 8.0.30 Session lost
Thomas, On 1/8/16 8:00 AM, Thomas Scheffler wrote: > Am 08.01.16 um 11:43 schrieb Olaf Kock: >> Is there any chance that the first and correctly authenticated cookies >> (despite the debug output "secure=false") are https-only cookies and >> won't get transmitted in http, thus triggering new sessions? E.g. any >> chance they get rewritten at another level (Apache httpd, ServletFilter, >> others) to be secure only - or that the debug output is slightly >> incorrect because it omits the secure flag? > > This is from a test installation on the productive server where it can > only be observed. For simplicity I use the maven cargo plugin to setup > the tomcat here. It shows the same behavior on the productive server, > where it uses HTTPS in combination with Apache HTTPD. > > I use BeanUtil.describe() to produce the cookie String. So this should > all be correct. > > This error comes up on every browser with at least a certain number of > request to that servlet. It has something to do with a race condition or > side effect I'm not aware off. > > If I do not use container authentication, HTTP sessions won't get lost. > > Hunting this bugs for so many weeks now and ran out of ideas. Tomcat will change the session identifier when the user authenticates. If you are creating a session before login, you'll see that the session id changes when authentication is successful. This is to protect against session-fixation attacks. Can you explain why the changing session id breaks your application? Are you storing session ids somewhere and just not updating the session id list when the session id changes? It should be possibly to listen for that event and update your session id list. Or maybe there's a better way to accomplish your goal rather than keeping your own session id list. (I'm guessing you have a session id list because it would best explain the behavior you are describing here.) -chris - To unsubscribe, e-mail: users-unsubscr...@tomcat.apache.org For additional commands, e-mail: users-h...@tomcat.apache.org