Skip to content

Commit 67e3204

Browse files
authored
Merge pull request from GHSA-rpgx-h675-r3jf
* mitigate possible privilege escalation * code cleanup
1 parent f6a84b3 commit 67e3204

File tree

1 file changed

+116
-9
lines changed

1 file changed

+116
-9
lines changed

Diff for: BuildScripts/setup.ps1

+116-9
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,127 @@
1+
2+
<#
3+
.SYNOPSIS
4+
test if current session/identity is elevated
5+
(a.k.a. check if we've got admin privileges)
6+
#>
7+
function Test-Admin {
8+
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent()
9+
$principal = New-Object System.Security.Principal.WindowsPrincipal( $identity )
10+
return $principal.IsInRole( [System.Security.Principal.WindowsBuiltInRole]::Administrator )
11+
}
12+
13+
<#
14+
.SYNOPSIS
15+
get name of 'WellKnownSidType' in the current user's system locale
16+
#>
17+
function Get-LocalizedWellKnownPrincipalName {
18+
param (
19+
[Parameter(Mandatory = $true)]
20+
[Security.Principal.WellKnownSidType] $WellKnownSidType
21+
)
22+
$sid = New-Object -TypeName 'System.Security.Principal.SecurityIdentifier' -ArgumentList @($WellKnownSidType, $null)
23+
$account = $sid.Translate([Security.Principal.NTAccount])
24+
25+
return $account.Value
26+
}
27+
28+
<#
29+
.SYNOPSIS
30+
ensure a given folder is only writeable by administrative users
31+
32+
.NOTES
33+
we need to do this in order to mitigate privilege escalation attacks!
34+
35+
Attack Vector 1: Boxstarter folders are added to PATH, therefore they must be protected in a way so
36+
that a random user may not put arbitrary files/dlls in these folders.
37+
(files may be replaces with hijacked/malicious ones)
38+
39+
Attack Vector 2: 'BuildPackages' contains Boxstarter Packages that may be installed after system reboots.
40+
If a user would be able to modify those packages, it would be easy to run arbitrary PowerShell code with
41+
SYSTEM privileges.
42+
43+
see Ensure-Permissions
44+
https://github.com/chocolatey/choco/blob/master/nuget/chocolatey/tools/chocolateysetup.psm1
45+
#>
46+
function Ensure-Permissions {
47+
[CmdletBinding()]
48+
param(
49+
[string]$folder
50+
)
51+
Write-Debug "Ensure-Permissions"
52+
53+
$currentEA = $ErrorActionPreference
54+
$ErrorActionPreference = 'Stop'
55+
try {
56+
# get current acl
57+
$acl = (Get-Item $folder).GetAccessControl('Access,Owner')
58+
59+
Write-Debug "Removing existing permissions."
60+
$acl.Access | ForEach-Object {
61+
Write-Debug "Remove '$($_.FileSystemRights)' for user '$($_.IdentityReference)'"
62+
$acl.RemoveAccessRuleAll($_)
63+
}
64+
65+
$inheritanceFlags = ([Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [Security.AccessControl.InheritanceFlags]::ObjectInherit)
66+
$propagationFlags = [Security.AccessControl.PropagationFlags]::None
67+
68+
$rightsFullControl = [Security.AccessControl.FileSystemRights]::FullControl
69+
$rightsReadExecute = [Security.AccessControl.FileSystemRights]::ReadAndExecute
70+
71+
Write-Output "Restricting write permissions of '$folder' to Administrators"
72+
$builtinAdmins = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid)
73+
$adminsAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($builtinAdmins, $rightsFullControl, $inheritanceFlags, $propagationFlags, "Allow")
74+
$acl.SetAccessRule($adminsAccessRule)
75+
$localSystem = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::LocalSystemSid)
76+
$localSystemAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($localSystem, $rightsFullControl, $inheritanceFlags, $propagationFlags, "Allow")
77+
$acl.SetAccessRule($localSystemAccessRule)
78+
$builtinUsers = Get-LocalizedWellKnownPrincipalName -WellKnownSidType ([Security.Principal.WellKnownSidType]::BuiltinUsersSid)
79+
$usersAccessRule = New-Object System.Security.AccessControl.FileSystemAccessRule($builtinUsers, $rightsReadExecute, $inheritanceFlags, $propagationFlags, "Allow")
80+
$acl.SetAccessRule($usersAccessRule)
81+
82+
Write-Debug "Set Owner to Administrators"
83+
$builtinAdminsSid = New-Object System.Security.Principal.SecurityIdentifier([Security.Principal.WellKnownSidType]::BuiltinAdministratorsSid, $null)
84+
$acl.SetOwner($builtinAdminsSid)
85+
86+
Write-Debug "Removing inheritance with no copy"
87+
$acl.SetAccessRuleProtection($true, $false)
88+
89+
# enact the changes against the actual
90+
(Get-Item $folder).SetAccessControl($acl)
91+
92+
}
93+
catch {
94+
Write-Warning $_.Exception
95+
Write-Warning "Not able to set permissions for $folder."
96+
}
97+
$ErrorActionPreference = $currentEA
98+
}
99+
1100
function Install-Boxstarter($here, $ModuleName, $installArgs = "") {
101+
102+
if (!(Test-Admin)) {
103+
throw "Installation of Boxstarter requires Administrative permissions. Please run from elevated prompt."
104+
}
105+
2106
$boxstarterPath = Join-Path $env:ProgramData Boxstarter
3-
if(!(test-Path $boxstarterPath)){
4-
mkdir $boxstarterPath
107+
if (!(test-Path $boxstarterPath)) {
108+
New-Item -ItemType Directory $boxstarterPath | Out-Null
5109
}
6-
$packagePath=Join-Path $boxstarterPath BuildPackages
7-
if(!(test-Path $packagePath)){
8-
mkdir $packagePath
110+
$packagePath = Join-Path $boxstarterPath BuildPackages
111+
if (!(test-Path $packagePath)) {
112+
New-Item -ItemType Directory $packagePath | Out-Null
9113
}
10-
foreach($ModulePath in (Get-ChildItem $here | Where-Object { $_.PSIsContainer })){
11-
$target=Join-Path $boxstarterPath $modulePath.BaseName
12-
if(test-Path $target){
114+
foreach ($ModulePath in (Get-ChildItem $here | Where-Object { $_.PSIsContainer })) {
115+
$target = Join-Path $boxstarterPath $modulePath.BaseName
116+
if (test-Path $target) {
13117
Remove-Item $target -Recurse -Force
14118
}
15119
}
16120
Copy-Item "$here\*" $boxstarterPath -Recurse -Force -Exclude ChocolateyInstall.ps1, Setup.*
17121

122+
# set permissions to mitigate possible privilege escalation
123+
Ensure-Permissions -folder $boxstarterPath
124+
18125
PersistBoxStarterPathToEnvironmentVariable "PSModulePath" $boxstarterPath
19126
PersistBoxStarterPathToEnvironmentVariable "Path" $boxstarterPath
20127
$binPath = "$here\..\..\..\bin"
@@ -46,7 +153,7 @@ PS:>Get-Help Boxstarter
46153
$startMenu = [System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::CommonStartMenu)
47154
$startMenu += "\Programs\Boxstarter"
48155
if(!(Test-Path $startMenu)){
49-
mkdir $startMenu
156+
New-Item -ItemType Directory $startMenu | Out-Null
50157
}
51158
$target="powershell.exe"
52159
$targetArgs="-ExecutionPolicy bypass -NoExit -Command `"&'$boxstarterPath\BoxstarterShell.ps1'`""

0 commit comments

Comments
 (0)