CVE-2015-10066: Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') (CWE-89)
value: A vulnerability was found in tynx wuersch and classified as critical. Affected by this issue is the function packValue/getByCustomQuery of the file backend/base/Store.class.php. The manipulation leads to sql injection. The patch is identified as 66d4718750a741d1053d327a79e285fd50372519. It is recommended to apply a patch to fix this issue. VDB-218462 is the identifier assigned to this vulnerability.
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: 2023-01-18T00:15Z
Repository: https://github.com/tynx/wuersch
Language: PHP
Files changed: backend/base/Store.class.php
Commit date: 2015-03-27 14:42:22 +0100
Commit message: sotre is sql-injection-safe as we work now with pdo->prepare

Diff: diff --git a/backend/base/Store.class.php b/backend/base/Store.class.php
index 474527e..d5e0a46 100644
--- a/backend/base/Store.class.php
+++ b/backend/base/Store.class.php
@@ -32,17 +32,18 @@ class Store{
 	}
 
 	public function getById($table, $id){
 		$query = 'SELECT * FROM `wuersch`.`' . $table . '` WHERE ';
 		if(!is_numeric($id) && strlen($id)==32){
-			$query .= '`id_md5`="' . $id . '"';
+			$query .= '`id_md5`=?';
 		}else{
-			$query .= '`id`=' . $id;
+			$query .= '`id`=?';
 		}
-		$sth = Store::$pdo->prepare($query . ';');
-		$sth->execute();
-		$result = $sth->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
+		$stmt = Store::$pdo->prepare($query . ';');
+		$stmt->bindParam(1, $id);
+		$stmt->execute();
+		$result = $stmt->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
 		if(count($result) === 1){
 			return $result[0];
 		}
 		return null;
 	}
@@ -54,51 +55,58 @@ class Store{
 		return $result;
 	}
 
 	public function getByColumns($table, $columns, $combination = 'AND'){
 		$query = 'SELECT * FROM `wuersch`.`' . $table . '` WHERE ';
+		
 		foreach($columns as $key=>$value){
-			$query .= '`' . $key . '`=';
-			if(is_numeric($value))
-				$query .= $value;
-			else
-				$query .= '"' . $value . '"';
-			$query .= ' ' . $combination . ' ';
+			$query .= '`' . $key . '`=? ' . $combination . ' ';
 		}
 		$query = substr($query, 0, (-2-strlen($combination)));
-		$sth = Store::$pdo->prepare($query . ' LIMIT 100;');
-		$sth->execute();
-		return $sth->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
+		$stmt = Store::$pdo->prepare($query . ';');
+		foreach(array_values($columns) as $i=>$value)
+			$stmt->bindParam($i+1, $value);
+		$stmt->execute();
+		return $stmt->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
 	}
 
 	public function insert($table, $data){
 		if(!is_array($data))
 			return -1;
-		$columns = '`' . implode('`, `', array_keys($data)) . '`';
-		$values = '';
-		foreach($data as $value){
-			$values .= $this->packValue($value) . ', ';
+		$query = 'INSERT INTO `wuersch`.`' . $table . '` (';
+		$query .= '`' . implode('`, `', array_keys($data)) . '`) VALUES (';
+		for($i=0; $i<count($data); $i++){
+			$query .= '?, ';
+		}
+		$query = substr($query, 0, -2) . ');';
+		$stmt = Store::$pdo->prepare($query);
+		foreach(array_values($data) as $i=>$value){
+			$stmt->bindParam($i+1, $value);
 		}
-		$values = substr($values, 0, -2);
-		$result = Store::$pdo->exec('INSERT INTO `wuersch`.`' . $table . '`(' . $columns . ') VALUES(' . $values . ');');
+		
+		$result = $stmt->execute();
 		return Store::$pdo->lastInsertId();
 	}
 
 	public function update($table, $id, $data){
 		if(!is_array($data))
 			return false;
 		$columns = '';
+		$query = 'UPDATE `wuersch`.`' . $table . '` SET ';
 		foreach($data as $name=>$value){
-			$columns .= '`' . $name . '`=' . $this->packValue($value) . ', ';
+			$query .= '`' . $name . '`=?, ';
 		}
-		$columns = substr($columns, 0, -2);
-		$query = 'UPDATE `wuersch`.`' . $table . '` SET ' . $columns . ' ';
+		$query = substr($query, 0, -2);
 		if(!is_numeric($id) && strlen($id)==32){
-			$query .= 'WHERE `id_md5`="' . $id . '"';
+			$query .= ' WHERE `id_md5`=?;';
 		}else{
-			$query .= 'WHERE `id`=' . $id;
+			$query .= ' WHERE `id`=?;';
 		}
-		return Store::$pdo->exec($query . ';');
+		$stmt = Store::$pdo->prepare($query);
+		foreach(array_values($data) as $i=>$value)
+			$stmt->bindParam($i+1, $value);
+		$stmt->bindParam(count($data)+1, $id);
+		return $stmt->execute();
 	}
 }
 
 ?>

Vulnerable code: 			$query .= '`id_md5`="' . $id . '"';
			$query .= '`id`=' . $id;
		$sth = Store::$pdo->prepare($query . ';');
		$sth->execute();
		$result = $sth->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
			$query .= '`' . $key . '`=';
			if(is_numeric($value))
				$query .= $value;
			else
				$query .= '"' . $value . '"';
			$query .= ' ' . $combination . ' ';
		$sth = Store::$pdo->prepare($query . ' LIMIT 100;');
		$sth->execute();
		return $sth->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
		$columns = '`' . implode('`, `', array_keys($data)) . '`';
		$values = '';
		foreach($data as $value){
			$values .= $this->packValue($value) . ', ';
		$values = substr($values, 0, -2);
		$result = Store::$pdo->exec('INSERT INTO `wuersch`.`' . $table . '`(' . $columns . ') VALUES(' . $values . ');');
			$columns .= '`' . $name . '`=' . $this->packValue($value) . ', ';
		$columns = substr($columns, 0, -2);
		$query = 'UPDATE `wuersch`.`' . $table . '` SET ' . $columns . ' ';
			$query .= 'WHERE `id_md5`="' . $id . '"';
			$query .= 'WHERE `id`=' . $id;
		return Store::$pdo->exec($query . ';');
Fixed code: 			$query .= '`id_md5`=?';
			$query .= '`id`=?';
		$stmt = Store::$pdo->prepare($query . ';');
		$stmt->bindParam(1, $id);
		$stmt->execute();
		$result = $stmt->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
		
			$query .= '`' . $key . '`=? ' . $combination . ' ';
		$stmt = Store::$pdo->prepare($query . ';');
		foreach(array_values($columns) as $i=>$value)
			$stmt->bindParam($i+1, $value);
		$stmt->execute();
		return $stmt->fetchAll(PDO::FETCH_CLASS, ucfirst($table));
		$query = 'INSERT INTO `wuersch`.`' . $table . '` (';
		$query .= '`' . implode('`, `', array_keys($data)) . '`) VALUES (';
		for($i=0; $i<count($data); $i++){
			$query .= '?, ';
		}
		$query = substr($query, 0, -2) . ');';
		$stmt = Store::$pdo->prepare($query);
		foreach(array_values($data) as $i=>$value){
			$stmt->bindParam($i+1, $value);
		
		$result = $stmt->execute();
		$query = 'UPDATE `wuersch`.`' . $table . '` SET ';
			$query .= '`' . $name . '`=?, ';
		$query = substr($query, 0, -2);
			$query .= ' WHERE `id_md5`=?;';
			$query .= ' WHERE `id`=?;';
		$stmt = Store::$pdo->prepare($query);
		foreach(array_values($data) as $i=>$value)
			$stmt->bindParam($i+1, $value);
		$stmt->bindParam(count($data)+1, $id);
		return $stmt->execute();