Vulnerability: Ampache before version 4.2.2 allows unauthenticated users to perform SQL injection. Refer to the referenced GitHub Security Advisory for details and a workaround. This is fixed in version 4.2.2 and the development branch.
Vulnerability ID: CVE-2020-15153
CWE: CWE-89
Severity score: 6.4
Project: https://github.com/ampache/ampache
Published: 2021-04-30
File: lib/class/database_object.abstract.php
Commit message: Update database_object.abstract.php

cast int for object_id
Commit author: lachlan-00

Vulnerable version (before fix):
 abstract class database_object      */     public function get_info($object_id, $table_name = '')     {         $table_name = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));          // Make sure we've got a real id         if ($object_id < 1) {             return array();         }          if (self::is_cached($table_name, $object_id)) {             return self::get_from_cache($table_name, $object_id);         }          $sql        = "SELECT * FROM `$table_name` WHERE `id`='$object_id'";         $db_results = Dba::read($sql);          if (!$db_results) {             return array();         }          $row = Dba::fetch_assoc($db_results);          self::add_to_cache($table_name, $object_id, $row);          return $row;     } // get_info

Fixed version (after fix):
 abstract class database_object      */     public function get_info($object_id, $table_name = '')     {         $table     = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));         $object_id = (int) $object_id;          // Make sure we've got a real id         if ($object_id < 1) {             return array();         }          if (self::is_cached($table, $object_id)) {             return self::get_from_cache($table, $object_id);         }          $params     = array($object_id);         $sql        = "SELECT * FROM `$table` WHERE `id`= ?";         $db_results = Dba::read($sql, $params);          if (!$db_results) {             return array();         }          $row = Dba::fetch_assoc($db_results);          self::add_to_cache($table, $object_id, $row);          return $row;     } // get_info

Patch:
patch: @@ -45,27 +45,29 @@ abstract class database_object
      */
     public function get_info($object_id, $table_name = '')
     {
-        $table_name = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));
+        $table     = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));
+        $object_id = (int) $object_id;
 
         // Make sure we've got a real id
         if ($object_id < 1) {
             return array();
         }
 
-        if (self::is_cached($table_name, $object_id)) {
-            return self::get_from_cache($table_name, $object_id);
+        if (self::is_cached($table, $object_id)) {
+            return self::get_from_cache($table, $object_id);
         }
 
-        $sql        = "SELECT * FROM `$table_name` WHERE `id`='$object_id'";
-        $db_results = Dba::read($sql);
+        $params     = array($object_id);
+        $sql        = "SELECT * FROM `$table` WHERE `id`= ?";
+        $db_results = Dba::read($sql, $params);
 
         if (!$db_results) {
             return array();
         }
 
         $row = Dba::fetch_assoc($db_results);
 
-        self::add_to_cache($table_name, $object_id, $row);
+        self::add_to_cache($table, $object_id, $row);
 
         return $row;
     } // get_info
path: lib/class/database_object.abstract.php