CVE-2020-15264 (published 2020-10-20T21:15Z)

The Boxstarter installer before version 2.13.0 configures C:\\ProgramData\\Boxstarter to be in the system-wide PATH environment variable. However, this directory is writable by normal, unprivileged users. To exploit the vulnerability, place a DLL in this directory that a privileged service is looking for. For example, WptsExtensions.dll When Windows starts, it'll execute the code in DllMain() with SYSTEM privileges. Any unprivileged user can execute code with SYSTEM privileges. The issue is fixed in version 3.13.0

Severity: HIGH
CVSS v2 base score: 7.2 (AV:L/AC:L/Au:N/C:C/I:C/A:C)
CVSS v3 base score: 7.8, HIGH (CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H)

Weakness information:
cwe_id: CWE-668
cwe_name: Exposure of Resource to Wrong Sphere
description: The product exposes a resource to the wrong control sphere, providing unintended actors with inappropriate access to the resource.
extended_description: 
            Resources such as files and directories may be inadvertently exposed through mechanisms such as insecure permissions, or when a program accidentally operates on the wrong object. For example, a program may intend that private files can only be provided to a specific user. This effectively defines a control sphere that is intended to prevent attackers from accessing these private files. If the file permissions are insecure, then parties other than the user will be able to access those files.
            A separate control sphere might effectively require that the user can only access the private files, but not any other files on the system. If the program does not ensure that the user is only requesting private files, then the user might be able to access other files on the system.
            In either case, the end result is that a resource has been exposed to the wrong party.
         
         
cwe_id: CWE-73
cwe_name: External Control of File Name or Path
description: The product allows user input to control or influence paths or file names that are used in filesystem operations.
extended_description: 
            This could allow an attacker to access or modify system files or other files that are critical to the application.
            Path manipulation errors occur when the following two conditions are met:
            
               1. An attacker can specify a path used in an operation on the filesystem.
               2. By specifying the resource, the attacker gains a capability that would not otherwise be permitted.
            
            For example, the program may give the attacker the ability to overwrite the specified file or run with a configuration controlled by the attacker.
         
         

Fix information:
repo_url: https://github.com/chocolatey/boxstarter
commit_details: repo_url: https://github.com/chocolatey/boxstarter
author: Manfred Wallner
author_date: 2020-10-13 12:31:35+02:00
msg: Merge pull request from GHSA-rpgx-h675-r3jf

* mitigate possible privilege escalation

* code cleanup
repository: repo_url: https://github.com/chocolatey/boxstarter
repo_name: chocolatey/boxstarter
description: Repeatable, reboot resilient windows environment installations made easy using Chocolatey packages
repo_language: PowerShell
owner: chocolatey
file_changes: filename: setup.ps1
change_type: ModificationType.MODIFY
diff: @@ -1,20 +1,127 @@
+
+<#
+.SYNOPSIS
+    test if current session/identity is elevated 
+    (a.k.a. check if we've got admin privileges)
+#>
+function Test-Admin {
+    $identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
+    $principal = New-Object System.Security.Principal.WindowsPrincipal( $identity )
+    return $principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator )
+}
+
+<#
+.SYNOPSIS
+    get name of 'WellKnownSidType' in the current user's system locale
+#>
+function Get-LocalizedWellKnownPrincipalName {
+    param (
+        [Parameter(Mandatory = $true)]
+        [Security.Principal.WellKnownSidType] $WellKnownSidType
+    )
+    $sid = New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList @($WellKnownSidType, $null)
+    $account = $sid.Translate([Security.Principal.NTAccount])
+
+    return $account.Value
+}
+
+<#
+.SYNOPSIS
+    ensure a given folder is only writeable by administrative users
+
+.NOTES
+    we need to do this in order to mitigate privilege escalation attacks!
+    
+    Attack Vector 1: Boxstarter folders are added to PATH, therefore they must be protected in a way so 
+    that a random user may not put arbitrary files/dlls in these folders.
+    (files may be replaces with hijacked/malicious ones)
+    
+    Attack Vector 2: 'BuildPackages' contains Boxstarter Packages that may be installed after system reboots.
+    If a user would be able to modify those packages, it would be easy to run arbitrary PowerShell code with 
+    SYSTEM privileges.
+    
+    see Ensure-Permissions 
+    https://github.com/chocolatey/choco/blob/master/nuget/chocolatey/tools/chocolateysetup.psm1
+#>
+function Ensure-Permissions {
+    [CmdletBinding()]
+    param(
+        [string]$folder
+    )
+    Write-Debug "Ensure-Permissions"
+
+    $currentEA = $ErrorActionPreference
+    $ErrorActionPreference = 'Stop'
+    try {
+        # get current acl
+        $acl = (Get-Item $folder).GetAccessControl('Access,Owner')
+
+        Write-Debug "Removing existing permissions."
+        $acl.Access | ForEach-Object {
+            Write-Debug "Remove '$($_.FileSystemRights)' for user '$($_.IdentityReference)'"
+            $acl.RemoveAccessRuleAll($_) 
+        }
+
+        $inheritanceFlags = ([Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [Security.AccessControl.InheritanceFlags]::ObjectInherit)
+        $propagationFlags = [Security.AccessControl.PropagationFlags]::None
+
+        $rightsFullControl = [Security.AccessControl.FileSystemRights]::FullControl
+        $rightsReadExecute = [Security.AccessControl.FileSystemRights]::ReadAndExecute
+
+        Write-Output "Restricting write permissions of '$folder' to Administrators"
+        $builtinAdmins = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
+        $adminsAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($builtinAdmins, $rightsFullControl, $inheritanceFlags, $propagationFlags, "Allow")
+        $acl.SetAccessRule($adminsAccessRule)
+        $localSystem = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::LocalSystemSid)
+        $localSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($localSystem, $rightsFullControl, $inheritanceFlags, $propagationFlags, "Allow")
+        $acl.SetAccessRule($localSystemAccessRule)
+        $builtinUsers = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::BuiltinUsersSid)
+        $usersAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($builtinUsers, $rightsReadExecute, $inheritanceFlags, $propagationFlags, "Allow")
+        $acl.SetAccessRule($usersAccessRule)
+
+        Write-Debug "Set Owner to Administrators"
+        $builtinAdminsSid = New-Object System.Security.Principal.SecurityIdentifier([Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid, $null)
+        $acl.SetOwner($builtinAdminsSid)
+
+        Write-Debug "Removing inheritance with no copy"
+        $acl.SetAccessRuleProtection($true, $false)
+
+        # enact the changes against the actual
+        (Get-Item $folder).SetAccessControl($acl)
+
+    }
+    catch {
+        Write-Warning $_.Exception
+        Write-Warning "Not able to set permissions for $folder."
+    }
+    $ErrorActionPreference = $currentEA
+}
+
 function Install-Boxstarter($here, $ModuleName, $installArgs = "") {
+
+    if (!(Test-Admin)) {
+        throw "Installation of Boxstarter requires Administrative permissions. Please run from elevated prompt."
+    }
+
     $boxstarterPath = Join-Path $env:ProgramData Boxstarter
-    if(!(test-Path $boxstarterPath)){
-        mkdir $boxstarterPath
+    if (!(test-Path $boxstarterPath)) {
+        New-Item -ItemType Directory $boxstarterPath | Out-Null
     }
-    $packagePath=Join-Path $boxstarterPath BuildPackages
-    if(!(test-Path $packagePath)){
-        mkdir $packagePath
+    $packagePath = Join-Path $boxstarterPath BuildPackages
+    if (!(test-Path $packagePath)) {
+        New-Item -ItemType Directory $packagePath | Out-Null
     }
-    foreach($ModulePath in (Get-ChildItem $here | Where-Object { $_.PSIsContainer })){
-        $target=Join-Path $boxstarterPath $modulePath.BaseName
-        if(test-Path $target){
+    foreach ($ModulePath in (Get-ChildItem $here | Where-Object { $_.PSIsContainer })) {
+        $target = Join-Path $boxstarterPath $modulePath.BaseName
+        if (test-Path $target) {
             Remove-Item $target -Recurse -Force
         }
     }
     Copy-Item "$here\*" $boxstarterPath -Recurse -Force -Exclude ChocolateyInstall.ps1, Setup.*
 
+    # set permissions to mitigate possible privilege escalation
+    Ensure-Permissions -folder $boxstarterPath
+
     PersistBoxStarterPathToEnvironmentVariable "PSModulePath" $boxstarterPath
     PersistBoxStarterPathToEnvironmentVariable "Path" $boxstarterPath
     $binPath =  "$here\..\..\..\bin"
@@ -46,7 +153,7 @@ PS:>Get-Help Boxstarter
         $startMenu = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::CommonStartMenu)
         $startMenu += "\Programs\Boxstarter"
         if(!(Test-Path $startMenu)){
-            mkdir $startMenu
+            New-Item -ItemType Directory $startMenu | Out-Null
         }
         $target="powershell.exe"
         $targetArgs="-ExecutionPolicy bypass -NoExit -Command `"&'$boxstarterPath\BoxstarterShell.ps1'`""

programming_language: PowerShell