Windows Unprivileged - Summary
Note that absolutely none of this is authoritative or directly based on relevant documentation. It’s mostly what I found and figured out and guessed and (in some cases) made up. Some of it may be wrong or dangerous or lead to disaster or confusion. I am not taking responsibility here for anything. Read and act on it at your own peril!
This post is like a summary of previous posts, giving an overview over what (I think) should be configured on a Windows Server. It summarises recommended (by me) JEA configurations, the process of creating resource groups, group memberships, and some notes on access control lists you might want to edit.
I will update this post as needed over the next few years. Updates will be marked as such arbitrarily.
1. Do not add any domain groups or domain users to the local Administrators group
I read somewhere that it is a best practice not to grant administrator privileges to domain users. Administrator tasks should always be done using a local administrator user (or ideally using delegated permissions).
2. Create Just Enough Admin configurations for common tasks
In many cases you can just allow use of every cmdlet in a certain module to all relevant users.
Prepare the directory for JEA configurations if it does not exist yet:
New-Item -Type Directory -Path 'C:\Program Files\WindowsPowerShell\Modules\JEA\RoleCapabilities' -Force
Also recall that you can remove a JEA configuration (or remove it to register a new version of it) by using the Unregister-PSSessionConfiguration cmdlet.
This allows a user who is a member of JEA_WindowsFeature to install and remove Windows features like IIS and DNS.
# Create a local group to allow access to the JEA configuration
New-LocalGroup "JEA_WindowsFeature"
# Define the JEA configuration
$htWindowsFeatureSessionConfiguration = @{"JEA_WindowsFeature" = @{RoleCapabilities="WindowsFeature"}}
$htWindowsFeatureRoleCapability = @{'ModulesToImport'='ServerManager','Dism'; 'VisibleCmdlets'='*-WindowsFeature','*-WindowsCapability'; 'VisibleProviders'='FileSystem'}
# Create the JEA configuration
Set-Location "C:\Program Files\WindowsPowerShell\Modules\JEA"
New-PSSessionConfigurationFile -Path "WindowsFeature.pssc" -SessionType RestrictedRemoteServer -RunAsVirtualAccount -RoleDefinitions $htWindowsFeatureSessionConfiguration
New-PSRoleCapabilityFile -Path "RoleCapabilities\WindowsFeature.psrc" @htWindowsFeatureRoleCapability
# Register the JEA configuration
Register-PSSessionConfiguration WindowsFeature -Path .\WindowsFeature.pssc
A user added to the JEA group can then import the PSSessionConfiguration by proudly chanting the following magical formula:
Import-PSSession (New-PSSession -ConfigurationName WindowsFeature) -AllowClobber
This allows a user in the JEA_Process group to stop any process. (This is perhaps not desireable. But it appears to be less dangerous than it sounds.)
New-LocalGroup "JEA_Process"
$htProcessSessionConfiguration = @{"JEA_Process" = @{RoleCapabilities="Process"}}
$htProcessRoleCapability = @{'VisibleCmdlets'='Get-Process','Stop-Process'; 'VisibleProviders'='FileSystem'}
Set-Location "C:\Program Files\WindowsPowerShell\Modules\JEA"
New-PSSessionConfigurationFile -Path "Process.pssc" -SessionType RestrictedRemoteServer -RunAsVirtualAccount -RoleDefinitions $htProcessSessionConfiguration
New-PSRoleCapabilityFile -Path "RoleCapabilities\Process.psrc" @htProcessRoleCapability
Register-PSSessionConfiguration Process -Path .\Process.pssc
Note again that this allows users in JEA_Process to stop any unprotected process on the system owned by anyone. There is a use case for this. If you don’t see it, don’t do it!
You probably want to give web administrators access to IIS cmdlets. Also install the web management service and give them access to their respective web sites.
New-LocalGroup "JEA_IIS"
$htIISSessionConfiguration = @{"JEA_IIS" = @{RoleCapabilities="IIS"}}
$htIISRoleCapability = @{'ModulesToImport'='IISAdministration','WebAdministration'; 'VisibleCmdlets'='*-IIS*','*-Web*'; 'VisibleExternalCommands'='C:\Windows\System32\iisreset.exe'; 'VisibleProviders'='Variable','FileSystem'}
Set-Location "C:\Program Files\WindowsPowerShell\Modules\JEA"
New-PSSessionConfigurationFile -Path "IIS.pssc" -SessionType RestrictedRemoteServer -RunAsVirtualAccount -RoleDefinitions $htIISSessionConfiguration
New-PSRoleCapabilityFile -Path "RoleCapabilities\IIS.psrc" @htIISRoleCapability
Register-PSSessionConfiguration IIS -Path .\IIS.pssc
You can allow all members of JEA_SmbShare total access to all SMB shares. This is probably also less dangerous than it sounds. Like the processes JEA it does allow users to harm the system though.
New-LocalGroup "JEA_SmbShare"
$htSmbShareSessionConfiguration = @{"JEA_SmbShare" = @{RoleCapabilities="SmbShare"}}
$htSmbShareRoleCapability = @{'ModulesToImport'='SmbShare'; 'VisibleCmdlets'='*-Smb*'; 'VisibleProviders'='FileSystem'};
Set-Location "C:\Program Files\WindowsPowerShell\Modules\JEA"
New-PSSessionConfigurationFile -Path "SmbShare.pssc" -SessionType RestrictedRemoteServer -RunAsVirtualAccount -RoleDefinitions $htSmbShareSessionConfiguration
New-PSRoleCapabilityFile -Path "RoleCapabilities\SmbShare.psrc" @htSmbShareRoleCapability
Register-PSSessionConfiguration SmbShare -Path .\SmbShare.pssc
You likely want to create resource groups for services.
A resource group is a group that has no other purpose than to grant access to an object the ACL of which is too difficult to edit. Generally file system and registry ACLs are easy to edit (Explorer and Registry Editor can do it, so can PowerShell to an extent) whereas the ACLs of services (among other objects) are difficult to edit (PowerShell cannot do it and no GUI tool to do it exists).
$sid = (New-LocalGroup RG_GeneralTestService-0x34).SID.Value
$sddl = (sc.exe sdshow GeneralTestService)[1] # first line is empty
$sddl = $sddl -replace "S:","(A;;0x34;;;$sid)S:" # adds new access rule to sddl
sc.exe sdset GeneralTestService $sddl
sc.exe sdshow GeneralTestService # to verify
I also recommend configuring services to have a service SID so you can assign permissions to the service without assigning them to the service’s account.
sc.exe sidtype GeneralTestService UNRESTRICTED
Also, you probably want to create groups to allow access to each service’s registry key.
Set-Location "HKLM:\SOFTWARE\AB\GeneralTestService"
$acl = Get-Acl .
New-LocalGroup "REG_GeneralTestService"
$rule = New-Object System.Security.AccessControl.RegistryAccessRule("REG_GeneralTestService","FullControl","Allow")
$acl.AddAccessRule($rule)
Set-Acl . $acl
(Get-Acl .).Access
All of this is explained in more detail in the posted linked above.
To be continued…
Next: TBD