CVE-2022-23064: Improper Neutralization of Special Elements in Output Used by a Downstream Component ('Injection') (CWE-74)
value: In Snipe-IT, versions v3.0-alpha to v5.3.7 are vulnerable to Host Header Injection. By sending a specially crafted host header in the reset password request, it is possible to send password reset links to users which once clicked lead to an attacker controlled server and thus leading to password reset token leak. This leads to account take over.
CWE description: The product constructs all or part of a command, data structure, or record using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify how it is parsed or interpreted when it is sent to a downstream component.
CVSS v3 base score: 8.8
Published: 2022-05-02T13:15Z
Repository: https://github.com/snipe/snipe-it
Language: PHP
Files changed: .env.example, app/Providers/AppServiceProvider.php
Commit date: 2022-01-18 15:52:59 -0800
Commit message: Force UrlGenerator's Root URL to be the base of APP_URL unless overriden
(For v5)

Diff: diff --git a/.env.example b/.env.example
index 31e3cca14b6..e82b5c5bcd9 100644
--- a/.env.example
+++ b/.env.example
@@ -143,10 +143,11 @@ RESET_PASSWORD_LINK_EXPIRES=900
 APP_LOG=single
 APP_LOG_MAX_FILES=10
 APP_LOCKED=false
 APP_CIPHER=AES-256-CBC
 APP_FORCE_TLS=false
+APP_ALLOW_INSECURE_HOSTS=false
 GOOGLE_MAPS_API=
 LDAP_MEM_LIM=500M
 LDAP_TIME_LIM=600
 IMPORT_TIME_LIMIT=600
 IMPORT_MEMORY_LIMIT=500M
diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php
index c2651c3aef7..a74c48e4188 100644
--- a/app/Providers/AppServiceProvider.php
+++ b/app/Providers/AppServiceProvider.php
@@ -41,10 +41,18 @@ class AppServiceProvider extends ServiceProvider
                 $url->forceScheme('https');
             } else {
                 \Log::warning("'APP_FORCE_TLS' is set to true, but 'APP_URL' does not start with 'https://'. Will not force TLS on connections.");
             }
         }
+
+        // TODO - isn't it somehow 'gauche' to check the environment directly; shouldn't we be using config() somehow?
+        if ( ! env('APP_ALLOW_INSECURE_HOSTS')) {  // unless you set APP_ALLOW_INSECURE_HOSTS, you should PROHIBIT forging domain parts of URL via Host: headers
+            $url_parts = parse_url(config('app.url'));
+            $root_url = $url_parts['scheme'].'://'.$url_parts['host'].( isset($url_parts['port']) ? ':'.$url_parts['port'] : '');
+            \URL::forceRootUrl($root_url);
+        }
+
         Schema::defaultStringLength(191);
         Asset::observe(AssetObserver::class);
         Accessory::observe(AccessoryObserver::class);
         Component::observe(ComponentObserver::class);
         Consumable::observe(ConsumableObserver::class);

Fixed code: APP_ALLOW_INSECURE_HOSTS=false

        // TODO - isn't it somehow 'gauche' to check the environment directly; shouldn't we be using config() somehow?
        if ( ! env('APP_ALLOW_INSECURE_HOSTS')) {  // unless you set APP_ALLOW_INSECURE_HOSTS, you should PROHIBIT forging domain parts of URL via Host: headers
            $url_parts = parse_url(config('app.url'));
            $root_url = $url_parts['scheme'].'://'.$url_parts['host'].( isset($url_parts['port']) ? ':'.$url_parts['port'] : '');
            \URL::forceRootUrl($root_url);
        }