mirror of https://github.com/raandree/NTFSSecurity
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
93 lines
6.2 KiB
93 lines
6.2 KiB
[CmdletBinding()]
|
|
param (
|
|
[Parameter(Mandatory)] [string] $ModulePath,
|
|
[Parameter(Mandatory)] [string] $OutFile,
|
|
[Parameter(Mandatory)] [string] $Variant,
|
|
[string] $OtherServer = ''
|
|
)
|
|
|
|
# Runs inside a machine of the operating-system matrix, in Windows PowerShell 5.1 under the token that Probe-EffectiveAccess.ps1 chose for
|
|
# the variant, and asks Get-NTFSEffectiveAccess the same question in several ways: for the account of the token, Everyone, the local
|
|
# Administrator, and the domain Administrator and Domain Users on a computer in a domain, each for the default server name, localhost, an
|
|
# empty name, the names of this computer, and the computers of -OtherServer (a comma-separated list). For every call it writes the result,
|
|
# the number of warnings, and the native error with the failing method, so that the failing call of the authorization manager shows. It
|
|
# changes nothing but a folder below $env:TEMP.
|
|
$ErrorActionPreference = 'Continue'
|
|
$ProgressPreference = 'SilentlyContinue'
|
|
$stamp = '[{0:HH:mm:ss}]'
|
|
function Write-Probe { param ([string] $Message) ($stamp -f [DateTime]::UtcNow) + ' ' + $Message | Add-Content -LiteralPath $OutFile }
|
|
|
|
$null = New-Item -ItemType Directory -Path (Split-Path -Path $OutFile -Parent) -Force
|
|
Set-Content -LiteralPath $OutFile -Value ''
|
|
try {
|
|
Import-Module -Name (Join-Path -Path $ModulePath -ChildPath 'NTFSSecurity.psd1') -Force -ErrorAction Stop
|
|
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
|
$principal = New-Object -TypeName 'Security.Principal.WindowsPrincipal' -ArgumentList $identity
|
|
$current = Get-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion'
|
|
Write-Probe ('START variant={0} user={1} sid={2} administrator={3} os={4} {5}.{6} dll={7}' -f $Variant, $identity.Name, $identity.User.Value,
|
|
$principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator), $current.ProductName, $current.CurrentBuildNumber, $current.UBR,
|
|
(Get-FileHash -Algorithm SHA256 -LiteralPath (Join-Path -Path $ModulePath -ChildPath 'NTFSSecurity.dll')).Hash.Substring(0, 12))
|
|
$groups = @(& whoami.exe /groups /fo csv | ConvertFrom-Csv)
|
|
Write-Probe ('groups={0}; deny only: {1}' -f $groups.Count, ((@($groups | Where-Object -FilterScript { $_.Attributes -match 'deny' } | ForEach-Object -Process { $_.'Group Name' })) -join ', '))
|
|
Write-Probe ('integrity: {0}' -f ((@($groups | Where-Object -FilterScript { $_.'Group Name' -like 'Mandatory Label*' } | ForEach-Object -Process { $_.'Group Name' })) -join ', '))
|
|
$privileges = @(& whoami.exe /priv /fo csv | ConvertFrom-Csv)
|
|
Write-Probe ('privileges present={0} enabled: {1}' -f $privileges.Count, ((@($privileges | Where-Object -FilterScript { $_.State -eq 'Enabled' } | ForEach-Object -Process { $_.'Privilege Name' })) -join ', '))
|
|
|
|
$folder = Join-Path -Path $env:TEMP -ChildPath ('probe-{0}' -f [guid]::NewGuid().ToString('N'))
|
|
$null = New-Item -ItemType Directory -Path $folder
|
|
$fqdn = try { [Net.Dns]::GetHostEntry($env:COMPUTERNAME).HostName } catch { $env:COMPUTERNAME }
|
|
function Resolve-Sid {
|
|
param ([string] $Name)
|
|
try { (New-Object -TypeName 'Security.Principal.NTAccount' -ArgumentList $Name).Translate([Security.Principal.SecurityIdentifier]).Value } catch { '' }
|
|
}
|
|
|
|
$computer = Get-CimInstance -ClassName Win32_ComputerSystem
|
|
Write-Probe ('computer {0} domain joined={1} domain={2}' -f $env:COMPUTERNAME, $computer.PartOfDomain, $computer.Domain)
|
|
$accounts = [ordered]@{ 'self' = ''; 'Everyone' = 'S-1-1-0'; 'local Administrator' = (Resolve-Sid -Name ('{0}\Administrator' -f $env:COMPUTERNAME)) }
|
|
if ($computer.PartOfDomain) {
|
|
$accounts['domain Administrator'] = Resolve-Sid -Name ('{0}\Administrator' -f $computer.Domain)
|
|
$accounts['Domain Users'] = Resolve-Sid -Name ('{0}\Domain Users' -f $computer.Domain)
|
|
}
|
|
|
|
$servers = [ordered]@{ 'no -ServerName' = $null; 'localhost' = 'localhost'; 'empty name' = ''; 'computer name' = $env:COMPUTERNAME; 'fqdn' = $fqdn }
|
|
foreach ($name in @($OtherServer -split ',' | Where-Object -FilterScript { $_ })) { $servers["other computer $name"] = $name }
|
|
$cases = foreach ($accountName in $accounts.Keys) {
|
|
if ($accountName -ne 'self' -and -not $accounts[$accountName]) { continue }
|
|
foreach ($serverName in $servers.Keys) {
|
|
$arguments = @{}
|
|
if ($accounts[$accountName]) { $arguments.Account = $accounts[$accountName] }
|
|
if ($null -ne $servers[$serverName]) { $arguments.ServerName = $servers[$serverName] }
|
|
@{ Name = ('{0}, {1}' -f $accountName, $serverName); Arguments = $arguments }
|
|
}
|
|
}
|
|
|
|
foreach ($case in $cases) {
|
|
$arguments = $case.Arguments
|
|
$errorList = $null
|
|
$warningList = $null
|
|
try {
|
|
$result = @(Get-NTFSEffectiveAccess -Path $folder @arguments -ErrorVariable errorList -WarningVariable warningList -ErrorAction SilentlyContinue -WarningAction SilentlyContinue)
|
|
}
|
|
catch {
|
|
$result = @()
|
|
$errorList = @($_)
|
|
}
|
|
|
|
$access = if ($result.Count -gt 0) { ('{0}' -f $result[0].AccessRights) } else { 'none' }
|
|
$warnings = @($warningList | ForEach-Object -Process { ('{0}' -f $_.Message) -replace '\s+', ' ' } | ForEach-Object -Process { if ($_.Length -gt 60) { $_.Substring(0, 60) } else { $_ } })
|
|
Write-Probe ('CASE {0}: results={1} access={2} errors={3} warnings={4}' -f $case.Name, $result.Count, $access, @($errorList).Count, $warnings.Count)
|
|
foreach ($record in @($errorList)) {
|
|
$inner = $record.Exception
|
|
while ($inner.InnerException) { $inner = $inner.InnerException }
|
|
$native = if ($inner -is [ComponentModel.Win32Exception]) { $inner.NativeErrorCode } else { '' }
|
|
$frames = (('{0}' -f $inner.StackTrace) -split "`r?`n" | Select-Object -First 1 | ForEach-Object -Process { $_.Trim() -replace '^at ', '' -replace '\(.*$', '' }) -join ' <- '
|
|
Write-Probe (' ERROR id={0} type={1} native={2} message={3} frames={4}' -f $record.FullyQualifiedErrorId, $inner.GetType().Name, $native, $inner.Message, $frames)
|
|
}
|
|
}
|
|
|
|
Remove-Item -LiteralPath $folder -Recurse -Force -ErrorAction SilentlyContinue
|
|
Write-Probe 'DONE'
|
|
}
|
|
catch {
|
|
Write-Probe ('FAILED: {0}' -f $_)
|
|
}
|
|
|