Add anti-ClickJack XFS hardening for old browsers

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
This commit is contained in:
Brian Tully 2015-06-14 18:49:53 -04:00
parent 5bde65705a
commit 056151cc70
5 changed files with 55 additions and 2 deletions

View File

@ -493,7 +493,6 @@ OpenStack dashboard to use a specific API version for a given service API.
"volume": 2 "volume": 2
} }
``OPENSTACK_ENABLE_PASSWORD_RETRIEVE`` ``OPENSTACK_ENABLE_PASSWORD_RETRIEVE``
-------------------------------------- --------------------------------------
@ -1031,6 +1030,29 @@ provided see: ``"/horizon/openstack_dashboard/static/themes/webroot"``
Alias /dashboard/media %HORIZON_DIR%/openstack_dashboard/static 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) Django Settings (Partial)
========================= =========================

View File

@ -19,7 +19,6 @@ WEBROOT = '/'
# Do not set it to '/home/', as this will cause circular redirect loop # Do not set it to '/home/', as this will cause circular redirect loop
# LOGIN_REDIRECT_URL = WEBROOT # LOGIN_REDIRECT_URL = WEBROOT
# Required for Django 1.5. # Required for Django 1.5.
# If horizon is running in production (DEBUG is False), set this # If horizon is running in production (DEBUG is False), set this
# with the list of host/domain names that the application can serve. # 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 # and are not encrypted on the browser. This is an experimental API and
# may be deprecated in the future without notice. # may be deprecated in the future without notice.
#REST_API_ADDITIONAL_SETTINGS = [] #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

View File

@ -1,4 +1,5 @@
{% load branding i18n %} {% load branding i18n %}
{% load context_selection %}
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
@ -10,6 +11,7 @@
{% block css %} {% block css %}
{% include "_stylesheets.html" %} {% include "_stylesheets.html" %}
{% endblock %} {% endblock %}
{% iframe_embed_settings %}
{% include "horizon/_conf.html" %} {% include "horizon/_conf.html" %}
{% include "horizon/client_side/_script_loader.html" %} {% include "horizon/client_side/_script_loader.html" %}
{% include "horizon/_custom_head_js.html" %} {% include "horizon/_custom_head_js.html" %}

View File

@ -0,0 +1,12 @@
{% if disallow_iframe_embed %}
<style id="anti-clickjack">body{display:none !important;}</style>
<script type='text/javascript' charset="utf-8">
if (self === top) {
var antiClickjack = document.getElementById("anti-clickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
top.location = self.location;
}
</script>
{% endif %}

View File

@ -88,3 +88,13 @@ def show_region_list(context):
'regions': sorted(request.user.available_services_regions), 'regions': sorted(request.user.available_services_regions),
'request': request} 'request': request}
return context 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