CVE-2015-10084 (published 2023-02-21T15:15Z)

A vulnerability was found in irontec klear-library chloe and classified as critical. Affected by this issue is the function _prepareWhere of the file Controller/Rest/BaseController.php. The manipulation leads to sql injection. Upgrading to version marla is able to address this issue. The name of the patch is b25262de52fdaffde2a4434fc2a84408b304fbc5. It is recommended to upgrade the affected component. The identifier of this vulnerability is VDB-221504.

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/irontec/klear-library
commit_details: repo_url: https://github.com/irontec/klear-library
author: Mikel Madariaga
author_date: 2015-10-15 12:01:25+02:00
msg: Fix sql injection && Permitir la ejecución de sentencias sql complejas predefinidas en controladores REST vía Zend_Db_Expr
repository: repo_url: https://github.com/irontec/klear-library
repo_name: irontec/klear-library
description: Zend Framework 1 external external library for public sites (Klear based sites)
repo_language: PHP
owner: irontec
file_changes: filename: BaseController.php
change_type: ModificationType.MODIFY
diff: @@ -379,22 +379,24 @@ class Iron_Controller_Rest_BaseController extends \Zend_Rest_Controller
         }
 
         $search = json_decode($search);
+        return implode(" AND ", $this->_parseWhere($search));
+    }
 
+    protected function _parseWhere($search) 
+    {
         $itemsSearch = array();
         foreach ($search as $key => $val) {
 
-            if (is_scalar($val)) {
+            if ($val instanceof \Zend_Db_Expr) {
+                $itemsSearch[] = $val->__toString();
+            } else if (is_scalar($val)) {
                 $itemsSearch[] = $this->_prepareScalarCondition($key, $val);
             } else if (is_object($val)){
                 $itemsSearch[] = $this->_prepareAdvancedCondition($key, $val);
             }
         }
-
-        if (empty($itemsSearch)) {
-            return '';
-        }
-        return implode(" AND ", $itemsSearch);
-    }
+        return $itemsSearch;
+    }   
 
     protected function _prepareScalarCondition($key, $val) {
 
@@ -412,32 +414,68 @@ class Iron_Controller_Rest_BaseController extends \Zend_Rest_Controller
         $dbAdapter = Zend_Db_Table::getDefaultAdapter();
         switch (strtolower(key($val))) {
 
+            case 'notEqual':
+                $key = $dbAdapter->quoteIdentifier($key) . " != ?";
+                return $dbAdapter->quoteInto($key, current($val));
+                break;
+
+            case 'isnull':
+                return $dbAdapter->quoteIdentifier($key) . " is null";
+                break;
+
+            case 'isnotnull':
+                return $dbAdapter->quoteIdentifier($key) . " is null";
+                break;
+
+            case 'gt':
+                $key = $dbAdapter->quoteIdentifier($key) . " > ?";
+                return $dbAdapter->quoteInto($key, current($val));
+                break;
+
+            case 'gte':
+                $key = $dbAdapter->quoteIdentifier($key) . " >= ?";
+                return $dbAdapter->quoteInto($key, current($val));
+                break;
+                
+            case 'lt':
+                $key = $dbAdapter->quoteIdentifier($key) . " < ?";
+                return $dbAdapter->quoteInto($key, current($val));
+                break;
+
+            case 'lte':
+                $key = $dbAdapter->quoteIdentifier($key) . " <= ?";
+                return $dbAdapter->quoteInto($key, current($val));
+                break;
+                
             case 'between':
-                $values = $this->_cleanArray($val);
+                $values = $this->_cleanArray(current($val));
                 return $dbAdapter->quoteIdentifier($key) . ' between '. $values[0] . ' AND ' . $values[1];
 
             case 'notin':
-
-                $values = $this->_cleanArray($val);
+                $values = $this->_cleanArray(current($val));
                 return $dbAdapter->quoteIdentifier($key) . ' not in ('. implode(",", $values) . ') ';
 
             case 'in':
-
-                $values = $this->_cleanArray($val);
+                $values = $this->_cleanArray(current($val));
                 return $dbAdapter->quoteIdentifier($key) . ' in ('. implode(",", $values) . ') ';
 
             case 'like':
-
-                $key = $dbAdapter->quoteIdentifier($key) . " like '%?%'";
-                return $dbAdapter->quoteInto($key, $val);
+                $key = $dbAdapter->quoteIdentifier($key) . " like ?";
+                return $dbAdapter->quoteInto($key, current($val));
 
             case 'notlike':
+                $key = $dbAdapter->quoteIdentifier($key) . " not like ?";
+                return $dbAdapter->quoteInto($key, current($val));
+                break;
 
-                $key = $dbAdapter->quoteIdentifier($key) . " not like '%?%'";
-                return $dbAdapter->quoteInto($key, $val);
+            case 'or':
+                $conditions = array();
+                foreach ($val as $subKey => $subVal) {
+                    $conditions += $this->_parseWhere($subVal);
+                }
+                return '('. implode(' OR ', $conditions) .')';
                 break;
         }
-
         return '';
     }
 

programming_language: PHP