CVE-2022-21666: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: Useful Simple Open-Source CMS (USOC) is a content management system (CMS) for programmers. Versions prior to Pb2.4Bfx3 allowed Sql injection in usersearch.php only for users with administrative privileges. Users should replace the file `admin/pages/useredit.php` with a newer version. USOC version Pb2.4Bfx3 contains a fixed version of `admin/pages/useredit.php`.
CWE 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.
CVSS v3 base score: 7.2
Published: 2022-01-10T20:15Z
Repository: https://github.com/Aaron-Junker/USOC
Language: PHP
Files changed: admin/pages/usersearch.php
Commit date: 2022-01-09 08:04:05 +0100
Commit message: Update usersearch.php
Diff: diff --git a/admin/pages/usersearch.php b/admin/pages/usersearch.php
index 0fb22a92..d779e5e6 100644
--- a/admin/pages/usersearch.php
+++ b/admin/pages/usersearch.php
@@ -1,117 +1,141 @@
 <?php
-    if($U->userHasPermission("Backend", "User","Search")){
+  if($U->userHasPermission("Backend", "User")){
 ?>
-    <!DOCTYPE html>
-    <html lang="<?php echo $U->getSetting("site.lang"); ?>" dir="ltr">
-        <head>
-            <style>
-                tbody > tr > th {
-                    font-weight: normal;
-                }
-            </style>
-            <meta charset="utf-8">
-            <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.user.search"); ?></title>
-        </head>
-        <body>
-            <a href="javascript:window.close()"><?php echo $U->getLang("admin.exit"); ?></a>
-            <p><?php echo $U->getLang("admin.user.search.intro"); ?></p>
-            <form>
-                <label for="Name"><?php echo $U->getLang("admin.user.field.username"); ?>:</label><br />
-                <input type="text" name="Name" /><br />
-                <label for="Mail"><?php echo $U->getLang("admin.user.field.mail"); ?>:</label><br />
-                <input type="mail" name="Mail" /><br />
-                <input type="hidden" name="URL" value="usersearch" />
-                <input type="submit" value="<?php echo $U->getLang("admin.user.search.action"); ?>" />
-            </form>
-            <?php
-                if(isset($_GET["Name"])){
-                    if($_GET["Name"] !== ""){
-                        $sql = "SELECT * FROM User WHERE Username='".mysqli::real_escape_string($_GET["Name"])."';";
-                        $dbRes = mysqli_query($U->db_link, $sql);
-                    }
-                }
-                if(isset($_GET["Mail"])){
-                    if($_GET["Mail"] !== ""){
-                        $sql = "SELECT * FROM User WHERE Mail='".mysqli::real_escape_string($_GET["Mail"])."';";
-                        $dbRes = mysqli_query($U->db_link, $sql);
-                    }
-                }
-                if(isset($_GET["Id"])){
-                    if($_GET["Id"] !== ""){
-                        $sql = "SELECT * FROM User WHERE Id='".mysqli::real_escape_string($_GET["Id"])."';";
-                        $dbRes = mysqli_query($U->db_link, $sql);
-                    }
-                }
-                if(isset($_GET["Mail"]) || isset($_GET["Name"]) || isset($_GET["Id"])){
-                    $userhere = False;
-                    while($row = mysqli_fetch_array($dbRes, MYSQLI_ASSOC)){
-                        $userhere = True;
-            ?>
-                        <h4><?php echo str_replace("%a",$row["Username"],$U->getLang("admin.user.search.title")); ?></h4>
-                        <table>
-                            <tbody>
-                                <tr>
-                                    <th>
-                                        Id:
-                                    </th>
-                                    <th>
-                                        <?php echo $row["Id"]; ?>
-                                    </th>
-                                </tr>
-                                <tr>
-                                    <th>
-                                        <?php echo $U->getLang("admin.user.field.mail"); ?>:
-                                    </th>
-                                    <th>
-                                        <?php echo $row["Mail"]; ?>
-                                    </th>
-                                </tr>
-                                <tr>
-                                    <th>
-                                        <?php echo $U->getLang("admin.user.field.permissionlevel"); ?>
-                                    </th>
-                                    <th>
-                                        <?php echo $U->getPermissionName($row["Type"]); ?>
-                                    </th>
-                                </tr>
-                                <tr>
-                                    <th>
-                                        <?php echo $U->getLang("admin.user.field.blocked"); ?>
-                                    </th>
-                                    <th>
-                                        <?php echo $row["blocked"]==0?$U->getLang("admin.no"):$U->getLang("admin.yes"); ?>
-                                    </th>
-                                </tr>
-                            </tbody>
-                        </table>
-            <?php
-                    }
-                    if(!$userhere&&isset($_GET["Mail"])&&$_GET["Mail"]!==""){
-                        echo str_replace("%a", $U->getLang("admin.user.field.mail"), str_replace("%b", $_GET["Mail"], $U->getLang("admin.user.notFound.property")));
-                    }
-                    if(!$userhere&&isset($_GET["Name"])&&$_GET["Name"]!==""){
-                        echo str_replace("%a", $U->getLang("admin.user.field.username"), str_replace("%b", $_GET["Name"], $U->getLang("admin.user.notFound.property")));
-                    }
-                    if(!$userhere&&isset($_GET["Id"])){
-                        echo str_replace("%a", $U->getLang("admin.user.field.id"), str_replace("%b", $_GET["Id"], $U->getLang("admin.user.notFound.property")));
-                    }
+  <!DOCTYPE html>
+  <html lang="<?php echo $U->getSetting("site.lang"); ?>" dir="ltr">
+    <head>
+      <meta charset="utf-8">
+      <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.user.edit"); ?></title>
+    </head>
+    <body>
+      <a href="<?php echo $_SERVER['PHP_SELF']; ?>?URL=mainpage"><?php echo $U->getLang("admin.back"); ?></a>
+      <?php
+        if(isset($_POST["N"])&& !isset($_POST["Submit"])){
+          $sql = "SELECT * FROM user WHERE id='".mysqli::real_escape_string($_POST["N"])."';";
+          $dbRes = mysqli_query($U->db_link, $sql);
+          $userhere = False;
+          while($row = mysqli_fetch_array($dbRes, MYSQLI_ASSOC)){
+            $user_Type = $row["Type"];
+            $user_Blocked = $row["blocked"];
+            $userhere = True;
+          }
+          if($userhere){
+            if($_SESSION["User_ID"] !== md5($_POST["N"])){
+    ?>
+              <form action="<?php echo $_SERVER['PHP_SELF']; ?>?URL=useredit" method="post">
+                <?php
+                  if($U->userHasPermission("Backend", "User","Permission")){
+                ?>
+                  <label for="A"><?php echo $U->getLang("admin.user.permissionLevel"); ?></label>
+                  <select name="A" type="checkbox" value="<?php echo $user_Type; ?>">
+                    <?php
+                      // Creates a select list with all permission levels
+                      foreach($U->getPermissionName(-1) as $key => $value){
+                        echo "<option name='".$key."'".($key==$user_Type?" selected":"").">".$value."</option>";
+                      }
+                    ?>
+                  </select>
+                  <br />
+                <?php
+                  }
+                  if($U->userHasPermission("Backend", "User","Block")){
+                ?>
+                    <label for="G"><?php echo $U->getLang("admin.user.block"); ?></label>
+                    <input name="G" type="checkbox" <?php echo $user_Blocked=="1"?"checked":""; ?> /><br />
+                <?php
+                  }
+                  if($U->userHasPermission("Backend", "User","Permission")||$U->userHasPermission("Backend", "User","Block")){
+                ?>
+                    <input type="submit" name="Submit"/>
+                    <input type='hidden' name='N' value='<?php echo $_POST["N"]; ?>' />
+                <?php
+                  }
+                ?>
+              </form>
+              <?php
+                if($U->userHasPermission("Backend", "User","Search")){
+              ?>
+                <!-- Link to user search page (Opens in a pop-up) --> 
+                <a href="javascript:window.open('index.php?URL=usersearch&Id=<?php echo $_POST["N"]; ?>', 'Search user', 'width=500,height=500,status=no,titlebar=no,location=no,toolbar=no,left=300');"><?php echo $U->getLang("admin.user.moreInformation"); ?></a>
+              <?php
                 }
-            ?>
-        </body>
-    </html>
+              ?>
+    <?php            
+            }else{
+              echo "<br />".$U->getLang("admin.user.yourself");
+            }
+          }else{
+            echo "<br />".str_replace("%a", $_POST["N"], $U->getLang("admin.user.notFound"));
+          }
+        }elseif(isset($_POST["Submit"])){
+          if(isset($_POST["A"])&&$U->userHasPermission("Backend", "User","Permission")){
+            $permissionLevel = $_POST["A"];
+          }elseif(!$U->userHasPermission("Backend", "User","Permission")){
+            $permissionLevel = false;
+          }
+          if(isset($_POST["G"])&&$U->userHasPermission("Backend", "User","Block")){
+            $b = 1;
+          }elseif($U->userHasPermission("Backend", "User","Block")){
+            $b = 0;
+          }else{
+            $b = false;
+          }
+          if($_SESSION["User_ID"] !== md5($_POST["N"])){
+            $sql = "UPDATE User ".($permissionLevel === false?"":"SET Type='".$permissionLevel."'".($b==false?"":", ")).($b==false?"":"blocked ='".$b."' ")."WHERE Id='".mysqli::real_escape_string($_POST["N"])."';";
+            $dbRes = mysqli_query($U->db_link, $sql);
+            echo "<br />".$U->getLang("admin.user.changed");
+          }else{
+            // When the user tries to edit himself
+            echo "<br />".$U->getLang("admin.user.yourself");
+          }
+        }else{
+          $sql = "SELECT * FROM User;";
+          $dbRes = mysqli_query($U->db_link, $sql);
+          // Allow only values in the range from the lowest Id to the highest id
+          $highestId = 0;
+          // BUG: #54 Lowest ID don't work if over 10000000000000000000000000 accounts are created
+          $lowestId = 10000000000000000000000000;
+          while($row = mysqli_fetch_array($dbRes, MYSQLI_ASSOC)){
+            if($row["Id"] > $highestId){
+              $highestId = $row["Id"];
+            }
+            if($row["Id"] < $lowestId){
+              $lowestId = $row["Id"];
+            }
+          }
+          $text = <<<'HEREDOC'
+          <form action="$_SERVER["PHP_SELF"]?URL=useredit" method="post">
+            <label for="N">ID:</label><input name="N" type="number" min="%b" max="%a" />
+            <input type="submit" />
+          </form>
+          HEREDOC;
+          $text = str_replace('$_SERVER["PHP_SELF"]', $_SERVER['PHP_SELF'], $text);
+          $text = str_replace('%a', $highestId, $text);
+          $text = str_replace('%b', $lowestId, $text);
+          echo $text;
+          if($U->userHasPermission("Backend", "User","Search")){
+      ?>
+            <!-- Link to user search page (Opens in a pop-up) -->
+            <a href="javascript:window.open('index.php?URL=usersearch', 'Search user', 'width=500,height=500,status=no,titlebar=no,location=no,toolbar=no,left=300');"><?php echo $U->getLang("admin.user.search"); ?></a>
+      <?php
+          }
+        }
+      ?>
+    </body>
+  </html>
 <?php
   }else{
 ?>
   <!DOCTYPE html>
   <html lang="<?php echo $U->getSetting("site.lang"); ?>" dir="ltr">
     <head>
       <meta charset="utf-8">
-      <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.settings"); ?></title>
+      <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.user"); ?></title>
     </head>
     <body>
-        <a href="javascript:window.close()"><?php echo $U->getLang("admin.exit"); ?></a>
+      <a href="<?php echo $_SERVER['PHP_SELF']; ?>?URL=mainpage"><?php echo $U->getLang("admin.back"); ?></a>
       <p><?php echo $U->getLang("rights.error"); ?></p>
     </body>
   </html>
 <?php
   }

Vulnerable code:     if($U->userHasPermission("Backend", "User","Search")){
    <!DOCTYPE html>
    <html lang="<?php echo $U->getSetting("site.lang"); ?>" dir="ltr">
        <head>
            <style>
                tbody > tr > th {
                    font-weight: normal;
                }
            </style>
            <meta charset="utf-8">
            <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.user.search"); ?></title>
        </head>
        <body>
            <a href="javascript:window.close()"><?php echo $U->getLang("admin.exit"); ?></a>
            <p><?php echo $U->getLang("admin.user.search.intro"); ?></p>
            <form>
                <label for="Name"><?php echo $U->getLang("admin.user.field.username"); ?>:</label><br />
                <input type="text" name="Name" /><br />
                <label for="Mail"><?php echo $U->getLang("admin.user.field.mail"); ?>:</label><br />
                <input type="mail" name="Mail" /><br />
                <input type="hidden" name="URL" value="usersearch" />
                <input type="submit" value="<?php echo $U->getLang("admin.user.search.action"); ?>" />
            </form>
            <?php
                if(isset($_GET["Name"])){
                    if($_GET["Name"] !== ""){
                        $sql = "SELECT * FROM User WHERE Username='".mysqli::real_escape_string($_GET["Name"])."';";
                        $dbRes = mysqli_query($U->db_link, $sql);
                    }
                }
                if(isset($_GET["Mail"])){
                    if($_GET["Mail"] !== ""){
                        $sql = "SELECT * FROM User WHERE Mail='".mysqli::real_escape_string($_GET["Mail"])."';";
                        $dbRes = mysqli_query($U->db_link, $sql);
                    }
                }
                if(isset($_GET["Id"])){
                    if($_GET["Id"] !== ""){
                        $sql = "SELECT * FROM User WHERE Id='".mysqli::real_escape_string($_GET["Id"])."';";
                        $dbRes = mysqli_query($U->db_link, $sql);
                    }
                }
                if(isset($_GET["Mail"]) || isset($_GET["Name"]) || isset($_GET["Id"])){
                    $userhere = False;
                    while($row = mysqli_fetch_array($dbRes, MYSQLI_ASSOC)){
                        $userhere = True;
            ?>
                        <h4><?php echo str_replace("%a",$row["Username"],$U->getLang("admin.user.search.title")); ?></h4>
                        <table>
                            <tbody>
                                <tr>
                                    <th>
                                        Id:
                                    </th>
                                    <th>
                                        <?php echo $row["Id"]; ?>
                                    </th>
                                </tr>
                                <tr>
                                    <th>
                                        <?php echo $U->getLang("admin.user.field.mail"); ?>:
                                    </th>
                                    <th>
                                        <?php echo $row["Mail"]; ?>
                                    </th>
                                </tr>
                                <tr>
                                    <th>
                                        <?php echo $U->getLang("admin.user.field.permissionlevel"); ?>
                                    </th>
                                    <th>
                                        <?php echo $U->getPermissionName($row["Type"]); ?>
                                    </th>
                                </tr>
                                <tr>
                                    <th>
                                        <?php echo $U->getLang("admin.user.field.blocked"); ?>
                                    </th>
                                    <th>
                                        <?php echo $row["blocked"]==0?$U->getLang("admin.no"):$U->getLang("admin.yes"); ?>
                                    </th>
                                </tr>
                            </tbody>
                        </table>
            <?php
                    }
                    if(!$userhere&&isset($_GET["Mail"])&&$_GET["Mail"]!==""){
                        echo str_replace("%a", $U->getLang("admin.user.field.mail"), str_replace("%b", $_GET["Mail"], $U->getLang("admin.user.notFound.property")));
                    }
                    if(!$userhere&&isset($_GET["Name"])&&$_GET["Name"]!==""){
                        echo str_replace("%a", $U->getLang("admin.user.field.username"), str_replace("%b", $_GET["Name"], $U->getLang("admin.user.notFound.property")));
                    }
                    if(!$userhere&&isset($_GET["Id"])){
                        echo str_replace("%a", $U->getLang("admin.user.field.id"), str_replace("%b", $_GET["Id"], $U->getLang("admin.user.notFound.property")));
                    }
            ?>
        </body>
    </html>
      <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.settings"); ?></title>
        <a href="javascript:window.close()"><?php echo $U->getLang("admin.exit"); ?></a>
Fixed code:   if($U->userHasPermission("Backend", "User")){
  <!DOCTYPE html>
  <html lang="<?php echo $U->getSetting("site.lang"); ?>" dir="ltr">
    <head>
      <meta charset="utf-8">
      <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.user.edit"); ?></title>
    </head>
    <body>
      <a href="<?php echo $_SERVER['PHP_SELF']; ?>?URL=mainpage"><?php echo $U->getLang("admin.back"); ?></a>
      <?php
        if(isset($_POST["N"])&& !isset($_POST["Submit"])){
          $sql = "SELECT * FROM user WHERE id='".mysqli::real_escape_string($_POST["N"])."';";
          $dbRes = mysqli_query($U->db_link, $sql);
          $userhere = False;
          while($row = mysqli_fetch_array($dbRes, MYSQLI_ASSOC)){
            $user_Type = $row["Type"];
            $user_Blocked = $row["blocked"];
            $userhere = True;
          }
          if($userhere){
            if($_SESSION["User_ID"] !== md5($_POST["N"])){
    ?>
              <form action="<?php echo $_SERVER['PHP_SELF']; ?>?URL=useredit" method="post">
                <?php
                  if($U->userHasPermission("Backend", "User","Permission")){
                ?>
                  <label for="A"><?php echo $U->getLang("admin.user.permissionLevel"); ?></label>
                  <select name="A" type="checkbox" value="<?php echo $user_Type; ?>">
                    <?php
                      // Creates a select list with all permission levels
                      foreach($U->getPermissionName(-1) as $key => $value){
                        echo "<option name='".$key."'".($key==$user_Type?" selected":"").">".$value."</option>";
                      }
                    ?>
                  </select>
                  <br />
                <?php
                  }
                  if($U->userHasPermission("Backend", "User","Block")){
                ?>
                    <label for="G"><?php echo $U->getLang("admin.user.block"); ?></label>
                    <input name="G" type="checkbox" <?php echo $user_Blocked=="1"?"checked":""; ?> /><br />
                <?php
                  }
                  if($U->userHasPermission("Backend", "User","Permission")||$U->userHasPermission("Backend", "User","Block")){
                ?>
                    <input type="submit" name="Submit"/>
                    <input type='hidden' name='N' value='<?php echo $_POST["N"]; ?>' />
                <?php
                  }
                ?>
              </form>
              <?php
                if($U->userHasPermission("Backend", "User","Search")){
              ?>
                <!-- Link to user search page (Opens in a pop-up) --> 
                <a href="javascript:window.open('index.php?URL=usersearch&Id=<?php echo $_POST["N"]; ?>', 'Search user', 'width=500,height=500,status=no,titlebar=no,location=no,toolbar=no,left=300');"><?php echo $U->getLang("admin.user.moreInformation"); ?></a>
              <?php
              ?>
    <?php            
            }else{
              echo "<br />".$U->getLang("admin.user.yourself");
            }
          }else{
            echo "<br />".str_replace("%a", $_POST["N"], $U->getLang("admin.user.notFound"));
          }
        }elseif(isset($_POST["Submit"])){
          if(isset($_POST["A"])&&$U->userHasPermission("Backend", "User","Permission")){
            $permissionLevel = $_POST["A"];
          }elseif(!$U->userHasPermission("Backend", "User","Permission")){
            $permissionLevel = false;
          }
          if(isset($_POST["G"])&&$U->userHasPermission("Backend", "User","Block")){
            $b = 1;
          }elseif($U->userHasPermission("Backend", "User","Block")){
            $b = 0;
          }else{
            $b = false;
          }
          if($_SESSION["User_ID"] !== md5($_POST["N"])){
            $sql = "UPDATE User ".($permissionLevel === false?"":"SET Type='".$permissionLevel."'".($b==false?"":", ")).($b==false?"":"blocked ='".$b."' ")."WHERE Id='".mysqli::real_escape_string($_POST["N"])."';";
            $dbRes = mysqli_query($U->db_link, $sql);
            echo "<br />".$U->getLang("admin.user.changed");
          }else{
            // When the user tries to edit himself
            echo "<br />".$U->getLang("admin.user.yourself");
          }
        }else{
          $sql = "SELECT * FROM User;";
          $dbRes = mysqli_query($U->db_link, $sql);
          // Allow only values in the range from the lowest Id to the highest id
          $highestId = 0;
          // BUG: #54 Lowest ID don't work if over 10000000000000000000000000 accounts are created
          $lowestId = 10000000000000000000000000;
          while($row = mysqli_fetch_array($dbRes, MYSQLI_ASSOC)){
            if($row["Id"] > $highestId){
              $highestId = $row["Id"];
            }
            if($row["Id"] < $lowestId){
              $lowestId = $row["Id"];
            }
          }
          $text = <<<'HEREDOC'
          <form action="$_SERVER["PHP_SELF"]?URL=useredit" method="post">
            <label for="N">ID:</label><input name="N" type="number" min="%b" max="%a" />
            <input type="submit" />
          </form>
          HEREDOC;
          $text = str_replace('$_SERVER["PHP_SELF"]', $_SERVER['PHP_SELF'], $text);
          $text = str_replace('%a', $highestId, $text);
          $text = str_replace('%b', $lowestId, $text);
          echo $text;
          if($U->userHasPermission("Backend", "User","Search")){
      ?>
            <!-- Link to user search page (Opens in a pop-up) -->
            <a href="javascript:window.open('index.php?URL=usersearch', 'Search user', 'width=500,height=500,status=no,titlebar=no,location=no,toolbar=no,left=300');"><?php echo $U->getLang("admin.user.search"); ?></a>
      <?php
          }
        }
      ?>
    </body>
  </html>
      <title><?php echo $U->getLang("admin") ?> - <?php echo $U->getLang("admin.user"); ?></title>
      <a href="<?php echo $_SERVER['PHP_SELF']; ?>?URL=mainpage"><?php echo $U->getLang("admin.back"); ?></a>