CVE-2022-3562: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site Scripting (XSS) - Stored in GitHub repository librenms/librenms prior to 22.10.0.
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: 2022-11-20T05:15Z
Repository: https://github.com/librenms/librenms
Language: PHP
Files changed: includes/html/pages/bill.inc.php, includes/html/pages/bill/addoreditbill.inc.php, includes/html/table/bills.inc.php
Commit date: 2022-10-17 09:04:22 +0200
Commit message: Fix billing xss (#14465)

bill_name and bill_notes fields allow html injection
Diff: diff --git a/includes/html/pages/bill.inc.php b/includes/html/pages/bill.inc.php
index b1682490682..1505dd28aae 100644
--- a/includes/html/pages/bill.inc.php
+++ b/includes/html/pages/bill.inc.php
@@ -85,11 +85,11 @@ if (bill_permitted($bill_id)) {
         }
 
         echo '</div></div>';
     }//end print_port_list?>
 
-    <h2><?php   echo "Bill: ${bill_data['bill_name']}"; ?></h2>
+    <h2>Bill: <?php echo htmlentities($bill_data['bill_name']); ?></h2>
 
     <?php
     print_optionbar_start();
     echo '<strong>Bill</strong> &raquo; ';
     $menu_options = [
diff --git a/includes/html/pages/bill/addoreditbill.inc.php b/includes/html/pages/bill/addoreditbill.inc.php
index 8912df10520..c94d38ac73b 100644
--- a/includes/html/pages/bill/addoreditbill.inc.php
+++ b/includes/html/pages/bill/addoreditbill.inc.php
@@ -1,10 +1,10 @@
 <h4>Bill Information</h4>
 <div class="form-group">
   <label for="bill_name" class="col-sm-4 control-label">Description</label>
   <div class="col-sm-8">
-    <input class="form-control input-sm" type="text" id="bill_name" name="bill_name" value="<?php echo $bill_data['bill_name']; ?>">
+    <input class="form-control input-sm" type="text" id="bill_name" name="bill_name" value="<?php echo htmlentities($bill_data['bill_name']); ?>">
   </div>
 </div>
 <div class="form-group">
   <label class="col-sm-4 control-label" for="bill_type">Billing Type</label>
   <div class="col-sm-8">
@@ -89,23 +89,23 @@
 <fieldset>
     <h4>Optional Information</h4>
     <div class="form-group">
       <label class="col-sm-4 control-label" for="bill_custid">Customer Reference</label>
       <div class="col-sm-8">
-        <input class="form-control input-sm" type="text" name="bill_custid" value="<?php echo $bill_data['bill_custid'] ?>">
+        <input class="form-control input-sm" type="text" name="bill_custid" value="<?php echo htmlentities($bill_data['bill_custid']); ?>">
       </div>
     </div>
     <div class="form-group">
       <label class="col-sm-4 control-label" for="bill_ref">Billing Reference</label>
       <div class="col-sm-8">
-        <input class="form-control input-sm" type="text" name="bill_ref" value="<?php echo $bill_data['bill_ref']; ?>">
+        <input class="form-control input-sm" type="text" name="bill_ref" value="<?php echo htmlentities($bill_data['bill_ref']); ?>">
       </div>
     </div>
     <div class="form-group">
       <label class="col-sm-4 control-label" for="bill_notes">Notes</label>
       <div class="col-sm-8">
-        <input class="form-control input-sm" type="textarea" name="bill_notes" value="<?php echo $bill_data['bill_notes']; ?>">
+        <input class="form-control input-sm" type="textarea" name="bill_notes" value="<?php echo htmlentities($bill_data['bill_notes']); ?>">
       </div>
     </div>
 </fieldset>
 
 <script type="text/javascript">
diff --git a/includes/html/table/bills.inc.php b/includes/html/table/bills.inc.php
index da0bcbd8841..be5aecffe47 100644
--- a/includes/html/table/bills.inc.php
+++ b/includes/html/table/bills.inc.php
@@ -92,11 +92,11 @@ foreach (dbFetchRows($sql, $param) as $bill) {
     $dir_95th = $bill['dir_95th'];
     $total_data = format_bytes_billing($bill['total_data']);
     $rate_average = $bill['rate_average'];
     $url = \LibreNMS\Util\Url::generate(['page' => 'bill', 'bill_id' => $bill['bill_id']]);
     $used95th = Number::formatSi($bill['rate_95th'], 2, 3, '') . 'bps';
-    $notes = $bill['bill_notes'];
+    $notes = htmlentities($bill['bill_notes']);
 
     if ($prev) {
         $percent = $bill['bill_percent'];
         $overuse = $bill['bill_overuse'];
     } else {
@@ -140,11 +140,11 @@ foreach (dbFetchRows($sql, $param) as $bill) {
     $background = \LibreNMS\Util\Color::percentage($percent, null);
     $right_background = $background['right'];
     $left_background = $background['left'];
     $overuse_formatted = (($overuse <= 0) ? '-' : "<span style='color: #${background['left']}; font-weight: bold;'>$overuse_formatted</span>");
 
-    $bill_name = "<a href='$url'><span style='font-weight: bold;' class='interface'>${bill['bill_name']}</span></a><br />" .
+    $bill_name = "<a href='$url'><span style='font-weight: bold;' class='interface'>" . htmlentities($bill['bill_name']) . '</span></a><br />' .
                     date('Y-m-d', strtotime($datefrom)) . ' to ' . date('Y-m-d', strtotime($dateto));
     $bar = print_percentage_bar(250, 20, $percent, null, 'ffffff', $background['left'], $percent . '%', 'ffffff', $background['right']);
     $actions = '';
 
     if (! $prev && Auth::user()->hasGlobalAdmin()) {

Vulnerable code:     <h2><?php   echo "Bill: ${bill_data['bill_name']}"; ?></h2>
    <input class="form-control input-sm" type="text" id="bill_name" name="bill_name" value="<?php echo $bill_data['bill_name']; ?>">
        <input class="form-control input-sm" type="text" name="bill_custid" value="<?php echo $bill_data['bill_custid'] ?>">
        <input class="form-control input-sm" type="text" name="bill_ref" value="<?php echo $bill_data['bill_ref']; ?>">
        <input class="form-control input-sm" type="textarea" name="bill_notes" value="<?php echo $bill_data['bill_notes']; ?>">
    $notes = $bill['bill_notes'];
    $bill_name = "<a href='$url'><span style='font-weight: bold;' class='interface'>${bill['bill_name']}</span></a><br />" .
Fixed code:     <h2>Bill: <?php echo htmlentities($bill_data['bill_name']); ?></h2>
    <input class="form-control input-sm" type="text" id="bill_name" name="bill_name" value="<?php echo htmlentities($bill_data['bill_name']); ?>">
        <input class="form-control input-sm" type="text" name="bill_custid" value="<?php echo htmlentities($bill_data['bill_custid']); ?>">
        <input class="form-control input-sm" type="text" name="bill_ref" value="<?php echo htmlentities($bill_data['bill_ref']); ?>">
        <input class="form-control input-sm" type="textarea" name="bill_notes" value="<?php echo htmlentities($bill_data['bill_notes']); ?>">
    $notes = htmlentities($bill['bill_notes']);
    $bill_name = "<a href='$url'><span style='font-weight: bold;' class='interface'>" . htmlentities($bill['bill_name']) . '</span></a><br />' .