Security advisory GHSA-ch7p-mpv4-4vg4: CoreShop Vulnerable to SQL Injection via Admin Reports
Package: coreshop/core-shop (composer), vulnerable version: 4.1.7, fixed in: 4.1.8
CWE: CWE-564
CWE-89
Files changed by the fix:
src/CoreShop/Bundle/CoreBundle/Report/AbandonedCartsReport.php
src/CoreShop/Bundle/CoreBundle/Report/CarriersReport.php
src/CoreShop/Bundle/CoreBundle/Report/CartsReport.php
src/CoreShop/Bundle/CoreBundle/Report/CategoriesReport.php
src/CoreShop/Bundle/CoreBundle/Report/CustomersReport.php
src/CoreShop/Bundle/CoreBundle/Report/ManufacturerReport.php
src/CoreShop/Bundle/CoreBundle/Report/PaymentProvidersReport.php
src/CoreShop/Bundle/CoreBundle/Report/ProductsReport.php
src/CoreShop/Bundle/CoreBundle/Report/SalesReport.php
src/CoreShop/Bundle/CoreBundle/Report/VouchersReport.php

Fix diff:
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/AbandonedCartsReport.php b/src/CoreShop/Bundle/CoreBundle/Report/AbandonedCartsReport.php
index 2662e1969a..a98114b86c 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/AbandonedCartsReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/AbandonedCartsReport.php
@@ -97,15 +97,19 @@ public function getReportData(ParameterBag $parameterBag): array
                         LEFT JOIN object_$userClassId AS `user` ON `user`.oo_id = cart.customer__id
                         LEFT JOIN coreshop_payment_provider AS `pg` ON `pg`.id = cart.paymentProvider
                         WHERE cart.items <> ''
-                          AND cart.store = $storeId
-                          AND cart.creationDate > ?
-                          AND cart.creationDate < ?
+                          AND cart.store = :storeId
+                          AND cart.creationDate > :fromTimestamp
+                          AND cart.creationDate < :toTimestamp
                           AND cart.saleState = '" . OrderSaleStates::STATE_CART . "'
                      GROUP BY cart.oo_id
                      ORDER BY cart.creationDate DESC
-                     LIMIT $offset,$limit";
+                     LIMIT " . (int) $offset . ', ' . (int) $limit;
 
-        $data = $this->db->fetchAllAssociative($sqlQuery, [$fromTimestamp, $toTimestamp]);
+        $data = $this->db->fetchAllAssociative($sqlQuery, [
+            'storeId' => $storeId,
+            'fromTimestamp' => $fromTimestamp,
+            'toTimestamp' => $toTimestamp,
+        ]);
         $this->totalRecords = (int) $this->db->fetchOne('SELECT FOUND_ROWS()');
 
         foreach ($data as &$entry) {
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/CarriersReport.php b/src/CoreShop/Bundle/CoreBundle/Report/CarriersReport.php
index 5d2ba0526d..82455c88bd 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/CarriersReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/CarriersReport.php
@@ -62,24 +62,28 @@ public function getReportData(ParameterBag $parameterBag): array
 
         $tableName = 'object_query_' . $this->orderRepository->getClassId();
         $sql = "
-              SELECT carrier, 
-                    COUNT(1) as total, 
-                    COUNT(1) / t.cnt * 100 as `percentage` 
-              FROM $tableName as `order` 
-              INNER JOIN objects as o 
-                ON o.id = `order`.oo_id 
-              CROSS JOIN 
+              SELECT carrier,
+                    COUNT(1) as total,
+                    COUNT(1) / t.cnt * 100 as `percentage`
+              FROM $tableName as `order`
+              INNER JOIN objects as o
+                ON o.id = `order`.oo_id
+              CROSS JOIN
                 (
-                  SELECT COUNT(1) as cnt 
-                  FROM $tableName as `order` 
-                  INNER JOIN objects as o 
-                    ON o.id = `order`.oo_id  
-                  WHERE store = $storeId AND creationDate > $fromTimestamp AND creationDate < $toTimestamp
-                ) t 
-              WHERE store = $storeId AND carrier IS NOT NULL AND creationDate > $fromTimestamp AND creationDate < $toTimestamp AND saleState='" . OrderSaleStates::STATE_ORDER . "' 
+                  SELECT COUNT(1) as cnt
+                  FROM $tableName as `order`
+                  INNER JOIN objects as o
+                    ON o.id = `order`.oo_id
+                  WHERE store = :storeId AND creationDate > :fromTimestamp AND creationDate < :toTimestamp
+                ) t
+              WHERE store = :storeId AND carrier IS NOT NULL AND creationDate > :fromTimestamp AND creationDate < :toTimestamp AND saleState='" . OrderSaleStates::STATE_ORDER . "'
               GROUP BY carrier";
 
-        $results = $this->db->fetchAllAssociative($sql);
+        $results = $this->db->fetchAllAssociative($sql, [
+            'storeId' => $storeId,
+            'fromTimestamp' => $fromTimestamp,
+            'toTimestamp' => $toTimestamp,
+        ]);
         $data = [];
 
         foreach ($results as $result) {
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/CartsReport.php b/src/CoreShop/Bundle/CoreBundle/Report/CartsReport.php
index 35e05f5a66..542e7b149d 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/CartsReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/CartsReport.php
@@ -81,11 +81,11 @@ protected function getData(ParameterBag $parameterBag): array
                     CASE WHEN orderCount IS NULL THEN 0 ELSE orderCount END as orders,
                     CASE WHEN cartCount IS NULL THEN 0 ELSE cartCount END as carts
                 FROM (
-                  SELECT 
+                  SELECT
                     COUNT(*) as orderCount,
                     DATE(FROM_UNIXTIME(orderDate)) as orderDateTimestamp
                   FROM object_query_$orderClassId AS orders
-                  WHERE store = $storeId AND orderDate > $fromTimestamp AND orderDate < $toTimestamp and orders.saleState = '" . OrderSaleStates::STATE_ORDER . "'
+                  WHERE store = :storeId AND orderDate > :fromTimestamp AND orderDate < :toTimestamp and orders.saleState = '" . OrderSaleStates::STATE_ORDER . "'
                   GROUP BY DATE(FROM_UNIXTIME(orderDate))
                 ) as ordersQuery
                 $join OUTER JOIN (
@@ -93,13 +93,19 @@ protected function getData(ParameterBag $parameterBag): array
                     COUNT(*) as cartCount,
                     DATE(FROM_UNIXTIME(creationDate)) as cartDateTimestamp
                   FROM object_$orderClassId AS carts
-                  WHERE store = $storeId AND creationDate > $fromTimestamp AND creationDate < $toTimestamp and carts.saleState = '" . OrderSaleStates::STATE_CART . "'
+                  WHERE store = :storeId AND creationDate > :fromTimestamp AND creationDate < :toTimestamp and carts.saleState = '" . OrderSaleStates::STATE_CART . "'
                   GROUP BY DATE(FROM_UNIXTIME(creationDate))
                 ) as cartsQuery ON cartsQuery.cartDateTimestamp = ordersQuery.orderDateTimestamp
             ";
         }
 
-        $data = $this->db->fetchAllAssociative(implode(\PHP_EOL . 'UNION ALL' . \PHP_EOL, $queries) . '  ORDER BY timestamp ASC');
+        $queryParams = [
+            'storeId' => $storeId,
+            'fromTimestamp' => $fromTimestamp,
+            'toTimestamp' => $toTimestamp,
+        ];
+
+        $data = $this->db->fetchAllAssociative(implode(\PHP_EOL . 'UNION ALL' . \PHP_EOL, $queries) . '  ORDER BY timestamp ASC', $queryParams);
 
         foreach ($data as &$day) {
             $date = Carbon::createFromTimestamp(strtotime($day['timestamp']));
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/CategoriesReport.php b/src/CoreShop/Bundle/CoreBundle/Report/CategoriesReport.php
index 18753142ad..2aa9beb9f0 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/CategoriesReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/CategoriesReport.php
@@ -79,6 +79,17 @@ public function getReportData(ParameterBag $parameterBag): array
             return [];
         }
 
+        $orderStateInClause = '';
+        $orderStateParams = [];
+        if ($orderStateFilter !== null) {
+            $orderStatePlaceholders = [];
+            foreach ($orderStateFilter as $i => $state) {
+                $orderStatePlaceholders[] = ':orderState' . $i;
+                $orderStateParams['orderState' . $i] = $state;
+            }
+            $orderStateInClause = ' AND `orders`.orderState IN (' . implode(', ', $orderStatePlaceholders) . ')';
+        }
+
         $query = "
             SELECT SQL_CALC_FOUND_ROWS
               `categories`.oo_id as categoryId,
@@ -90,23 +101,22 @@ public function getReportData(ParameterBag $parameterBag): array
               SUM(orderItems.quantity) AS `quantityCount`,
               COUNT(orderItems.product__id) AS `orderCount`
             FROM object_$categoryClassId AS categories
-            INNER JOIN object_localized_query_" . $categoryClassId . '_' . $locale . " AS localizedCategories ON localizedCategories.ooo_id = categories.oo_id 
-            INNER JOIN dependencies AS catProductDependencies ON catProductDependencies.targetId = categories.oo_id AND catProductDependencies.targettype = \"object\" 
+            INNER JOIN object_localized_query_" . $categoryClassId . '_' . $locale . " AS localizedCategories ON localizedCategories.ooo_id = categories.oo_id
+            INNER JOIN dependencies AS catProductDependencies ON catProductDependencies.targetId = categories.oo_id AND catProductDependencies.targettype = \"object\"
             INNER JOIN object_query_$orderItemClassId AS orderItems ON orderItems.product__id = catProductDependencies.sourceId
             INNER JOIN object_relations_$orderClassId AS orderRelations ON orderRelations.dest_id = orderItems.oo_id AND orderRelations.fieldname = \"items\"
             INNER JOIN object_query_$orderClassId AS `orders` ON `orders`.oo_id = orderRelations.src_id
-            WHERE orders.store = $storeId" . (($orderStateFilter !== null) ? ' AND `orders`.orderState IN (' . rtrim(str_repeat('?,', count($orderStateFilter)), ',') . ')' : '') . " AND orders.orderDate > ? AND orders.orderDate < ? AND orderItems.product__id IS NOT NULL AND saleState='" . OrderSaleStates::STATE_ORDER . "'
+            WHERE orders.store = :storeId" . $orderStateInClause . " AND orders.orderDate > :fromTimestamp AND orders.orderDate < :toTimestamp AND orderItems.product__id IS NOT NULL AND saleState='" . OrderSaleStates::STATE_ORDER . "'
             GROUP BY categories.oo_id
             ORDER BY quantityCount DESC
-            LIMIT $offset,$limit";
+            LIMIT " . (int) $offset . ', ' . (int) $limit;
 
-        $queryParameters = [];
+        $queryParameters = array_merge([
+            'storeId' => $storeId,
+            'fromTimestamp' => $from->getTimestamp(),
+            'toTimestamp' => $to->getTimestamp(),
+        ], $orderStateParams);
 
-        if ($orderStateFilter !== null) {
-            array_push($queryParameters, ...$orderStateFilter);
-        }
-        $queryParameters[] = $from->getTimestamp();
-        $queryParameters[] = $to->getTimestamp();
         $results = $this->db->fetchAllAssociative($query, $queryParameters);
 
         if (count($results) === 0) {
@@ -122,15 +132,15 @@ public function getReportData(ParameterBag $parameterBag): array
               SUM(orderItems.quantity) AS `quantityCount`,
               COUNT(orderItems.product__id) AS `orderCount`
             FROM object_$categoryClassId AS categories
-            INNER JOIN object_localized_query_" . $categoryClassId . '_' . $locale . " AS localizedCategories ON localizedCategories.ooo_id = categories.oo_id 
-            INNER JOIN dependencies AS catProductDependencies ON catProductDependencies.sourceId = categories.oo_id AND catProductDependencies.sourcetype = \"object\" 
+            INNER JOIN object_localized_query_" . $categoryClassId . '_' . $locale . " AS localizedCategories ON localizedCategories.ooo_id = categories.oo_id
+            INNER JOIN dependencies AS catProductDependencies ON catProductDependencies.sourceId = categories.oo_id AND catProductDependencies.sourcetype = \"object\"
             INNER JOIN object_query_$orderItemClassId AS orderItems ON orderItems.product__id = catProductDependencies.targetId
             INNER JOIN object_relations_$orderClassId AS orderRelations ON orderRelations.dest_id = orderItems.oo_id AND orderRelations.fieldname = \"items\"
             INNER JOIN object_query_$orderClassId AS `orders` ON `orders`.oo_id = orderRelations.src_id
-            WHERE orders.store = $storeId" . (($orderStateFilter !== null) ? ' AND `orders`.orderState IN (' . rtrim(str_repeat('?,', count($orderStateFilter)), ',') . ')' : '') . " AND orders.orderDate > ? AND orders.orderDate < ? AND orderItems.product__id IS NOT NULL
+            WHERE orders.store = :storeId" . $orderStateInClause . " AND orders.orderDate > :fromTimestamp AND orders.orderDate < :toTimestamp AND orderItems.product__id IS NOT NULL
             GROUP BY categories.oo_id
             ORDER BY quantityCount DESC
-            LIMIT $offset,$limit";
+            LIMIT " . (int) $offset . ', ' . (int) $limit;
             $results = $this->db->fetchAllAssociative($query, $queryParameters);
         }
 
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/CustomersReport.php b/src/CoreShop/Bundle/CoreBundle/Report/CustomersReport.php
index 4206901ec6..cdae1c9da8 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/CustomersReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/CustomersReport.php
@@ -60,16 +60,19 @@ public function getReportData(ParameterBag $parameterBag): array
             SELECT SQL_CALC_FOUND_ROWS
               customer.oo_id,
               customer.email as `emailAddress`,
-              SUM(orders.totalNet) as sales, 
+              SUM(orders.totalNet) as sales,
               COUNT(customer.oo_id) as `orderCount`
             FROM object_query_$orderClassId AS orders
             INNER JOIN object_query_$customerClassId AS customer ON orders.customer__id = customer.oo_id
-            WHERE  orders.orderState = '$orderCompleteState' AND orders.orderDate > ? AND orders.orderDate < ? AND customer.oo_id IS NOT NULL AND saleState='" . OrderSaleStates::STATE_ORDER . "'
+            WHERE  orders.orderState = '$orderCompleteState' AND orders.orderDate > :fromTimestamp AND orders.orderDate < :toTimestamp AND customer.oo_id IS NOT NULL AND saleState='" . OrderSaleStates::STATE_ORDER . "'
             GROUP BY customer.oo_id
             ORDER BY COUNT(customer.oo_id) DESC
-            LIMIT $offset,$limit";
+            LIMIT " . (int) $offset . ', ' . (int) $limit;
 
-        $results = $this->db->fetchAllAssociative($query, [$from->getTimestamp(), $to->getTimestamp()]);
+        $results = $this->db->fetchAllAssociative($query, [
+            'fromTimestamp' => $from->getTimestamp(),
+            'toTimestamp' => $to->getTimestamp(),
+        ]);
         $this->totalRecords = (int) $this->db->fetchOne('SELECT FOUND_ROWS()');
 
         foreach ($results as &$result) {
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/ManufacturerReport.php b/src/CoreShop/Bundle/CoreBundle/Report/ManufacturerReport.php
index 7e9833ff4e..420bfb5de2 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/ManufacturerReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/ManufacturerReport.php
@@ -87,6 +87,17 @@ public function getReportData(ParameterBag $parameterBag): array
             }
         }
 
+        $orderStateInClause = '';
+        $orderStateParams = [];
+        if ($orderStateFilter !== null) {
+            $orderStatePlaceholders = [];
+            foreach ($orderStateFilter as $i => $state) {
+                $orderStatePlaceholders[] = ':orderState' . $i;
+                $orderStateParams['orderState' . $i] = $state;
+            }
+            $orderStateInClause = ' AND `orders`.orderState IN (' . implode(', ', $orderStatePlaceholders) . ')';
+        }
+
         $query = '
             SELECT SQL_CALC_FOUND_ROWS
               `manufacturers`.oo_id as manufacturerId,
@@ -98,21 +109,21 @@ public function getReportData(ParameterBag $parameterBag): array
               SUM(orderItems.quantity) AS `quantityCount`,
               COUNT(orderItems.product__id) AS `orderCount`
             FROM ' . ($nameIsLocalized ? 'object_localized_' . $manufacturerClassId . '_' . $this->localeService->getLocaleCode() : 'object_' . $manufacturerClassId) . " AS manufacturers
-            INNER JOIN dependencies AS manProductDependencies ON manProductDependencies.targetId = manufacturers.oo_id AND manProductDependencies.targettype = \"object\" 
+            INNER JOIN dependencies AS manProductDependencies ON manProductDependencies.targetId = manufacturers.oo_id AND manProductDependencies.targettype = \"object\"
             INNER JOIN object_query_$orderItemClassId AS orderItems ON orderItems.product__id = manProductDependencies.sourceid
             INNER JOIN object_relations_$orderClassId AS orderRelations ON orderRelations.dest_id = orderItems.oo_id AND orderRelations.fieldname = \"items\"
             INNER JOIN object_query_$orderClassId AS `orders` ON `orders`.oo_id = orderRelations.src_id
-            WHERE orders.store = $storeId" . (($orderStateFilter !== null) ? ' AND `orders`.orderState IN (' . rtrim(str_repeat('?,', count($orderStateFilter)), ',') . ')' : '') . " AND orders.orderDate > ? AND orders.orderDate < ? AND orderItems.product__id IS NOT NULL AND saleState='" . OrderSaleStates::STATE_ORDER . "'
+            WHERE orders.store = :storeId" . $orderStateInClause . " AND orders.orderDate > :fromTimestamp AND orders.orderDate < :toTimestamp AND orderItems.product__id IS NOT NULL AND saleState='" . OrderSaleStates::STATE_ORDER . "'
             GROUP BY manufacturers.oo_id
             ORDER BY quantityCount DESC
-            LIMIT $offset,$limit";
+            LIMIT " . (int) $offset . ', ' . (int) $limit;
+
+        $queryParameters = array_merge([
+            'storeId' => $storeId,
+            'fromTimestamp' => $from->getTimestamp(),
+            'toTimestamp' => $to->getTimestamp(),
+        ], $orderStateParams);
 
-        $queryParameters = [];
-        if ($orderStateFilter !== null) {
-            array_push($queryParameters, ...$orderStateFilter);
-        }
-        $queryParameters[] = $from->getTimestamp();
-        $queryParameters[] = $to->getTimestamp();
         $results = $this->db->fetchAllAssociative($query, $queryParameters);
 
         $this->totalRecords = (int) $this->db->fetchOne('SELECT FOUND_ROWS()');
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/PaymentProvidersReport.php b/src/CoreShop/Bundle/CoreBundle/Report/PaymentProvidersReport.php
index e5abb16c3e..50544004ed 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/PaymentProvidersReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/PaymentProvidersReport.php
@@ -62,24 +62,28 @@ public function getReportData(ParameterBag $parameterBag): array
 
         $tableName = 'object_query_' . $this->orderRepository->getClassId();
         $sql = "
-            SELECT  paymentProvider, 
-                    COUNT(1) as total, 
-                    COUNT(1) / t.cnt * 100 as `percentage` 
-            FROM $tableName as `order` 
-            INNER JOIN objects as o 
-              ON o.id = `order`.oo_id 
-            CROSS JOIN 
+            SELECT  paymentProvider,
+                    COUNT(1) as total,
+                    COUNT(1) / t.cnt * 100 as `percentage`
+            FROM $tableName as `order`
+            INNER JOIN objects as o
+              ON o.id = `order`.oo_id
+            CROSS JOIN
             (
-              SELECT COUNT(1) as cnt 
-              FROM $tableName as `order` 
-              INNER JOIN objects as o 
-                ON o.id = `order`.oo_id  
-              WHERE store = $storeId AND creationDate > $fromTimestamp AND creationDate < $toTimestamp
-            ) t 
-          WHERE store = $storeId AND creationDate > $fromTimestamp AND creationDate < $toTimestamp AND saleState='" . OrderSaleStates::STATE_ORDER . "' 
+              SELECT COUNT(1) as cnt
+              FROM $tableName as `order`
+              INNER JOIN objects as o
+                ON o.id = `order`.oo_id
+              WHERE store = :storeId AND creationDate > :fromTimestamp AND creationDate < :toTimestamp
+            ) t
+          WHERE store = :storeId AND creationDate > :fromTimestamp AND creationDate < :toTimestamp AND saleState='" . OrderSaleStates::STATE_ORDER . "'
           GROUP BY paymentProvider";
 
-        $results = $this->db->fetchAllAssociative($sql);
+        $results = $this->db->fetchAllAssociative($sql, [
+            'storeId' => $storeId,
+            'fromTimestamp' => $fromTimestamp,
+            'toTimestamp' => $toTimestamp,
+        ]);
         $data = [];
 
         foreach ($results as $result) {
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/ProductsReport.php b/src/CoreShop/Bundle/CoreBundle/Report/ProductsReport.php
index a3a7aaeddb..a99bfdcf62 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/ProductsReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/ProductsReport.php
@@ -88,7 +88,17 @@ public function getReportData(ParameterBag $parameterBag): array
             return [];
         }
 
-        $queryParameters = [];
+        $orderStateInClause = '';
+        $orderStateParams = [];
+        $orderStatePlaceholders = [];
+        if ($orderStateFilter !== null) {
+            foreach ($orderStateFilter as $i => $state) {
+                $orderStatePlaceholders[] = ':orderState' . $i;
+                $orderStateParams['orderState' . $i] = $state;
+            }
+            $orderStateInClause = ' AND `order`.orderState IN (' . implode(', ', $orderStatePlaceholders) . ')';
+        }
+
         if ($objectTypeFilter === 'container') {
             $unionData = [];
             foreach ($this->productStackRepository->getClassIds() as $id) {
@@ -101,7 +111,7 @@ public function getReportData(ParameterBag $parameterBag): array
               SELECT SQL_CALC_FOUND_ROWS
                 products.id as productId,
                 products.`name` as productName,
-                SUM(orderItems.totalGross) AS sales, 
+                SUM(orderItems.totalGross) AS sales,
                 AVG(orderItems.totalGross) AS salesPrice,
                 SUM((orderItems.itemRetailPriceNet - orderItems.itemWholesalePrice) * orderItems.quantity) AS profit,
                 SUM(orderItems.quantity) AS `quantityCount`,
@@ -110,10 +120,10 @@ public function getReportData(ParameterBag $parameterBag): array
                 INNER JOIN object_query_$orderItemClassId AS orderItems ON products.id = orderItems.mainObjectId
                 INNER JOIN object_relations_$orderClassId AS orderRelations ON orderRelations.dest_id = orderItems.oo_id AND orderRelations.fieldname = \"items\"
                 INNER JOIN object_query_$orderClassId AS `order` ON `order`.oo_id = orderRelations.src_id
-                WHERE products.o_type = 'object' AND `order`.store = $storeId" . (($orderStateFilter !== null) ? ' AND `order`.orderState IN (' . rtrim(str_repeat('?,', count($orderStateFilter)), ',') . ')' : '') . " AND `order`.orderDate > ? AND `order`.orderDate < ? AND saleState='" . OrderSaleStates::STATE_ORDER . "'
+                WHERE products.o_type = 'object' AND `order`.store = :storeId" . $orderStateInClause . " AND `order`.orderDate > :fromTimestamp AND `order`.orderDate < :toTimestamp AND saleState='" . OrderSaleStates::STATE_ORDER . "'
                 GROUP BY products.o_id
 
-            LIMIT $offset,$limit";
+            LIMIT " . (int) $offset . ', ' . (int) $limit;
         } else {
             $productTypeCondition = '1=1';
             if ($objectTypeFilter === 'object') {
@@ -122,31 +132,37 @@ public function getReportData(ParameterBag $parameterBag): array
                 $productTypeCondition = 'orderItems.mainObjectId IS NOT NULL';
             }
 
+            $orderStateInClauseOrders = '';
+            if ($orderStateFilter !== null) {
+                $orderStateInClauseOrders = ' AND `orders`.orderState IN (' . implode(', ', $orderStatePlaceholders) . ')';
+            }
+
             $query = "
                 SELECT SQL_CALC_FOUND_ROWS
                   orderItems.objectId as productId,
                   orderItemsTranslated.name AS `productName`,
-                  
-                  SUM(orderItems.totalGross) AS sales, 
+
+                  SUM(orderItems.totalGross) AS sales,
                   AVG(orderItems.totalGross) AS salesPrice,
                   SUM((orderItems.itemRetailPriceNet - orderItems.itemWholesalePrice) * orderItems.quantity) AS profit,
-                  
+
                   SUM(orderItems.quantity) AS `quantityCount`,
                   COUNT(orderItems.objectId) AS `orderCount`
                 FROM object_query_$orderClassId AS orders
                 INNER JOIN object_relations_$orderClassId AS orderRelations ON orderRelations.src_id = orders.oo_id AND orderRelations.fieldname = \"items\"
                 INNER JOIN object_query_$orderItemClassId AS orderItems ON orderRelations.dest_id = orderItems.oo_id
                 INNER JOIN object_localized_query_" . $orderItemClassId . '_' . $locale . " AS orderItemsTranslated ON orderItems.oo_id = orderItemsTranslated.ooo_id
-                WHERE `orders`.store = $storeId AND $productTypeCondition" . (($orderStateFilter !== null) ? ' AND `orders`.orderState IN (' . rtrim(str_repeat('?,', count($orderStateFilter)), ',') . ')' : '') . " AND `orders`.orderDate > ? AND `orders`.orderDate < ?
+                WHERE `orders`.store = :storeId AND $productTypeCondition" . $orderStateInClauseOrders . " AND `orders`.orderDate > :fromTimestamp AND `orders`.orderDate < :toTimestamp
                 GROUP BY orderItems.objectId
                 ORDER BY orderCount DESC
-                LIMIT $offset,$limit";
+                LIMIT " . (int) $offset . ', ' . (int) $limit;
         }
-        if ($orderStateFilter !== null) {
-            array_push($queryParameters, ...$orderStateFilter);
-        }
-        $queryParameters[] = $from->getTimestamp();
-        $queryParameters[] = $to->getTimestamp();
+
+        $queryParameters = array_merge([
+            'storeId' => $storeId,
+            'fromTimestamp' => $from->getTimestamp(),
+            'toTimestamp' => $to->getTimestamp(),
+        ], $orderStateParams);
 
         $productSales = $this->db->fetchAllAssociative($query, $queryParameters);
 
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/SalesReport.php b/src/CoreShop/Bundle/CoreBundle/Report/SalesReport.php
index bfe542b0ab..2a1a0d0167 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/SalesReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/SalesReport.php
@@ -102,12 +102,16 @@ protected function getData(ParameterBag $parameterBag): array
         }
 
         $sqlQuery = "
-              SELECT DATE(FROM_UNIXTIME(orderDate)) AS dayDate, orderDate, SUM(totalGross) AS total 
+              SELECT DATE(FROM_UNIXTIME(orderDate)) AS dayDate, orderDate, SUM(totalGross) AS total
               FROM object_query_$classId as orders
-              WHERE orders.store = $storeId AND orders.orderState = '$orderCompleteState' AND orders.orderDate > ? AND orders.orderDate < ? AND saleState='" . OrderSaleStates::STATE_ORDER . "' 
+              WHERE orders.store = :storeId AND orders.orderState = '$orderCompleteState' AND orders.orderDate > :fromTimestamp AND orders.orderDate < :toTimestamp AND saleState='" . OrderSaleStates::STATE_ORDER . "'
               GROUP BY " . $groupSelector;
 
-        $results = $this->db->fetchAllAssociative($sqlQuery, [$from->getTimestamp(), $to->getTimestamp()]);
+        $results = $this->db->fetchAllAssociative($sqlQuery, [
+            'storeId' => $storeId,
+            'fromTimestamp' => $from->getTimestamp(),
+            'toTimestamp' => $to->getTimestamp(),
+        ]);
 
         foreach ($results as $result) {
             $date = Carbon::createFromTimestamp($result['orderDate']);
diff --git a/src/CoreShop/Bundle/CoreBundle/Report/VouchersReport.php b/src/CoreShop/Bundle/CoreBundle/Report/VouchersReport.php
index ab1fdf883d..c5ae5a2ab2 100644
--- a/src/CoreShop/Bundle/CoreBundle/Report/VouchersReport.php
+++ b/src/CoreShop/Bundle/CoreBundle/Report/VouchersReport.php
@@ -73,18 +73,22 @@ public function getReportData(ParameterBag $parameterBag): array
 
         $sqlQuery = "
               SELECT SQL_CALC_FOUND_ROWS
-              orderVouchers.voucherCode AS code, 
+              orderVouchers.voucherCode AS code,
               priceRule.name AS rule,
               orderVouchers.discountGross AS discount,
               orders.orderDate
               FROM object_collection_CoreShopProposalCartPriceRuleItem_$classId as orderVouchers
-              INNER JOIN object_query_$classId as orders ON orders.oo_id = orderVouchers.id 
-              LEFT JOIN coreshop_cart_price_rule AS priceRule ON orderVouchers.cartPriceRule = priceRule.id 
-              WHERE orderVouchers.voucherCode <> '' AND orders.store = $storeId AND orders.orderState = '$orderCompleteState' AND orders.orderDate > ? AND orders.orderDate < ? AND saleState='" . OrderSaleStates::STATE_ORDER . "'
+              INNER JOIN object_query_$classId as orders ON orders.oo_id = orderVouchers.id
+              LEFT JOIN coreshop_cart_price_rule AS priceRule ON orderVouchers.cartPriceRule = priceRule.id
+              WHERE orderVouchers.voucherCode <> '' AND orders.store = :storeId AND orders.orderState = '$orderCompleteState' AND orders.orderDate > :fromTimestamp AND orders.orderDate < :toTimestamp AND saleState='" . OrderSaleStates::STATE_ORDER . "'
               ORDER BY orders.orderDate DESC
-              LIMIT $offset,$limit";
+              LIMIT " . (int) $offset . ', ' . (int) $limit;
 
-        $results = $this->db->fetchAllAssociative($sqlQuery, [$from->getTimestamp(), $to->getTimestamp()]);
+        $results = $this->db->fetchAllAssociative($sqlQuery, [
+            'storeId' => $storeId,
+            'fromTimestamp' => $from->getTimestamp(),
+            'toTimestamp' => $to->getTimestamp(),
+        ]);
         $this->totalRecords = (int) $this->db->fetchOne('SELECT FOUND_ROWS()');
 
         foreach ($results as $result) {