You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Brian Burch <br...@pingtoo.com> on 2012/09/23 11:46:47 UTC

AuthenticatorBase setChangeSessionIdOnAuthentication without cookies

With reference to:

https://issues.apache.org/bugzilla/show_bug.cgi?id=53584

I reproduced the problem using the sample war on a back-level svn 
version of the trunk, then confirmed the problem was fixed on a later level.

I have been developing a new unit test case in 
org.apache.catalina.authenticator.TestFormAuthenticator to reproduce the 
behaviour demonstrated by the war. However, my new test failed because 
the client was challenged to relogin after successful authentication, 
even though it provided the correct jsessionid parameter value on 
subsequent GETs to the protected resource.

I discovered the default behaviour for AuthenticatorBase is to ask the 
Session Manager to generate a new sessionid after authentication. This 
behaviour seems to be intended to prevent session fixation attacks.

However, in the case where the client is not using cookies (my test 
disables them for its Context), there does not appear to be a way for 
the server to communicate the new jsessionid value to the client. The 
client has no idea that this has happened, so it appends the original 
session id to the next GET request. The Authenticator cannot find the 
original session id (it is deleted when the new one is generated), so it 
issues a new login challenge to the supposedly-unauthenticated client. 
In other words, the authentication is applied to just one request, 
rather than all subsequent requests.

I modified my test to traverse the Valve pipeline and set the 
FormAuthenticator changeSessionIdOnAuthentication flag to false. The 
test now works as intended.

Have I misunderstood the situation? If not, then two issues concern me:

1. It seems as if a session that does not use cookies and is prepared to 
use url rewriting will only work when the 
changeSessionIdOnAuthentication logic is disabled, or is there some way 
to get the new session id sent to the http client? [The demonstration 
war uses jsps which use response.encodeURL("j_security_check"), and 
response.sendRedirect(response.encodeRedirectURL("index.jsp")), which 
append the current jsessionid to the url.]

2. I can see AuthenticatorBase.changeSessionIdOnAuthentication is an 
instance variable. I am concerned about the scope of the Valve instance 
- I normally code my Valves at the Host level in server.xml, but not, of 
course, the Authenticators, which are defined by the login-config 
section of each webapp's web.xml. Does each Context have its own 
instance of the authenticator valve?

I would like to be sure of my understanding before proposing the test 
case as an enhancement, so any comments or advice would be helpful.

Thanks,

Brian

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: AuthenticatorBase setChangeSessionIdOnAuthentication without cookies

Posted by Brian Burch <br...@pingtoo.com>.
On 24/09/12 19:50, Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> Brian,
>
> On 9/23/12 5:46 AM, Brian Burch wrote:
>> However, in the case where the client is not using cookies (my
>> test disables them for its Context), there does not appear to be a
>> way for the server to communicate the new jsessionid value to the
>> client.
>
> How does the client get the session id in the first place if there
> aren't any cookies?

Sorry to suck you into this topic... unless it really interests you!

I explained at the start of this thread that I was writing a new unit 
test case to replicate bz53584. I was having trouble making it 
demonstrate Mark's fix, so I knew I had introduced a new failure mode - 
I just didn't understand it.

I am not nit-picking for every single corner case, but I want to expand 
the unit test case set for the FormsAuthenticator to include bz53584, 
but also any fairly plausible variants of it.

I hope you will find the general answer to your question in my 
continuing discussion with Mark on this thread.

However, if I understand you correctly, the answer (within the context 
of TestFormAuthenticator) is that the (junit) client gets the initial 
jsessionid by screen-scraping the j_security_check FORM's action 
parameter, which has been encoded by the 
/examples/jsp/security/protected/login.jsp.

> You should repeat that process for every response
> you get from the server.

You are correct. Once I understood what was going wrong with my 
prototype test case, I clarified my understanding with Mark's help and 
more research. The new version of the test is obliged to screen-scrape 
the new jsessionid value out of subsequent server responses, which are 
properly encoded by index.jsp.

Thanks for prompting me to explain. This thread might turn out to be 
useful in future, and I don't want to leave red herrings (mine, at 
least) lying about.

Regards,

Brian

> - -chris
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
> Comment: GPGTools - http://gpgtools.org
> Comment: Using GnuPG with Mozilla - http://www.enigmail.net/
>
> iEYEARECAAYFAlBgq30ACgkQ9CaO5/Lv0PD1EgCgjtt4+YUdhQZUL6ti+SoEnR0j
> TnYAnjWacJEwnYNtVqqJiydaJSmsiXu2
> =W12C
> -----END PGP SIGNATURE-----
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: AuthenticatorBase setChangeSessionIdOnAuthentication without cookies

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Brian,

On 9/23/12 5:46 AM, Brian Burch wrote:
> However, in the case where the client is not using cookies (my
> test disables them for its Context), there does not appear to be a
> way for the server to communicate the new jsessionid value to the
> client.

How does the client get the session id in the first place if there
aren't any cookies? You should repeat that process for every response
you get from the server.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
Comment: GPGTools - http://gpgtools.org
Comment: Using GnuPG with Mozilla - http://www.enigmail.net/

iEYEARECAAYFAlBgq30ACgkQ9CaO5/Lv0PD1EgCgjtt4+YUdhQZUL6ti+SoEnR0j
TnYAnjWacJEwnYNtVqqJiydaJSmsiXu2
=W12C
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: AuthenticatorBase setChangeSessionIdOnAuthentication without cookies

Posted by Brian Burch <br...@pingtoo.com>.
On 24/09/12 17:52, Mark Thomas wrote:
> On 24/09/2012 11:41, Brian Burch wrote:
>
>> I draw the following conclusions:
>>
>> 1. A client that can accept a Set-Cookie for JSESSIONID will be able to
>> maintain a persistent session (is that incorrectly overloading a
>> reserved word?), no matter whether the session ID is changed once, many
>> times, or not at all.
>
> Correct.
>
>> 2. A client that cannot accept cookies will only be able to maintain a
>> persistent session IF the server sends the correct (current) jsessionid
>> as a path parameter appended to ALL urls within its response. That is
>> achievable with servlets, jsps, jstl (all of which which can ask for an
>> encoded url to be inserted into the dynamic web page). It cannot work
>> with static html.
>
> Correct - Unless one starts parsing the static HTML e.g. via a filter
> and adding the path parameter. Messy but doable. There might even be a
> filter out there that does this. For example, httpd has a module that
> does this
>
>> 3. Therefore, any webapp that MIGHT need to authenticate a client that
>> does not accept cookies MUST generate EVERY protected resource url
>> dynamically (to include the session ID).
>
> Correct - part from the option above.
>
>> 4. Any webapp that cannot satify case 3 MUST turn off
>> changeSessionIdOnAuthentication for its Context and degrade the session
>> fixation protection for ALL of its clients.
>
> No sure I agree with this. If the URLs aren't being encoded then the
> session is going to break regardless of whether or not the session ID
> changes.

Thanks Mark, I interpret your comment to be applicable to "proper 
browser" behaviour, which is the appropriate context for a discussion on 
the users list.

Unlike a "proper browser", the tomcat junit test class does a quite lot 
of screen-scraping and cheating of headers and urls (not very elegant, 
but it makes no claims to generality). My additional code was able to 
easily identify the initial jsessionid, but detecting and handling a 
changed value turned out to be more convoluted.

I think this thread can be wrapped up now without (hopefully) causing 
confusion to future readers.

Regards,

Brian

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: AuthenticatorBase setChangeSessionIdOnAuthentication without cookies

Posted by Mark Thomas <ma...@apache.org>.
On 24/09/2012 11:41, Brian Burch wrote:

> I draw the following conclusions:
> 
> 1. A client that can accept a Set-Cookie for JSESSIONID will be able to
> maintain a persistent session (is that incorrectly overloading a
> reserved word?), no matter whether the session ID is changed once, many
> times, or not at all.

Correct.

> 2. A client that cannot accept cookies will only be able to maintain a
> persistent session IF the server sends the correct (current) jsessionid
> as a path parameter appended to ALL urls within its response. That is
> achievable with servlets, jsps, jstl (all of which which can ask for an
> encoded url to be inserted into the dynamic web page). It cannot work
> with static html.

Correct - Unless one starts parsing the static HTML e.g. via a filter
and adding the path parameter. Messy but doable. There might even be a
filter out there that does this. For example, httpd has a module that
does this

> 3. Therefore, any webapp that MIGHT need to authenticate a client that
> does not accept cookies MUST generate EVERY protected resource url
> dynamically (to include the session ID).

Correct - part from the option above.

> 4. Any webapp that cannot satify case 3 MUST turn off
> changeSessionIdOnAuthentication for its Context and degrade the session
> fixation protection for ALL of its clients.

No sure I agree with this. If the URLs aren't being encoded then the
session is going to break regardless of whether or not the session ID
changes.

> Do you agree, or have I misunderstood something in my analysis?

Mark

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: AuthenticatorBase setChangeSessionIdOnAuthentication without cookies

Posted by Brian Burch <br...@pingtoo.com>.
On 23/09/12 11:10, Mark Thomas wrote:

Thanks for looking at my questions, Mark. I hoped you would find time, 
because you fixed the original bug quite recently and would still 
remember the rather convoluted logic for FORM authentication.

> On 23/09/2012 10:46, Brian Burch wrote:
>> With reference to:
>>
>> https://issues.apache.org/bugzilla/show_bug.cgi?id=53584
>>
>> I reproduced the problem using the sample war on a back-level svn
>> version of the trunk, then confirmed the problem was fixed on a later
>> level.
>>
>> I have been developing a new unit test case in
>> org.apache.catalina.authenticator.TestFormAuthenticator to reproduce the
>> behaviour demonstrated by the war. However, my new test failed because
>> the client was challenged to relogin after successful authentication,
>> even though it provided the correct jsessionid parameter value on
>> subsequent GETs to the protected resource.
>>
>> I discovered the default behaviour for AuthenticatorBase is to ask the
>> Session Manager to generate a new sessionid after authentication. This
>> behaviour seems to be intended to prevent session fixation attacks.
>
> Correct.
>
>> However, in the case where the client is not using cookies (my test
>> disables them for its Context), there does not appear to be a way for
>> the server to communicate the new jsessionid value to the client. The
>> client has no idea that this has happened, so it appends the original
>> session id to the next GET request. The Authenticator cannot find the
>> original session id (it is deleted when the new one is generated), so it
>> issues a new login challenge to the supposedly-unauthenticated client.
>> In other words, the authentication is applied to just one request,
>> rather than all subsequent requests.
>
> The new session ID will be encoded in the URLs sent back to the client
> (assuming that the application uses the API to encode them).
>
>> I modified my test to traverse the Valve pipeline and set the
>> FormAuthenticator changeSessionIdOnAuthentication flag to false. The
>> test now works as intended.
>>
>> Have I misunderstood the situation?
>
> I'm not sure.
>
>> If not, then two issues concern me:
>>
>> 1. It seems as if a session that does not use cookies and is prepared to
>> use url rewriting will only work when the
>> changeSessionIdOnAuthentication logic is disabled, or is there some way
>> to get the new session id sent to the http client? [The demonstration
>> war uses jsps which use response.encodeURL("j_security_check"), and
>> response.sendRedirect(response.encodeRedirectURL("index.jsp")), which
>> append the current jsessionid to the url.]
>
> Post authentication, they should return the new session ID back to the
> client. If they are returning the old ID

... or no ID at all ...

> then that is a problem.

I draw the following conclusions:

1. A client that can accept a Set-Cookie for JSESSIONID will be able to 
maintain a persistent session (is that incorrectly overloading a 
reserved word?), no matter whether the session ID is changed once, many 
times, or not at all.

2. A client that cannot accept cookies will only be able to maintain a 
persistent session IF the server sends the correct (current) jsessionid 
as a path parameter appended to ALL urls within its response. That is 
achievable with servlets, jsps, jstl (all of which which can ask for an 
encoded url to be inserted into the dynamic web page). It cannot work 
with static html.

3. Therefore, any webapp that MIGHT need to authenticate a client that 
does not accept cookies MUST generate EVERY protected resource url 
dynamically (to include the session ID).

4. Any webapp that cannot satify case 3 MUST turn off 
changeSessionIdOnAuthentication for its Context and degrade the session 
fixation protection for ALL of its clients.

Do you agree, or have I misunderstood something in my analysis?

>> 2. I can see AuthenticatorBase.changeSessionIdOnAuthentication is an
>> instance variable. I am concerned about the scope of the Valve instance
>> - I normally code my Valves at the Host level in server.xml, but not, of
>> course, the Authenticators, which are defined by the login-config
>> section of each webapp's web.xml. Does each Context have its own
>> instance of the authenticator valve?
>
> Yes. A quick check with JConsole will confirm this.
>
>> I would like to be sure of my understanding before proposing the test
>> case as an enhancement, so any comments or advice would be helpful.
>
> HTH,

Yes, a lot, thanks! I have enough clarity of thought to get on with the 
new test case now.

> Mark
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: AuthenticatorBase setChangeSessionIdOnAuthentication without cookies

Posted by Mark Thomas <ma...@apache.org>.
On 23/09/2012 10:46, Brian Burch wrote:
> With reference to:
> 
> https://issues.apache.org/bugzilla/show_bug.cgi?id=53584
> 
> I reproduced the problem using the sample war on a back-level svn
> version of the trunk, then confirmed the problem was fixed on a later
> level.
> 
> I have been developing a new unit test case in
> org.apache.catalina.authenticator.TestFormAuthenticator to reproduce the
> behaviour demonstrated by the war. However, my new test failed because
> the client was challenged to relogin after successful authentication,
> even though it provided the correct jsessionid parameter value on
> subsequent GETs to the protected resource.
> 
> I discovered the default behaviour for AuthenticatorBase is to ask the
> Session Manager to generate a new sessionid after authentication. This
> behaviour seems to be intended to prevent session fixation attacks.

Correct.

> However, in the case where the client is not using cookies (my test
> disables them for its Context), there does not appear to be a way for
> the server to communicate the new jsessionid value to the client. The
> client has no idea that this has happened, so it appends the original
> session id to the next GET request. The Authenticator cannot find the
> original session id (it is deleted when the new one is generated), so it
> issues a new login challenge to the supposedly-unauthenticated client.
> In other words, the authentication is applied to just one request,
> rather than all subsequent requests.

The new session ID will be encoded in the URLs sent back to the client
(assuming that the application uses the API to encode them).

> I modified my test to traverse the Valve pipeline and set the
> FormAuthenticator changeSessionIdOnAuthentication flag to false. The
> test now works as intended.
> 
> Have I misunderstood the situation?

I'm not sure.

> If not, then two issues concern me:
> 
> 1. It seems as if a session that does not use cookies and is prepared to
> use url rewriting will only work when the
> changeSessionIdOnAuthentication logic is disabled, or is there some way
> to get the new session id sent to the http client? [The demonstration
> war uses jsps which use response.encodeURL("j_security_check"), and
> response.sendRedirect(response.encodeRedirectURL("index.jsp")), which
> append the current jsessionid to the url.]

Post authentication, they should return the new session ID back to the
client. If they are returning the old ID then that is a problem.

> 2. I can see AuthenticatorBase.changeSessionIdOnAuthentication is an
> instance variable. I am concerned about the scope of the Valve instance
> - I normally code my Valves at the Host level in server.xml, but not, of
> course, the Authenticators, which are defined by the login-config
> section of each webapp's web.xml. Does each Context have its own
> instance of the authenticator valve?

Yes. A quick check with JConsole will confirm this.

> I would like to be sure of my understanding before proposing the test
> case as an enhancement, so any comments or advice would be helpful.

HTH,

Mark


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org