#Requires -RunAsAdministrator [CmdletBinding()] param( [Parameter(Mandatory = $true)] [switch]$AcknowledgeDisposableVm ) $ErrorActionPreference = "Stop" if (-not $IsWindows -and $PSVersionTable.PSEdition -ne "Desktop") { throw "This validation must run on native Windows." } if (-not $AcknowledgeDisposableVm) { throw "Pass -AcknowledgeDisposableVm on an isolated disposable Windows VM." } $root = Split-Path $PSScriptRoot -Parent $transitionScript = Join-Path $root "Upgrade-MinerOpsAgentCredential.ps1" $enrollmentScript = Join-Path $root "Enroll-MinerOpsAgent.ps1" $installerScript = Join-Path $root "install.ps1" $harnessSupportScript = Join-Path $PSScriptRoot ` "MinerOpsNativeHarnessSupport.ps1" $standardUserProbeScript = Join-Path $PSScriptRoot ` "Invoke-MinerOpsStandardUserProbe.ps1" . $harnessSupportScript $originalGetItemState = Get-MinerOpsNativeGetItemState . $transitionScript function Import-NativeFunctionDefinition { param( [Parameter(Mandatory = $true)][string]$ScriptPath, [Parameter(Mandatory = $true)][string]$Name ) $tokens = $null $parseErrors = $null $ast = [Management.Automation.Language.Parser]::ParseFile( $ScriptPath, [ref]$tokens, [ref]$parseErrors ) if ($parseErrors.Count -gt 0) { throw "$ScriptPath parser errors: $($parseErrors.Message -join '; ')" } $definitions = @($ast.FindAll({ param($node) $node -is [Management.Automation.Language.FunctionDefinitionAst] -and $node.Name -ceq $Name }, $true)) if ($definitions.Count -ne 1) { throw "Expected exactly one $Name definition in $ScriptPath." } Set-Item -Path ("Function:\script:{0}" -f $Name) ` -Value $definitions[0].Body.GetScriptBlock() } foreach ($functionImport in @( @{ Path = $enrollmentScript Name = "Assert-MinerOpsEnrollmentNoReparsePath" }, @{ Path = $enrollmentScript Name = "Assert-MinerOpsEnrollmentTrustedAncestors" }, @{ Path = $installerScript Name = "Assert-MinerOpsInstallerNoReparsePath" }, @{ Path = $installerScript Name = "Assert-MinerOpsInstallerTrustedAncestors" }, @{ Path = $enrollmentScript Name = "Get-MinerOpsEnrollmentDirectorySids" }, @{ Path = $enrollmentScript Name = "New-MinerOpsEnrollmentCredentialAcl" }, @{ Path = $enrollmentScript Name = "New-MinerOpsEnrollmentProtectedFileCreateNewStream" }, @{ Path = $enrollmentScript Name = "Get-MinerOpsEnrollmentStreamAcl" }, @{ Path = $enrollmentScript Name = "Test-MinerOpsEnrollmentCredentialAcl" }, @{ Path = $installerScript Name = "Get-MinerOpsInstallerDirectorySids" }, @{ Path = $installerScript Name = "New-MinerOpsInstallerProtectedFileAcl" }, @{ Path = $installerScript Name = "New-MinerOpsInstallerProtectedFileCreateNewStream" }, @{ Path = $installerScript Name = "Get-MinerOpsInstallerStreamAcl" }, @{ Path = $installerScript Name = "Test-MinerOpsInstallerProtectedFileAcl" } )) { Import-NativeFunctionDefinition ` -ScriptPath ([string]$functionImport.Path) ` -Name ([string]$functionImport.Name) } $validationId = [guid]::NewGuid().ToString("N").Substring(0, 10) $workRoot = Join-Path $env:ProgramData "MinerOpsCredentialValidation-$validationId" $taskName = "MinerOpsCredentialValidation-$validationId" $userName = "mopsval$($validationId.Substring(0, 8))" $publicResult = Join-Path $env:PUBLIC "minerops-acl-result-$validationId.txt" $readerPath = Join-Path $env:PUBLIC "minerops-acl-reader-$validationId.ps1" $readerSupportPath = Join-Path $env:PUBLIC ` "minerops-native-harness-support-$validationId.ps1" $testUser = $null $taskCreated = $false $passed = 0 $originalPowerShellLocation = (Get-Location).Path $originalProcessCurrentDirectory = [Environment]::CurrentDirectory function Assert-Native { param( [Parameter(Mandatory = $true)][bool]$Condition, [Parameter(Mandatory = $true)][string]$Message ) if (-not $Condition) { throw $Message } } function Invoke-NativeTest { param( [Parameter(Mandatory = $true)][string]$Name, [Parameter(Mandatory = $true)][scriptblock]$Action ) & $Action $script:passed++ Write-Host "PASS: $Name" } function Invoke-NativeGetItemTrace { param([Parameter(Mandatory = $true)][scriptblock]$Action) return @(Invoke-MinerOpsNativeGetItemTrace -Action $Action) } function Assert-AllNativeRootValidators { param([Parameter(Mandatory = $true)][string]$Path) [void](Assert-MinerOpsNoReparseDirectoryPath -Path $Path) [void](Assert-MinerOpsTrustedAncestorNamespace -Path $Path) [void](Assert-MinerOpsEnrollmentNoReparsePath -Path $Path) [void](Assert-MinerOpsEnrollmentTrustedAncestors -Path $Path) [void](Assert-MinerOpsInstallerNoReparsePath -Path $Path) [void](Assert-MinerOpsInstallerTrustedAncestors -Path $Path) } function Invoke-StandardUserOperation { param( [Parameter(Mandatory = $true)] [ValidateSet( "read", "create", "modify", "delete", "rename", "prepare_swap", "swap" )] [string]$Operation, [Parameter(Mandatory = $true)][string]$Path, [string]$Destination = "", [ValidateSet("None", "Path")][string]$BackupMode = "None", [string]$BackupPath = "" ) Remove-Item -LiteralPath $publicResult -Force -ErrorAction SilentlyContinue $arguments = @( "-NoLogo", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", ('"{0}"' -f $readerPath), "-Operation", $Operation, "-InputPath", ('"{0}"' -f $Path), "-DestinationPath", ('"{0}"' -f $Destination), "-BackupMode", $BackupMode, "-BackupPath", ('"{0}"' -f $BackupPath), "-ResultPath", ('"{0}"' -f $publicResult), "-SupportPath", ('"{0}"' -f $readerSupportPath) ) -join " " $process = Start-Process ` -FilePath "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" ` -Credential $testUser ` -ArgumentList $arguments ` -LoadUserProfile ` -Wait ` -PassThru Assert-Native (Test-Path -LiteralPath $publicResult -PathType Leaf) ` "Standard-user $Operation helper did not write a result." try { $result = Get-Content -LiteralPath $publicResult -Raw | ConvertFrom-Json } catch { throw "Standard-user $Operation helper wrote an invalid result." } Assert-Native ([string]$result.operation -ceq $Operation) ` "Standard-user helper recorded the wrong operation." $expectedExit = Get-MinerOpsNativeStatusExitCode ` -Status ([string]$result.status) Assert-Native ($process.ExitCode -eq $expectedExit) ` "Standard-user $Operation helper exit/result mismatch." return $result } function Assert-StandardUserDenied { param( [Parameter(Mandatory = $true)] [ValidateSet("read", "create", "modify", "delete", "rename")] [string]$Operation, [Parameter(Mandatory = $true)][string]$Path, [string]$Destination = "" ) $result = Invoke-StandardUserOperation ` -Operation $Operation -Path $Path -Destination $Destination $detail = "outer=$($result.outer_exception_type), " + "outer_hresult=$($result.outer_hresult), " + "leaf=$($result.leaf_exception_type), " + "leaf_hresult=$($result.leaf_hresult), " + "native=$($result.native_error), " + "chain=$(@($result.exception_chain_types) -join ' -> ')" Assert-Native ([string]$result.status -ceq "security_denied") ` "Standard-user $Operation was not denied by security ($detail)." } function Get-NativeStreamSha256 { param([Parameter(Mandatory = $true)]$Stream) $originalPosition = $Stream.Position $sha256 = [Security.Cryptography.SHA256]::Create() try { $Stream.Position = 0 return [BitConverter]::ToString( $sha256.ComputeHash($Stream) ).Replace("-", "") } finally { $Stream.Position = $originalPosition $sha256.Dispose() } } function Get-NativeUnprotectedFileEvidence { param([Parameter(Mandatory = $true)][string]$Path) $stream = [IO.File]::Open( $Path, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite -bor [IO.FileShare]::Delete ) try { $identity = Get-MinerOpsNativeFileIdentity -Stream $stream $acl = Get-MinerOpsStreamAcl -Stream $stream return [pscustomobject]@{ Identity = [string]$identity.Identity VolumeSerialNumber = [uint32]$identity.VolumeSerialNumber FileIndex = [uint64]$identity.FileIndex NumberOfLinks = [uint32]$identity.NumberOfLinks OwnerSid = [string]$acl.GetOwner( [Security.Principal.SecurityIdentifier] ).Value AclSddl = [string]$acl.Sddl ContentHash = Get-NativeStreamSha256 -Stream $stream } } finally { $stream.Dispose() } } function Get-NativeProtectedFileEvidence { param( [Parameter(Mandatory = $true)][string]$Path, [Parameter(Mandatory = $true)][string]$ExpectedParent ) $content = Read-MinerOpsProtectedCredentialText ` -Path $Path -ExpectedParent $ExpectedParent $stream = Open-MinerOpsProtectedCredentialFile ` -Path $Path -ExpectedParent $ExpectedParent try { $identity = Get-MinerOpsNativeFileIdentity -Stream $stream $acl = Get-MinerOpsStreamAcl -Stream $stream $ownerSid = [string]$acl.GetOwner( [Security.Principal.SecurityIdentifier] ).Value return [pscustomobject]@{ Identity = [string]$identity.Identity VolumeSerialNumber = [uint32]$identity.VolumeSerialNumber FileIndex = [uint64]$identity.FileIndex NumberOfLinks = [uint32]$identity.NumberOfLinks AclTrusted = [bool](Test-MinerOpsCredentialAcl -Acl $acl) AclSddl = [string]$acl.Sddl OwnerSid = $ownerSid OwnerTrusted = $ownerSid -in @("S-1-5-18", "S-1-5-32-544") ContentHash = Get-NativeStreamSha256 -Stream $stream } } finally { $stream.Dispose() } } try { (New-Object IO.DirectoryInfo($workRoot)).Create( (New-MinerOpsAgentDirectoryAcl) ) [void](Assert-MinerOpsCredentialDirectory -Path $workRoot) $driveRootTarget = Join-Path $workRoot "drive-root-target" (New-Object IO.DirectoryInfo($driveRootTarget)).Create( (New-MinerOpsAgentDirectoryAcl) ) [void](Assert-MinerOpsCredentialDirectory -Path $driveRootTarget) $driveRelativeTrap = Join-Path $workRoot "drive-relative-trap" (New-Object IO.DirectoryInfo($driveRelativeTrap)).Create( (New-MinerOpsAgentDirectoryAcl) ) $trapAcl = Get-Acl -LiteralPath $driveRelativeTrap $authenticatedUsers = New-Object ` System.Security.Principal.SecurityIdentifier("S-1-5-11") $trapAcl.AddAccessRule((New-Object ` System.Security.AccessControl.FileSystemAccessRule( $authenticatedUsers, [System.Security.AccessControl.FileSystemRights]::Modify, [System.Security.AccessControl.InheritanceFlags]::None, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow ))) Set-Acl -LiteralPath $driveRelativeTrap -AclObject $trapAcl Invoke-NativeTest "all security enumerators preserve C:\ as the first component" { $expectedRoot = [IO.Path]::GetPathRoot( [IO.Path]::GetFullPath($driveRootTarget) ) Assert-Native ($expectedRoot -ceq "C:\") ` "Disposable validation path was not rooted at C:\." $driveRelativeRoot = $expectedRoot.TrimEnd("\") Assert-Native ($driveRelativeRoot -ceq "C:") ` "Drive-relative control value was not C:." $validators = @( @{ Name = "credential reparse"; Action = { Assert-MinerOpsNoReparseDirectoryPath -Path $driveRootTarget } }, @{ Name = "credential ancestors"; Action = { Assert-MinerOpsTrustedAncestorNamespace -Path $driveRootTarget } }, @{ Name = "enrollment reparse"; Action = { Assert-MinerOpsEnrollmentNoReparsePath -Path $driveRootTarget } }, @{ Name = "enrollment ancestors"; Action = { Assert-MinerOpsEnrollmentTrustedAncestors -Path $driveRootTarget } }, @{ Name = "installer reparse"; Action = { Assert-MinerOpsInstallerNoReparsePath -Path $driveRootTarget } }, @{ Name = "installer ancestors"; Action = { Assert-MinerOpsInstallerTrustedAncestors -Path $driveRootTarget } } ) foreach ($validator in $validators) { $action = [scriptblock]$validator.Action $observed = @(Invoke-NativeGetItemTrace -Action $action) Assert-Native ($observed.Count -gt 0) ` "$($validator.Name) did not enumerate filesystem components." Assert-Native ($observed[0] -ceq $expectedRoot) ` "$($validator.Name) began at '$($observed[0])', not '$expectedRoot'." Assert-Native ($observed -cnotcontains $driveRelativeRoot) ` "$($validator.Name) generated drive-relative root '$driveRelativeRoot'." foreach ($component in $observed) { Assert-Native ( [IO.Path]::IsPathRooted($component) -and [IO.Path]::GetFullPath($component).StartsWith( $expectedRoot, [StringComparison]::OrdinalIgnoreCase ) ) "$($validator.Name) generated non-root-qualified component '$component'." } } $directRootChild = Join-Path $expectedRoot ( "MinerOpsDriveRootValidation-$validationId" ) $rootEdgeValidators = @( @{ Name = "credential reparse root"; Action = { Assert-MinerOpsNoReparseDirectoryPath -Path $expectedRoot } }, @{ Name = "credential direct-root ancestor"; Action = { Assert-MinerOpsTrustedAncestorNamespace -Path $directRootChild } }, @{ Name = "enrollment reparse root"; Action = { Assert-MinerOpsEnrollmentNoReparsePath -Path $expectedRoot } }, @{ Name = "enrollment direct-root ancestor"; Action = { Assert-MinerOpsEnrollmentTrustedAncestors -Path $directRootChild } }, @{ Name = "installer reparse root"; Action = { Assert-MinerOpsInstallerNoReparsePath -Path $expectedRoot } }, @{ Name = "installer direct-root ancestor"; Action = { Assert-MinerOpsInstallerTrustedAncestors -Path $directRootChild } } ) foreach ($validator in $rootEdgeValidators) { $action = [scriptblock]$validator.Action $observed = @(Invoke-NativeGetItemTrace -Action $action) Assert-Native ($observed.Count -eq 1) ` "$($validator.Name) did not enumerate exactly one root component." Assert-Native ($observed[0] -ceq $expectedRoot) ` "$($validator.Name) enumerated '$($observed[0])', not '$expectedRoot'." Assert-Native ($observed -cnotcontains $driveRelativeRoot) ` "$($validator.Name) generated drive-relative root '$driveRelativeRoot'." } Assert-MinerOpsNativeGetItemState -Expected $originalGetItemState ` -Context "root-qualified validator traces" } Invoke-NativeTest "absolute validation ignores a hostile PowerShell location" { $trapRules = @((Get-Acl -LiteralPath $driveRelativeTrap).GetAccessRules( $true, $true, [System.Security.Principal.SecurityIdentifier] )) $trapRule = @($trapRules | Where-Object { $_.IdentityReference.Value -eq "S-1-5-11" -and ($_.FileSystemRights -band [System.Security.AccessControl.FileSystemRights]::Delete) -ne 0 }) Assert-Native ($trapRule.Count -gt 0) ` "Drive-relative trap does not grant Authenticated Users Delete rights." $before = (Get-Location).Path try { Set-Location -LiteralPath $driveRelativeTrap Assert-AllNativeRootValidators -Path $driveRootTarget } finally { Set-Location -LiteralPath $before } } Invoke-NativeTest "absolute validation ignores process current directory" { $beforeLocation = (Get-Location).Path $beforeProcessDirectory = [Environment]::CurrentDirectory try { Set-Location -LiteralPath "C:\" [Environment]::CurrentDirectory = $driveRelativeTrap Assert-AllNativeRootValidators -Path $driveRootTarget } finally { [Environment]::CurrentDirectory = $beforeProcessDirectory Set-Location -LiteralPath $beforeLocation } } Invoke-NativeTest "untrusted ancestor namespace still fails closed" { $untrustedAncestor = Join-Path $workRoot "untrusted-ancestor" (New-Object IO.DirectoryInfo($untrustedAncestor)).Create( (New-MinerOpsAgentDirectoryAcl) ) $ancestorAcl = Get-Acl -LiteralPath $untrustedAncestor $ancestorAcl.AddAccessRule((New-Object ` System.Security.AccessControl.FileSystemAccessRule( $authenticatedUsers, [System.Security.AccessControl.FileSystemRights]::Modify, [System.Security.AccessControl.InheritanceFlags]::None, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow ))) Set-Acl -LiteralPath $untrustedAncestor -AclObject $ancestorAcl $untrustedChild = Join-Path $untrustedAncestor "child" (New-Object IO.DirectoryInfo($untrustedChild)).Create( (New-MinerOpsAgentDirectoryAcl) ) foreach ($validator in @( { Assert-MinerOpsTrustedAncestorNamespace -Path $untrustedChild }, { Assert-MinerOpsEnrollmentTrustedAncestors -Path $untrustedChild }, { Assert-MinerOpsInstallerTrustedAncestors -Path $untrustedChild } )) { try { & $validator throw "Untrusted ancestor was accepted." } catch { Assert-Native ( $_.Exception.Message -match "untrusted namespace replacement" ) "Untrusted ancestor produced an unexpected error." } } } $passwordPlain = "M0ps!" + [guid]::NewGuid().ToString("N") + "z9" $password = ConvertTo-SecureString $passwordPlain -AsPlainText -Force $passwordPlain = $null New-LocalUser ` -Name $userName ` -Password $password ` -PasswordNeverExpires ` -UserMayNotChangePassword | Out-Null $usersGroup = Get-LocalGroup -SID "S-1-5-32-545" Add-LocalGroupMember -Group $usersGroup.Name -Member $userName $testUser = New-Object Management.Automation.PSCredential( "$env:COMPUTERNAME\$userName", $password ) Copy-Item -LiteralPath $standardUserProbeScript ` -Destination $readerPath -Force Copy-Item -LiteralPath $harnessSupportScript ` -Destination $readerSupportPath -Force Invoke-NativeTest "protected CreateNew applies and reads back ACL before content" { $path = Join-Path $workRoot "protected-before-content.json" $script:nativeAclReadbackSawEmptyFile = $false $script:nativeOriginalGetStreamAcl = (Get-Command Get-MinerOpsStreamAcl).ScriptBlock try { Set-Item Function:\Get-MinerOpsStreamAcl { param($Stream) Assert-Native ($Stream.Length -eq 0) ` "ACL read-back occurred after content was written." $script:nativeAclReadbackSawEmptyFile = $true & $script:nativeOriginalGetStreamAcl -Stream $Stream } Write-MinerOpsProtectedCredentialJson ` -Path $path ` -ExpectedParent $workRoot ` -Value @{ agent_secret = "protected-after-verification" } } finally { Set-Item Function:\Get-MinerOpsStreamAcl ` $script:nativeOriginalGetStreamAcl } Assert-Native $script:nativeAclReadbackSawEmptyFile ` "Protected creation did not read the ACL from the empty open file." $content = Read-MinerOpsProtectedCredentialText ` -Path $path -ExpectedParent $workRoot Assert-Native ($content -match "protected-after-verification") ` "Protected credential content was not durably written." } Invoke-NativeTest "enrollment and installer protected CreateNew mirrors work natively" { $implementations = @( @{ Name = "enrollment" NewAcl = { New-MinerOpsEnrollmentCredentialAcl } Create = { param($Path, $Acl) New-MinerOpsEnrollmentProtectedFileCreateNewStream ` -Path $Path -Acl $Acl } GetAcl = { param($Stream) Get-MinerOpsEnrollmentStreamAcl -Stream $Stream } TestAcl = { param($Acl) Test-MinerOpsEnrollmentCredentialAcl -Acl $Acl } }, @{ Name = "installer" NewAcl = { New-MinerOpsInstallerProtectedFileAcl } Create = { param($Path, $Acl) New-MinerOpsInstallerProtectedFileCreateNewStream ` -Path $Path -Acl $Acl } GetAcl = { param($Stream) Get-MinerOpsInstallerStreamAcl -Stream $Stream } TestAcl = { param($Acl) Test-MinerOpsInstallerProtectedFileAcl -Acl $Acl } } ) foreach ($implementation in $implementations) { $path = Join-Path $workRoot ( "{0}-protected-create.state" -f $implementation.Name ) $stream = $null $competing = $null try { $acl = & $implementation.NewAcl $stream = & $implementation.Create $path $acl Assert-Native ($stream.Length -eq 0) ` "$($implementation.Name) wrote before ACL verification." $readBack = & $implementation.GetAcl $stream Assert-Native ([bool](& $implementation.TestAcl $readBack)) ` "$($implementation.Name) ACL read-back failed." try { $competing = [IO.File]::Open( $path, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite ) throw "$($implementation.Name) protected file was not exclusive." } catch [IO.IOException] { } } finally { if ($null -ne $competing) { $competing.Dispose() } if ($null -ne $stream) { $stream.Dispose() } } } } Invoke-NativeTest "recovery and pending DACLs deny a standard user" { foreach ($leaf in @("recovery.json", "agent-config.json.pending")) { $path = Join-Path $workRoot $leaf Write-MinerOpsProtectedCredentialJson ` -Path $path ` -ExpectedParent $workRoot ` -Value ([ordered]@{ agent_id = "00000000-0000-4000-8000-000000000111" agent_secret = "disposable-validation-secret" }) Assert-StandardUserDenied -Operation read -Path $path } } Invoke-NativeTest "directory DACL denies standard-user child creation" { $untrustedChild = Join-Path $workRoot "standard-user-create.json" Assert-StandardUserDenied -Operation create -Path $untrustedChild Assert-Native (-not (Test-Path -LiteralPath $untrustedChild)) ` "Denied standard-user create left a child file." } Invoke-NativeTest "file DACL denies standard-user modify, delete, and rename" { $protectedPath = Join-Path $workRoot "delete-rename-source.json" $renamedPath = Join-Path $workRoot "delete-rename-destination.json" Write-MinerOpsProtectedCredentialJson ` -Path $protectedPath -ExpectedParent $workRoot ` -Value @{ agent_secret = "disposable-delete-test" } Assert-StandardUserDenied -Operation modify -Path $protectedPath Assert-Native ( [IO.File]::ReadAllText($protectedPath) -match "disposable-delete-test" ) "Denied standard-user modify changed the file." Assert-StandardUserDenied -Operation delete -Path $protectedPath Assert-Native (Test-Path -LiteralPath $protectedPath -PathType Leaf) ` "Denied standard-user delete removed the file." Assert-StandardUserDenied -Operation rename -Path $protectedPath ` -Destination $renamedPath Assert-Native ( (Test-Path -LiteralPath $protectedPath -PathType Leaf) -and -not (Test-Path -LiteralPath $renamedPath) ) "Denied standard-user rename changed the namespace." } Invoke-NativeTest "standard-user replacement swap is denied" { $activePath = Join-Path $workRoot "swap-active.json" $replacementPath = Join-Path $env:PUBLIC ( "minerops-swap-source-$validationId.json" ) $renamedTargetPath = Join-Path $workRoot "swap-active-renamed.json" try { Assert-Native (-not (Test-Path -LiteralPath $replacementPath)) ` "Swap source unexpectedly existed before standard-user creation." $prepareResult = Invoke-StandardUserOperation ` -Operation prepare_swap -Path $replacementPath Assert-Native ( [string]$prepareResult.status -ceq "succeeded" -and [bool]$prepareResult.source_exists -and [bool]$prepareResult.input_owned_by_caller -and [bool]$prepareResult.source_created_by_caller -and [bool]$prepareResult.source_read_verified -and [bool]$prepareResult.source_modify_verified -and [bool]$prepareResult.source_rename_verified -and [bool]$prepareResult.source_delete_access_verified -and [bool]$prepareResult.source_replace_access_verified ) "Standard user did not create and control the swap source." $sourceBefore = Get-NativeUnprotectedFileEvidence ` -Path $replacementPath Write-MinerOpsProtectedCredentialJson ` -Path $activePath -ExpectedParent $workRoot ` -Value @{ agent_secret = "protected-active" } $targetBefore = Get-NativeProtectedFileEvidence ` -Path $activePath -ExpectedParent $workRoot $sourceFullPath = [IO.Path]::GetFullPath($replacementPath) $targetFullPath = [IO.Path]::GetFullPath($activePath) $sourceDrive = [IO.DriveInfo]::new( [IO.Path]::GetPathRoot($sourceFullPath) ) $targetDrive = [IO.DriveInfo]::new( [IO.Path]::GetPathRoot($targetFullPath) ) $standardUserSid = [string]( Get-LocalUser -Name $userName -ErrorAction Stop ).SID.Value $fixture = [ordered]@{ SourceExists = Test-Path ` -LiteralPath $sourceFullPath -PathType Leaf TargetExists = Test-Path ` -LiteralPath $targetFullPath -PathType Leaf PathsDistinct = -not $sourceFullPath.Equals( $targetFullPath, [StringComparison]::OrdinalIgnoreCase ) SourceCreatedByStandardUser = [bool]$prepareResult.source_created_by_caller SourceOwnedByStandardUser = [bool]$prepareResult.input_owned_by_caller -and $sourceBefore.OwnerSid -ceq $standardUserSid SourceReadable = [bool]$prepareResult.source_read_verified SourceModifiable = [bool]$prepareResult.source_modify_verified SourceRenameable = [bool]$prepareResult.source_rename_verified SourceDeleteCapable = [bool]$prepareResult.source_delete_access_verified SourceReplaceAccessVerified = [bool]$prepareResult.source_replace_access_verified TargetAclTrusted = [bool]$targetBefore.AclTrusted TargetOwnerTrusted = [bool]$targetBefore.OwnerTrusted TargetIdentityCaptured = -not [string]::IsNullOrWhiteSpace($targetBefore.Identity) SourceIdentityCaptured = -not [string]::IsNullOrWhiteSpace($sourceBefore.Identity) FileIdentitiesDistinct = $sourceBefore.Identity -cne $targetBefore.Identity # No backup is deliberately selected. It avoids copying the # protected destination into an attacker-readable namespace. BackupArgumentValid = $true BackupPathsDistinct = $true BackupExpectedStateVerified = $true BackupConfidentialitySafe = $true SameVolume = $sourceBefore.VolumeSerialNumber -eq $targetBefore.VolumeSerialNumber NtfsVolume = $sourceDrive.DriveFormat -ceq "NTFS" -and $targetDrive.DriveFormat -ceq "NTFS" } Assert-MinerOpsNativeSwapFixtureReady -Fixture $fixture $swapResult = Invoke-StandardUserOperation ` -Operation swap -Path $replacementPath ` -Destination $activePath -BackupMode None Assert-Native ( [string]$swapResult.input_full_path -ceq $sourceFullPath -and [string]$swapResult.destination_full_path -ceq $targetFullPath -and [string]$swapResult.backup_mode -ceq "None" -and [string]::IsNullOrEmpty( [string]$swapResult.backup_full_path ) -and [bool]$swapResult.backup_argument_was_native_null -and [string]$swapResult.replace_overload -ceq "System.IO.File.Replace(String,String,String)" -and [bool]$swapResult.source_existed_before_attack -and [bool]$swapResult.destination_existed_before_attack -and $null -eq $swapResult.backup_existed_before_attack ) "Standard-user swap did not use the verified File.Replace arguments." $postconditions = [ordered]@{ TargetExists = Test-Path -LiteralPath $activePath -PathType Leaf TargetIdentityUnchanged = $false TargetContentUnchanged = $false TargetAclTrusted = $false TargetAclUnchanged = $false TargetOwnerTrusted = $false TargetOwnerUnchanged = $false TargetSingleLink = $false SourceExists = Test-Path ` -LiteralPath $replacementPath -PathType Leaf SourceIdentityUnchanged = $false SourceContentUnchanged = $false AttackerSourceNotPromoted = $false TargetDeniedStandardUserRead = $false TargetDeniedStandardUserModify = $false TargetDeniedStandardUserDelete = $false TargetDeniedStandardUserRename = $false NoAttackerReadableBackup = [bool]$swapResult.backup_argument_was_native_null -and [string]::IsNullOrEmpty( [string]$swapResult.backup_full_path ) } $readResult = Invoke-StandardUserOperation ` -Operation read -Path $activePath $postconditions.TargetDeniedStandardUserRead = [string]$readResult.status -ceq "security_denied" $modifyResult = Invoke-StandardUserOperation ` -Operation modify -Path $activePath $postconditions.TargetDeniedStandardUserModify = [string]$modifyResult.status -ceq "security_denied" $deleteResult = Invoke-StandardUserOperation ` -Operation delete -Path $activePath $postconditions.TargetDeniedStandardUserDelete = [string]$deleteResult.status -ceq "security_denied" $renameResult = Invoke-StandardUserOperation ` -Operation rename -Path $activePath ` -Destination $renamedTargetPath $postconditions.TargetDeniedStandardUserRename = [string]$renameResult.status -ceq "security_denied" $postconditions.TargetExists = Test-Path ` -LiteralPath $activePath -PathType Leaf if ([bool]$postconditions.TargetExists) { try { $targetAfter = Get-NativeProtectedFileEvidence ` -Path $activePath -ExpectedParent $workRoot $postconditions.TargetIdentityUnchanged = $targetAfter.Identity -ceq $targetBefore.Identity $postconditions.TargetContentUnchanged = $targetAfter.ContentHash -ceq $targetBefore.ContentHash $postconditions.TargetAclTrusted = $targetAfter.AclTrusted $postconditions.TargetAclUnchanged = $targetAfter.AclSddl -ceq $targetBefore.AclSddl $postconditions.TargetOwnerTrusted = [bool]$targetAfter.OwnerTrusted $postconditions.TargetOwnerUnchanged = $targetAfter.OwnerSid -ceq $targetBefore.OwnerSid $postconditions.TargetSingleLink = $targetAfter.NumberOfLinks -eq 1 $postconditions.AttackerSourceNotPromoted = $targetAfter.Identity -cne $sourceBefore.Identity -and $targetAfter.ContentHash -cne $sourceBefore.ContentHash } catch { # The consolidated assertion below reports each failed # target-security postcondition without exposing content. } } $postconditions.SourceExists = Test-Path ` -LiteralPath $replacementPath -PathType Leaf if ([bool]$postconditions.SourceExists) { try { $sourceAfter = Get-NativeUnprotectedFileEvidence ` -Path $replacementPath $postconditions.SourceIdentityUnchanged = $sourceAfter.Identity -ceq $sourceBefore.Identity $postconditions.SourceContentUnchanged = $sourceAfter.ContentHash -ceq $sourceBefore.ContentHash } catch { } } Assert-MinerOpsNativeSwapSecurityOutcome ` -Result $swapResult -Postconditions $postconditions } finally { Remove-Item -LiteralPath $replacementPath -Force ` -ErrorAction SilentlyContinue } } Invoke-NativeTest "ACL setup and verification failures write no secret" { $setupFailurePath = Join-Path $workRoot "acl-setup-failure.json" $originalNewAcl = (Get-Command New-MinerOpsCredentialAcl).ScriptBlock try { Set-Item Function:\New-MinerOpsCredentialAcl { throw "injected native ACL setup failure" } try { Write-MinerOpsProtectedCredentialJson ` -Path $setupFailurePath ` -ExpectedParent $workRoot ` -Value @{ agent_secret = "must-not-appear" } throw "ACL setup injection unexpectedly succeeded." } catch { Assert-Native ($_.Exception.Message -match "ACL setup failure") ` "Unexpected ACL setup injection error." } } finally { Set-Item Function:\New-MinerOpsCredentialAcl $originalNewAcl } Assert-Native (-not (Test-Path -LiteralPath $setupFailurePath)) ` "ACL setup failure left a credential file." $verificationFailurePath = Join-Path $workRoot ( "acl-verification-failure.json" ) $originalGetAcl = (Get-Command Get-MinerOpsStreamAcl).ScriptBlock try { Set-Item Function:\Get-MinerOpsStreamAcl { param($Stream) throw "injected native ACL verification failure" } try { Write-MinerOpsProtectedCredentialJson ` -Path $verificationFailurePath ` -ExpectedParent $workRoot ` -Value @{ agent_secret = "must-not-appear" } throw "ACL verification injection unexpectedly succeeded." } catch { Assert-Native ( $_.Exception.Message -match "ACL verification failure" ) "Unexpected ACL verification injection error." } } finally { Set-Item Function:\Get-MinerOpsStreamAcl $originalGetAcl } Assert-Native (-not (Test-Path -LiteralPath $verificationFailurePath)) ` "ACL verification failure left a credential file." } Invoke-NativeTest "pre-created credential pathname is never truncated" { $path = Join-Path $workRoot "pre-created-pending.json" $sentinel = '{"attacker_controlled":"preserve-exactly"}' [IO.File]::WriteAllText($path, $sentinel) try { Write-MinerOpsProtectedCredentialJson ` -Path $path -ExpectedParent $workRoot ` -Value @{ agent_secret = "must-not-be-written" } throw "Pre-created pathname was adopted." } catch { Assert-Native ($_.Exception.Message -match "already exists|exist") ` "Pre-created pathname produced an unexpected error." } Assert-Native ([IO.File]::ReadAllText($path) -ceq $sentinel) ` "CreateNew failure modified the pre-created pathname." } Invoke-NativeTest "attacker-created hard-linked credential target is rejected" { $sourcePath = Join-Path $workRoot "hard-link-source.json" $targetPath = Join-Path $workRoot "hard-link-pending.json" Write-MinerOpsProtectedCredentialJson ` -Path $sourcePath -ExpectedParent $workRoot ` -Value @{ harmless = "preexisting" } [void](New-Item -ItemType HardLink -Path $targetPath ` -Target $sourcePath) try { Write-MinerOpsProtectedCredentialJson ` -Path $targetPath -ExpectedParent $workRoot ` -Value @{ agent_secret = "must-not-be-written" } throw "Hard-linked CreateNew target was adopted." } catch { Assert-Native ( $_.Exception.Message -match "already exists|exist" ) "Hard-linked target produced an unexpected error." } Assert-Native ( (Test-Path -LiteralPath $sourcePath -PathType Leaf) -and (Test-Path -LiteralPath $targetPath -PathType Leaf) ) "Failed CreateNew deleted hard-link evidence." Assert-Native ( -not ([IO.File]::ReadAllText($sourcePath).Contains( "must-not-be-written" )) ) "Credential content was written through a hard-link alias." } Invoke-NativeTest "insecure existing artifact is repaired then rejected" { $insecurePath = Join-Path $workRoot "insecure-recovery.json" [IO.File]::WriteAllText($insecurePath, '{"agent_secret":"untrusted"}') $script:nativeRepairPath = $insecurePath $script:nativeRepairWasExclusive = $false $script:nativeOriginalSetStreamAcl = (Get-Command Set-MinerOpsStreamAcl).ScriptBlock try { Set-Item Function:\Set-MinerOpsStreamAcl { param($Stream, $Acl) $competing = $null try { $competing = [IO.File]::Open( $script:nativeRepairPath, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite ) throw "Credential repair handle was not exclusive." } catch [IO.IOException] { $script:nativeRepairWasExclusive = $true } finally { if ($null -ne $competing) { $competing.Dispose() } } & $script:nativeOriginalSetStreamAcl ` -Stream $Stream -Acl $Acl } try { [void](Read-MinerOpsProtectedCredentialText ` -Path $insecurePath -ExpectedParent $workRoot) throw "Insecure artifact was trusted." } catch { Assert-Native ($_.Exception.Message -match "will not be trusted") ` "Insecure artifact did not fail closed." } } finally { Set-Item Function:\Set-MinerOpsStreamAcl ` $script:nativeOriginalSetStreamAcl } Assert-Native $script:nativeRepairWasExclusive ` "Existing-artifact repair was not exclusive." Assert-StandardUserDenied -Operation read -Path $insecurePath } Invoke-NativeTest "repair fails closed when security rights cannot be acquired" { $path = Join-Path $workRoot "repair-rights-denied.json" [IO.File]::WriteAllText($path, '{"agent_secret":"untrusted"}') $beforeSddl = (Get-Acl -LiteralPath $path).Sddl $originalOpen = (Get-Command Open-MinerOpsFileStreamWithRights).ScriptBlock try { Set-Item Function:\Open-MinerOpsFileStreamWithRights { param($Path, $Rights) throw [System.UnauthorizedAccessException]::new( "injected security-right acquisition failure" ) } try { [void](Read-MinerOpsProtectedCredentialText ` -Path $path -ExpectedParent $workRoot) throw "Security-right acquisition failure was ignored." } catch { Assert-Native ( $_.Exception.Message -match "right acquisition failure" ) "Security-right acquisition failure did not propagate." } } finally { Set-Item Function:\Open-MinerOpsFileStreamWithRights $originalOpen } Assert-Native ((Get-Acl -LiteralPath $path).Sddl -ceq $beforeSddl) ` "Denied repair used a fallback ACL mutation." Assert-Native ( [IO.File]::ReadAllText($path) -ceq '{"agent_secret":"untrusted"}' ) "Denied repair changed credential content." } Invoke-NativeTest "durable blocker prevents ACL-repair laundering" { $recoveryPath = Join-Path $workRoot "agent-credential-transition.recovery.json" [IO.File]::WriteAllText( $recoveryPath, '{"agent_secret":"must-never-be-authoritative"}' ) $blocker = Ensure-MinerOpsQuarantineBlocker ` -TargetRoot $workRoot -Reason "native-acl-repair-test" $opened = Open-MinerOpsProtectedCredentialFile ` -Path $recoveryPath -ExpectedParent $workRoot -AllowAclRepair $opened.Dispose() # This is the exact interrupted window: ACL repaired, authority name # still present, and the process could terminate before quarantine. Assert-Native (Test-Path -LiteralPath $recoveryPath -PathType Leaf) ` "ACL-repair window was not established." Assert-Native (Test-Path -LiteralPath $blocker -PathType Leaf) ` "Blocked-state marker was not durable before ACL repair." try { Assert-MinerOpsNoQuarantineBlocker -TargetRoot $workRoot throw "Durable blocker did not fail the second invocation closed." } catch { Assert-Native ($_.Exception.Message -match "evidence is quarantined") ` "Durable blocker produced an unexpected error." } [void](Move-MinerOpsArtifactToQuarantine ` -Path $recoveryPath -ExpectedParent $workRoot -Role "recovery") Assert-Native (-not (Test-Path -LiteralPath $recoveryPath)) ` "Repaired recovery remained authoritative." try { Assert-MinerOpsNoQuarantineBlocker -TargetRoot $workRoot throw "Quarantine evidence did not keep the next run blocked." } catch { Assert-Native ($_.Exception.Message -match "evidence is quarantined") ` "Quarantine evidence produced an unexpected error." } foreach ($evidence in @(Get-MinerOpsQuarantineArtifacts ` -TargetRoot $workRoot)) { Assert-StandardUserDenied -Operation read -Path $evidence.FullName } } Invoke-NativeTest "native two-rename install preserves protected result" { $activePath = Join-Path $workRoot "replace-active.json" $pendingPath = Join-Path $workRoot "replace-pending.json" $priorPath = Join-Path $workRoot "replace-prior.json" Write-MinerOpsProtectedCredentialJson ` -Path $activePath -ExpectedParent $workRoot ` -Value @{ agent_secret = "legacy-test-secret" } Write-MinerOpsProtectedCredentialJson ` -Path $pendingPath -ExpectedParent $workRoot ` -Value @{ agent_secret = "new-test-secret" } Invoke-MinerOpsRecoverableConfigInstall ` -PendingPath $pendingPath -ConfigPath $activePath ` -PriorPath $priorPath -TargetRoot $workRoot Assert-Native (-not (Test-Path -LiteralPath $pendingPath)) ` "Two-rename install did not consume pending source." Assert-Native (Test-Path -LiteralPath $priorPath -PathType Leaf) ` "Two-rename install did not retain the prior remnant." $result = Read-MinerOpsProtectedCredentialText ` -Path $activePath -ExpectedParent $workRoot Assert-Native ($result -match "new-test-secret") ` "Two-rename install did not install the pending content." Assert-StandardUserDenied -Operation read -Path $activePath } Invoke-NativeTest "active-missing pending install converges natively" { $activePath = Join-Path $workRoot "missing-active.json" $pendingPath = Join-Path $workRoot "missing-active.pending" $priorPath = Join-Path $workRoot "missing-active.prior" Write-MinerOpsProtectedCredentialJson ` -Path $pendingPath -ExpectedParent $workRoot ` -Value @{ agent_secret = "authenticated-pending" } Invoke-MinerOpsRecoverableConfigInstall ` -PendingPath $pendingPath -ConfigPath $activePath ` -PriorPath $priorPath -TargetRoot $workRoot Assert-Native (Test-Path -LiteralPath $activePath -PathType Leaf) ` "Active-missing install did not restore active." Assert-Native (-not (Test-Path -LiteralPath $priorPath)) ` "Active-missing install manufactured prior authority." } Invoke-NativeTest "directory junction is rejected by all reparse validators" { $junctionTarget = Join-Path $workRoot "junction-target" $junctionPath = Join-Path $workRoot "junction-path" [void](New-Item -ItemType Directory -Path $junctionTarget) [void](New-Item -ItemType Junction -Path $junctionPath ` -Target $junctionTarget) foreach ($validator in @( { Assert-MinerOpsNoReparseDirectoryPath -Path $junctionPath }, { Assert-MinerOpsEnrollmentNoReparsePath -Path $junctionPath }, { Assert-MinerOpsInstallerNoReparsePath -Path $junctionPath } )) { try { [void](& $validator) throw "Directory junction was accepted." } catch { Assert-Native ($_.Exception.Message -match "reparse point") ` "Directory junction produced an unexpected error." } } } Invoke-NativeTest "permissive directory is hardened with a durable repair marker" { $permissivePath = Join-Path $workRoot "permissive-directory" [void](New-Item -ItemType Directory -Path $permissivePath) $acl = Get-Acl -LiteralPath $permissivePath $users = New-Object System.Security.Principal.SecurityIdentifier( "S-1-5-32-545" ) $acl.AddAccessRule((New-Object ` System.Security.AccessControl.FileSystemAccessRule( $users, [System.Security.AccessControl.FileSystemRights]::Modify, [System.Security.AccessControl.InheritanceFlags]"ContainerInherit, ObjectInherit", [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow ))) Set-Acl -LiteralPath $permissivePath -AclObject $acl $state = Initialize-MinerOpsCredentialDirectory -Path $permissivePath Assert-Native ([bool]$state.WasRepaired) ` "Permissive directory was not identified as repaired." [void](Assert-MinerOpsCredentialDirectory -Path $permissivePath) $blockers = @(Get-MinerOpsFilesystemTrustBlockerPaths ` -Path $permissivePath) Assert-Native ($blockers.Count -gt 0) ` "External directory trust blocker was not durable." foreach ($blocker in $blockers) { $record = Read-MinerOpsFilesystemTrustBlocker ` -Path $blocker.FullName -TargetRoot $permissivePath Assert-Native ([string]$record.state -ceq "blocked") ` "Filesystem trust blocker ACL/content verification failed." } Assert-Native ([bool]$state.TrustEpochNewlyBlocked) ` "Directory repair did not force a new blocked trust epoch." } $serviceScript = Join-Path $workRoot "MinerOpsAgentService.ps1" [IO.File]::WriteAllText($serviceScript, "Start-Sleep -Seconds 600`r`n") $action = New-ScheduledTaskAction ` -Execute "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" ` -Argument ('-NoProfile -ExecutionPolicy Bypass -File "{0}"' -f ` $serviceScript) $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" ` -LogonType ServiceAccount -RunLevel Highest Register-ScheduledTask ` -TaskName $taskName ` -Action $action ` -Principal $principal | Out-Null $taskCreated = $true foreach ($originallyRunning in @($true, $false)) { $label = if ($originallyRunning) { "running" } else { "stopped" } Invoke-NativeTest "native Scheduled Task restores originally $label intent" { Set-MinerOpsScheduledTaskState ` -Name $taskName -TargetRoot $workRoot ` -ShouldRun $originallyRunning $statePath = Join-Path $workRoot "task-state-$label.json" Write-MinerOpsProtectedCredentialJson ` -Path $statePath ` -ExpectedParent $workRoot ` -Value @{ original_task_running = $originallyRunning } Stop-MinerOpsAgentTask -Name $taskName -TargetRoot $workRoot $state = Read-MinerOpsProtectedCredentialText ` -Path $statePath -ExpectedParent $workRoot | ConvertFrom-Json Set-MinerOpsScheduledTaskState ` -Name $taskName ` -TargetRoot $workRoot ` -ShouldRun ([bool]$state.original_task_running) $final = Get-MinerOpsVerifiedScheduledTask ` -Name $taskName -TargetRoot $workRoot Assert-Native ( ([string]$final.State -eq "Running") -eq $originallyRunning -and ([string]$final.State -eq "Ready") -eq (-not $originallyRunning) ) "Native Scheduled Task final state was wrong." } } Invoke-NativeTest "strict verifier rejects missing and Disabled tasks" { try { [void](Get-MinerOpsVerifiedScheduledTask ` -Name "$taskName-missing" -TargetRoot $workRoot) throw "Missing task was accepted." } catch { Assert-Native ($_.Exception.Message -match "missing") ` "Missing task produced an unexpected error." } Disable-ScheduledTask -TaskName $taskName | Out-Null try { [void](Get-MinerOpsVerifiedScheduledTask ` -Name $taskName -TargetRoot $workRoot) throw "Disabled task was accepted." } catch { Assert-Native ($_.Exception.Message -match "disabled") ` "Disabled task produced an unexpected error." } Enable-ScheduledTask -TaskName $taskName | Out-Null } Write-Host "$passed native Windows credential-transition tests passed." Write-Host "This proves root-qualified drive enumeration, current-directory independence, creation-time protected FileStreams, same-handle ACL read-back, native NTFS boundary enforcement, fail-closed ACL repair, durable blocking, hard-link refusal, two-rename primitives, junction rejection, and strict Scheduled Task state restoration." Write-Host "Run the companion validation procedure for hostile pre-repair handles, installer/enrollment hard links, full strict-task failures, and hard process-termination/rerun convergence." } finally { [Environment]::CurrentDirectory = $originalProcessCurrentDirectory Set-Location -LiteralPath $originalPowerShellLocation ` -ErrorAction SilentlyContinue if ($taskCreated) { Stop-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue Unregister-ScheduledTask ` -TaskName $taskName -Confirm:$false -ErrorAction SilentlyContinue } if (Get-LocalUser -Name $userName -ErrorAction SilentlyContinue) { Remove-LocalUser -Name $userName -ErrorAction SilentlyContinue } Remove-Item -LiteralPath $readerPath -Force -ErrorAction SilentlyContinue Remove-Item -LiteralPath $readerSupportPath -Force ` -ErrorAction SilentlyContinue Remove-Item -LiteralPath $publicResult -Force -ErrorAction SilentlyContinue Remove-Item -LiteralPath $workRoot -Recurse -Force -ErrorAction SilentlyContinue Assert-MinerOpsNativeGetItemState -Expected $originalGetItemState ` -Context "native harness final cleanup" }