Vulnerability: An issue was discovered in ZoneMinder v1.32.3. Reflected XSS exists in web/skins/classic/views/plugin.php via the zm/index.php?view=plugin pl parameter.
Vulnerability ID: CVE-2019-6777
CWE: CWE-79
Severity score: 2.9
Project: https://github.com/mnoorenberghe/ZoneMinder
Published: 2019-01-24
File: web/skins/classic/views/plugin.php
Commit message: plugin.php: Fix XSS and directory traversal bugs. Fixes #2436

This view seems like dead code so maybe it should be removed instead.
Commit author: Matthew Noorenberghe

Vulnerable version (before fix):
    return; } $monitor = dbFetchMonitor ( $mid ); $plugin = $_REQUEST['pl'];  $plugin_path = dirname(ZM_PLUGINS_CONFIG_PATH)."/".$plugin;  function pLang($name) <body>   <div id="page">     <div id="header">       <h2><?php echo translate('Monitor') ?> <?php echo $monitor['Name'] ?> - <?php echo translate('Zone') ?> <?php echo $newZone['Name'] ?> - <?php echo translate('Plugin') ?> <?php echo $plugin ?></h2>     </div>     <div id="content">       <form name="pluginForm" id="pluginForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">         <input type="hidden" name="view" value="<?php echo $view ?>"/>         <input type="hidden" name="action" value="plugin"/>         <input type="hidden" name="mid" value="<?php echo $mid ?>"/>         <input type="hidden" name="zid" value="<?php echo $zid ?>"/>         <input type="hidden" name="pl" value="<?php echo $plugin ?>"/>          <div id="settingsPanel">           <table id="pluginSettings" cellspacing="0">

Fixed version (after fix):
    return; } $monitor = dbFetchMonitor ( $mid ); // Only allow certain filename characters (not including a period) to prevent directory traversal. $plugin = preg_replace('/[^-a-zA-Z0-9]/', '', $_REQUEST['pl']);  $plugin_path = dirname(ZM_PLUGINS_CONFIG_PATH)."/".$plugin;  function pLang($name) <body>   <div id="page">     <div id="header">       <h2><?php echo translate('Monitor') ?> <?php echo $monitor['Name'] ?> - <?php echo translate('Zone') ?> <?php echo $newZone['Name'] ?> - <?php echo translate('Plugin') ?> <?php echo validHtmlStr($plugin) ?></h2>     </div>     <div id="content">       <form name="pluginForm" id="pluginForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">         <input type="hidden" name="view" value="<?php echo $view ?>"/>         <input type="hidden" name="action" value="plugin"/>         <input type="hidden" name="mid" value="<?php echo $mid ?>"/>         <input type="hidden" name="zid" value="<?php echo $zid ?>"/>         <input type="hidden" name="pl" value="<?php echo validHtmlStr($plugin) ?>"/>          <div id="settingsPanel">           <table id="pluginSettings" cellspacing="0">

Patch:
patch: @@ -36,7 +36,8 @@
    return;
 }
 $monitor = dbFetchMonitor ( $mid );
-$plugin = $_REQUEST['pl'];
+// Only allow certain filename characters (not including a period) to prevent directory traversal.
+$plugin = preg_replace('/[^-a-zA-Z0-9]/', '', $_REQUEST['pl']);
 
 $plugin_path = dirname(ZM_PLUGINS_CONFIG_PATH)."/".$plugin;
 
@@ -103,15 +104,15 @@ function pLang($name)
 <body>
   <div id="page">
     <div id="header">
-      <h2><?php echo translate('Monitor') ?> <?php echo $monitor['Name'] ?> - <?php echo translate('Zone') ?> <?php echo $newZone['Name'] ?> - <?php echo translate('Plugin') ?> <?php echo $plugin ?></h2>
+      <h2><?php echo translate('Monitor') ?> <?php echo $monitor['Name'] ?> - <?php echo translate('Zone') ?> <?php echo $newZone['Name'] ?> - <?php echo translate('Plugin') ?> <?php echo validHtmlStr($plugin) ?></h2>
     </div>
     <div id="content">
       <form name="pluginForm" id="pluginForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
         <input type="hidden" name="view" value="<?php echo $view ?>"/>
         <input type="hidden" name="action" value="plugin"/>
         <input type="hidden" name="mid" value="<?php echo $mid ?>"/>
         <input type="hidden" name="zid" value="<?php echo $zid ?>"/>
-        <input type="hidden" name="pl" value="<?php echo $plugin ?>"/>
+        <input type="hidden" name="pl" value="<?php echo validHtmlStr($plugin) ?>"/>
 
         <div id="settingsPanel">
           <table id="pluginSettings" cellspacing="0">
path: web/skins/classic/views/plugin.php