Switch to use {} form in JS, also *actually* implement key-based tokens.
[csrf-magic.git] / README.txt
blobae44c6936e5390770e615eea7c79c337da54a4c6
2 [[  csrf-magic  ]]
4 Add the following line to the top of all web-accessible PHP pages. If you have
5 a common file included by everything, put it there.
7     include_once '/path/to/csrf-magic.php';
9 Do it, test it, then forget about it. csrf-magic is protecting you if nothing
10 bad happens. Read on if you run into problems.
13 1.  WHAT DOES IT DO?
15 CSRF, or cross-site request forgery, is a relatively new attack vector on
16 websites today.  It involves an attacker tricking a browser into performing
17 an action on another website.  For example, Bob is the human resources manager
18 for a large and important company.  He has the ability to hire and fire with
19 a click of a button... specifically, a web form button.  Mallory, as a practical
20 joke, decides to setup a CSRF attack against Bob; she crafts a webpage which
21 submits a form onto the internal website that performs hirings and firings; then
22 she sends Bob an email to this webpage.  The next day, every employee wakes up
23 to find a rather nasty pink slip in their inbox.
25 The current standard for preventing CSRF is creating a nonce that every user
26 submits with any form he/she submits.  This is reasonably effective [1], but
27 incredibly tedious work; if you were hand-writing your forms or have multiple
28 avenues for POST data to enter your application, adding CSRF protection may not
29 seem worth the trouble (trust me, it certainly is).
31 This is where csrf-magic comes into play.  csrf-magic uses PHP's output
32 buffering capabilities to dynamically rewrite forms and scripts in your document.
33 It will also intercept POST requests and check their token (various algorithms
34 are used, some generate nonces, some generate user-specific tokens).  This means
35 with a traditional website with forms, you can drop it into your application,
36 and forget about it!
39 2.  AJAX
41 csrf-magic has the ability to dynamically rewrite AJAX requests which use
42 XMLHttpRequest.  However, due to the invasiveness of this procedure, it is
43 not enabled by default.  You can enable it by adding this code before you
44 include csrf-magic.php.
46     function csrf_startup() {
47         csrf_conf('rewrite-js', '/web/path/to/csrf-magic.js');
48     }
49     // include_once '/path/to/csrf-magic.php';
51 (Be sure to place csrf-magic.js somewhere web accessible).  csrf-magic.js will
52 automatically detect and play nice with the following JavaScript frameworks:
54     * jQuery
55     * Prototype
56     * script.aculo.us (via Prototype)
57     * MooTools
58     * Yahoo UI Library
59     * Ext
60     * Dojo
62 If you are not using any of these JavaScript libraries, AJAX requests will
63 only work for browsers with support for XmlHttpRequest.prototype (this excludes
64 all versions of Internet Explorer).
66 To rewrite your own JavaScript library to use csrf-magic.js, you should modify
67 your function that generates XMLHttpRequest to have this at the end:
69     return new CsrfMagic(xhrObject);
71 With whatever xhrObject may be. If you have literal instances of XMLHttpRequest
72 in your code, find and replace ''new XMLHttpRequest'' with ''new CsrfMagic''
73 (CsrfMagic will automatically instantiate an XMLHttpRequest object in a
74 cross-platform manner as necessary).
76 If you don't want csrf-magic monkeying around with your XMLHttpRequest object,
77 you can manually rewrite your AJAX code to include the variable. The important
78 information is stored in the global variables csrfMagicName and csrfMagicToken.
79 CsrfMagic.process may also be of interest, as it takes one parameter, a
80 querystring, and prepends the CSRF token to the value.
83 3.  CONFIGURE
85 csrf-magic has some configuration options that you can set inside the
86 csrf_startup() function. They are described in csrf-magic.php, and you can
87 set them using the convenience function csrf_conf($name, $value).
89 For example, this is a recommended configuration:
91     /**
92      * This is a function that gets called if a csrf check fails. csrf-magic will
93      * then exit afterwards.
94      */
95     function my_csrf_callback() {
96         echo "You're doing bad things young man!";
97     }
99     function csrf_startup() {
101         // This is a secret value that must be set in order to enable username
102         // and IP based checks. Don't show this to anyone.
103         csrf_conf('secret', 'ABCDEFG123456');
105         // This enables JavaScript rewriting and will ensure your AJAX calls
106         // don't stop working.
107         csrf_conf('rewrite-js', '/csrf-magic.js');
109         // This makes csrf-magic call my_csrf_callback() before exiting when
110         // there is a bad csrf token. This lets me customize the error page.
111         csrf_conf('callback', 'my_csrf_callback');
113         // While this is enabled by default to boost backwards compatibility,
114         // for security purposes it should ideally be off. Some users can be
115         // NATted or have dialup addresses which rotate frequently. Cookies
116         // are much more reliable.
117         csrf_conf('allow-ip', false);
119     }
121     // Finally, include the library
122     include_once '/path/to/csrf-magic.php';
124 Configuration gets stored in the $GLOBALS['csrf'] array.
127 4.  THANKS
129 My thanks to Chris Shiflett, for unintentionally inspiring the idea, as well
130 as telling me the original variant of the Bob and Mallory story,
131 and the Django CSRF Middleware authors, who thought up of this before me.
133 http://www.thespanner.co.uk/2007/08/20/protection-against-csrf/ is interesting
134 esp the frame breaker which we can automatically write in.
137 5.  FOOTNOTES
139 [1] There is an experimental attack in which a user makes an invisible iframe
140     of the website being attacked and overlays this on-top of an element on
141     their page that a user would normally click.  This iframe has a different
142     button from the other website which activates the action.  Nonces will
143     not protect against this type of attack, and csrf-magic doesn't deal with
144     this type of attack.
146     See also:
147         http://own-the.net/cat_CSRF-(XSRF)_news.html
150 6.   KNOWN BUGS
152 When an AJAX call is performed within an iframe, our rewriting of XMLHttpRequest
153 my fail for the first page load.  Subsequent page loads will work properly.
156 7.   TODO
158     * Minify csrf-magic.js for performance.
160     * Optional PHP5 exception support.
162     * Auto-generate secret.
164     * Make "first time" session more robust by double-submitting.
166     * Test manual JavaScript overloading instructions.
168     * Account for JavaScript generated-forms with some JavaScript that loads into
169       some global onsubmit handler and checks form submissions accordingly.