diff roundup/configuration.py @ 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 7aebd892b600
children d4cc71beb102
line wrap: on
line diff
--- a/roundup/configuration.py	Sat Mar 18 15:12:39 2017 -0400
+++ b/roundup/configuration.py	Sat Mar 18 16:59:01 2017 -0400
@@ -293,6 +293,19 @@
         else:
             raise OptionValueError(self, value, self.class_description)
 
+class CsrfSettingOption(Option):
+
+    """How should a csrf measure be enforced: required, yes, logfailure, no"""
+
+    class_description = "Allowed values: required, yes, logfailure, no"
+
+    def str2value(self, value):
+        _val = value.lower()
+        if _val in ("required", "yes", "logfailure", "no"):
+            return _val
+        else:
+            raise OptionValueError(self, value, self.class_description)
+
 class EmailBodyOption(Option):
 
     """When to replace message body or strip quoting: always, never or for new items only"""
@@ -633,6 +646,98 @@
             "variables supplied by your web server (in that order).\n"
             "Set this option to 'no' if you do not wish to use HTTP Basic\n"
             "Authentication in your web interface."),
+        (CsrfSettingOption, 'csrf_enforce_token', "yes",
+            """How do we deal with @csrf fields in posted forms.
+Set this to 'required' to block the post and notify
+    the user if the field is missing or invalid.
+Set this to 'yes' to block the post and notify the user
+    if the token is invalid, but accept the form if
+    the field is missing
+Set this to 'logfailure' to log a notice to the roundup
+    log if the field is invalid or missing, but accept
+    the post.
+Set this to 'no' to ignore the field and accept the post.
+            """),
+        (IntegerNumberOption, 'csrf_token_lifetime', "20160",
+            """csrf_tokens have a limited lifetime. If they are not
+used they are purged from the database after this
+number of minutes. Default (20160) is 2 weeks."""),
+        (CsrfSettingOption, 'csrf_enforce_token', "yes",
+            """How do we deal with @csrf fields in posted forms.
+Set this to 'required' to block the post and notify
+    the user if the field is missing or invalid.
+Set this to 'yes' to block the post and notify the user
+    if the token is invalid, but accept the form if
+    the field is missing
+Set this to 'logfailure' to log a notice to the roundup
+    log if the field is invalid or missing, but accept
+    the post.
+Set this to 'no' to ignore the field and accept the post.
+            """),
+        (CsrfSettingOption, 'csrf_enforce_header_X-REQUESTED-WITH', "yes",
+            """This is only used for xmlrpc requests. This test is
+done after Origin and Referer headers are checked. It only
+verifies that the X-Requested-With header exists. The value
+is ignored.
+Set this to 'required' to block the post and notify
+    the user if the header is missing or invalid.
+Set this to 'yes' is the same as required.
+Set this to 'logfailure' is the same as 'no'.
+Set this to 'no' to ignore the header and accept the post."""),
+        (CsrfSettingOption, 'csrf_enforce_header_referer', "yes",
+            """Verify that the Referer http header matches the
+tracker.web setting in config.ini.
+Set this to 'required' to block the post and notify
+    the user if the header is missing or invalid.
+Set this to 'yes' to block the post and notify the user
+    if the header is invalid, but accept the form if
+    the field is missing
+Set this to 'logfalure' to log a notice to the roundup
+    log if the header is invalid or missing, but accept
+    the post.
+Set this to 'no' to ignore the header and accept the post."""),
+        (CsrfSettingOption, 'csrf_enforce_header_origin', "yes",
+            """Verify that the Origin http header matches the
+tracker.web setting in config.ini.
+Set this to 'required' to block the post and notify
+    the user if the header is missing or invalid.
+Set this to 'yes' to block the post and notify the user
+    if the header is invalid, but accept the form if
+    the field is missing
+Set this to 'logfailure' to log a notice to the roundup
+    log if the header is invalid or missing, but accept
+    the post.
+Set this to 'no' to ignore the header and accept the post."""),
+        (CsrfSettingOption, 'csrf_enforce_header_x-forwarded-host', "yes",
+            """Verify that the X-Forwarded-Host http header matches
+the host part of the tracker.web setting in config.ini.
+Set this to 'required' to block the post and notify
+    the user if the header is missing or invalid.
+Set this to 'yes' to block the post and notify the user
+    if the header is invalid, but accept the form if
+    the field is missing
+Set this to 'logfailure' to log a notice to the roundup
+    log if the header is invalid or missing, but accept
+    the post.
+Set this to 'no' to ignore the header and accept the post."""),
+        (CsrfSettingOption, 'csrf_enforce_header_host', "yes",
+            """"If there is no X-Forward-Host header, verify that
+the Host http header matches the host part of the
+tracker.web setting in config.ini.
+Set this to 'required' to block the post and notify
+    the user if the header is missing or invalid.
+Set this to 'yes' to block the post and notify the user
+    if the header is invalid, but accept the form if
+    the field is missing
+Set this to 'logfailure' to log a notice to the roundup
+    log if the header is invalid or missing, but accept
+    the post.
+Set this to 'no' to ignore the header and accept the post."""),
+        (IntegerNumberOption, 'csrf_header_min_count', "1",
+            """Minimum number of header checks that must pass
+to accept the request. Set to 0 to accept post
+even if no header checks pass. Usually the Host header check
+always passes, so setting it less than 1 is not recommended."""),
         (BooleanOption, 'use_browser_language', "yes",
             "Whether to use HTTP Accept-Language, if present.\n"
             "Browsers send a language-region preference list.\n"

Roundup Issue Tracker: http://roundup-tracker.org/