Make sure form submissions that cause server-side changes use your own forms. There are two ways you can do this:
Check the referrer header. If it is not present, or if it does not show the correct URL as the referrer, reject the submission. This has the advantage of being simple and sane, but the disadvantage that users who have told their browsers to omit the referrer header (out of concern for privacy) or lie about the referrer (in order to gain access to porn sites that use the referrer for the wrong purpose) will have trouble. This strategy doesn't work if the form uses GET and the page can contain user-generated content with links. Include a hidden field in the form and check its value when the form is submitted. A simple scheme is to use an MD5 hash of the login cookie, some information about the form, and a secret on the server. Another possibility is to use a randomly generated one-time key for every form you serve, assuming you have a sufficiently unpredictable source of random numbers. This has the disadvantage of making it unsafe for users to save the HTML for forms and upload them to, say, bug databases.
Since so few sites protect their visitors against CSRF attacks, browser makers have discussed possible client-side fixes for CSRF. We didn't come up with anything good. For reference, see bug 38933, bug 40132, bug 246476, and bug 246519. At most, browsers might be able to prevent CSRFs from web sites to intranet sites, but not between web sites. Other common holes
Don't put private user data or restricted-access data in JavaScript files whose URLs can be guessed. JavaScript files can be included from sites in other domains, and they will be executed on the attacker's domain. The only thing keeping most HTML and text files from being read this way is that they result in JavaScript syntax errors. One way to avoid this kind of hole is to serve HTML files containing scripts (to be loaded in hidden iframes) rather than naked scripts.
Example: Bugzilla was vulnerable for a short time when it allowed bug lists to be returned in a JavaScript format (bug 195530. While bug lists do not contain user data, they sometimes include information about restricted-access bug reports. Example: An early version of Gmail served contact lists as an array literal. Even through the array was not referenced, it was possible to determine the contents of the array by overriding the Array constructor.
Don't load an untrusted site in a frame. The site will be able to load data into other frames, leading to a spoofing attack. If you visitors use Internet Explorer, don't use frames at all, because other sites can replace your site's frames. See bug 246448 for more information.
Don't put passwords (or any data that should remain private) in a URL if the page at that URL contains external links. When users click those links, the entire URL is sent as a referrer. https sites are not safe, because links to other https sites include the full referrer.
If your site is http://www.amazon.co.uk/, your server should ignore cookies that are set for all of co.uk. This is difficult if you use cookies in client-side JavaScript, but it can be done. Future versions of Firefox will disallow setting cookies for all of "co.uk" the same way it disallows setting cookies for all of "com" (bug 252342).
If your page is designed to be displayed as an iframe on other sites, you may want specify a background color. If your page is displayed in an <yframe> and does not specify a background color, the background will be transparent, not white (bug 154957).
Even if you protect against traditional CSRF attacks, malicious sites can make users click parts of your site without realizing it. Examples of attacks include sub-reaction-time page changes, pages that load your site in an iframe and cover all but an 8px-by-8px portion of the iframe, and pages that load your site in a 99% transparent iframe. Removing "One-click purchase" buttons helps, but only a little. One possible solution to the attacks involving iframes is to add a script that detects when the page is loaded in a frame and prevents form posting. (This solution should not be confused with the classical "break out of frames" script; it needs to be faster than that.)
If you echo site-relative URLs, be careful not to echo "relative" URLs starting with //. These are interpreted as being relative to the protocol rather than relative to the site. Bugzilla once had a bug where the login form could be made to submit off-site: bug 325079.
0
comments, (708 reads) All Articles by, GentleGiant