diff --git a/README.md b/README.md index 2838f329..c042df51 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,10 @@ Professional support for Rdiffweb is available by contacting [IKUS Soft](https:/ # Changelog +## 2.4.1 (2022-09-08) + +* Add Clickjacking Defense + ## 2.4.0 (2022-06-21) This new release brings a lot of improvement since the last version, multiple bug fixes diff --git a/rdiffweb/controller/tests/test_csrf.py b/rdiffweb/controller/tests/test_csrf.py index fd631626..af58d0c2 100644 --- a/rdiffweb/controller/tests/test_csrf.py +++ b/rdiffweb/controller/tests/test_csrf.py @@ -71,3 +71,11 @@ def test_post_without_origin(self): self.getPage('/', method='POST') # Then the request is accepted with 200 OK self.assertStatus(200) + + def test_clickjacking_defense(self): + # Given a POST request made to rdiffweb + # When the request is made without an origin + self.getPage('/') + # Then the request is accepted with 200 OK + self.assertStatus(200) + self.assertHeaderItemValue('X-Frame-Options', 'DENY') diff --git a/rdiffweb/tools/security.py b/rdiffweb/tools/security.py index 0d31560f..6fe62659 100644 --- a/rdiffweb/tools/security.py +++ b/rdiffweb/tools/security.py @@ -36,10 +36,13 @@ class CsrfAuth(HandlerTool): """ This tool provide CSRF mitigation. - First, by defining `SameSite=Lax` on the cookie - Second by validating the `Origin` and `Referer`. + * Define X-Frame-Options = DENY + * Define Cookies SameSite=Lax + * Validate `Origin` and `Referer` on POST, PUT, PATCH, DELETE - Ref.: https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html + Ref.: + https://cheatsheetseries.owasp.org/cheatsheets/Cross-Site_Request_Forgery_Prevention_Cheat_Sheet.html + https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html """ def __init__(self): @@ -48,14 +51,17 @@ def __init__(self): self._priority = 71 def _setup(self): - cherrypy.request.hooks.attach('before_finalize', self._set_same_site) + cherrypy.request.hooks.attach('before_finalize', self._set_headers) return super()._setup() - def _set_same_site(self): + def _set_headers(self): + response = cherrypy.serving.response + # Define X-Frame-Options to avoid Clickjacking + response.headers['X-Frame-Options'] = 'DENY' # Awaiting bug fix in cherrypy # https://github.com/cherrypy/cherrypy/issues/1767 # Force SameSite to Lax - cookie = cherrypy.serving.response.cookie.get('session_id', None) + cookie = response.cookie.get('session_id', None) if cookie: cookie['samesite'] = 'Lax'