CVE-2023-37267: Insufficient Information (NVD-CWE-noinfo)
value: Umbraco is a ASP.NET CMS. Under rare conditions a restart of Umbraco can allow unauthorized users access to admin-level permissions. This vulnerability was patched in versions 10.6.1, 11.4.2 and 12.0.1.
CWE description: There is insufficient information about the issue to classify it; details are unkown or unspecified.
CVSS v3 base score: 9.8
Published: 2023-07-13T14:15Z
Repository: https://github.com/umbraco/Umbraco-CMS
Language: C#
Files changed: src/Umbraco.Infrastructure/Runtime/RuntimeState.cs, src/Umbraco.Web.BackOffice/Install/InstallApiController.cs
Commit date: 2023-07-13 06:10:51 +0200
Commit message: Merge pull request from GHSA-h8wc-r4jh-mg7m

* Don't login after install

* Fail the install if database is not created

---------

Co-authored-by: Zeegaan <nge@umbraco.dk>
Co-authored-by: Nikolaj <nikolajlauridsen@protonmail.ch>

Diff: diff --git a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs
index 6597fadf61a..2e2e5dbe594 100644
--- a/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs
+++ b/src/Umbraco.Infrastructure/Runtime/RuntimeState.cs
@@ -210,11 +210,11 @@ public void DetermineRuntimeLevel()
                     _logger.LogDebug("Could not connect to database.");
 
                     if (_globalSettings.Value.InstallMissingDatabase || _databaseProviderMetadata.CanForceCreateDatabase(_databaseFactory))
                     {
                         // ok to install on a configured but missing database
-                        Level = RuntimeLevel.Install;
+                        Level = RuntimeLevel.BootFailed;
                         Reason = RuntimeLevelReason.InstallMissingDatabase;
                         return;
                     }
 
                     // else it is bad enough that we want to throw
diff --git a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs
index 52068c6f8d9..b7109337915 100644
--- a/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs
+++ b/src/Umbraco.Web.BackOffice/Install/InstallApiController.cs
@@ -1,7 +1,8 @@
 using System.Reflection;
 using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.Logging;
 using Newtonsoft.Json.Linq;
 using Umbraco.Cms.Core;
 using Umbraco.Cms.Core.Install;
 using Umbraco.Cms.Core.Install.Models;
@@ -23,37 +24,47 @@ namespace Umbraco.Cms.Web.BackOffice.Install;
 [AngularJsonOnlyConfiguration]
 [InstallAuthorize]
 [Area(Constants.Web.Mvc.InstallArea)]
 public class InstallApiController : ControllerBase
 {
-    private readonly IBackOfficeSignInManager _backOfficeSignInManager;
-    private readonly IBackOfficeUserManager _backOfficeUserManager;
     private readonly DatabaseBuilder _databaseBuilder;
     private readonly InstallStatusTracker _installStatusTracker;
     private readonly InstallStepCollection _installSteps;
     private readonly ILogger<InstallApiController> _logger;
     private readonly IProfilingLogger _proflog;
     private readonly IRuntime _runtime;
 
+    [Obsolete("Use the constructor without IBackOfficeUserManager & IBackOfficeSignInManager instead, scheduled for removal in v14")]
     public InstallApiController(
         DatabaseBuilder databaseBuilder,
         IProfilingLogger proflog,
         ILogger<InstallApiController> logger,
         InstallHelper installHelper,
         InstallStepCollection installSteps,
         InstallStatusTracker installStatusTracker,
         IRuntime runtime,
         IBackOfficeUserManager backOfficeUserManager,
         IBackOfficeSignInManager backOfficeSignInManager)
+        : this(databaseBuilder, proflog, logger, installHelper, installSteps, installStatusTracker, runtime)
+    {
+    }
+
+    [ActivatorUtilitiesConstructor]
+    public InstallApiController(
+        DatabaseBuilder databaseBuilder,
+        IProfilingLogger proflog,
+        ILogger<InstallApiController> logger,
+        InstallHelper installHelper,
+        InstallStepCollection installSteps,
+        InstallStatusTracker installStatusTracker,
+        IRuntime runtime)
     {
         _databaseBuilder = databaseBuilder ?? throw new ArgumentNullException(nameof(databaseBuilder));
         _proflog = proflog ?? throw new ArgumentNullException(nameof(proflog));
         _installSteps = installSteps;
         _installStatusTracker = installStatusTracker;
         _runtime = runtime;
-        _backOfficeUserManager = backOfficeUserManager;
-        _backOfficeSignInManager = backOfficeSignInManager;
         InstallHelper = installHelper;
         _logger = logger;
     }
 
 
@@ -86,24 +97,12 @@ public InstallSetup GetSetup()
     }
 
     [HttpPost]
     public async Task<ActionResult> CompleteInstall()
     {
-        RuntimeLevel levelBeforeRestart = _runtime.State.Level;
-
         await _runtime.RestartAsync();
 
-        if (levelBeforeRestart == RuntimeLevel.Install)
-        {
-            BackOfficeIdentityUser? identityUser =
-                await _backOfficeUserManager.FindByIdAsync(Core.Constants.Security.SuperUserIdAsString);
-            if (identityUser is not null)
-            {
-                _backOfficeSignInManager.SignInAsync(identityUser, false);
-            }
-        }
-
         return NoContent();
     }
 
     public async Task<ActionResult<InstallProgressResultModel>> PostPerformInstall(InstallInstructions installModel)
     {

Vulnerable code:                         Level = RuntimeLevel.Install;
    private readonly IBackOfficeSignInManager _backOfficeSignInManager;
    private readonly IBackOfficeUserManager _backOfficeUserManager;
        _backOfficeUserManager = backOfficeUserManager;
        _backOfficeSignInManager = backOfficeSignInManager;
        RuntimeLevel levelBeforeRestart = _runtime.State.Level;

        if (levelBeforeRestart == RuntimeLevel.Install)
        {
            BackOfficeIdentityUser? identityUser =
                await _backOfficeUserManager.FindByIdAsync(Core.Constants.Security.SuperUserIdAsString);
            if (identityUser is not null)
            {
                _backOfficeSignInManager.SignInAsync(identityUser, false);
            }
        }

Fixed code:                         Level = RuntimeLevel.BootFailed;
using Microsoft.Extensions.DependencyInjection;
    [Obsolete("Use the constructor without IBackOfficeUserManager & IBackOfficeSignInManager instead, scheduled for removal in v14")]
        : this(databaseBuilder, proflog, logger, installHelper, installSteps, installStatusTracker, runtime)
    {
    }

    [ActivatorUtilitiesConstructor]
    public InstallApiController(
        DatabaseBuilder databaseBuilder,
        IProfilingLogger proflog,
        ILogger<InstallApiController> logger,
        InstallHelper installHelper,
        InstallStepCollection installSteps,
        InstallStatusTracker installStatusTracker,
        IRuntime runtime)