CVE-2023-2943 (published 2023-05-27T22:15Z)

Code Injection in GitHub repository openemr/openemr prior to 7.0.1.

CVSS v3 base score: 8.8, HIGH (CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-94
cwe_name: Improper Control of Generation of Code ('Code Injection')
description: The product constructs all or part of a code segment using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the syntax or behavior of the intended code segment.
extended_description: 
            When a product allows a user's input to contain code syntax, it might be possible for an attacker to craft the code in such a way that it will alter the intended control flow of the product. Such an alteration could lead to arbitrary code execution.
            Injection problems encompass a wide variety of issues -- all mitigated in very different ways. For this reason, the most effective way to discuss these weaknesses is to note the distinct features which classify them as injection weaknesses. The most important issue to note is that all injection problems share one thing in common -- i.e., they allow for the injection of control plane data into the user-controlled data plane. This means that the execution of the process may be altered by sending code in through legitimate data channels, using no other mechanism. While buffer overflows, and many other flaws, involve the use of some further issue to gain execution, injection problems need only for the data to be parsed. The most classic instantiations of this category of weakness are SQL injection and format string vulnerabilities.
         
         

Fix information:
repo_url: https://github.com/openemr/openemr
commit_details: repo_url: https://github.com/openemr/openemr
author: stephen waite
author_date: 2023-01-15 20:32:38-05:00
msg: bug fix (#6079)

* bug fix

* better fix and remove prefix underscore private visibility

* better fix

* even better fix

* revert

* jsAttr()

* another fix

* another fix

* use |=

* review fixes

* typo

* remove whitespace
repository: repo_url: https://github.com/openemr/openemr
repo_name: openemr/openemr
description: The most popular open source electronic health records and medical practice management solution.
repo_language: PHP
owner: openemr
file_changes: filename: pnotes.inc.php
change_type: ModificationType.MODIFY
diff: @@ -389,7 +389,7 @@ function addPnote(
         'INSERT INTO pnotes (date, body, pid, user, groupname, ' .
         'authorized, activity, title, assigned_to, message_status, update_by, update_date) VALUES ' .
         '(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())',
-        array($datetime, $body, $pid, $user, $_SESSION['authProvider'], $authorized, $activity, $title, $assigned_to, $message_status, $_SESSION['authUserID'])
+        array($datetime, $body, $pid, $user, ($_SESSION['authProvider'] ?? null), $authorized, $activity, $title, $assigned_to, $message_status, ($_SESSION['authUserID'] ?? null))
     );
 }
 

programming_language: PHP
filename: add_edit_event_user.php
change_type: ModificationType.MODIFY
diff: @@ -43,7 +43,7 @@ require_once("$srcdir/patient.inc.php");
 require_once("$srcdir/forms.inc.php");
 require_once("$srcdir/appointments.inc.php");
 
-use OpenEMR\Core\Header;
+use OpenEMR\Services\AppointmentService;
 
 // Things that might be passed by our opener.
 //
@@ -64,6 +64,24 @@ if (!empty($eid) && !$checkEidInAppt) {
     exit();
 }
 
+if (!empty($_POST['form_pid'])) {
+    if ($_POST['form_pid'] != $_SESSION['pid']) {
+        echo js_escape("error");
+        exit();
+    }
+
+    if (! getAvailableSlots($_POST['form_date'], date('Y-m-d', strtotime("+1 year " . $_POST['form_date'])), $_POST['form_provider_ae'])) {
+        echo js_escape("error");
+        exit();
+    }
+
+    $appointment_service = (new AppointmentService())->getOneCalendarCategory($_POST['form_category']);
+    if (($_POST['form_duration'] * 60) != ($appointment_service[0]['pc_duration'])) {
+        echo js_escape("error");
+        exit();
+    }
+}
+
 if ($date) {
     $date = substr($date, 0, 4) . '-' . substr($date, 4, 2) . '-' . substr($date, 6);
 } else {
@@ -135,7 +153,7 @@ if (($_POST['form_action'] ?? null) == "save") {
     $event_date = fixDate($_POST['form_date']);
 
 // Compute start and end time strings to be saved.
-    if ($_POST['form_allday']) {
+    if ($_POST['form_allday'] ?? null) {
         $tmph = 0;
         $tmpm = 0;
         $duration = 24 * 60;
@@ -165,7 +183,7 @@ if (($_POST['form_action'] ?? null) == "save") {
 
 // More garbage, but this time 1 character of it is used to save the
 // repeat type.
-    if ($_POST['form_repeat']) {
+    if ($_POST['form_repeat'] ?? null) {
         $recurrspec = 'a:5:{' .
             's:17:"event_repeat_freq";s:1:"' . $_POST['form_repeat_freq'] . '";' .
             's:22:"event_repeat_freq_type";s:1:"' . $_POST['form_repeat_type'] . '";' .
@@ -185,7 +203,7 @@ if (($_POST['form_action'] ?? null) == "save") {
 //for example monday, or thursday. We set the start date on the first day of the week
 //that the event is scheduled. For example if you set the event to repeat on each monday
 //the start date of the event will be set on the first monday after the day the event is scheduled
-    if ($_POST['form_repeat_type'] == 5) {
+    if (($_POST['form_repeat_type'] ?? null) == 5) {
         $exploded_date = explode("-", $event_date);
         $edate = date("D", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2], $exploded_date[0]));
         if ($edate == "Tue") {
@@ -201,7 +219,7 @@ if (($_POST['form_action'] ?? null) == "save") {
         } elseif ($edate == "Sun") {
             $event_date = date("Y-m-d", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2] + 1, $exploded_date[0]));
         }
-    } elseif ($_POST['form_repeat_type'] == 6) {
+    } elseif (($_POST['form_repeat_type'] ?? null) == 6) {
         $exploded_date = explode("-", $event_date);
         $edate = date("D", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2], $exploded_date[0]));
         if ($edate == "Wed") {
@@ -217,7 +235,7 @@ if (($_POST['form_action'] ?? null) == "save") {
         } elseif ($edate == "Mon") {
             $event_date = date("Y-m-d", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2] + 1, $exploded_date[0]));
         }
-    } elseif ($_POST['form_repeat_type'] == 7) {
+    } elseif (($_POST['form_repeat_type'] ?? null) == 7) {
         $exploded_date = explode("-", $event_date);
         $edate = date("D", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2], $exploded_date[0]));
         if ($edate == "Thu") {
@@ -233,7 +251,7 @@ if (($_POST['form_action'] ?? null) == "save") {
         } elseif ($edate == "Tue") {
             $event_date = date("Y-m-d", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2] + 1, $exploded_date[0]));
         }
-    } elseif ($_POST['form_repeat_type'] == 8) {
+    } elseif (($_POST['form_repeat_type'] ?? null) == 8) {
         $exploded_date = explode("-", $event_date);
         $edate = date("D", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2], $exploded_date[0]));
         if ($edate == "Fri") {
@@ -249,7 +267,7 @@ if (($_POST['form_action'] ?? null) == "save") {
         } elseif ($edate == "Wed") {
             $event_date = date("Y-m-d", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2] + 1, $exploded_date[0]));
         }
-    } elseif ($_POST['form_repeat_type'] == 9) {
+    } elseif (($_POST['form_repeat_type'] ?? null) == 9) {
         $exploded_date = explode("-", $event_date);
         $edate = date("D", mktime(0, 0, 0, $exploded_date[1], $exploded_date[2], $exploded_date[0]));
         if ($edate == "Sat") {
@@ -305,7 +323,7 @@ if (($_POST['form_action'] ?? null) == "save") {
                         "'" . add_escape_custom($_POST['form_category']) . "', " .
                         "'" . add_escape_custom($row['pc_multiple']) . "', " .
                         "'" . add_escape_custom($to_be_inserted) . "', " .
-                        "'" . add_escape_custom($_POST['form_pid']) . "', " .
+                        "'" . add_escape_custom($_SESSION['pid']) . "', " .
                         "'" . add_escape_custom($_POST['form_title']) . "', " .
                         "NOW(), " .
                         "'" . add_escape_custom($_POST['form_comments']) . "', " .
@@ -332,7 +350,7 @@ if (($_POST['form_action'] ?? null) == "save") {
             foreach ($_POST['form_provider_ae'] as $provider) {
                 sqlStatement("UPDATE openemr_postcalendar_events SET " .
                     "pc_catid = '" . add_escape_custom($_POST['form_category']) . "', " .
-                    "pc_pid = '" . add_escape_custom($_POST['form_pid']) . "', " .
+                    "pc_pid = '" . add_escape_custom($_SESSION['pid']) . "', " .
                     "pc_title = '" . add_escape_custom($_POST['form_title']) . "', " .
                     "pc_time = NOW(), " .
                     "pc_hometext = '" . add_escape_custom($_POST['form_comments']) . "', " .
@@ -365,22 +383,22 @@ if (($_POST['form_action'] ?? null) == "save") {
             sqlStatement("UPDATE openemr_postcalendar_events SET " .
                 "pc_catid = '" . add_escape_custom($_POST['form_category']) . "', " .
                 "pc_aid = '" . add_escape_custom($prov) . "', " .
-                "pc_pid = '" . add_escape_custom($_POST['form_pid']) . "', " .
+                "pc_pid = '" . add_escape_custom($_SESSION['pid']) . "', " .
                 "pc_title = '" . add_escape_custom($_POST['form_title']) . "', " .
                 "pc_time = NOW(), " .
                 "pc_hometext = '" . add_escape_custom($_POST['form_comments']) . "', " .
                 "pc_informant = '" . add_escape_custom($_SESSION['providerId']) . "', " .
                 "pc_eventDate = '" . add_escape_custom($event_date) . "', " .
-                "pc_endDate = '" . add_escape_custom(fixDate($_POST['form_enddate'])) . "', " .
+                "pc_endDate = '" . add_escape_custom(fixDate($_POST['form_enddate'] ?? '')) . "', " .
                 "pc_duration = '" . add_escape_custom(($duration * 60)) . "', " .
-                "pc_recurrtype = '" . ($_POST['form_repeat'] ? '1' : '0') . "', " .
+                "pc_recurrtype = '" . (($_POST['form_repeat'] ?? null) ? '1' : '0') . "', " .
                 "pc_recurrspec = '" . add_escape_custom($recurrspec) . "', " .
                 "pc_startTime = '" . add_escape_custom($starttime) . "', " .
                 "pc_endTime = '" . add_escape_custom($endtime) . "', " .
-                "pc_alldayevent = '" . add_escape_custom($_POST['form_allday']) . "', " .
+                "pc_alldayevent = '" . add_escape_custom(($_POST['form_allday'] ?? '')) . "', " .
                 "pc_apptstatus = '" . add_escape_custom($_POST['form_apptstatus']) . "', " .
-                "pc_prefcatid = '" . add_escape_custom($_POST['form_prefcat']) . "', " .
-                "pc_facility = '" . (int)$_POST['facility'] . "' " . // FF stuff
+                "pc_prefcatid = '" . add_escape_custom(($_POST['form_prefcat'] ?? '')) . "', " .
+                "pc_facility = '" . (int)($_POST['facility'] ?? null) . "' " . // FF stuff
                 "WHERE pc_eid = '" . add_escape_custom($eid) . "'");
         }
 
@@ -416,7 +434,7 @@ if (($_POST['form_action'] ?? null) == "save") {
                     "'" . add_escape_custom($_POST['form_category']) . "', " .
                     "'" . add_escape_custom($new_multiple_value) . "', " .
                     "'" . add_escape_custom($provider) . "', " .
-                    "'" . add_escape_custom($_POST['form_pid']) . "', " .
+                    "'" . add_escape_custom($_SESSION['pid']) . "', " .
                     "'" . add_escape_custom($_POST['form_title']) . "', " .
                     "NOW(), " .
                     "'" . add_escape_custom($_POST['form_comments']) . "', " .
@@ -446,24 +464,24 @@ if (($_POST['form_action'] ?? null) == "save") {
                 ") VALUES ( " .
                 "'" . add_escape_custom($_POST['form_category']) . "', " .
                 "'" . add_escape_custom($_POST['form_provider_ae']) . "', " .
-                "'" . add_escape_custom($_POST['form_pid']) . "', " .
+                "'" . add_escape_custom($_SESSION['pid']) . "', " .
                 "'" . add_escape_custom($_POST['form_title']) . "', " .
                 "NOW(), " .
                 "'" . add_escape_custom($_POST['form_comments']) . "', " .
                 "'" . add_escape_custom($_SESSION['providerId']) . "', " .
                 "'" . add_escape_custom($event_date) . "', " .
-                "'" . add_escape_custom(fixDate($_POST['form_enddate'])) . "', " .
+                "'" . add_escape_custom(fixDate(($_POST['form_enddate'] ?? ''))) . "', " .
                 "'" . add_escape_custom(($duration * 60)) . "', " .
-                "'" . ($_POST['form_repeat'] ? '1' : '0') . "', " .
+                "'" . (($_POST['form_repeat'] ?? null) ? '1' : '0') . "', " .
                 "'" . add_escape_custom($recurrspec) . "', " .
                 "'" . add_escape_custom($starttime) . "', " .
                 "'" . add_escape_custom($endtime) . "', " .
-                "'" . add_escape_custom($_POST['form_allday']) . "', " .
+                "'" . add_escape_custom(($_POST['form_allday'] ?? '')) . "', " .
                 "'" . add_escape_custom($_POST['form_apptstatus']) . "', " .
-                "'" . add_escape_custom($_POST['form_prefcat']) . "', " .
+                "'" . add_escape_custom(($_POST['form_prefcat'] ?? null)) . "', " .
                 "'" . add_escape_custom($locationspec) . "', " .
                 "1, " .
-                "1, " . (int)$_POST['facility'] . ")"); // FF stuff
+                "1, " . (int)($_POST['facility'] ?? null) . ")"); // FF stuff
         } // INSERT single
     } // else - insert
 } elseif (($_POST['form_action'] ?? null) == "delete") {
@@ -496,7 +514,7 @@ if (!empty($_POST['form_action'])) {
     $note .= ". " . xl("Use Portal Dashboard to confirm with patient.");
     $title = xl("Patient Reminders");
     $user = sqlQueryNoLog("SELECT users.username FROM users WHERE authorized = 1 And id = ?", array($_POST['form_provider_ae']));
-    $rtn = addPnote($_POST['form_pid'], $note, 1, 1, $title, $user['username'], '', 'New');
+    $rtn = addPnote($_SESSION['pid'], $note, 1, 1, $title, $user['username'], '', 'New');
 
     $_SESSION['whereto'] = '#appointmentcard';
     header('Location:./home.php');
@@ -657,12 +675,12 @@ if ($userid) {
         <form method='post' name='theaddform' id='theaddform' action='add_edit_event_user.php?eid=<?php echo attr_url($eid); ?>'>
             <div class="col-12">
                 <input type="hidden" name="form_action" id="form_action" value="" />
-                <input type='hidden' name='form_title' id='form_title' value='<?php echo $row['pc_catid'] ? attr($row['pc_title']) : xla("Office Visit"); ?>' />
-                <input type='hidden' name='form_apptstatus' id='form_apptstatus' value='<?php echo $row['pc_apptstatus'] ? attr($row['pc_apptstatus']) : "^" ?>' />
+                <input type='hidden' name='form_title' id='form_title' value='<?php echo ($row['pc_catid'] ?? '') ? attr($row['pc_title']) : xla("Office Visit"); ?>' />
+                <input type='hidden' name='form_apptstatus' id='form_apptstatus' value='<?php echo ($row['pc_apptstatus'] ?? '') ? attr($row['pc_apptstatus'] ?? '') : "^" ?>' />
                 <div class="row form-group">
                     <div class="input-group col-12 col-md-6">
                         <label class="mr-2" for="form_category"><?php echo xlt('Visit'); ?>:</label>
-                        <select class="form-control mb-1" onchange='set_category()' id='form_category' name='form_category' value='<?php echo ($row['pc_catid'] > "") ? attr($row['pc_catid']) : '5'; ?>'>
+                        <select class="form-control mb-1" onchange='set_category()' id='form_category' name='form_category' value='<?php echo (($row['pc_catid'] ?? '') > "") ? attr($row['pc_catid']) : '5'; ?>'>
                             <?php echo $catoptions ?>
                         </select>
                     </div>
@@ -684,7 +702,7 @@ if ($userid) {
                         </div>
                         <div class="input-group">
                             <label class="mr-2" for="form_duration"><?php echo xlt('Duration'); ?></label>
-                            <input class="form-control" type='text' size='1' id='form_duration' name='form_duration' value='<?php echo $row['pc_duration'] ? ($row['pc_duration'] * 1 / 60) : attr($thisduration) ?>' readonly />
+                            <input class="form-control" type='text' size='1' id='form_duration' name='form_duration' value='<?php echo ($row['pc_duration'] ?? '') ? ($row['pc_duration'] * 1 / 60) : attr($thisduration) ?>' readonly />
                             <span class="input-group-append">
                             <span class="input-group-text"><?php echo "&nbsp;" . xlt('minutes'); ?></span>
                         </span>
@@ -730,7 +748,7 @@ if ($userid) {
                     </div>
                 </div>
                 <div class="row input-group my-1">
-                    <?php if ($_GET['eid'] && $row['pc_apptstatus'] !== 'x') { ?>
+                    <?php if (($_GET['eid'] ?? null) && $row['pc_apptstatus'] !== 'x') { ?>
                         <input type='button' id='form_cancel' class='btn btn-danger' onsubmit='return false' value='<?php echo xla('Cancel Appointment'); ?>' onclick="cancel_appointment()" />
                     <?php } ?>
                     <input type='button' name='form_save' class='btn btn-success' onsubmit='return false' value='<?php echo xla('Save'); ?>' onclick="validate()" />

programming_language: PHP
filename: find_appt_popup_user.php
change_type: ModificationType.MODIFY
diff: @@ -81,10 +81,14 @@ function doOneDay($catid, $udate, $starttime, $duration, $prefcatid)
             // only IN events with a matching preferred category or with no preferred
             // category; other IN events are to be treated as OUT events.
             if ($input_catid) {
-                if ($prefcatid == $input_catid || !$prefcatid) {
-                    $slots[$i] |= 1;
+                if (!empty($slots[$i])) {
+                    if ($prefcatid == $input_catid || !$prefcatid) {
+                        $slots[$i] |= 1;
+                    } else {
+                        $slots[$i] |= 2;
+                    }
                 } else {
-                    $slots[$i] |= 2;
+                    $slots[$i] |= 1;
                 }
             } else {
                 $slots[$i] |= 1;
@@ -114,7 +118,7 @@ if ($input_catid) {
 $info_msg = "";
 
 $searchdays = 7; // default to a 1-week lookahead
-if ($_REQUEST['searchdays']) {
+if ($_REQUEST['searchdays'] ?? null) {
     $searchdays = $_REQUEST['searchdays'];
 }
 

programming_language: PHP
filename: secure_chat.php
change_type: ModificationType.MODIFY
diff: @@ -406,7 +406,7 @@ $msgApp = new ChatController();
             };
 
             $scope.renderMessageBody = function (html) {
-                return html;
+                return jsAttr(html);
             };
             $scope.init();
         }]);

programming_language: PHP
filename: ChatController.php
change_type: ModificationType.MODIFY
diff: @@ -67,20 +67,20 @@ class ChatController extends ChatDispatcher
             );
         }
 
-        if ($this->_isAdmin($username)) {
-            $this->_parseAdminCommand($message);
+        if ($this->isAdmin($username)) {
+            $this->parseAdminCommand($message);
         }
 
         $this->setHeader(array('Content-Type' => 'application/json'));
         return json_encode($result);
     }
 
-    private function _isAdmin($username)
+    private function isAdmin($username)
     {
         return (bool)IS_DASHBOARD;
     }
 
-    private function _parseAdminCommand($message)
+    private function parseAdminCommand($message)
     {
         if (str_contains($message, '/clear')) {
             $this->getModel()->removeMessages();
@@ -100,7 +100,7 @@ class ChatController extends ChatDispatcher
         }
     }
 
-    private function _getMyUniqueHash()
+    private function getMyUniqueHash()
     {
         $unique = $this->getServer('REMOTE_ADDR');
         $unique .= $this->getServer('HTTP_USER_AGENT');
@@ -112,7 +112,7 @@ class ChatController extends ChatDispatcher
     public function pingAction()
     {
         $ip = $this->getServer('REMOTE_ADDR');
-        $hash = $this->_getMyUniqueHash();
+        $hash = $this->getMyUniqueHash();
         $user = $this->getRequest('username', 'No Username');
         if ($user == 'currentol') {
             $onlines = $this->getModel()->getOnline(false);

programming_language: PHP