CVE-2020-15153: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: 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.
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: 9.8
Published: 2021-04-30T16:15Z
Repository: https://github.com/ampache/ampache
Language: PHP
Files changed: lib/class/database_object.abstract.php
Commit date: 2020-08-18 17:25:36 +1000
Commit message: Update database_object.abstract.php

cast int for object_id

Diff: diff --git a/lib/class/database_object.abstract.php b/lib/class/database_object.abstract.php
index 85bdf3aa7..449a33d64 100644
--- a/lib/class/database_object.abstract.php
+++ b/lib/class/database_object.abstract.php
@@ -43,31 +43,33 @@ abstract class database_object
      * @param string $table_name
      * @return array
      */
     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
 
     /**

Vulnerable code:         $table_name = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));
        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);
        self::add_to_cache($table_name, $object_id, $row);
Fixed code:         $table     = $table_name ? Dba::escape($table_name) : Dba::escape(strtolower(get_class($this)));
        $object_id = (int) $object_id;
        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);
        self::add_to_cache($table, $object_id, $row);