CVE-2017-12066: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site scripting (XSS) vulnerability in aggregate_graphs.php in Cacti before 1.1.16 allows remote authenticated users to inject arbitrary web script or HTML via specially crafted HTTP Referer headers, related to the $cancel_url variable. NOTE: this vulnerability exists because of an incomplete fix (lack of the htmlspecialchars ENT_QUOTES flag) for CVE-2017-11163.
CWE description: The product does not neutralize or incorrectly neutralizes user-controllable input before it is placed in output that is used as a web page that is served to other users.
CVSS v3 base score: 5.4
Published: 2017-08-01T05:29Z
Repository: https://github.com/Cacti/cacti
Language: PHP
Files changed: docs/CHANGELOG, lib/html_form.php, spikekill.php
Commit date: 2017-07-26 07:01:27 -0500
Commit message: Resolving Issue #877

Improving resolution to #847 and one additional vulnerability.

Diff: diff --git a/docs/CHANGELOG b/docs/CHANGELOG
index 4aa7db372..5ab67ccfe 100644
--- a/docs/CHANGELOG
+++ b/docs/CHANGELOG
@@ -1,9 +1,10 @@
 Cacti CHANGELOG
 
 1.1.16
 -issue#875: When modifying Realm permissions, realms that are listed multiple times don't stay in sync
+-issue#877: Improving resolution to issue#847 and one additional vulnerability
 -issue: Address additional corner cases around get_order_string usage
 
 1.1.15
 -issue: PHP Fatal Exception on upgrade from 1.1.11 or earlier
 -feature: Added test to detect install upgrade code problems
diff --git a/lib/html_form.php b/lib/html_form.php
index 49ca865a7..0b6613840 100644
--- a/lib/html_form.php
+++ b/lib/html_form.php
@@ -1111,12 +1111,12 @@ function form_confirm($title_text, $body_text, $cancel_url, $action_url) { ?>
 function form_confirm_buttons($action_url, $cancel_url) {
 	global $config;
 	?>
 	<tr>
 		<td align='right'>
-			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $cancel_url);?>")' value='<?php print __esc('Cancel');?>'>
-			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $action_url . '&confirm=true');?>")' value='<?php print __esc('Delete');?>'>
+			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $cancel_url, ENT_QUOTES);?>")' value='<?php print __esc('Cancel');?>'>
+			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $action_url . '&confirm=true', ENT_QUOTES);?>")' value='<?php print __esc('Delete');?>'>
 		</td>
 	</tr>
 <?php }
 
 /* form_save_button - draws a (save|create) and cancel button at the bottom of
@@ -1148,11 +1148,11 @@ function form_save_button($cancel_url, $force_type = '', $key_field = 'id', $aja
 	} elseif ($force_type == 'export') {
 		$alt = __esc('Export');
 	}
 
 	if ($force_type != 'import' && $force_type != 'export' && $force_type != 'save' && $cancel_url != '') {
-		$cancel_action = "<input type='button' onClick='cactiReturnTo(\"" . htmlspecialchars($cancel_url) . "\")' value='" . $calt . "'>";
+		$cancel_action = "<input type='button' onClick='cactiReturnTo(\"" . htmlspecialchars($cancel_url, ENT_QUOTES) . "\")' value='" . $calt . "'>";
 	} else {
 		$cancel_action = '';
 	}
 
 	?>
diff --git a/spikekill.php b/spikekill.php
index e8ba7daf4..8d4d5c296 100644
--- a/spikekill.php
+++ b/spikekill.php
@@ -41,11 +41,11 @@ if (isset_request_var('method')) {
 }
 
 if (is_realm_allowed(1043)) {
 	$local_data_ids = db_fetch_assoc_prepared('SELECT DISTINCT data_template_rrd.local_data_id
 		FROM graph_templates_item
-		LEFT JOIN data_template_rrd 
+		LEFT JOIN data_template_rrd
 		ON graph_templates_item.task_item_id=data_template_rrd.id
 		WHERE graph_templates_item.local_graph_id = ?', array(get_filter_request_var('local_graph_id')));
 
 	$results = '';
 	if (sizeof($local_data_ids)) {
@@ -55,24 +55,24 @@ if (is_realm_allowed(1043)) {
 			if ($data_source_path != '') {
 				if ($debug) {
 					cacti_log(read_config_option('path_php_binary') . ' -q ' . $config['base_path'] . '/cli/removespikes.php ' .
 						' -R=' . $data_source_path . (isset_request_var('dryrun') ? ' --dryrun' : '') .
 						(isset_request_var('method') ? ' -M=' . get_nfilter_request_var('method'):'') .
-						(isset_request_var('avgnan') ? ' -A=' . get_nfilter_request_var('avgnan'):'') .
-						(isset_request_var('outlier-start') ? ' --outlier-start=' . get_nfilter_request_var('outlier-start'):'') .
-						(isset_request_var('outlier-end') ? ' --outlier-end=' . get_nfilter_request_var('outlier-end'):'') .
-						' -U=' . $_SESSION['sess_user_id'] . 
+						(isset_request_var('avgnan') ? ' -A=' . escapeshellarg(get_nfilter_request_var('avgnan')):'') .
+						(isset_request_var('outlier-start') ? ' --outlier-start=' . escapeshellarg(get_nfilter_request_var('outlier-start')):'') .
+						(isset_request_var('outlier-end') ? ' --outlier-end=' . escapeshellarg(get_nfilter_request_var('outlier-end')):'') .
+						' -U=' . $_SESSION['sess_user_id'] .
 						' --html', false);
 				}
 
 				$results .= shell_exec(read_config_option('path_php_binary') . ' -q ' . $config['base_path'] . '/cli/removespikes.php ' .
 					' -R=' . $data_source_path . (isset_request_var('dryrun') ? ' --dryrun' : '') .
 					(isset_request_var('method') ? ' -M=' . get_nfilter_request_var('method'):'') .
-					(isset_request_var('avgnan') ? ' -A=' . get_nfilter_request_var('avgnan'):'') .
-					(isset_request_var('outlier-start') ? ' --outlier-start=' . get_nfilter_request_var('outlier-start'):'') .
-					(isset_request_var('outlier-end') ? ' --outlier-end=' . get_nfilter_request_var('outlier-end'):'') .
-					' -U=' . $_SESSION['sess_user_id'] . 
+					(isset_request_var('avgnan') ? ' -A=' . escapeshellarg(get_nfilter_request_var('avgnan')):'') .
+					(isset_request_var('outlier-start') ? ' --outlier-start=' . escapeshellarg(get_nfilter_request_var('outlier-start')):'') .
+					(isset_request_var('outlier-end') ? ' --outlier-end=' . escapeshellarg(get_nfilter_request_var('outlier-end')):'') .
+					' -U=' . $_SESSION['sess_user_id'] .
 					' --html');
 			}
 		}
 	}
 

Vulnerable code: 			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $cancel_url);?>")' value='<?php print __esc('Cancel');?>'>
			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $action_url . '&confirm=true');?>")' value='<?php print __esc('Delete');?>'>
		$cancel_action = "<input type='button' onClick='cactiReturnTo(\"" . htmlspecialchars($cancel_url) . "\")' value='" . $calt . "'>";
		LEFT JOIN data_template_rrd 
						(isset_request_var('avgnan') ? ' -A=' . get_nfilter_request_var('avgnan'):'') .
						(isset_request_var('outlier-start') ? ' --outlier-start=' . get_nfilter_request_var('outlier-start'):'') .
						(isset_request_var('outlier-end') ? ' --outlier-end=' . get_nfilter_request_var('outlier-end'):'') .
						' -U=' . $_SESSION['sess_user_id'] . 
					(isset_request_var('avgnan') ? ' -A=' . get_nfilter_request_var('avgnan'):'') .
					(isset_request_var('outlier-start') ? ' --outlier-start=' . get_nfilter_request_var('outlier-start'):'') .
					(isset_request_var('outlier-end') ? ' --outlier-end=' . get_nfilter_request_var('outlier-end'):'') .
					' -U=' . $_SESSION['sess_user_id'] . 
Fixed code: -issue#877: Improving resolution to issue#847 and one additional vulnerability
			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $cancel_url, ENT_QUOTES);?>")' value='<?php print __esc('Cancel');?>'>
			<input type='button' onClick='cactiReturnTo("<?php print htmlspecialchars($config['url_path'] . $action_url . '&confirm=true', ENT_QUOTES);?>")' value='<?php print __esc('Delete');?>'>
		$cancel_action = "<input type='button' onClick='cactiReturnTo(\"" . htmlspecialchars($cancel_url, ENT_QUOTES) . "\")' value='" . $calt . "'>";
		LEFT JOIN data_template_rrd
						(isset_request_var('avgnan') ? ' -A=' . escapeshellarg(get_nfilter_request_var('avgnan')):'') .
						(isset_request_var('outlier-start') ? ' --outlier-start=' . escapeshellarg(get_nfilter_request_var('outlier-start')):'') .
						(isset_request_var('outlier-end') ? ' --outlier-end=' . escapeshellarg(get_nfilter_request_var('outlier-end')):'') .
						' -U=' . $_SESSION['sess_user_id'] .
					(isset_request_var('avgnan') ? ' -A=' . escapeshellarg(get_nfilter_request_var('avgnan')):'') .
					(isset_request_var('outlier-start') ? ' --outlier-start=' . escapeshellarg(get_nfilter_request_var('outlier-start')):'') .
					(isset_request_var('outlier-end') ? ' --outlier-end=' . escapeshellarg(get_nfilter_request_var('outlier-end')):'') .
					' -U=' . $_SESSION['sess_user_id'] .