CVE-2021-42235 (published 2022-05-04T17:15Z)

SQL injection in osTicket before 1.14.8 and 1.15.4 login and password reset process allows attackers to access the osTicket administration profile functionality.

Severity: HIGH
CVSS v2 base score: 7.5 (AV:N/AC:L/Au:N/C:P/I:P/A:P)
CVSS v3 base score: 9.8, CRITICAL (CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-89
cwe_name: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
description: The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
extended_description: 
            
            
         
         

Fix information:
repo_url: https://github.com/osTicket/osTicket
commit_details: repo_url: https://github.com/osTicket/osTicket
author: Peter Rotich
author_date: 2021-10-07 14:38:44+00:00
msg: security: SQL Injection

This mitigates a possible SQL injection vulnerability reported by
Bittylicious.
repository: repo_url: https://github.com/osTicket/osTicket
repo_name: osTicket/osTicket
description: The osTicket open source ticketing system official project repository, for versions 1.8 and later
repo_language: PHP
owner: osTicket
file_changes: filename: class.staff.php
change_type: ModificationType.MODIFY
diff: @@ -862,11 +862,11 @@ implements AuthenticatedUser, EmailContact, TemplateVariable, Searchable {
         if (is_array($var))
             return parent::lookup($var);
         elseif (is_numeric($var))
-            return parent::lookup(array('staff_id'=>$var));
+            return parent::lookup(array('staff_id' => (int) $var));
         elseif (Validator::is_email($var))
-            return parent::lookup(array('email'=>$var));
-        elseif (is_string($var))
-            return parent::lookup(array('username'=>$var));
+            return parent::lookup(array('email' => $var));
+        elseif (is_string($var) &&  Validator::is_username($var))
+            return parent::lookup(array('username' => (string) $var));
         else
             return null;
     }

programming_language: PHP
filename: class.user.php
change_type: ModificationType.MODIFY
diff: @@ -1341,10 +1341,10 @@ class UserAccount extends VerySimpleModel {
     }
 
     static function lookupByUsername($username) {
-        if (strpos($username, '@') !== false)
-            $user = static::lookup(array('user__emails__address'=>$username));
-        else
-            $user = static::lookup(array('username'=>$username));
+        if (Validator::is_email($username))
+            $user = static::lookup(array('user__emails__address' => $username));
+        elseif (Validator::is_userid($username))
+            $user = static::lookup(array('username' => $username));
 
         return $user;
     }

programming_language: PHP
filename: class.validator.php
change_type: ModificationType.MODIFY
diff: @@ -220,11 +220,18 @@ class Validator {
     static function is_username($username, &$error='') {
         if (strlen($username)<2)
             $error = __('Username must have at least two (2) characters');
-        elseif (!preg_match('/^[\p{L}\d._-]+$/u', $username))
+        elseif (is_numeric($username) || !preg_match('/^[\p{L}\d._-]+$/u', $username))
             $error = __('Username contains invalid characters');
         return $error == '';
     }
 
+    static  function is_userid($userid, &$error='') {
+        if (!self::is_username($userid)
+                    && !self::is_email($userid))
+            $error = __('Invalid User Id ');
+        return $error == '';
+    }
+
     static function is_formula($text, &$error='') {
         if (!preg_match('/^[^=\+@-].*$/s', $text))
             $error = __('Content cannot start with the following characters: = - + @');

programming_language: PHP
filename: pwreset.php
change_type: ModificationType.MODIFY
diff: @@ -15,7 +15,9 @@ if($_POST) {
     }
     switch ($_POST['do']) {
         case 'sendmail':
-            if (($acct=ClientAccount::lookupByUsername($_POST['userid']))) {
+            $userid = (string) $_POST['userid'];
+            if (Validator::is_userid($userid)
+                    && ($acct=ClientAccount::lookupByUsername($userid))) {
                 if (!$acct->isPasswdResetEnabled()) {
                     $banner = __('Password reset is not enabled for your account. Contact your administrator');
                 }

programming_language: PHP
filename: pwreset.php
change_type: ModificationType.MODIFY
diff: @@ -39,7 +39,9 @@ if($_POST) {
     }
     switch ($_POST['do']) {
         case 'sendmail':
-            if (($staff=Staff::lookup($_POST['userid']))) {
+            $userid = (string) $_POST['userid'];
+            if (Validator::is_userid($userid)
+                    && ($staff=Staff::lookup($userid))) {
                 if (!$staff->hasPassword()) {
                     if ($staff->sendResetEmail('registration-staff', false) !== false)
                         $msg = __('Registration email sent successfully.');
@@ -72,7 +74,8 @@ elseif ($_GET['token']) {
     $msg = __('Please enter your username or email');
     $_config = new Config('pwreset');
     if (($id = $_config->get($_GET['token']))
-            && ($staff = Staff::lookup($id)))
+            && is_numeric($id)
+            && ($staff = Staff::lookup( (int) $id)))
         // TODO: Detect staff confirmation (for welcome email)
         $tpl = 'pwreset.login.php';
     else

programming_language: PHP