Greetings all,
I've been researching the CSRF exploit and how it affects our web apps recently. The short story is that our code is pretty open to this at the moment. I've written up a proposal for fixing this but it will require a lot of coding so I'd love to have some more eyes on it to make sure I'm not making any stupid mistakes.
The proposal is here:: https://fedorahosted.org/fas/wiki/CSRF
The ticket for the overall CSRF fixing is here:: https://fedorahosted.org/fedora-infrastructure/ticket/992
I consider fixing this to be a fairly high priority so I'll be starting work on implementing this for a few pkgdb methods very soon. Assuming the technique works we'll need to port every method that can change data in every app to use this.
-Toshio
On Mon, 24 Nov 2008, Toshio Kuratomi wrote:
Greetings all,
I've been researching the CSRF exploit and how it affects our web apps recently. The short story is that our code is pretty open to this at the moment. I've written up a proposal for fixing this but it will require a lot of coding so I'd love to have some more eyes on it to make sure I'm not making any stupid mistakes.
The proposal is here:: https://fedorahosted.org/fas/wiki/CSRF
The ticket for the overall CSRF fixing is here:: https://fedorahosted.org/fedora-infrastructure/ticket/992
I consider fixing this to be a fairly high priority so I'll be starting work on implementing this for a few pkgdb methods very soon. Assuming the technique works we'll need to port every method that can change data in every app to use this.
This is well reasoned and inciteful. After F10 ships I've got a couple of things in the pipe to flush out but after that I'll work with you to get the major issues fixed as quickly as possible.
-Mike
On Mon, 24 Nov 2008, Mike McGrath wrote:
This is well reasoned and inciteful. After F10 ships I've got a couple of things in the pipe to flush out but after that I'll work with you to get the major issues fixed as quickly as possible.
Ugh, inciteful? really? You'd think I'd spell check these things by now :)
-Mike
On Mon, Nov 24, 2008 at 03:30:03PM -0600, Mike McGrath wrote:
On Mon, 24 Nov 2008, Mike McGrath wrote:
This is well reasoned and inciteful. After F10 ships I've got a couple of things in the pipe to flush out but after that I'll work with you to get the major issues fixed as quickly as possible.
Ugh, inciteful? really? You'd think I'd spell check these things by now :)
-Mike
Fedora-infrastructure-list mailing list Fedora-infrastructure-list@redhat.com https://www.redhat.com/mailman/listinfo/fedora-infrastructure-list
That's a riot!
On Mon November 24 2008, Toshio Kuratomi wrote:
I've been researching the CSRF exploit and how it affects our web apps recently. The short story is that our code is pretty open to this at the moment. I've written up a proposal for fixing this but it will require a lot of coding so I'd love to have some more eyes on it to make sure I'm not making any stupid mistakes.
The proposal is here:: https://fedorahosted.org/fas/wiki/CSRF
From the proposal: | make a GET request that can change state on the server
It is recommended to not use GET requests to change state on the server, therefore it would be probably better to change these GET requests to POST requests.
Regards, Till
On Tue, 25 Nov 2008, Till Maas wrote:
On Mon November 24 2008, Toshio Kuratomi wrote:
I've been researching the CSRF exploit and how it affects our web apps recently. The short story is that our code is pretty open to this at the moment. I've written up a proposal for fixing this but it will require a lot of coding so I'd love to have some more eyes on it to make sure I'm not making any stupid mistakes.
The proposal is here:: https://fedorahosted.org/fas/wiki/CSRF
From the proposal: | make a GET request that can change state on the server
It is recommended to not use GET requests to change state on the server, therefore it would be probably better to change these GET requests to POST requests.
GET vs POST is an interesting discussion. From a security point of view though the only advantage is in how we log and that GET requests stay in the logs.
Obviously though an authenticated web crawler could do accidently do some serious damage.
-Mike
On Tue November 25 2008, Mike McGrath wrote:
GET vs POST is an interesting discussion. From a security point of view though the only advantage is in how we log and that GET requests stay in the logs.
There may be also some other issues, e.g. when GET requests are used to submit confidential data, because then they may also be stored in the browsers history. But my concern was not about security issues.
Obviously though an authenticated web crawler could do accidently do some serious damage.
It would not be necessarily be serious damage, but the browser's session management could show annoying beheaviour, because then some requests could be made everytime a user restores are browser session.
Regards, Till
Till Maas wrote:
On Tue November 25 2008, Mike McGrath wrote:
GET vs POST is an interesting discussion. From a security point of view though the only advantage is in how we log and that GET requests stay in the logs.
There may be also some other issues, e.g. when GET requests are used to submit confidential data, because then they may also be stored in the browsers history. But my concern was not about security issues.
Obviously though an authenticated web crawler could do accidently do some serious damage.
It would not be necessarily be serious damage, but the browser's session management could show annoying beheaviour, because then some requests could be made everytime a user restores are browser session.
For these issues we could either concentrate on fixing or mitigating them. Fixing them would require the laborious changes I talked about earlier to change the way the framework already processes the POST and GET parameters before they get to us. Mitigation is easier -- we should make it part of our best practices to never have links or GET driven forms that make state changes when designing the UI and templates.
-Toshio
On Tue November 25 2008, Toshio Kuratomi wrote:
For these issues we could either concentrate on fixing or mitigating them. Fixing them would require the laborious changes I talked about earlier to change the way the framework already processes the POST and GET parameters before they get to us.
I guess it would be enough only to check whether the request is a POST-request without checking where the variables come from. This is maybe available in this variable: cherrypy.request.method
Mitigation is easier -- we should make it part of our best practices to never have links or GET driven forms that make state changes when designing the UI and templates.
This is also needed, if you check for the request method, because otherwise you would have broken links.
Regards, Till
Till Maas wrote:
On Tue November 25 2008, Toshio Kuratomi wrote:
For these issues we could either concentrate on fixing or mitigating them. Fixing them would require the laborious changes I talked about earlier to change the way the framework already processes the POST and GET parameters before they get to us.
I guess it would be enough only to check whether the request is a POST-request without checking where the variables come from. This is maybe available in this variable: cherrypy.request.method
The information is there. but it has to be checked. So someone would have to audit changes to see if a method now allows changes to be made without having added an error condition if the request was made via GET instead of POST. This is more on-going work than tying the check to the check for an authenticated user.
Mitigation is easier -- we should make it part of our best practices to never have links or GET driven forms that make state changes when designing the UI and templates.
This is also needed, if you check for the request method, because otherwise you would have broken links.
Right.
-Toshio
Till Maas wrote:
On Mon November 24 2008, Toshio Kuratomi wrote:
I've been researching the CSRF exploit and how it affects our web apps recently. The short story is that our code is pretty open to this at the moment. I've written up a proposal for fixing this but it will require a lot of coding so I'd love to have some more eyes on it to make sure I'm not making any stupid mistakes.
The proposal is here:: https://fedorahosted.org/fas/wiki/CSRF
From the proposal: | make a GET request that can change state on the server
It is recommended to not use GET requests to change state on the server, therefore it would be probably better to change these GET requests to POST requests.
The proposal doesn't specifically mention POST there as well but it should to make things clearer:
"Every time we submit a form or make a GET request that can change state on the server"
s/submit/POST/ /me changes that now.
The reasons the proposal is explicit about GET are:
1) We'd have to constantly audit code for places where GET is being used to alter state and change that. This is doable if the app authors are aware of this but not so scalable if it's me going through and making those changes.
2) It is hard in most web frameworks to separate GET and POST requests. The framework takes the request and abstracts whether a GET or POST was used to send the variables and just send the variables themselves into the methods. The methods that receive the calls would have to jump through hoops to tell where the variables came from.
So... if the proposal is secure for both POST and GET, I'd rather do that. If you can show where GET cannot be made secure (which is possible, I tried to examine the possibilities there and only came up with logging as a problem area but more eyes on this, the better) then we'll have to add a section for how to separate POST and GET requests in TurboGears and do periodic auditing to make sure methods which aren't marked POST-only aren't allowing changes to be made.
-Toshio
On Tue November 25 2008, Toshio Kuratomi wrote:
Till Maas wrote:
It is recommended to not use GET requests to change state on the server, therefore it would be probably better to change these GET requests to POST requests.
The proposal doesn't specifically mention POST there as well but it should to make things clearer:
"Every time we submit a form or make a GET request that can change state on the server"
s/submit/POST/ /me changes that now.
The reasons the proposal is explicit about GET are:
- We'd have to constantly audit code for places where GET is being used
to alter state and change that. This is doable if the app authors are aware of this but not so scalable if it's me going through and making those changes.
Now I am confused. Do you want to require the token for every request of an authenticated user then, regardless of whether or not they can change state on the server?
Regards, Till
Till Maas wrote:
On Tue November 25 2008, Toshio Kuratomi wrote:
Till Maas wrote:
It is recommended to not use GET requests to change state on the server, therefore it would be probably better to change these GET requests to POST requests.
The proposal doesn't specifically mention POST there as well but it should to make things clearer:
"Every time we submit a form or make a GET request that can change state on the server"
s/submit/POST/ /me changes that now.
The reasons the proposal is explicit about GET are:
- We'd have to constantly audit code for places where GET is being used
to alter state and change that. This is doable if the app authors are aware of this but not so scalable if it's me going through and making those changes.
Now I am confused. Do you want to require the token for every request of an authenticated user then, regardless of whether or not they can change state on the server?
To be easy to code, require the token for every request of an authenticated user.
-Toshio
On Wed November 26 2008, Toshio Kuratomi wrote:
To be easy to code, require the token for every request of an authenticated user.
If I understand your proposal correctly, a user would need to login again for every link he clicks from his bookmarks or any mail he gets from a Fedora webapplication, e.g. packagedb. And with every login a previous session is invalidated, which also includes links in another open browser tab, where the user logged after he clicked the previous link.
Regards, Till
Till Maas wrote:
On Wed November 26 2008, Toshio Kuratomi wrote:
To be easy to code, require the token for every request of an authenticated user.
If I understand your proposal correctly, a user would need to login again for every link he clicks from his bookmarks or any mail he gets from a Fedora webapplication, e.g. packagedb.
You are correct. This is mentioned in a different way in the "Other Notes" section:
"We can make all links between Fedora Services carry the special session information. That will allow a link from the pkgdb to bodhi to stay logged in, for example, but it will not allow a user to open up a second tab and be logged in there. So this destroys some of the single-sign-on ability that we have now."
I've now updated this to be clearer that this affects bookmarks and links in messages sent by the system.
If the proposal was to manually mark which methods make changes and only those, then we'd be able to do this instead: User can bookmark links to pages which present choices to users (like a form). The form will be submitted with the double submit method using the values of the current cookie.
The con of this is that the consequences of not marking a method are a security hole this way. One that we would have to audit the code to discover. I'm not a big fan of this tradeoff but I'm open to comments -- is this something that's so big a regression that we should bite the bullet and do it? Can we come up with another method that protects the users from failure by the programs author to properly mark the methods?
And with every login a previous session is invalidated, which also includes links in another open browser tab, where the user logged after he clicked the previous link.
So this is interesting. This is true since we wanted to remove the need to hash the tg-visit in javascript and thus the token is 100% statically derived. We could work around this in several ways:
1) In addition to checking the hash against the tg-visit, check against any non-expired session. If we did this check in the FAS server (all authentication goes back to the FAS server already) then I think that would work. So we'd send the FAS server the tg-visit cookie and the token. Then the FAS server would do the comparison of the token to the visit cookie; comparison to the visit to the current active sessions, and finally, if the token did not match the cookie, between the token and other non-expired sessions owned by the user.
This seems like a relatively simple change to the proposal (change the server in one place to do a transparent check for the rest of the code). The only question would be how easy it is to send the token to the FAS server via the TurboGears identity methods... from a brief refresher look at jsonfas I think this is doable but it would be the hardest part.
2) Change to have javascript hash the cookie dynamically. This brings in two dependencies: javascript and a hashing library. The cookie that's sent to the web site will be updated when the user logs in on the second tab. If we then switch back to the first tab and the javascript there reads the cookie value and hashes it, we will have a valid token when that's submitted. In case javascript is turned off we'd still need to include the cookie information statically, this just would be replaced in normal circumstances.
I've added #1 to the proposal for now.
-Toshio
On Wed November 26 2008, Toshio Kuratomi wrote:
Till Maas wrote:
On Wed November 26 2008, Toshio Kuratomi wrote:
To be easy to code, require the token for every request of an authenticated user.
If I understand your proposal correctly, a user would need to login again for every link he clicks from his bookmarks or any mail he gets from a Fedora webapplication, e.g. packagedb.
The con of this is that the consequences of not marking a method are a security hole this way. One that we would have to audit the code to discover. I'm not a big fan of this tradeoff but I'm open to comments -- is this something that's so big a regression that we should bite the bullet and do it? Can we come up with another method that protects the users from failure by the programs author to properly mark the methods?
How big the regression is if users have to log in for every external link they click on, depends on how often this happens. I believe that links to FAS are not exchanged very often, therefore it will not hurt very much. I guess there is also not so often a need to use FAS with tabs. But maybe there are people who have to use FAS more often. With Bodhi it is contrary, because there it is normal to get mails with links if someone added a comment to a package or for testers to exchange links to Bodhi updates. Also links to Bodhi updates are used in Bugzilla comments. There it would have a much bigger impact on the efficiency of testing new package updates imho.
Regarding the time needed for auditing applications: There may still be a lot of other vulnerabilites in these applications which cannot be fixed automatically. Therefore they still need to be written carefully. But maybe a compromise would be to require the token for all requests by default and then whitelist the ones, that are not meant to change state, e.g. requests like:
https://admin.fedoraproject.org/updates/pstreams-devel-0.6.0-6.fc10
And with every login a previous session is invalidated, which also includes links in another open browser tab, where the user logged after he clicked the previous link.
So this is interesting. This is true since we wanted to remove the need to hash the tg-visit in javascript and thus the token is 100% statically derived. We could work around this in several ways:
- In addition to checking the hash against the tg-visit, check against
any non-expired session. If we did this check in the FAS server (all authentication goes back to the FAS server already) then I think that would work. So we'd send the FAS server the tg-visit cookie and the token. Then the FAS server would do the comparison of the token to the visit cookie; comparison to the visit to the current active sessions, and finally, if the token did not match the cookie, between the token and other non-expired sessions owned by the user.
Another way would be to not change the session id if a user needs to supply the username/password again only because the token was missing. It would probably be enough to ask the user only to click a link that contains the matching token in case the token is missing.
Nevertheless it seems to me that securing all requests against CSRF automatically makes it a little easier to write a application, because the author does not need to care whether a request changes state or not. On the downside it has a high impact on usability or makes the automatic CSRF protection a lot more complicated. Also securing all requests may cost a lot of performance, because more requests need to be made. Last but not least is always more time spent on using an application than on writing it, therefore if the usability of an application is only enhanced a little, because of the many times it is used, there will be more manpower saved than is used to enhance the application.
Regards, Till
On Wed, Nov 26, 2008 at 04:53:00PM +0100, Till Maas wrote:
How big the regression is if users have to log in for every external link they click on, depends on how often this happens. I believe that links to FAS are not exchanged very often, therefore it will not hurt very much. I guess there is also not so often a need to use FAS with tabs. But maybe there are people who have to use FAS more often. With Bodhi it is contrary, because there it is normal to get mails with links if someone added a comment to a package or for testers to exchange links to Bodhi updates. Also links to Bodhi updates are used in Bugzilla comments. There it would have a much bigger impact on the efficiency of testing new package updates imho.
Regarding the time needed for auditing applications: There may still be a lot of other vulnerabilites in these applications which cannot be fixed automatically. Therefore they still need to be written carefully. But maybe a compromise would be to require the token for all requests by default and then whitelist the ones, that are not meant to change state, e.g. requests like:
https://admin.fedoraproject.org/updates/pstreams-devel-0.6.0-6.fc10
Nevertheless it seems to me that securing all requests against CSRF automatically makes it a little easier to write a application, because the author does not need to care whether a request changes state or not. On the downside it has a high impact on usability or makes the automatic CSRF protection a lot more complicated. Also securing all requests may cost a lot of performance, because more requests need to be made. Last but not least is always more time spent on using an application than on writing it, therefore if the usability of an application is only enhanced a little, because of the many times it is used, there will be more manpower saved than is used to enhance the application.
Has anyone taken a look at PubCookie? It sounds like we are trying to re-invent the wheel here, which is probably not a good idea when it comes to security-related infrastructure.
Chuck Anderson wrote:
On Wed, Nov 26, 2008 at 04:53:00PM +0100, Till Maas wrote:
How big the regression is if users have to log in for every external link they click on, depends on how often this happens. I believe that links to FAS are not exchanged very often, therefore it will not hurt very much. I guess there is also not so often a need to use FAS with tabs. But maybe there are people who have to use FAS more often. With Bodhi it is contrary, because there it is normal to get mails with links if someone added a comment to a package or for testers to exchange links to Bodhi updates. Also links to Bodhi updates are used in Bugzilla comments. There it would have a much bigger impact on the efficiency of testing new package updates imho.
Regarding the time needed for auditing applications: There may still be a lot of other vulnerabilites in these applications which cannot be fixed automatically. Therefore they still need to be written carefully. But maybe a compromise would be to require the token for all requests by default and then whitelist the ones, that are not meant to change state, e.g. requests like:
https://admin.fedoraproject.org/updates/pstreams-devel-0.6.0-6.fc10
Nevertheless it seems to me that securing all requests against CSRF automatically makes it a little easier to write a application, because the author does not need to care whether a request changes state or not. On the downside it has a high impact on usability or makes the automatic CSRF protection a lot more complicated. Also securing all requests may cost a lot of performance, because more requests need to be made. Last but not least is always more time spent on using an application than on writing it, therefore if the usability of an application is only enhanced a little, because of the many times it is used, there will be more manpower saved than is used to enhance the application.
Has anyone taken a look at PubCookie? It sounds like we are trying to re-invent the wheel here, which is probably not a good idea when it comes to security-related infrastructure.
It doesn't seem to have a way of protecting the apps from CSRF so it doesn't appear to apply directly to this situation. A very quick look at the docs seems like it's better than what we have now in that it redirects you to the actual login server for authentication instead of taking authentication on the web app and then proxying to the login server. However, it also is not flexible enough for our usage in and of itself because it only deals with authentication, not authorization. So we'd have to do quite a bit of work to integrate this.
We've been wanting to implement SSL Certificate auth which would get us away from the need for something like pubcookie in some respects as well. But there's two big barriers: 1) SSL Cert, like pub cookie is only for authentication, not authorization, 2) It looks like there's going to be some issues to work with between CSRF and SSL Certs.
-Toshio
Till Maas wrote:
On Wed November 26 2008, Toshio Kuratomi wrote:
Till Maas wrote:
On Wed November 26 2008, Toshio Kuratomi wrote:
To be easy to code, require the token for every request of an authenticated user.
If I understand your proposal correctly, a user would need to login again for every link he clicks from his bookmarks or any mail he gets from a Fedora webapplication, e.g. packagedb.
The con of this is that the consequences of not marking a method are a security hole this way. One that we would have to audit the code to discover. I'm not a big fan of this tradeoff but I'm open to comments -- is this something that's so big a regression that we should bite the bullet and do it? Can we come up with another method that protects the users from failure by the programs author to properly mark the methods?
How big the regression is if users have to log in for every external link they click on, depends on how often this happens. I believe that links to FAS are not exchanged very often, therefore it will not hurt very much. I guess there is also not so often a need to use FAS with tabs. But maybe there are people who have to use FAS more often. With Bodhi it is contrary, because there it is normal to get mails with links if someone added a comment to a package or for testers to exchange links to Bodhi updates. Also links to Bodhi updates are used in Bugzilla comments. There it would have a much bigger impact on the efficiency of testing new package updates imho.
Pretty much agreed on this analysis. My one note is that in my usage, at least, I already have to login most of the time when clicking on a link in bugzilla or email due to my session having expired already.
Regarding the time needed for auditing applications: There may still be a lot of other vulnerabilites in these applications which cannot be fixed automatically. Therefore they still need to be written carefully. But maybe a compromise would be to require the token for all requests by default and then whitelist the ones, that are not meant to change state, e.g. requests like:
https://admin.fedoraproject.org/updates/pstreams-devel-0.6.0-6.fc10
I thought of doing this but it still allows things to be insecure if what a method does gets changed and the whitelisting isn't updated.
With my proposal, the identity and the token are tied together. So you can't have an identity unless you A) have a username and password or B) have both a token and some form of alternate id (SSL Cert or cookie). Since it's natural to protect a resource by looking for a specific group, username, or just not being anonymous, you are protected from CSRF at the same time.
OTOH, if a whitelist of methods isn't updated when a form goes from merely showing information to changing data, you lose the CSRF protection.
And with every login a previous session is invalidated, which also includes links in another open browser tab, where the user logged after he clicked the previous link.
So this is interesting. This is true since we wanted to remove the need to hash the tg-visit in javascript and thus the token is 100% statically derived. We could work around this in several ways:
- In addition to checking the hash against the tg-visit, check against
any non-expired session. If we did this check in the FAS server (all authentication goes back to the FAS server already) then I think that would work. So we'd send the FAS server the tg-visit cookie and the token. Then the FAS server would do the comparison of the token to the visit cookie; comparison to the visit to the current active sessions, and finally, if the token did not match the cookie, between the token and other non-expired sessions owned by the user.
Another way would be to not change the session id if a user needs to supply the username/password again only because the token was missing. It would probably be enough to ask the user only to click a link that contains the matching token in case the token is missing.
Not changing the token can have security ramifications as it allows the browser to specify what the visit key will be once the user is authenticated. I can't think of any way for javascript to manipulate this ATM but there could be something that I'm not thinking of or browser security holes could introduce something in this area.
Nevertheless it seems to me that securing all requests against CSRF automatically makes it a little easier to write a application, because the author does not need to care whether a request changes state or not.
It not only makes it easier on the application author, it is secure if the application author does something wrong. This is the main advantage of this proposal.
On the downside it has a high impact on usability
This is the one I don't know about. It will change my usage a bit since I'll need to start clicking on links to the other apps in present app pages to open new tabs. But when I usually open links from external sources I'm already used to having to re-login due to the session expiring. So we need feedback here, do you often click on multiple things in close proximity and wouldn't be able to change to clicking within the app? Are you able to
or makes the automatic CSRF protection a lot more complicated.
This one's untrue as seen in the revised proposal.
Also securing all requests may cost a lot of performance, because more requests need to be made.
This one is probably not correct either. If the token and the tg-visit match, there's no extra request. If the token and tg-visit do not match, there's one extra request from FAS to the database. There are no extra json calls.
Last but not least is always more time spent on using an application than on writing it, therefore if the usability of an application is only enhanced a little, because of the many times it is used, there will be more manpower saved than is used to enhance the application.
This is true. But weighed against it is that usability takes a backseat to security. So is the usability loss high enough that we just have to be more vigilant in making sure that our list of secure/non-secure methods is kept up-to-date or is the security risk of people trying to hack us low enough that we can deal with the occasional bug that opens up a security vulnerability (which we won't find without auditing the code)?
Or best of all, can we add some other check that allows us to preserve the present usability and still refuse state-changing events if they haven't been marked as such.
-Toshio
On Wed, Nov 26, 2008 at 09:47:06AM -0800, Toshio Kuratomi wrote:
Pretty much agreed on this analysis. My one note is that in my usage, at least, I already have to login most of the time when clicking on a link in bugzilla or email due to my session having expired already.
Stange. I almost never have to re-login to bugzilla once I've logged in on a particular system.
Chuck Anderson wrote:
On Wed, Nov 26, 2008 at 09:47:06AM -0800, Toshio Kuratomi wrote:
Pretty much agreed on this analysis. My one note is that in my usage, at least, I already have to login most of the time when clicking on a link in bugzilla or email due to my session having expired already.
Stange. I almost never have to re-login to bugzilla once I've logged in on a particular system.
We're talking about comments added to bugzilla that link to the Fedora Web Applications (pkgdb, bodhi, etc).
Bugzilla has its own cookies and authentication structure that we won't be messing with as part of this.
-Toshio
On Wed November 26 2008, Toshio Kuratomi wrote:
Till Maas wrote:
How big the regression is if users have to log in for every external link they click on, depends on how often this happens. I believe that links to FAS are not exchanged very often, therefore it will not hurt very much. I guess there is also not so often a need to use FAS with tabs. But maybe there are people who have to use FAS more often. With Bodhi it is contrary, because there it is normal to get mails with links if someone added a comment to a package or for testers to exchange links to Bodhi updates. Also links to Bodhi updates are used in Bugzilla comments. There it would have a much bigger impact on the efficiency of testing new package updates imho.
Pretty much agreed on this analysis. My one note is that in my usage, at least, I already have to login most of the time when clicking on a link in bugzilla or email due to my session having expired already.
But in the future you would have to do this for every link everytime, even if you use many of them in a short timeframe.
Regarding the time needed for auditing applications: There may still be a lot of other vulnerabilites in these applications which cannot be fixed automatically. Therefore they still need to be written carefully. But maybe a compromise would be to require the token for all requests by default and then whitelist the ones, that are not meant to change state, e.g. requests like:
https://admin.fedoraproject.org/updates/pstreams-devel-0.6.0-6.fc10
I thought of doing this but it still allows things to be insecure if what a method does gets changed and the whitelisting isn't updated.
What it am apllication writer does not require authentication for some action that should require authentication? With this reasoning you could also require that every request has to be authenticated. Also do the actions behind a certain request / URL really change that often?
OTOH, if a whitelist of methods isn't updated when a form goes from merely showing information to changing data, you lose the CSRF protection.
If you also do not add proper authentication if a method gets updated to show confidential information, you lose the protection of the confidential information.
Is it maybe possible to modify the functions behind the API that are used to change state to require a valid token? Then the author of the webapplication needs to activly work agains the CSRF protection instead of accidently forgetting it.
Another way would be to not change the session id if a user needs to supply the username/password again only because the token was missing. It would probably be enough to ask the user only to click a link that contains the matching token in case the token is missing.
Not changing the token can have security ramifications as it allows the browser to specify what the visit key will be once the user is authenticated. I can't think of any way for javascript to manipulate this ATM but there could be something that I'm not thinking of or browser security holes could introduce something in this area.
How is it different to keep the same session id after sending a valid session id and token to the server than to keep it after sending a valid session and a username / password combination?
On the downside it has a high impact on usability
This is the one I don't know about. It will change my usage a bit since I'll need to start clicking on links to the other apps in present app pages to open new tabs. But when I usually open links from external sources I'm already used to having to re-login due to the session expiring. So we need feedback here, do you often click on multiple things in close proximity and wouldn't be able to change to clicking within the app? Are you able to
If I send you a bunch of links that point to Bodhi updates and your job is to add one comment to each update, then you have to provide your username and password once for each link. Currently you would only login once for the first link and open the others afterwards. I use as often as possible direct links from mails or bookmarks, because clicking through the webapp to get to a certain location takes a lot more time.
or makes the automatic CSRF protection a lot more complicated.
This one's untrue as seen in the revised proposal.
The revised proposal is not yet as usable as the current situation.
Also securing all requests may cost a lot of performance, because more requests need to be made.
This one is probably not correct either. If the token and the tg-visit match, there's no extra request. If the token and tg-visit do not match, there's one extra request from FAS to the database. There are no extra json calls.
If one has to click through the webapp instead of clicking directly on a link, there are also a lot more requests. Also if one can have multiple valid session ids, then more need to be stored on the server.
Or best of all, can we add some other check that allows us to preserve the present usability and still refuse state-changing events if they haven't been marked as such.
Imho this is not possible, because to refuse state-changing events, you need to be able to distinguish them from other events. If you have an algorithm for this, you can use it to mark thes events.
Regards, Till
Till Maas wrote:
On Wed November 26 2008, Toshio Kuratomi wrote:
Till Maas wrote:
How big the regression is if users have to log in for every external link they click on, depends on how often this happens. I believe that links to FAS are not exchanged very often, therefore it will not hurt very much. I guess there is also not so often a need to use FAS with tabs. But maybe there are people who have to use FAS more often. With Bodhi it is contrary, because there it is normal to get mails with links if someone added a comment to a package or for testers to exchange links to Bodhi updates. Also links to Bodhi updates are used in Bugzilla comments. There it would have a much bigger impact on the efficiency of testing new package updates imho.
Pretty much agreed on this analysis. My one note is that in my usage, at least, I already have to login most of the time when clicking on a link in bugzilla or email due to my session having expired already.
But in the future you would have to do this for every link everytime, even if you use many of them in a short timeframe.
Yes, I'm just wondering whether this is the normal usage because it isn't mine. As noted, I have to relogin nearly everytime I click on an external link because my session expires. (note: links inside of Fedora Apps and between Fedora Apps would carry the token so they wouldn't be subject to a relogin).
Regarding the time needed for auditing applications: There may still be a lot of other vulnerabilites in these applications which cannot be fixed automatically. Therefore they still need to be written carefully. But maybe a compromise would be to require the token for all requests by default and then whitelist the ones, that are not meant to change state, e.g. requests like:
https://admin.fedoraproject.org/updates/pstreams-devel-0.6.0-6.fc10
I thought of doing this but it still allows things to be insecure if what a method does gets changed and the whitelisting isn't updated.
What it am apllication writer does not require authentication for some action that should require authentication? With this reasoning you could also require that every request has to be authenticated.
This is different. It's very natural to think about user permissions when making a change. Just like Unix filesystem permissions, we're asking, does this user have permission to do this?
Protecting against CSRF is different. It's asking whether the user really made the request or if it was only the user's browser making the request. That's not a natural thing to check for.
Also do the actions behind a certain request / URL really change that often?
I don't know the answer to how often but the actions do change sometimes. For instance, a URL can be used to display a comment form on an update. When you submit a comment you are brought back to the comment form with the new comment added. So there's two ways to write this: Either the action could submit to a new URL and the URL redirects back to the comment form URL once the request is processed or the action could submit to the same URL with the comment form's inputs as optional arguments. In Bodhi the first method is presently chosen. If it is recoded to the second method, marking for the purposes of CSRF protection would need to be updated.
OTOH, if a whitelist of methods isn't updated when a form goes from merely showing information to changing data, you lose the CSRF protection.
If you also do not add proper authentication if a method gets updated to show confidential information, you lose the protection of the confidential information.
This is addressed above.
Is it maybe possible to modify the functions behind the API that are used to change state to require a valid token? Then the author of the webapplication needs to activly work agains the CSRF protection instead of accidently forgetting it.
This is something I thought for a bit on. However I'm not 100% satisfied with what can be done here.
In the present pkgdb, session.flush() must be called anytime data is changed in the database. So we could override that method to add this protection.
In FAS, adding a new certificate is not recorded in the database so overriding flush() is not enough to protect that.
In bodhi we're still using SQLObject so we'd have to override the equivalent of flush() there as well.
Additionally, there's autoflush methods that can be turned on in the database adapters. If a TG app uses autoflush, then we won't have a hook to override in this manner.
Another way would be to not change the session id if a user needs to supply the username/password again only because the token was missing. It would probably be enough to ask the user only to click a link that contains the matching token in case the token is missing.
Not changing the token can have security ramifications as it allows the browser to specify what the visit key will be once the user is authenticated. I can't think of any way for javascript to manipulate this ATM but there could be something that I'm not thinking of or browser security holes could introduce something in this area.
How is it different to keep the same session id after sending a valid session id and token to the server than to keep it after sending a valid session and a username / password combination?
I'm thinking of vulnerabilities when we add SSL Certs here instead of username/password.
Sending session + username/password tells us that the user is in charge of the request.
Sending session + token tells us that the browser was able to read information from the response so the same-origin-policy should protect us.
Sending session + SSL Cert does not tell us anything as the browser uses both cookies and SSL Certs when making a call to a different domain at the behest of a web page. Keeping the same session id in this case could be dangerous if there are flaws in the browser or the server code that allow the malicious web page to set the session cookie.
On the downside it has a high impact on usability
This is the one I don't know about. It will change my usage a bit since I'll need to start clicking on links to the other apps in present app pages to open new tabs. But when I usually open links from external sources I'm already used to having to re-login due to the session expiring. So we need feedback here, do you often click on multiple things in close proximity and wouldn't be able to change to clicking within the app? Are you able to
If I send you a bunch of links that point to Bodhi updates and your job is to add one comment to each update, then you have to provide your username and password once for each link. Currently you would only login once for the first link and open the others afterwards.
But this isn't my job. It's a hypothetical.
I use as often as possible direct links from mails or bookmarks, because clicking through the webapp to get to a certain location takes a lot more time.
<nod> So would it be better to fix the web app's UI?
or makes the automatic CSRF protection a lot more complicated.
This one's untrue as seen in the revised proposal.
The revised proposal is not yet as usable as the current situation.
True. But the current situation is less secure than the proposal. So we need to understand the relative value of each rather than aiming for something that is as usable as currently.
Also securing all requests may cost a lot of performance, because more requests need to be made.
This one is probably not correct either. If the token and the tg-visit match, there's no extra request. If the token and tg-visit do not match, there's one extra request from FAS to the database. There are no extra json calls.
If one has to click through the webapp instead of clicking directly on a link, there are also a lot more requests.
This might be true. Although better UI could resolve that.
Also if one can have multiple valid session ids, then more need to be stored on the server.
The server already stores these so there's not more information here.
Or best of all, can we add some other check that allows us to preserve the present usability and still refuse state-changing events if they haven't been marked as such.
Imho this is not possible, because to refuse state-changing events, you need to be able to distinguish them from other events. If you have an algorithm for this, you can use it to mark thes events.
Rather than impossible, I think that catching things at the session.flush() call is a step towards this. But there's a sacrifice in flexibility in doing things here that I'm not certain we can enforce.
-Toshio
infrastructure@lists.fedoraproject.org