Mercurial > p > roundup > code
comparison doc/customizing.txt @ 5201:a9ace22e0a2f
issue 2550690 - Adding anti-csrf measures to roundup following
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet
and
https://seclab.stanford.edu/websec/csrf/csrf.pdf
Basically implement Synchronizer (CSRF) Tokens per form on a page.
Single use (destroyed once used). Random input data for the token
includes:
system random implementation in python using /dev/urandom
(fallback to random based on timestamp as the seed. Not
as good, but should be ok for the short lifetime of the
token??)
the id (in cpython it's the memory address) of the object
requesting a token. In theory this depends on memory layout, the
history of the process (how many previous objects have been
allocated from the heap etc.) I claim without any proof that for
long running processes this is another source of randomness. For
short running processes with little activity it could be guessed.
last the floating point time.time() value is added. This may
only have 1 second resolution so may be guessable.
Hopefully for a short lived (2 week by default) token this is
sufficient. Also in the current implementation the user is notified when
validation fails and is told why. This allows the roundup admin to find
the log entry (at error level) and try to resolve the issue. In the
future user notification may change but for now this is probably best.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Sat, 18 Mar 2017 16:59:01 -0400 |
| parents | e0732fd6a6c7 |
| children | 8d2c1c9a49e1 |
comparison
equal
deleted
inserted
replaced
| 5200:16a8a3f0772c | 5201:a9ace22e0a2f |
|---|---|
| 1642 **editCSV** | 1642 **editCSV** |
| 1643 Determine whether the user has permission to edit this class. | 1643 Determine whether the user has permission to edit this class. |
| 1644 **search** | 1644 **search** |
| 1645 Determine whether the user has permission to view this class. | 1645 Determine whether the user has permission to view this class. |
| 1646 | 1646 |
| 1647 Protecting users from web application attacks | |
| 1648 --------------------------------------------- | |
| 1649 | |
| 1650 There is a class of attacks known as Cross Site Request Forgeries | |
| 1651 (CSRF). Malicious code running in the browser can making a | |
| 1652 request to roundup while you are logged into roundup. The | |
| 1653 malicious code piggy backs on your existing roundup session to | |
| 1654 make changes without your knowledge. Roundup 1.6 has support for | |
| 1655 defending against this by analyzing the | |
| 1656 | |
| 1657 * Referer, | |
| 1658 * Origin, and | |
| 1659 * Host or | |
| 1660 * X-Forwarded-Host | |
| 1661 | |
| 1662 HTTP headers. It compares the headers to the value of the web setting | |
| 1663 in the [tracker] section of the tracker's ``config.ini``. | |
| 1664 | |
| 1665 Also a per form token (also called a nonce) can be enabled for | |
| 1666 the tracker using the ``csrf_enforce_token`` option in | |
| 1667 config.ini. When enabled, roundup will validate a hidden form | |
| 1668 field called ``@csrf``. If the validation fails (or the token | |
| 1669 is used more than one) the request is rejected. The ``@csrf`` | |
| 1670 input field is added automatically by calling the ``submit`` | |
| 1671 function/path. It can also be added manually by calling | |
| 1672 anti_csrf_nonce() directly. For example: | |
| 1673 | |
| 1674 <input name="@csrf" type="hidden" | |
| 1675 tal:attributes="value python:utils.anti_csrf_nonce(lifetime=10)"> | |
| 1676 | |
| 1677 By default a nonce lifetime is 2 weeks. However the lifetime (in | |
| 1678 minutes) can be set by passing a lifetime argument as shown | |
| 1679 above. The example above makes the nonce lifetime 10 minutes. | |
| 1680 | |
| 1681 Search for @csrf in this document for more examples. There are | |
| 1682 more examples and information in ``upgrading.txt``. | |
| 1683 | |
| 1684 The token protects you because malicious code supplied by another | |
| 1685 site is unable to obtain the token. Thus many attempts they make | |
| 1686 to submit a request are rejected. | |
| 1687 | |
| 1688 The protection on the xmlrpc interface is untested, but is based | |
| 1689 on a valid header check against the roundup url and the presence | |
| 1690 of the ``X-REQUESTED-WITH`` header. Work to improve this is a | |
| 1691 future project after the 1.6 release. | |
| 1692 | |
| 1693 The enforcement levels an be modified in ``config.ini``. Refer to | |
| 1694 that file for details. | |
| 1647 | 1695 |
| 1648 Special form variables | 1696 Special form variables |
| 1649 ---------------------- | 1697 ---------------------- |
| 1650 | 1698 |
| 1651 Item properties and their values are edited with html FORM | 1699 Item properties and their values are edited with html FORM |
| 2364 | 2412 |
| 2365 If the "form" arg is given, it's passed through to the | 2413 If the "form" arg is given, it's passed through to the |
| 2366 javascript help_window function - it's the name of the form | 2414 javascript help_window function - it's the name of the form |
| 2367 the "property" belongs to. | 2415 the "property" belongs to. |
| 2368 | 2416 |
| 2369 submit generate a submit button (and action hidden element) | 2417 submit generate a submit button (and action and @csrf hidden elements) |
| 2370 renderWith render this class with the given template. | 2418 renderWith render this class with the given template. |
| 2371 history returns 'New node - no history' :) | 2419 history returns 'New node - no history' :) |
| 2372 is_edit_ok is the user allowed to Edit the current class? | 2420 is_edit_ok is the user allowed to Edit the current class? |
| 2373 is_view_ok is the user allowed to View the current class? | 2421 is_view_ok is the user allowed to View the current class? |
| 2374 =========== ============================================================= | 2422 =========== ============================================================= |
| 2397 There are several methods available on these wrapper objects: | 2445 There are several methods available on these wrapper objects: |
| 2398 | 2446 |
| 2399 =============== ======================================================== | 2447 =============== ======================================================== |
| 2400 Method Description | 2448 Method Description |
| 2401 =============== ======================================================== | 2449 =============== ======================================================== |
| 2402 submit generate a submit button (and action hidden element) | 2450 submit generate a submit button (and action and @csrf hidden elements) |
| 2403 journal return the journal of the current item (**not | 2451 journal return the journal of the current item (**not |
| 2404 implemented**) | 2452 implemented**) |
| 2405 history render the journal of the current item as HTML | 2453 history render the journal of the current item as HTML |
| 2406 renderQueryForm specific to the "query" class - render the search form | 2454 renderQueryForm specific to the "query" class - render the search form |
| 2407 for the query | 2455 for the query |
| 3608 <td colspan="3" tal:content="structure context/submit"> | 3656 <td colspan="3" tal:content="structure context/submit"> |
| 3609 submit button will go here | 3657 submit button will go here |
| 3610 </td> | 3658 </td> |
| 3611 </tr> | 3659 </tr> |
| 3612 | 3660 |
| 3661 The ``context/submit`` bit generates the submit button but also | |
| 3662 generates the @action and @csrf hidden fields. The @action field is | |
| 3663 used to tell roundup how to process the form. The @csrf field provides | |
| 3664 a unique single use token to defend against CSRF attacks. (More about | |
| 3665 anti-csrf measures can be found in ``upgrading.txt``.) | |
| 3666 | |
| 3613 Finally we finish off the tags we used at the start to do the METAL | 3667 Finally we finish off the tags we used at the start to do the METAL |
| 3614 stuff:: | 3668 stuff:: |
| 3615 | 3669 |
| 3616 </td> | 3670 </td> |
| 3617 </tal:block> | 3671 </tal:block> |
| 5095 3. after the ``tal:block`` which lists the index items (marked by | 5149 3. after the ``tal:block`` which lists the index items (marked by |
| 5096 ``tal:repeat="i batch"``) add a new table row:: | 5150 ``tal:repeat="i batch"``) add a new table row:: |
| 5097 | 5151 |
| 5098 <tr> | 5152 <tr> |
| 5099 <td tal:attributes="colspan python:len(request.columns)"> | 5153 <td tal:attributes="colspan python:len(request.columns)"> |
| 5154 <input name="@csrf" type="hidden" | |
| 5155 tal:attributes="value python:utils.anti_csrf_nonce()"> | |
| 5100 <input type="submit" value=" Save Changes "> | 5156 <input type="submit" value=" Save Changes "> |
| 5101 <input type="hidden" name="@action" value="edit"> | 5157 <input type="hidden" name="@action" value="edit"> |
| 5102 <tal:block replace="structure request/indexargs_form" /> | 5158 <tal:block replace="structure request/indexargs_form" /> |
| 5103 </td> | 5159 </td> |
| 5104 </tr> | 5160 </tr> |
| 5105 | 5161 |
| 5106 which gives us a submit button, indicates that we are performing an edit | 5162 which gives us a submit button, indicates that we are performing an |
| 5107 on any changed statuses. The final ``tal:block`` will make sure that the | 5163 edit on any changed statuses, and provides a defense against cross |
| 5108 current index view parameters (filtering, columns, etc) will be used in | 5164 site request forgery attacks. |
| 5109 rendering the next page (the results of the editing). | 5165 |
| 5166 The final ``tal:block`` will make sure that the current index view | |
| 5167 parameters (filtering, columns, etc) will be used in rendering the | |
| 5168 next page (the results of the editing). | |
| 5110 | 5169 |
| 5111 | 5170 |
| 5112 Displaying only message summaries in the issue display | 5171 Displaying only message summaries in the issue display |
| 5113 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 5172 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 5114 | 5173 |
| 5187 that category. The first page includes a table of help, explaining | 5246 that category. The first page includes a table of help, explaining |
| 5188 what the category names mean, and then the core of the form:: | 5247 what the category names mean, and then the core of the form:: |
| 5189 | 5248 |
| 5190 <form method="POST" onSubmit="return submit_once()" | 5249 <form method="POST" onSubmit="return submit_once()" |
| 5191 enctype="multipart/form-data"> | 5250 enctype="multipart/form-data"> |
| 5251 <input name="@csrf" type="hidden" | |
| 5252 tal:attributes="value python:utils.anti_csrf_nonce()"> | |
| 5192 <input type="hidden" name="@template" value="add_page1"> | 5253 <input type="hidden" name="@template" value="add_page1"> |
| 5193 <input type="hidden" name="@action" value="page1_submit"> | 5254 <input type="hidden" name="@action" value="page1_submit"> |
| 5194 | 5255 |
| 5195 <strong>Category:</strong> | 5256 <strong>Category:</strong> |
| 5196 <tal:block tal:replace="structure context/category/menu" /> | 5257 <tal:block tal:replace="structure context/category/menu" /> |
| 5203 <form method="POST" onSubmit="return submit_once()" | 5264 <form method="POST" onSubmit="return submit_once()" |
| 5204 enctype="multipart/form-data" | 5265 enctype="multipart/form-data" |
| 5205 tal:condition="context/is_edit_ok" | 5266 tal:condition="context/is_edit_ok" |
| 5206 tal:define="cat request/form/category/value"> | 5267 tal:define="cat request/form/category/value"> |
| 5207 | 5268 |
| 5269 <input name="@csrf" type="hidden" | |
| 5270 tal:attributes="value python:utils.anti_csrf_nonce()"> | |
| 5208 <input type="hidden" name="@template" value="add_page2"> | 5271 <input type="hidden" name="@template" value="add_page2"> |
| 5209 <input type="hidden" name="@required" value="title"> | 5272 <input type="hidden" name="@required" value="title"> |
| 5210 <input type="hidden" name="category" tal:attributes="value cat"> | 5273 <input type="hidden" name="category" tal:attributes="value cat"> |
| 5211 . | 5274 . |
| 5212 . | 5275 . |
