You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ofbiz.apache.org by David E Jones <da...@hotwaxmedia.com> on 2009/03/05 22:55:28 UTC

Cross-Site Request Forging (XSRF)

I've been thinking more about the XSRF problem and what we can do to  
make OFBiz more secure from this sort of attack. This is related to  
OFBIZ-1959 and there is more discussion and introduction to it there.

The trick is that we want to allow certain things:

1. the client's IP address can change during a session (also an  
attacker could be behind the same NAT router as the victim)
2. the client may have multiple browser windows or tabs open that are  
part of the same session
3. the client can jump from any page in an application to any other  
page in that application
4. once authenticated the client stays authenticated for the remainder  
of the session (doesn't have to re-auth for each page request)

Because of these once a user has authenticated the main secure token  
they pass around is their session ID. In many cases this session ID is  
NOT communicated in a secure, ie it is passed over the network in  
plain text (it is often in the URL, or the user may hit HTTP requests  
and HTTPS requests). In any case, if an attacker can find the  
jsessionid then they can forge a request and act like the original user.

In reality this is a problem that app servers should take care of, and  
could take care of in a generic way, but they don't (not any I know of  
anyway). For example they could do things like using different  
jsessionid values for secure and non-secure communication (ie  
different values for HTTPS and HTTP) and only allow the non-secure one  
(HTTP) to go in the URL.

Even with that in place we'd still have to do certain things, but  
these would be very doable in OFBiz. For example we'd have to make a  
few small changes so that requests with https=true simply cannot be  
accessed through HTTP (this is not strictly enforced right now). And  
even with that they may still be issues, and would certainly be issues  
for requests that don't use HTTPS.

One option is to have the framework generate a random token that is  
generated for each request so that the next request to the server MUST  
pass that token otherwise we treat it as if the user is not logged in,  
and in fact we would just logout the user and make them re-auth.  
That's an annoyance for the false positive cases, but much more secure.

The major false positive case that concerns me related to this is the  
use of 2 common browser features:

1. the back button: if you go back you'll have a page with an old  
token in the links and clicking on any link or submitting any form  
would require you to re-auth

2. multiple windows/tabs: if you begin your session in one tab, then  
open another page in the same webapp in another tab it will be part of  
the session; if you then go back to the original tab and click on  
something the random token will be stale/old and you'll have to re- 
auth, and that will cause the token to update so when you go back to  
the second tab and hit any link you'll again have to re-auth

The solution of a random token wouldn't be too hard to implement, but  
this constraint is a real pain. We could restrict this to secure pages  
only, but basically it means that for those pages users can't use the  
back button or multiple tabs/windows... and I don't like that one bit!

The only solution I can think of to this would basically make the  
whole thing useless. We could remember past tokens so that as long as  
you have one of the valid tokens for the session then it's okay.  
However, if we do that then the random tokens will be no more secure  
than the jsessionid. We could try harder to keep them more "secret",  
but if they go into a parameter or even a cookie then they aren't  
really secure. Maybe we could change all links to form submissions  
somehow... or maybe not. We'd be back to where intercepting a request  
that is part of a session could easily reveal the jsessionid AND a  
random token that would be valid for the rest of that session. Ie,  
we're back to square one.

BTW, even if we go with this, it still isn't perfect. The random  
tokens would that an attacker would have to watch for responses as all  
tokens in requests would be invalidated unless they can keep that  
request from making it to the server (a real man-in-the-middle attack  
like that is a tough one to handle!). They would have to look at  
responses to get a token and the jsessionid and then send the forged  
request before the user hits another page.

In other words, for all of this pain, especially not being able to use  
back or multiple tabs/windows, we effectively shorten the vulnerable  
time period and restrict the attack methods a bit.

================================

One thing that we could do to help with this problem, at least for  
secure pages, is to tighten things up a bit. I'm thinking of 2 things:

1. if a request has https=true then we will not accept http requests  
AT ALL, we will just return an error message (currently if it is a  
form submission we just accept it)

2. if a request has https=true we will ONLY pass encrypted data (ie  
body parameters, not URL parameters) to the service it calls; events  
may need to be changed to better support this since they have direct  
access to the request object, but for services we can easily filter  
this out; that means URL parameters will be ignored in secure requests  
that call services

These things, and perhaps others, would help this problem a lot for  
secure requests. For non-secure requests... well they aren't very  
secure anyway! ... and they would continue to be more vulnerable to  
XSRF attacks too.

Anyway, comments and suggestions would be well appreciated...

-David



Re: Cross-Site Request Forging (XSRF)

Posted by Jacques Le Roux <ja...@les7arts.com>.
I agree with Adrian. As you well explained David, we can't expect to have a totally secured without paying some price (sometimes too 
high) in usability, etc.
So yes +1 for this, I can't see a better way.

Jacques

From: "Adrian Crum" <ad...@hlmksw.com>
> David,
>
> Thank you for the thorough explanation of the problem!
>
> From my perspective, any steps taken to improve security are a benefit. At the same time, any steps taken to improve security can 
> be thwarted by a skilled hacker.
>
> I think a reasonable approach is to implement measures that improve security without impacting the user experience in a bad way. I 
> believe that is the approach you're describing. So, yes - let's go ahead and make some incremental changes.
>
> Let's keep in mind that OFBiz software doesn't stand alone in the effort to prevent attacks - the effort also requires a properly 
> configured network and well-trained users.
>
> -Adrian
>
> David E Jones wrote:
>>
>> I've been thinking more about the XSRF problem and what we can do to make OFBiz more secure from this sort of attack. This is 
>> related to OFBIZ-1959 and there is more discussion and introduction to it there.
>>
>> The trick is that we want to allow certain things:
>>
>> 1. the client's IP address can change during a session (also an attacker could be behind the same NAT router as the victim)
>> 2. the client may have multiple browser windows or tabs open that are part of the same session
>> 3. the client can jump from any page in an application to any other page in that application
>> 4. once authenticated the client stays authenticated for the remainder of the session (doesn't have to re-auth for each page 
>> request)
>>
>> Because of these once a user has authenticated the main secure token they pass around is their session ID. In many cases this 
>> session ID is NOT communicated in a secure, ie it is passed over the network in plain text (it is often in the URL, or the user 
>> may hit HTTP requests and HTTPS requests). In any case, if an attacker can find the jsessionid then they can forge a request and 
>> act like the original user.
>>
>> In reality this is a problem that app servers should take care of, and could take care of in a generic way, but they don't (not 
>> any I know of anyway). For example they could do things like using different jsessionid values for secure and non-secure 
>> communication (ie different values for HTTPS and HTTP) and only allow the non-secure one (HTTP) to go in the URL.
>>
>> Even with that in place we'd still have to do certain things, but these would be very doable in OFBiz. For example we'd have to 
>> make a few small changes so that requests with https=true simply cannot be accessed through HTTP (this is not strictly enforced 
>> right now). And even with that they may still be issues, and would certainly be issues for requests that don't use HTTPS.
>>
>> One option is to have the framework generate a random token that is generated for each request so that the next request to the 
>> server MUST pass that token otherwise we treat it as if the user is not logged in, and in fact we would just logout the user and 
>> make them re-auth. That's an annoyance for the false positive cases, but much more secure.
>>
>> The major false positive case that concerns me related to this is the use of 2 common browser features:
>>
>> 1. the back button: if you go back you'll have a page with an old token in the links and clicking on any link or submitting any 
>> form would require you to re-auth
>>
>> 2. multiple windows/tabs: if you begin your session in one tab, then open another page in the same webapp in another tab it will 
>> be part of the session; if you then go back to the original tab and click on something the random token will be stale/old and 
>> you'll have to re-auth, and that will cause the token to update so when you go back to the second tab and hit any link you'll 
>> again have to re-auth
>>
>> The solution of a random token wouldn't be too hard to implement, but this constraint is a real pain. We could restrict this to 
>> secure pages only, but basically it means that for those pages users can't use the back button or multiple tabs/windows... and I 
>> don't like that one bit!
>>
>> The only solution I can think of to this would basically make the whole thing useless. We could remember past tokens so that as 
>> long as you have one of the valid tokens for the session then it's okay. However, if we do that then the random tokens will be no 
>> more secure than the jsessionid. We could try harder to keep them more "secret", but if they go into a parameter or even a cookie 
>> then they aren't really secure. Maybe we could change all links to form submissions somehow... or maybe not. We'd be back to 
>> where intercepting a request that is part of a session could easily reveal the jsessionid AND a random token that would be valid 
>> for the rest of that session. Ie, we're back to square one.
>>
>> BTW, even if we go with this, it still isn't perfect. The random tokens would that an attacker would have to watch for responses 
>> as all tokens in requests would be invalidated unless they can keep that request from making it to the server (a real 
>> man-in-the-middle attack like that is a tough one to handle!). They would have to look at responses to get a token and the 
>> jsessionid and then send the forged request before the user hits another page.
>>
>> In other words, for all of this pain, especially not being able to use back or multiple tabs/windows, we effectively shorten the 
>> vulnerable time period and restrict the attack methods a bit.
>>
>> ================================
>>
>> One thing that we could do to help with this problem, at least for secure pages, is to tighten things up a bit. I'm thinking of 2 
>> things:
>>
>> 1. if a request has https=true then we will not accept http requests AT ALL, we will just return an error message (currently if 
>> it is a form submission we just accept it)
>>
>> 2. if a request has https=true we will ONLY pass encrypted data (ie body parameters, not URL parameters) to the service it calls; 
>> events may need to be changed to better support this since they have direct access to the request object, but for services we can 
>> easily filter this out; that means URL parameters will be ignored in secure requests that call services
>>
>> These things, and perhaps others, would help this problem a lot for secure requests. For non-secure requests... well they aren't 
>> very secure anyway! ... and they would continue to be more vulnerable to XSRF attacks too.
>>
>> Anyway, comments and suggestions would be well appreciated...
>>
>> -David
>>
>>
>>
> 



Re: Cross-Site Request Forging (XSRF)

Posted by Adrian Crum <ad...@hlmksw.com>.
David,

Thank you for the thorough explanation of the problem!

 From my perspective, any steps taken to improve security are a benefit. 
At the same time, any steps taken to improve security can be thwarted by 
a skilled hacker.

I think a reasonable approach is to implement measures that improve 
security without impacting the user experience in a bad way. I believe 
that is the approach you're describing. So, yes - let's go ahead and 
make some incremental changes.

Let's keep in mind that OFBiz software doesn't stand alone in the effort 
to prevent attacks - the effort also requires a properly configured 
network and well-trained users.

-Adrian

David E Jones wrote:
> 
> I've been thinking more about the XSRF problem and what we can do to 
> make OFBiz more secure from this sort of attack. This is related to 
> OFBIZ-1959 and there is more discussion and introduction to it there.
> 
> The trick is that we want to allow certain things:
> 
> 1. the client's IP address can change during a session (also an attacker 
> could be behind the same NAT router as the victim)
> 2. the client may have multiple browser windows or tabs open that are 
> part of the same session
> 3. the client can jump from any page in an application to any other page 
> in that application
> 4. once authenticated the client stays authenticated for the remainder 
> of the session (doesn't have to re-auth for each page request)
> 
> Because of these once a user has authenticated the main secure token 
> they pass around is their session ID. In many cases this session ID is 
> NOT communicated in a secure, ie it is passed over the network in plain 
> text (it is often in the URL, or the user may hit HTTP requests and 
> HTTPS requests). In any case, if an attacker can find the jsessionid 
> then they can forge a request and act like the original user.
> 
> In reality this is a problem that app servers should take care of, and 
> could take care of in a generic way, but they don't (not any I know of 
> anyway). For example they could do things like using different 
> jsessionid values for secure and non-secure communication (ie different 
> values for HTTPS and HTTP) and only allow the non-secure one (HTTP) to 
> go in the URL.
> 
> Even with that in place we'd still have to do certain things, but these 
> would be very doable in OFBiz. For example we'd have to make a few small 
> changes so that requests with https=true simply cannot be accessed 
> through HTTP (this is not strictly enforced right now). And even with 
> that they may still be issues, and would certainly be issues for 
> requests that don't use HTTPS.
> 
> One option is to have the framework generate a random token that is 
> generated for each request so that the next request to the server MUST 
> pass that token otherwise we treat it as if the user is not logged in, 
> and in fact we would just logout the user and make them re-auth. That's 
> an annoyance for the false positive cases, but much more secure.
> 
> The major false positive case that concerns me related to this is the 
> use of 2 common browser features:
> 
> 1. the back button: if you go back you'll have a page with an old token 
> in the links and clicking on any link or submitting any form would 
> require you to re-auth
> 
> 2. multiple windows/tabs: if you begin your session in one tab, then 
> open another page in the same webapp in another tab it will be part of 
> the session; if you then go back to the original tab and click on 
> something the random token will be stale/old and you'll have to re-auth, 
> and that will cause the token to update so when you go back to the 
> second tab and hit any link you'll again have to re-auth
> 
> The solution of a random token wouldn't be too hard to implement, but 
> this constraint is a real pain. We could restrict this to secure pages 
> only, but basically it means that for those pages users can't use the 
> back button or multiple tabs/windows... and I don't like that one bit!
> 
> The only solution I can think of to this would basically make the whole 
> thing useless. We could remember past tokens so that as long as you have 
> one of the valid tokens for the session then it's okay. However, if we 
> do that then the random tokens will be no more secure than the 
> jsessionid. We could try harder to keep them more "secret", but if they 
> go into a parameter or even a cookie then they aren't really secure. 
> Maybe we could change all links to form submissions somehow... or maybe 
> not. We'd be back to where intercepting a request that is part of a 
> session could easily reveal the jsessionid AND a random token that would 
> be valid for the rest of that session. Ie, we're back to square one.
> 
> BTW, even if we go with this, it still isn't perfect. The random tokens 
> would that an attacker would have to watch for responses as all tokens 
> in requests would be invalidated unless they can keep that request from 
> making it to the server (a real man-in-the-middle attack like that is a 
> tough one to handle!). They would have to look at responses to get a 
> token and the jsessionid and then send the forged request before the 
> user hits another page.
> 
> In other words, for all of this pain, especially not being able to use 
> back or multiple tabs/windows, we effectively shorten the vulnerable 
> time period and restrict the attack methods a bit.
> 
> ================================
> 
> One thing that we could do to help with this problem, at least for 
> secure pages, is to tighten things up a bit. I'm thinking of 2 things:
> 
> 1. if a request has https=true then we will not accept http requests AT 
> ALL, we will just return an error message (currently if it is a form 
> submission we just accept it)
> 
> 2. if a request has https=true we will ONLY pass encrypted data (ie body 
> parameters, not URL parameters) to the service it calls; events may need 
> to be changed to better support this since they have direct access to 
> the request object, but for services we can easily filter this out; that 
> means URL parameters will be ignored in secure requests that call services
> 
> These things, and perhaps others, would help this problem a lot for 
> secure requests. For non-secure requests... well they aren't very secure 
> anyway! ... and they would continue to be more vulnerable to XSRF 
> attacks too.
> 
> Anyway, comments and suggestions would be well appreciated...
> 
> -David
> 
> 
> 

Re: Cross-Site Request Forging (XSRF)

Posted by Jacques Le Roux <ja...@les7arts.com>.
Thanks David for your continued effort on this!

Jacques

From: "David E Jones" <da...@hotwaxmedia.com>
> 
> On Mar 5, 2009, at 2:55 PM, David E Jones wrote:
> 
>> One thing that we could do to help with this problem, at least for  
>> secure pages, is to tighten things up a bit. I'm thinking of 2 things:
>>
>> 1. if a request has https=true then we will not accept http requests  
>> AT ALL, we will just return an error message (currently if it is a  
>> form submission we just accept it)
>>
>> 2. if a request has https=true we will ONLY pass encrypted data (ie  
>> body parameters, not URL parameters) to the service it calls; events  
>> may need to be changed to better support this since they have direct  
>> access to the request object, but for services we can easily filter  
>> this out; that means URL parameters will be ignored in secure  
>> requests that call services
>>
>> These things, and perhaps others, would help this problem a lot for  
>> secure requests. For non-secure requests... well they aren't very  
>> secure anyway! ... and they would continue to be more vulnerable to  
>> XSRF attacks too.
> 
> In SVN rev 751501 I have implemented both of these.
> 
> For #2 there could be some forms that this breaks. I couldn't find  
> any, but if a form sent via POST has URL parameters as well as the  
> form/body parameters and a URL parameter is the same name as an IN  
> parameter for the service being called it will result in an error.  
> Basically with forms all parameters should go in form/body fields  
> (which is our common practice, and which is more secure anyway since  
> URL parameters are not encrypted).
> 
> -David
>


Re: Cross-Site Request Forging (XSRF)

Posted by David E Jones <da...@hotwaxmedia.com>.
On Mar 5, 2009, at 2:55 PM, David E Jones wrote:

> One thing that we could do to help with this problem, at least for  
> secure pages, is to tighten things up a bit. I'm thinking of 2 things:
>
> 1. if a request has https=true then we will not accept http requests  
> AT ALL, we will just return an error message (currently if it is a  
> form submission we just accept it)
>
> 2. if a request has https=true we will ONLY pass encrypted data (ie  
> body parameters, not URL parameters) to the service it calls; events  
> may need to be changed to better support this since they have direct  
> access to the request object, but for services we can easily filter  
> this out; that means URL parameters will be ignored in secure  
> requests that call services
>
> These things, and perhaps others, would help this problem a lot for  
> secure requests. For non-secure requests... well they aren't very  
> secure anyway! ... and they would continue to be more vulnerable to  
> XSRF attacks too.

In SVN rev 751501 I have implemented both of these.

For #2 there could be some forms that this breaks. I couldn't find  
any, but if a form sent via POST has URL parameters as well as the  
form/body parameters and a URL parameter is the same name as an IN  
parameter for the service being called it will result in an error.  
Basically with forms all parameters should go in form/body fields  
(which is our common practice, and which is more secure anyway since  
URL parameters are not encrypted).

-David


Re: Cross-Site Request Forging (XSRF)

Posted by Al Byers <by...@automationgroups.com>.
David,

I am just thinking out loud here, but if there were no AJAX calls, then your
original approach would work and if there were only AJAX calls then, as I
described, all the requests could be run thru a common xhr object and it
could handle the tokens. So what if we used a dual random token approach -
using some method to identify which type of token on is ( a range, a prefix,
etc.).

-Al

Re: Cross-Site Request Forging (XSRF)

Posted by David E Jones <da...@hotwaxmedia.com>.
Yes, AJAX calls are an interesting point... If AJAX requests used the  
random token even a single call would reset the token and break  
things. If they did not use the random token they are a gaping  
security hole.

I don't think we're going to do the random token thing, unless someone  
sponsors and contributes it and by default it is turned off. If we do  
the AJAX stuff will be an issue... and I can't think of a good  
solution. The thought crossed my mind of using a stateless pattern and  
have them not use the session (OFBiz services work this way by default  
anyway), but then the browser would have to pass auth credentials with  
each request, and the browser wouldn't generally know them.

Allowing X previous tokens to work opens a larger vulnerability window  
when AJAX isn't used, and for long-lived pages there could be hundreds  
of AJAX requests for a single page before the user clicks on a link to  
go to another page.

Anyway, yes that is a conundrum.

-David


On Mar 5, 2009, at 4:02 PM, Al Byers wrote:

> David,
>
> I am trying to think of the effect this will have as applications  
> have more
> and more AJAX calls. It seems like it would come down to  
> implementing a
> central object for processing such requests and the developer would  
> not need
> to worry about it, but then a mix of page requests and ajax calls  
> would be a
> problem. I guess it would just mean that every page that is loaded  
> would
> update the central ajax processing object with its token.
>
> But then, a lot of times, there are asynchronous ajax requests going  
> on that
> would make it impossible to keep a single token going. But,  
> generally, you
> would only have one secure ajax request active at a time. Did you  
> say this
> would only be for secure requests? Maybe allowing a rolling list of  
> the last
> x tokens would help in the ajax environment when you want to allow
> concurrent secure requests. Varying the size of "x" would make the  
> system
> more or less secure, right?
>
> In short, with more and more apps trying to emulate a desktop  
> environment,
> this will be more of a problem, but on the other hand, such a client- 
> side
> framework could take care of most of the work in making this happen.
>
> -Al


Re: Cross-Site Request Forging (XSRF)

Posted by Al Byers <by...@automationgroups.com>.
David,

I am trying to think of the effect this will have as applications have more
and more AJAX calls. It seems like it would come down to implementing a
central object for processing such requests and the developer would not need
to worry about it, but then a mix of page requests and ajax calls would be a
problem. I guess it would just mean that every page that is loaded would
update the central ajax processing object with its token.

But then, a lot of times, there are asynchronous ajax requests going on that
would make it impossible to keep a single token going. But, generally, you
would only have one secure ajax request active at a time. Did you say this
would only be for secure requests? Maybe allowing a rolling list of the last
x tokens would help in the ajax environment when you want to allow
concurrent secure requests. Varying the size of "x" would make the system
more or less secure, right?

In short, with more and more apps trying to emulate a desktop environment,
this will be more of a problem, but on the other hand, such a client-side
framework could take care of most of the work in making this happen.

-Al