From 056151cc70da3a708acfe2fa9a6da2dff165e939 Mon Sep 17 00:00:00 2001 From: Brian Tully Date: Sun, 14 Jun 2015 18:49:53 -0400 Subject: [PATCH] Add anti-ClickJack XFS hardening for old browsers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Cross-Frame Scripting (XFS) vulnerability can allow an attacker to load the vulnerable application inside an HTML iframe tag on a malicious page. An attacker could use XFS to devise a Clickjacking attack to conduct phishing, frame sniffing, social engineering or Cross-Site Request Forgery attacks. Although many pages within Horizon leverage the X-Frame-Options header with the recommended SAMEORIGIN policy, some (still popular) older browsers don’t support this setting. Namely, browsers older than IE 8 and Firefox 3.6.9 don’t recognize the header and are thus vulnerable to an attack known as ClickJacking unless an additional mitigating control is present. To support legacy browsers, a suggested best practice is to add a frame breaking script to the base/global template file. Reference: http://tinyurl.com/anticlickjack Change-Id: Ibd7acd0d7b4c4d58afcd59f025735bfc9e4c2957 Closes-Bug: 1461154 --- doc/source/topics/settings.rst | 24 ++++++++++++++++++- .../local/local_settings.py.example | 9 ++++++- openstack_dashboard/templates/base.html | 2 ++ .../context_selection/_anti_clickjack.html | 12 ++++++++++ .../templatetags/context_selection.py | 10 ++++++++ 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 openstack_dashboard/templates/context_selection/_anti_clickjack.html diff --git a/doc/source/topics/settings.rst b/doc/source/topics/settings.rst index 4b28d3e6e8..cafc9d3a19 100755 --- a/doc/source/topics/settings.rst +++ b/doc/source/topics/settings.rst @@ -493,7 +493,6 @@ OpenStack dashboard to use a specific API version for a given service API. "volume": 2 } - ``OPENSTACK_ENABLE_PASSWORD_RETRIEVE`` -------------------------------------- @@ -1031,6 +1030,29 @@ provided see: ``"/horizon/openstack_dashboard/static/themes/webroot"`` Alias /dashboard/media %HORIZON_DIR%/openstack_dashboard/static +``DISALLOW_IFRAME_EMBED`` +------------------------- + +.. versionadded:: 8.0.0(Liberty) + +Default: ``True`` + +This setting can be used to defend against Clickjacking and prevent Horizon from +being embedded within an iframe. Legacy browsers are still vulnerable to a +Cross-Frame Scripting (XFS) vulnerability, so this option allows extra security +hardening where iframes are not used in deployment. When set to true, a +``"frame-buster"`` script is inserted into the template header that prevents the +web page from being framed and therefore defends against clickjacking. + +For more information see: +http://tinyurl.com/anticlickjack + +.. note:: + + If your deployment requires the use of iframes, you can set this setting to + ``False`` to exclude the frame-busting code and allow iframe embedding. + + Django Settings (Partial) ========================= diff --git a/openstack_dashboard/local/local_settings.py.example b/openstack_dashboard/local/local_settings.py.example index dad51064ce..2ef436c7cc 100644 --- a/openstack_dashboard/local/local_settings.py.example +++ b/openstack_dashboard/local/local_settings.py.example @@ -19,7 +19,6 @@ WEBROOT = '/' # Do not set it to '/home/', as this will cause circular redirect loop # LOGIN_REDIRECT_URL = WEBROOT - # Required for Django 1.5. # If horizon is running in production (DEBUG is False), set this # with the list of host/domain names that the application can serve. @@ -639,3 +638,11 @@ REST_API_REQUIRED_SETTINGS = ['OPENSTACK_HYPERVISOR_FEATURES'] # and are not encrypted on the browser. This is an experimental API and # may be deprecated in the future without notice. #REST_API_ADDITIONAL_SETTINGS = [] + +# DISALLOW_IFRAME_EMBED can be used to prevent Horizon from being embedded +# within an iframe. Legacy browsers are still vulnerable to a Cross-Frame +# Scripting (XFS) vulnerability, so this option allows extra security hardening +# where iframes are not used in deployment. Default setting is True. +# For more information see: +# http://tinyurl.com/anticlickjack +# DISALLOW_IFRAME_EMBED = True diff --git a/openstack_dashboard/templates/base.html b/openstack_dashboard/templates/base.html index ad45764c1c..73943eb448 100644 --- a/openstack_dashboard/templates/base.html +++ b/openstack_dashboard/templates/base.html @@ -1,4 +1,5 @@ {% load branding i18n %} +{% load context_selection %} @@ -10,6 +11,7 @@ {% block css %} {% include "_stylesheets.html" %} {% endblock %} + {% iframe_embed_settings %} {% include "horizon/_conf.html" %} {% include "horizon/client_side/_script_loader.html" %} {% include "horizon/_custom_head_js.html" %} diff --git a/openstack_dashboard/templates/context_selection/_anti_clickjack.html b/openstack_dashboard/templates/context_selection/_anti_clickjack.html new file mode 100644 index 0000000000..62e456830c --- /dev/null +++ b/openstack_dashboard/templates/context_selection/_anti_clickjack.html @@ -0,0 +1,12 @@ +{% if disallow_iframe_embed %} + + + +{% endif %} diff --git a/openstack_dashboard/templatetags/context_selection.py b/openstack_dashboard/templatetags/context_selection.py index 5befc5d98c..11ec8564cc 100644 --- a/openstack_dashboard/templatetags/context_selection.py +++ b/openstack_dashboard/templatetags/context_selection.py @@ -88,3 +88,13 @@ def show_region_list(context): 'regions': sorted(request.user.available_services_regions), 'request': request} return context + + +@register.inclusion_tag('context_selection/_anti_clickjack.html', + takes_context=True) +def iframe_embed_settings(context): + disallow_iframe_embed = getattr(settings, + 'DISALLOW_IFRAME_EMBED', + True) + context = {'disallow_iframe_embed': disallow_iframe_embed} + return context