From dcc18f980d48539aea9a52840501dbdb79dad2b1 Mon Sep 17 00:00:00 2001 From: Hanne Moa Date: Fri, 1 Mar 2024 09:52:59 +0100 Subject: [PATCH] Add simple clickjacking prevention (#2816) Support X-Frame-Options with a default of SAMEORIGIN. --- python/nav/django/settings.py | 5 ++++- python/nav/web/security.py | 20 ++++++++++++++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/python/nav/django/settings.py b/python/nav/django/settings.py index dfd3e33251..d9aacb4ef5 100644 --- a/python/nav/django/settings.py +++ b/python/nav/django/settings.py @@ -126,6 +126,7 @@ # Middleware MIDDLEWARE = ( + 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'nav.web.auth.middleware.AuthenticationMiddleware', @@ -261,12 +262,14 @@ # Configured in etc/webfront/webfront.conf: # [security] # needs_tls = yes +# frames_allow = self SECURE_BROWSER_XSS_FILTER = True # Does no harm _websecurity_config = WebSecurityConfigParser() -_needs_tls = bool(_websecurity_config.getboolean('security', 'needs_tls')) +_needs_tls = bool(_websecurity_config.getboolean('needs_tls')) SESSION_COOKIE_SECURE = _needs_tls +X_FRAME_OPTIONS = _websecurity_config.get_x_frame_options() # Hack for hackers to use features like debug_toolbar etc. # https://code.djangoproject.com/wiki/SplitSettings (Rob Golding's method) diff --git a/python/nav/web/security.py b/python/nav/web/security.py index cb3d64cce4..21a43ac968 100644 --- a/python/nav/web/security.py +++ b/python/nav/web/security.py @@ -1,11 +1,27 @@ from pathlib import Path -from nav.config import NAVConfigParser +from nav.config import NavConfigParserDefaultSection -class WebSecurityConfigParser(NAVConfigParser): +class WebSecurityConfigParser(NavConfigParserDefaultSection): + SECTION = "security" DEFAULT_CONFIG_FILES = [str(Path('webfront') / 'webfront.conf')] DEFAULT_CONFIG = u""" [security] needs_tls=no +allow_frames=self """ + FRAMES_OPTION = 'allow_frames' + FRAMES_DEFAULT = 'self' + + def __init__(self): + super().__init__(self.SECTION) + + # clickjacking-settings + + def get_x_frame_options(self): + "Translate CSP frame ancestors to the old X-Frame-Options header" + frames_flag = self.get(self.FRAMES_OPTION) or self.FRAMES_DEFAULT + if frames_flag == 'none': + return 'DENY' + return 'SAMEORIGIN'