From d33fec9c3f3d1b5edddefec8f93305a827c4faea Mon Sep 17 00:00:00 2001 From: Matt N Date: Wed, 16 Jan 2019 06:59:58 -0800 Subject: [PATCH] Add a CSP script-src policy with nonce-source and convert more inline event handlers (#2413) * Add Content-Security-Policy-Report-Only: script-src 'self' 'nonce-' policy * Use @data-on-click-this to attach inline click event handlers which expect being called with 'this' Only handle ones that don't return a value. * Use @data-on-click to attach inline click event handlers with no args and no return value * Use @data-on-click-true to attach inline click event handlers with 'true' as the only argument * Enforce a script-src CSP on views without inline JS * Convert some onchange attributes to data-on-change --- web/includes/Group.php | 2 +- web/includes/functions.php | 22 ++++++++ web/index.php | 4 ++ .../classic/includes/export_functions.php | 12 ++--- web/skins/classic/includes/functions.php | 9 ++-- web/skins/classic/js/skin.js | 24 +++++++++ web/skins/classic/views/_monitor_filters.php | 10 ++-- web/skins/classic/views/bandwidth.php | 2 +- web/skins/classic/views/console.php | 12 ++--- web/skins/classic/views/control.php | 2 +- web/skins/classic/views/controlcap.php | 2 +- web/skins/classic/views/controlcaps.php | 4 +- web/skins/classic/views/controlpreset.php | 2 +- web/skins/classic/views/device.php | 2 +- web/skins/classic/views/devices.php | 4 +- web/skins/classic/views/donate.php | 4 +- web/skins/classic/views/download.php | 6 +-- web/skins/classic/views/error.php | 2 +- web/skins/classic/views/event.php | 54 +++++++++---------- web/skins/classic/views/eventdetail.php | 2 +- web/skins/classic/views/export.php | 16 +++--- web/skins/classic/views/filter.php | 34 ++++++------ web/skins/classic/views/frames.php | 2 +- web/skins/classic/views/function.php | 2 +- web/skins/classic/views/group.php | 2 +- web/skins/classic/views/groups.php | 6 +-- web/skins/classic/views/js/filter.js | 3 +- web/skins/classic/views/log.php | 26 ++++----- web/skins/classic/views/logout.php | 2 +- web/skins/classic/views/monitor.php | 2 +- web/skins/classic/views/monitorpreset.php | 3 +- web/skins/classic/views/monitorprobe.php | 4 +- web/skins/classic/views/monitors.php | 2 +- web/skins/classic/views/montage.php | 6 +-- web/skins/classic/views/montagereview.php | 16 +++--- web/skins/classic/views/onvifprobe.php | 10 ++-- web/skins/classic/views/optionhelp.php | 2 +- web/skins/classic/views/options.php | 6 +-- web/skins/classic/views/plugin.php | 3 +- web/skins/classic/views/privacy.php | 2 +- web/skins/classic/views/server.php | 2 +- web/skins/classic/views/settings.php | 2 +- web/skins/classic/views/storage.php | 2 +- web/skins/classic/views/user.php | 2 +- web/skins/classic/views/version.php | 10 ++-- web/skins/classic/views/video.php | 2 +- web/skins/classic/views/watch.php | 20 +++---- web/skins/classic/views/zone.php | 2 +- web/skins/classic/views/zones.php | 4 +- 49 files changed, 215 insertions(+), 161 deletions(-) diff --git a/web/includes/Group.php b/web/includes/Group.php index 82c1daba9..89849309b 100644 --- a/web/includes/Group.php +++ b/web/includes/Group.php @@ -188,7 +188,7 @@ class Group { session_write_close(); return htmlSelect( 'Group[]', Group::get_dropdown_options(), isset($_SESSION['Group'])?$_SESSION['Group']:null, array( - 'onchange' => 'this.form.submit();', + 'data-on-change' => 'submitThisForm', 'class'=>'chosen', 'multiple'=>'multiple', 'data-placeholder'=>'All', diff --git a/web/includes/functions.php b/web/includes/functions.php index cd278ba79..6473be91b 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -35,6 +35,28 @@ function noCacheHeaders() { header('Pragma: no-cache'); // HTTP/1.0 } +function CSPHeaders($view, $nonce) { + switch ($view) { + case "bandwidth": + case "function": + case "log": + case "logout": + case "options": + case "version": { + // Enforce script-src on pages where inline scripts and event handlers have been fixed. + // 'unsafe-inline' is only for backwards compatibility with browsers which + // only support CSP 1 (with no nonce-* support). + header("Content-Security-Policy: script-src 'unsafe-inline' 'self' 'nonce-$nonce'"); + break; + } + default: { + // Use Report-Only mode on all other pages. + header("Content-Security-Policy-Report-Only: script-src 'unsafe-inline' 'self' 'nonce-$nonce'"); + break; + } + } +} + function CORSHeaders() { if ( isset($_SERVER['HTTP_ORIGIN']) ) { diff --git a/web/index.php b/web/index.php index d9677d146..29e67d628 100644 --- a/web/index.php +++ b/web/index.php @@ -172,6 +172,10 @@ $view = null; if ( isset($_REQUEST['view']) ) $view = detaintPath($_REQUEST['view']); +# Add CSP Headers +$cspNonce = bin2hex(openssl_random_pseudo_bytes(16)); +CSPHeaders($view, $cspNonce); + $request = null; if ( isset($_REQUEST['request']) ) $request = detaintPath($_REQUEST['request']); diff --git a/web/skins/classic/includes/export_functions.php b/web/skins/classic/includes/export_functions.php index 7750f165b..eb505f18b 100644 --- a/web/skins/classic/includes/export_functions.php +++ b/web/skins/classic/includes/export_functions.php @@ -263,12 +263,12 @@ function exportEventImages( $event, $exportDetail, $exportFrames, $myfilelist )

- +
 
diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index e39c56b4a..535d8ba31 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -120,7 +120,7 @@ echo output_link_if_exists( array( -