CVE-2023-3229: Business Logic Errors (CWE-840)
value: Business Logic Errors in GitHub repository fossbilling/fossbilling prior to 0.5.0.
CWE description: Weaknesses in this category identify some of the underlying problems that commonly allow attackers to manipulate the business logic of an application. Errors in business logic can be devastating to an entire application. They can be difficult to find automatically, since they typically involve legitimate use of the application's functionality. However, many business logic errors can exhibit patterns that are similar to well-understood implementation and design weaknesses.
CVSS v3 base score: 6.5
Published: 2023-06-14T06:15Z
Repository: https://github.com/fossbilling/fossbilling
Language: PHP
Files changed: src/modules/Cart/Service.php
Commit date: 2023-06-12 06:28:00 +0200
Commit message: Prevent checkouts with disabled products (#1308)


Diff: diff --git a/src/modules/Cart/Service.php b/src/modules/Cart/Service.php
index 8e1feec0..c7b7794f 100644
--- a/src/modules/Cart/Service.php
+++ b/src/modules/Cart/Service.php
@@ -498,10 +498,15 @@ class Service implements InjectionAwareInterface
         $i = 0;
 
         foreach ($this->getCartProducts($cart) as $p) {
             $item = $this->cartProductToApiArray($p);
 
+            $product = $this->di['db']->getExistingModelById('Product', $item['product_id']);
+            if (is_null($product) || $product->status !== 'enabled') {
+                throw new \Box_Exception("Unable to complete order. One or more of the selected products are invalid.");
+            }
+
             /*
              * Convert the domain name to lowercase letters.
              * Using a capital letter in a domain name still points to the same name, so this isn't going to break anything
              * It will, however, avoid instances like this when a domain name is entered with a capital letter:
              * https://github.com/boxbilling/boxbilling/discussions/1022#discussioncomment-1311819
@@ -512,11 +517,11 @@ class Service implements InjectionAwareInterface
             $item['domain']['owndomain_sld'] = (isset($item['domain']['owndomain_sld'])) ? strtolower($item['domain']['owndomain_sld']) : null;
             $item['domain']['register_sld'] = (isset($item['domain']['register_sld'])) ? strtolower($item['domain']['register_sld']) : null;
             $item['domain']['transfer_sld'] = (isset($item['domain']['transfer_sld'])) ? strtolower($item['domain']['transfer_sld']) : null;
 
             // Domain TLD must begin with a period - add if not present for owndomain.
-            $item['domain']['owndomain_tld'] = (isset( $item['domain']['owndomain_tld'])) ? (str_contains($item['domain']['owndomain_tld'], '.') ? $item['domain']['owndomain_tld'] : '.' . $item['domain']['owndomain_tld']) : null;
+            $item['domain']['owndomain_tld'] = (isset($item['domain']['owndomain_tld'])) ? (str_contains($item['domain']['owndomain_tld'], '.') ? $item['domain']['owndomain_tld'] : '.' . $item['domain']['owndomain_tld']) : null;
 
             $order = $this->di['db']->dispense('ClientOrder');
             $order->client_id = $client->id;
             $order->promo_id = $cart->promo_id;
             $order->product_id = $item['product_id'];

Vulnerable code:             $item['domain']['owndomain_tld'] = (isset( $item['domain']['owndomain_tld'])) ? (str_contains($item['domain']['owndomain_tld'], '.') ? $item['domain']['owndomain_tld'] : '.' . $item['domain']['owndomain_tld']) : null;
Fixed code:             $product = $this->di['db']->getExistingModelById('Product', $item['product_id']);
            if (is_null($product) || $product->status !== 'enabled') {
                throw new \Box_Exception("Unable to complete order. One or more of the selected products are invalid.");
            }

            $item['domain']['owndomain_tld'] = (isset($item['domain']['owndomain_tld'])) ? (str_contains($item['domain']['owndomain_tld'], '.') ? $item['domain']['owndomain_tld'] : '.' . $item['domain']['owndomain_tld']) : null;