CVE-2013-1770 (PHP, published 2014-04-02T16:05Z)
Description: value: Cross-site scripting (XSS) vulnerability in views_view.php in Ganglia Web 3.5.7 allows remote attackers to inject arbitrary web script or HTML via the view_name parameter.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-79 \u2014 Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting')
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.
Repository: https://github.com/ganglia/ganglia-web
Files changed:
functions.php
get_context.php
views_view.php
Commit message: Add limitation for view names. Fixes #160


Vulnerable code:
$user['viewname'] = isset($_GET["vn"]) ?
    escapeshellcmd( clean_string( rawurldecode($_GET["vn"]) ) ) : '';
<?php

include_once("./eval_conf.php");
include_once("./functions.php");

if( ! checkAccess(GangliaAcl::ALL_VIEWS, GangliaAcl::VIEW, $conf) ) {
  die("You do not have access to view views.");
}

// Load the metric caching code we use if we need to display graphs
retrieve_metrics_cache();

$base = isset($_GET['base']) ? rawurlencode($_GET['base']) . "/" : "";
?>

<html>
<head>
<script type="text/javascript" src="<?php print $base; ?>js/jquery-1.9.1.min.js"></script>
<script type="text/javascript" src="<?php print $base; ?>js/jquery-ui-1.9.1.custom.min.js"></script>
<link type="text/css" href="css/smoothness/jquery-ui-1.9.1.custom.min.css" rel="stylesheet"/>
<link rel="stylesheet" href="./styles.css" type="text/css">
</head>
<body>
  <div>

<?php
  $available_views = get_available_views();
  $view_name = $_GET['vn'];

  // Let's find the view definition
  foreach ($available_views as $view_id => $view) {
    if ($view['view_name'] == $view_name) {
      $view_elements = get_view_graph_elements($view);
      $range_args = "";
      if (isset($_GET['r']) && $_GET['r'] != "") 
	$range_args .= "&amp;r=" . rawurlencode($_GET['r']);
      if (isset($_GET['cs']) && isset($_GET['ce'])) 
	$range_args .= "&amp;cs=" . rawurlencode($_GET['cs']) . "&amp;ce=" . rawurlencode($_GET['ce']);

      if (count($view_elements) != 0) {
	foreach ($view_elements as $id => $element) {
	  $legend = isset($element['hostname']) ? $element['hostname'] : "Aggregate graph";
          $base = isset($_GET['base']) ? rawurlencode($_GET['base']) : '.';
	  print "<a href=\"" . $base . "/graph_all_periods.php?" . htmlentities($element['graph_args']) ."&amp;z=large\"><img title=\"" . $legend . " - " . $element['name'] . "\" border=0 src=\"" . $base . "/graph.php?" . htmlentities($element['graph_args']) . "&amp;z=small" . $range_args .  "\" style=\"padding:2px;\"></a>";
	}
      } else {
	print "No graphs defined for this view. Please add some";
      }
    }
  } 
?>
  </div>
</body>
</html>

      if ($view['view_name'] == $_GET['view_name']) {
                $_GET['view_name'] . 
      $empty_view = array ("view_name" => $_GET['view_name'],
      $view_suffix = str_replace(" ", "_", $_GET['view_name']);
      if ($view['view_name'] == $_GET['view_name']) {
      $_GET['view_name'] . 
      $view_suffix = str_replace(" ", "_", $_GET['view_name']);
      if ($view['view_name'] == $_GET['view_name']) {
      $_GET['view_name'] . 

Fixed code:
#------------------------------------------------------------------------------
# Allowed view name characters are alphanumeric plus space, dash and underscore
function is_proper_view_name( $string )
{
  if(preg_match("/[^a-zA-z0-9_\-\ ]/", $string)){
    return false;
  } else {
    return true;
  }
}


$user['viewname'] = '';
if ( isset($_GET["vn"]) &&  is_proper_view_name ($_GET["vn"]) ) {
    $user['viewname'] = $_GET["vn"];
}
$user['view_name'] = $_REQUEST['view_name'];

if( !is_proper_view_name ( $user['view_name'])){
?>
<div class="ui-widget">
  <div class="ui-state-default ui-corner-all" styledefault="padding: 0 .7em;"> 
    <p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span> 
    View names valid characters are 0-9, a-z, A-Z, -, _ and space. View has not been created.</p>
  </div>
</div>
<?php
  exit(0);
}

      if ($view['view_name'] == $user['view_name']) {
        break;
                $user['view_name'] . 
      $empty_view = array ("view_name" => $user['view_name'],
      $view_suffix = str_replace(" ", "_", $user['view_name']);
      if ($view['view_name'] == $user['view_name']) {
        break;
      $user['view_name'] . 
      $view_suffix = str_replace(" ", "_", $user['view_name']);
      if ($view['view_name'] == $user['view_name']) {
      $user['view_name'] .