From 5035ed29c72483b446ed1320290b33cce293b90b Mon Sep 17 00:00:00 2001 From: Hanne Moa Date: Wed, 21 Feb 2024 10:24:40 +0100 Subject: [PATCH 1/4] Create new config section for web security settings --- python/nav/django/settings.py | 15 +++++++++++++++ python/nav/etc/webfront/webfront.conf | 3 +++ python/nav/web/security.py | 11 +++++++++++ 3 files changed, 29 insertions(+) create mode 100644 python/nav/web/security.py diff --git a/python/nav/django/settings.py b/python/nav/django/settings.py index 1847ec24ca..4d7c6ea68c 100644 --- a/python/nav/django/settings.py +++ b/python/nav/django/settings.py @@ -29,6 +29,7 @@ from nav.db import get_connection_parameters import nav.buildconf from nav.jwtconf import JWTConf +from nav.web.security import WebSecurityConfigParser ALLOWED_HOSTS = ['*'] @@ -252,6 +253,20 @@ 'nav.web.info.searchproviders.UnrecognizedNeighborSearchProvider', ] +# Web security options supported by Django +# * https://docs.djangoproject.com/en/3.2/ref/middleware/#module-django.middleware.security +# * https://docs.djangoproject.com/en/3.2/topics/http/sessions/ +# * https://docs.djangoproject.com/en/3.2/ref/clickjacking/ +# Example conf: +# [security] +# ssl = on + +SECURE_BROWSER_XSS_FILTER = True # Does no harm + +_websecurity_config = WebSecurityConfigParser() +_tls_enabled = bool(_websecurity_config.getboolean('security', 'tls')) +SESSION_COOKIE_SECURE = _tls_enabled + # Hack for hackers to use features like debug_toolbar etc. # https://code.djangoproject.com/wiki/SplitSettings (Rob Golding's method) if _config_dir: diff --git a/python/nav/etc/webfront/webfront.conf b/python/nav/etc/webfront/webfront.conf index 302aaa1774..05ca2a3c2a 100644 --- a/python/nav/etc/webfront/webfront.conf +++ b/python/nav/etc/webfront/webfront.conf @@ -130,3 +130,6 @@ enabled = no # Some remote user systems need to be visited *after* NAV has logged the user # out. The default/unset value is "/" #post-logout-redirect-url=/magic/logout?nexthop=/ + +[security] +# tls = off diff --git a/python/nav/web/security.py b/python/nav/web/security.py new file mode 100644 index 0000000000..815d2f162d --- /dev/null +++ b/python/nav/web/security.py @@ -0,0 +1,11 @@ +from pathlib import Path + +from nav.config import NAVConfigParser + + +class WebSecurityConfigParser(NAVConfigParser): + DEFAULT_CONFIG_FILES = [str(Path('webfront') / 'webfront.conf')] + DEFAULT_CONFIG = u""" +[security] +tls=off +""" From cfcf50b794915aea8537c0535b7fc6ad0ae02f7d Mon Sep 17 00:00:00 2001 From: Hanne Moa Date: Mon, 26 Feb 2024 14:38:02 +0100 Subject: [PATCH 2/4] Rename "tls" config-flag to "needs_tls" --- python/nav/django/settings.py | 6 +++--- python/nav/etc/webfront/webfront.conf | 5 ++++- python/nav/web/security.py | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/python/nav/django/settings.py b/python/nav/django/settings.py index 4d7c6ea68c..54a896f172 100644 --- a/python/nav/django/settings.py +++ b/python/nav/django/settings.py @@ -259,13 +259,13 @@ # * https://docs.djangoproject.com/en/3.2/ref/clickjacking/ # Example conf: # [security] -# ssl = on +# needs_tls = yes SECURE_BROWSER_XSS_FILTER = True # Does no harm _websecurity_config = WebSecurityConfigParser() -_tls_enabled = bool(_websecurity_config.getboolean('security', 'tls')) -SESSION_COOKIE_SECURE = _tls_enabled +_needs_tls = bool(_websecurity_config.getboolean('security', 'needs_tls')) +SESSION_COOKIE_SECURE = _needs_tls # 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/etc/webfront/webfront.conf b/python/nav/etc/webfront/webfront.conf index 05ca2a3c2a..ab104db44f 100644 --- a/python/nav/etc/webfront/webfront.conf +++ b/python/nav/etc/webfront/webfront.conf @@ -132,4 +132,7 @@ enabled = no #post-logout-redirect-url=/magic/logout?nexthop=/ [security] -# tls = off +# Whether NAV must be run under TLS or not. Toggling this to `yes` toggles web +# security features that are only available with TLS/SSL enabled. In +# development mode this defaults to `no`. +# needs_tls = no diff --git a/python/nav/web/security.py b/python/nav/web/security.py index 815d2f162d..cb3d64cce4 100644 --- a/python/nav/web/security.py +++ b/python/nav/web/security.py @@ -7,5 +7,5 @@ class WebSecurityConfigParser(NAVConfigParser): DEFAULT_CONFIG_FILES = [str(Path('webfront') / 'webfront.conf')] DEFAULT_CONFIG = u""" [security] -tls=off +needs_tls=no """ From a3d27624b469490950a02f7cd4c797944df11658 Mon Sep 17 00:00:00 2001 From: Hanne Moa Date: Tue, 27 Feb 2024 08:23:12 +0100 Subject: [PATCH 3/4] Document the new config section --- NOTES.rst | 16 +++++++++++++++ doc/howto/index.rst | 1 + doc/howto/securing-nav-in-production.rst | 26 ++++++++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 doc/howto/securing-nav-in-production.rst diff --git a/NOTES.rst b/NOTES.rst index e4d60b4584..f33a5356d0 100644 --- a/NOTES.rst +++ b/NOTES.rst @@ -8,6 +8,22 @@ existing bug reports, go to https://github.com/uninett/nav/issues . To see an overview of upcoming release milestones and the issues they resolve, please go to https://github.com/uninett/nav/milestones . +NAV 5.9 +======= + +Web security +------------ + +While it is only relevant for older browsers, the HTTP header +``X-XSS-Protection`` is set to ``1; mode=block``. It does not affect browsers +that do not support it after all. + +There's a new section in :file:`webfront/webfront.conf`, ``[security]``. When +running in production with SSL/TLS turned on, there's a new flag ``needs_tls`` +that should also be toggled on. This'll turn on secure cookies (only sent over +SSL/TLS). See also the new howto +:doc:`Securing NAV in production `. + NAV 5.8 ======= diff --git a/doc/howto/index.rst b/doc/howto/index.rst index 4369b4f994..9e45bd2fbd 100644 --- a/doc/howto/index.rst +++ b/doc/howto/index.rst @@ -19,3 +19,4 @@ Howtos setting-up-logging using_the_api api_parameters + securing-nav-in-production diff --git a/doc/howto/securing-nav-in-production.rst b/doc/howto/securing-nav-in-production.rst new file mode 100644 index 0000000000..f53774a3c8 --- /dev/null +++ b/doc/howto/securing-nav-in-production.rst @@ -0,0 +1,26 @@ +========================== +Securing NAV in production +========================== + +Overview +======== + +The default configuration of NAV is set up to work well during development, but +needs to be tightened when running in production. + +NAV consists of pages controlled by NAV itself, and pages served directly by +the web server. Security features for NAV's own pages are controlled via the +``[security]``-section in the file :file:`webfront/webfront.conf`, while +security for the other pages are controlled directly by the web server. + + +SSL/TLS +======= + +This needs to be turned on in the webserver itself. While there is no reason to +serve any of NAV without SSL/TLS turned off, it is especially important for the +pages controlled by NAV. + +When the server serves NAV with SSL/TLS, ensure that the ``needs_tls``-flag in +the ``[security]``-section is set to ``yes``. This explicitly turns on secure +cookies, which is dependent on SSL being in use. From 6db0a3f3056bcff4ab5e69770ba32d44d1d2d2a1 Mon Sep 17 00:00:00 2001 From: Hanne Moa Date: Thu, 29 Feb 2024 07:50:25 +0100 Subject: [PATCH 4/4] Add a link to the correct config-file --- python/nav/django/settings.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python/nav/django/settings.py b/python/nav/django/settings.py index 54a896f172..dfd3e33251 100644 --- a/python/nav/django/settings.py +++ b/python/nav/django/settings.py @@ -253,11 +253,12 @@ 'nav.web.info.searchproviders.UnrecognizedNeighborSearchProvider', ] -# Web security options supported by Django +## Web security options supported by Django # * https://docs.djangoproject.com/en/3.2/ref/middleware/#module-django.middleware.security # * https://docs.djangoproject.com/en/3.2/topics/http/sessions/ # * https://docs.djangoproject.com/en/3.2/ref/clickjacking/ -# Example conf: +# +# Configured in etc/webfront/webfront.conf: # [security] # needs_tls = yes