CSRF EXPLOIT PREVENTION
Most of the prevention tactics involve requiring extra information with requests that deal with sensitive data. This extra information is usually a random token passed with the form submission or via cookie. When your web application handles these requests, it must take care to validate the token and reject any requests that fail to provide a valid token.
NOTE: Most of these defense tactics involve displaying a token in a form and then validating it in the form handler. One might naturally ask what prevents an attacker from simply creating some fancy Javascript that can create numerous page requests via AJAX such that the token can be fetched and then utilized in a subsequent exploit request (see Example 2 in prior post). The answer, as far as I can tell is the same-origin policy which is supposed to be enforced by web browsers. Briefly summarized, the same-origin policy makes it very hard for a script on one domain to formulate requests for another which provide all the authentication cookies. However, it is possible to configure one's server to permit such requests. It seems to be fairly complicated, however, and further research is recommended.
PREVENTION BY SYNCHRONIZER TOKEN
The Synchronizer Token Pattern involves generating a cryptographically secure token to supply with one's request. (See OWASP and Wikipedia descriptions and examples of this pattern and the requirements for the token. The token is typically added to a form as hidden input, appended to a url, etc. and then validated by the web application's handling script to make sure it's valid before proceeding with the sensitive data request. This is usually accomplished by checking any submitted token against an individual user's session.
OWASP offers some suggested PHP code to prevent CSRF. Personally, I wonder if this code, which looks like a shim for existing code is especially helpful. Issues:
the tokens are merely displayed in the form and should persist as long as the session does. A CSRF attack that was able to form multiple AJAX requests could read this form, extract CSRFName and CSRFToken, and then submit another request using these values. This would probably trigger a CORS warning as it seesm to in firefox, but the method does not seem especially secure to me
it does not use a cryptographically secure token generation method.
As with most synchronizer token approaches, a user clicking 'back' on their browser after a form submission might end up submitting the same token twice which would be rejected by the server.
Note that synchronizer token can complicate AJAX implementations. One would need to implement a method to supply a new synchronizer token via AJAX request. These tokens must be unique for a given session or this approach will not work. I.e., if AttackerUser can request a token that will also work for VictimUser, then this approach will not work at all.
The pros:
* tokens are unique to a given session, the method uses a different CSRFName every time a form is displayed, and each CSRFName can be submitted only once before being invalidated and wiped from session
PREVENTION BY REFERER OR ORIGIN CHECK
Which to check and what to check?
If we are the devs of SendMoney.example.com it we should probably check to make sure every request for sensitive data access or edits should have SendMoney.example.com (or some other trusted domain) in the REFERER or ORIGIN. On the other hand, if we want to explose an API, then excluding other domains could limit the accessibility of our API endpoints unless we concoct some other authentication scheme.
NOTE that HTTP_REFERER's value is supplied by the client software and might be spoofed if the client has been compromised. An example of a malicious HTTP_REFERER value in the exploit examples above might be:
http://attackerdomain.example.com/path/file.php
Or, try checking HTTP_ORIGIN -- although I'm not sure if we can depend on this value being set in older browsers? An example value from the exploits above would be:
http://attackerdomain.example.com
PREVENTION BY COOKIE-TO-HEADER TOKEN or DOUBLE-SUBMIT COOKIES
Wikipedia describes cookie-to-header token and OWASP describes double-submit cookies.
Basic idea is that when a user logs in (or possibly when a user session is established for non-authenticated users) , the server generates a token and sets it in a cookie on the client. This token will remain the same for the duration of the session (but may possibly change under certain circumstances. e.g., if fraud is detected). Then, any AJAX or javascript operations that deal with sensitive data will send a custom header with any subsequent requests. E.g.:
X-Csrf-Token: {token-goes-here}
Then the server will take care to check for this token whenever some sensitive data operation is performed. As the wikipedia page says:
Security of this technique is based on the assumption that only JavaScript running within the same origin will be able to read the cookie's value. JavaScript running from a rogue file or email will not be able to read it and copy into the custom header.
Pros:
Should make AJAX implementation easier as a single token exists for all operations
Cons:
What if an attacker can set this token's value? If browers permit third-party cookies, this may be possible?
PREVENTION BY ENCRYPTED TOKEN PATTERN
OWASP describes this pattern wherein the token is not a random token but rather an encrypted value that can only be decrypted by the server. The encrypted value may contain a timestamp, userid, or other information to constrain and/or verify the conditions under which the token is valid. Because the server alone has the encryption key, these values cannot be spoofed by a third party as long as the key is kept secret and not cracked. The contents of the token must be specific to a user session, however, such that tokens valid for one user are NOT valid for any other user. This approach also breaks down if any attacker can generate multiple authenticated requests originating from a victim -- but this situation should prevented with proper same-origin policy enforcement.
Derokorian was kind enough to share some CSRF prevention code in this thread. I believe it falls under the encrypted token pattern approach.