CVE-2022-0375: Improper Neutralization of Input During Web Page Generation ('Cross-site Scripting') (CWE-79)
value: Cross-site Scripting (XSS) - Stored in Packagist remdex/livehelperchat prior to 3.93v.
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: 4.8
Published: 2022-01-26T10:15Z
Repository: https://github.com/livehelperchat/livehelperchat
Language: PHP
Files changed: lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list.tpl.php, lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list_admin.tpl.php, lhc_web/design/defaulttheme/tpl/lhchat/messagelist/plain.tpl.php, lhc_web/design/defaulttheme/tpl/lhform/collected.tpl.php, lhc_web/design/defaulttheme/tpl/lhtheme/admincss.tpl.php, lhc_web/design/defaulttheme/tpl/lhtheme/adminthemeedit.tpl.php
Commit date: 2022-01-26 04:10:03 -0500
Commit message: fx #1734

Diff: diff --git a/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list.tpl.php b/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list.tpl.php
index 79292d18e01..e53c1f12e94 100644
--- a/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list.tpl.php
+++ b/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list.tpl.php
@@ -1,32 +1,29 @@
-<?php 
-
+<?php
 $lastOperatorChanged = false;
 $lastOperatorId = false;
+$lastOperatorNick = '';
 
-foreach ($messages as $msg ) : if ($msg->user_id > -1 || $msg->user_id == -2) : 
+$messagesStats = array(
+    'total_messages' => count($messages),
+    'counter_messages' => 0,
+);
 
-if ($lastOperatorId !== false && $lastOperatorId != $msg->user_id) {
-    $lastOperatorChanged = true;
-} else {
-    $lastOperatorChanged = false;
-}
+foreach ($messages as $msg) :
+    $msg = $msg->getState();
+    $messagesStats['counter_messages']++;
 
-$lastOperatorId = $msg->user_id;
+    if ($lastOperatorId !== false && ($lastOperatorId != $msg['user_id'] || $msg['name_support'] != $lastOperatorNick)) {
+        $lastOperatorChanged = true;
+        $lastOperatorNick = $msg['name_support'];
+    } else {
+        $lastOperatorChanged = false;
+    }
 
-if ($msg->meta_msg != '') {
-    $metaMessageData = json_decode($msg->meta_msg, true); $messageId = $msg->id;
-} else if (isset($metaMessageData)) {
-    unset($metaMessageData);
-}
+    $lastOperatorId = $msg['user_id'];
+    $lastOperatorNick = $msg['name_support'];
 
-?>
-<div class="message-row<?php echo $msg->user_id == 0 ? ' response' : ' message-admin'.($lastOperatorChanged == true ? ' operator-changes' : '')?>" id="msg-<?php echo $msg->id?>"><div class="msg-date"><?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?></div><span class="usr-tit<?php echo $msg->user_id == 0 ? ' vis-tit' : ' op-tit'?>"><?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?>:&nbsp;</span>
 
-    <?php $msgBody = $msg->msg; $paramsMessageRender = array('sender' => $msg->user_id);?>
-    <?php include(erLhcoreClassDesign::designtpl('lhchat/lists/msg_body.tpl.php'));?>
+    ?>
+    <?php include(erLhcoreClassDesign::designtpl('lhchat/lists/user_msg_row.tpl.php'));?>
+<?php endforeach; ?>
 
-    <?php if (isset($metaMessageData)) : ?>
-        <?php include(erLhcoreClassDesign::designtpl('lhgenericbot/message/meta_render.tpl.php'));?>
-    <?php endif; ?>
-</div>
-<?php endif; endforeach; ?>
\ No newline at end of file
diff --git a/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list_admin.tpl.php b/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list_admin.tpl.php
index 768c33cd730..2e9f69ca2c0 100644
--- a/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list_admin.tpl.php
+++ b/lhc_web/design/defaulttheme/tpl/lhchat/lists/msg_obj_list_admin.tpl.php
@@ -1,45 +1,8 @@
-<?php 
-
-$lastOperatorChanged = false;
-$lastOperatorId = false;
-$lastOperatorNick = '';
-
-foreach ($messages as $msg) : 
-
-if ($lastOperatorId !== false && ($lastOperatorId != $msg->user_id || $lastOperatorNick != $msg->name_support)) {
-    $lastOperatorChanged = true;
-    $lastOperatorNick = $msg->name_support;
-} else {
-    $lastOperatorChanged = false;
+<?php
+$messagesDefault = [];
+foreach ($messages as $msg) {
+    $messagesDefault[] = $msg->getState();
 }
-
-$lastOperatorId = $msg->user_id;
-
-    if ($msg->meta_msg != '') {
-        $metaMessageData = json_decode($msg->meta_msg, true); $messageId = $msg->id;
-    } else if (isset($metaMessageData)) {
-        unset($metaMessageData);
-    }
-
+$messages = $messagesDefault;
 ?>
-<?php if ($msg->user_id == -1) : ?>
-	<div class="message-row system-response" id="msg-<?php echo $msg->id?>"><div class="msg-date"><?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?></div><i><span class="usr-tit sys-tit"><?php echo erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncadmin','System assistant')?></span><?php echo erLhcoreClassBBCode::make_clickable(htmlspecialchars($msg->msg))?></i></div>
-<?php else : ?>
-    <?php if ($msg->msg != '' ||
-        isset($metaMessageData['content']['text_conditional']) ||
-        isset($metaMessageData['content']['chat_operation']) ||
-        isset($metaMessageData['content']['html']['content']) ||
-        isset($metaMessageData['content']['button_message'])
-    ) : ?>
-        <div class="message-row<?php echo $msg->user_id == 0 ? ' response' : ' message-admin'.($lastOperatorChanged == true ? ' operator-changes' : '')?>" id="msg-<?php echo $msg->id?>"><div class="msg-date"><?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?></div><span class="usr-tit<?php echo $msg->user_id == 0 ? ' vis-tit' : ' op-tit'?>"><?php if ($msg->user_id == 0) : ?><i class="material-icons"><?php echo ($chat->device_type == 0 ? 'computer' : ($chat->device_type == 1 ? 'smartphone' : 'tablet'))?></i><?php endif;?><?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?></span>
-            <?php $msgBody = $msg->msg; $paramsMessageRender = array('sender' => $msg->user_id, 'html_as_text' => true);?>
-            <?php include(erLhcoreClassDesign::designtpl('lhchat/lists/msg_body.tpl.php'));?>
-
-            <?php if (isset($metaMessageData)) : ?>
-                <?php include(erLhcoreClassDesign::designtpl('lhgenericbot/message/meta_render_admin.tpl.php'));?>
-            <?php endif; ?>
-            
-        </div>
-    <?php endif;?>
-<?php endif;?>
-<?php endforeach;?>
\ No newline at end of file
+<?php include(erLhcoreClassDesign::designtpl('lhchat/syncadmin.tpl.php'));?>
\ No newline at end of file
diff --git a/lhc_web/design/defaulttheme/tpl/lhchat/messagelist/plain.tpl.php b/lhc_web/design/defaulttheme/tpl/lhchat/messagelist/plain.tpl.php
index c76443dab65..aa68a1ef75a 100644
--- a/lhc_web/design/defaulttheme/tpl/lhchat/messagelist/plain.tpl.php
+++ b/lhc_web/design/defaulttheme/tpl/lhchat/messagelist/plain.tpl.php
@@ -1 +1,13 @@
-<?php foreach ($messages as $msg ) : ?><?php if (!isset($remove_meta) || $remove_meta == false ) :?>[<?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?>] [<?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?>] <?php endif;?><?php echo erLhcoreClassBBCodePlain::make_clickable($msg->msg, array('sender' => $msg->user_id)),"\n"?><?php endforeach; ?>
\ No newline at end of file
+<?php foreach ($messages as $msg ) :
+
+    if (isset($msg->meta_msg) && $msg->meta_msg != '') {
+        $metaMessageData = json_decode($msg->meta_msg, true); $messageId = isset($triggerMessageId) ? $triggerMessageId : $msg->id;
+    } else if (isset($metaMessageData)) {
+        unset($metaMessageData);
+    }
+
+    if (isset($metaMessageData['content']['whisper']) || empty($msg->msg)) {
+        continue;
+    }
+
+    ?><?php if (!isset($remove_meta) || $remove_meta == false ) :?>[<?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?>] [<?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?>] <?php endif;?><?php echo erLhcoreClassBBCodePlain::make_clickable($msg->msg, array('sender' => $msg->user_id)),"\n"?><?php endforeach; ?>
\ No newline at end of file
diff --git a/lhc_web/design/defaulttheme/tpl/lhform/collected.tpl.php b/lhc_web/design/defaulttheme/tpl/lhform/collected.tpl.php
index cbfa52e7244..b91a8d6fb0e 100644
--- a/lhc_web/design/defaulttheme/tpl/lhform/collected.tpl.php
+++ b/lhc_web/design/defaulttheme/tpl/lhform/collected.tpl.php
@@ -1,6 +1,6 @@
-<h1><?php echo htmlspecialchars($form)?></h1>
+<h1 ng-non-bindable><?php echo htmlspecialchars($form)?></h1>
 
 <div class="row pb-2">
 	<div class="col-6"><a href="<?php echo erLhcoreClassDesign::baseurl('form/downloadcollected')?>/<?php echo $form->id?>" class="btn btn-secondary"><?php echo erTranslationClassLhTranslation::getInstance()->getTranslation('form/collected','Download XLS');?></a></div>
 	<div class="col-6">
 	
@@ -10,11 +10,11 @@
     </div>
     
 	</div>
 </div>
 
-<table class="table" cellpadding="0" cellspacing="0">
+<table class="table" cellpadding="0" cellspacing="0" ng-non-bindable>
 <thead>
 <tr>
     <th><?php echo erTranslationClassLhTranslation::getInstance()->getTranslation('form/collected','Name');?></th>
     <th><?php echo erTranslationClassLhTranslation::getInstance()->getTranslation('form/collected','Identifier');?></th>
     <th><?php echo erTranslationClassLhTranslation::getInstance()->getTranslation('form/collected','Chat');?></th>
diff --git a/lhc_web/design/defaulttheme/tpl/lhtheme/admincss.tpl.php b/lhc_web/design/defaulttheme/tpl/lhtheme/admincss.tpl.php
index 59acb5c3e5d..9ee2084de7d 100644
--- a/lhc_web/design/defaulttheme/tpl/lhtheme/admincss.tpl.php
+++ b/lhc_web/design/defaulttheme/tpl/lhtheme/admincss.tpl.php
@@ -180,11 +180,11 @@ a {
     <?php if (isset($cssAttributes['btnpa_boc'])) : ?>border-color: #<?php echo $cssAttributes['btnpa_boc']?>;<?php endif;?>
 }
 <?php endif; ?>
 
 <?php if (isset($cssAttributes['buble_operator_background']) || isset($cssAttributes['buble_operator_text_color'])) : ?>
-    div.message-admin div.msg-body{
+    div.message-admin:not(.whisper-msg) div.msg-body{
         <?php if (isset($cssAttributes['buble_operator_background'])) : ?>background-color: #<?php echo $cssAttributes['buble_operator_background'];?>;<?php endif; ?>
         <?php if (isset($cssAttributes['buble_operator_text_color'])) : ?>color: #<?php echo $cssAttributes['buble_operator_text_color'];?>;<?php endif; ?>
     }
 
     <?php if (isset($cssAttributes['buble_operator_text_color'])) : ?>
diff --git a/lhc_web/design/defaulttheme/tpl/lhtheme/adminthemeedit.tpl.php b/lhc_web/design/defaulttheme/tpl/lhtheme/adminthemeedit.tpl.php
index 4461178dac5..9c1db8f9047 100644
--- a/lhc_web/design/defaulttheme/tpl/lhtheme/adminthemeedit.tpl.php
+++ b/lhc_web/design/defaulttheme/tpl/lhtheme/adminthemeedit.tpl.php
@@ -1,10 +1,7 @@
-<div class="row">
+<div class="row" ng-non-bindable>
     <div class="col-10"><h1><?php echo erTranslationClassLhTranslation::getInstance()->getTranslation('admintheme/form','Edit theme');?> - <?php echo htmlspecialchars($form->name)?></h1></div>
-    <?php /*?><div class="col-2">
-        <a class="btn btn-secondary" href="?export=1"><i class="material-icons mr-0">file_download</i></a>
-    </div>*/ ?>
 </div>
 
 <form action="<?php echo erLhcoreClassDesign::baseurl('theme/adminthemeedit')?>/<?php echo $form->id?>" method="post" autocomplete="off" enctype="multipart/form-data">
 
     <?php if (isset($updated)) : $msg = erTranslationClassLhTranslation::getInstance()->getTranslation('admintheme/form','Updated'); ?>

Vulnerable code: <?php 

foreach ($messages as $msg ) : if ($msg->user_id > -1 || $msg->user_id == -2) : 
if ($lastOperatorId !== false && $lastOperatorId != $msg->user_id) {
    $lastOperatorChanged = true;
} else {
    $lastOperatorChanged = false;
}
$lastOperatorId = $msg->user_id;
if ($msg->meta_msg != '') {
    $metaMessageData = json_decode($msg->meta_msg, true); $messageId = $msg->id;
} else if (isset($metaMessageData)) {
    unset($metaMessageData);
}
?>
<div class="message-row<?php echo $msg->user_id == 0 ? ' response' : ' message-admin'.($lastOperatorChanged == true ? ' operator-changes' : '')?>" id="msg-<?php echo $msg->id?>"><div class="msg-date"><?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?></div><span class="usr-tit<?php echo $msg->user_id == 0 ? ' vis-tit' : ' op-tit'?>"><?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?>:&nbsp;</span>
    <?php $msgBody = $msg->msg; $paramsMessageRender = array('sender' => $msg->user_id);?>
    <?php include(erLhcoreClassDesign::designtpl('lhchat/lists/msg_body.tpl.php'));?>
    <?php if (isset($metaMessageData)) : ?>
        <?php include(erLhcoreClassDesign::designtpl('lhgenericbot/message/meta_render.tpl.php'));?>
    <?php endif; ?>
</div>
<?php endif; endforeach; ?>
<?php 

$lastOperatorChanged = false;
$lastOperatorId = false;
$lastOperatorNick = '';

foreach ($messages as $msg) : 

if ($lastOperatorId !== false && ($lastOperatorId != $msg->user_id || $lastOperatorNick != $msg->name_support)) {
    $lastOperatorChanged = true;
    $lastOperatorNick = $msg->name_support;
} else {
    $lastOperatorChanged = false;

$lastOperatorId = $msg->user_id;

    if ($msg->meta_msg != '') {
        $metaMessageData = json_decode($msg->meta_msg, true); $messageId = $msg->id;
    } else if (isset($metaMessageData)) {
        unset($metaMessageData);
    }

<?php if ($msg->user_id == -1) : ?>
	<div class="message-row system-response" id="msg-<?php echo $msg->id?>"><div class="msg-date"><?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?></div><i><span class="usr-tit sys-tit"><?php echo erTranslationClassLhTranslation::getInstance()->getTranslation('chat/syncadmin','System assistant')?></span><?php echo erLhcoreClassBBCode::make_clickable(htmlspecialchars($msg->msg))?></i></div>
<?php else : ?>
    <?php if ($msg->msg != '' ||
        isset($metaMessageData['content']['text_conditional']) ||
        isset($metaMessageData['content']['chat_operation']) ||
        isset($metaMessageData['content']['html']['content']) ||
        isset($metaMessageData['content']['button_message'])
    ) : ?>
        <div class="message-row<?php echo $msg->user_id == 0 ? ' response' : ' message-admin'.($lastOperatorChanged == true ? ' operator-changes' : '')?>" id="msg-<?php echo $msg->id?>"><div class="msg-date"><?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?></div><span class="usr-tit<?php echo $msg->user_id == 0 ? ' vis-tit' : ' op-tit'?>"><?php if ($msg->user_id == 0) : ?><i class="material-icons"><?php echo ($chat->device_type == 0 ? 'computer' : ($chat->device_type == 1 ? 'smartphone' : 'tablet'))?></i><?php endif;?><?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?></span>
            <?php $msgBody = $msg->msg; $paramsMessageRender = array('sender' => $msg->user_id, 'html_as_text' => true);?>
            <?php include(erLhcoreClassDesign::designtpl('lhchat/lists/msg_body.tpl.php'));?>

            <?php if (isset($metaMessageData)) : ?>
                <?php include(erLhcoreClassDesign::designtpl('lhgenericbot/message/meta_render_admin.tpl.php'));?>
            <?php endif; ?>
            
        </div>
    <?php endif;?>
<?php endif;?>
<?php endforeach;?>
<?php foreach ($messages as $msg ) : ?><?php if (!isset($remove_meta) || $remove_meta == false ) :?>[<?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?>] [<?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?>] <?php endif;?><?php echo erLhcoreClassBBCodePlain::make_clickable($msg->msg, array('sender' => $msg->user_id)),"\n"?><?php endforeach; ?>
<h1><?php echo htmlspecialchars($form)?></h1>
<table class="table" cellpadding="0" cellspacing="0">
    div.message-admin div.msg-body{
<div class="row">
    <?php /*?><div class="col-2">
        <a class="btn btn-secondary" href="?export=1"><i class="material-icons mr-0">file_download</i></a>
    </div>*/ ?>
Fixed code: <?php
$lastOperatorNick = '';
$messagesStats = array(
    'total_messages' => count($messages),
    'counter_messages' => 0,
);
foreach ($messages as $msg) :
    $msg = $msg->getState();
    $messagesStats['counter_messages']++;
    if ($lastOperatorId !== false && ($lastOperatorId != $msg['user_id'] || $msg['name_support'] != $lastOperatorNick)) {
        $lastOperatorChanged = true;
        $lastOperatorNick = $msg['name_support'];
    } else {
        $lastOperatorChanged = false;
    }
    $lastOperatorId = $msg['user_id'];
    $lastOperatorNick = $msg['name_support'];
    ?>
    <?php include(erLhcoreClassDesign::designtpl('lhchat/lists/user_msg_row.tpl.php'));?>
<?php endforeach; ?>
<?php
$messagesDefault = [];
foreach ($messages as $msg) {
    $messagesDefault[] = $msg->getState();
$messages = $messagesDefault;
<?php include(erLhcoreClassDesign::designtpl('lhchat/syncadmin.tpl.php'));?>
<?php foreach ($messages as $msg ) :

    if (isset($msg->meta_msg) && $msg->meta_msg != '') {
        $metaMessageData = json_decode($msg->meta_msg, true); $messageId = isset($triggerMessageId) ? $triggerMessageId : $msg->id;
    } else if (isset($metaMessageData)) {
        unset($metaMessageData);
    }

    if (isset($metaMessageData['content']['whisper']) || empty($msg->msg)) {
        continue;
    }

    ?><?php if (!isset($remove_meta) || $remove_meta == false ) :?>[<?php echo date(erLhcoreClassModule::$dateDateHourFormat,$msg->time);?>] [<?php echo $msg->user_id == 0 ? htmlspecialchars($chat->nick) : htmlspecialchars($msg->name_support) ?>] <?php endif;?><?php echo erLhcoreClassBBCodePlain::make_clickable($msg->msg, array('sender' => $msg->user_id)),"\n"?><?php endforeach; ?>
<h1 ng-non-bindable><?php echo htmlspecialchars($form)?></h1>
<table class="table" cellpadding="0" cellspacing="0" ng-non-bindable>
    div.message-admin:not(.whisper-msg) div.msg-body{
<div class="row" ng-non-bindable>