diff options
Diffstat (limited to 'Tests/Privesc.tests.ps1')
-rw-r--r-- | Tests/Privesc.tests.ps1 | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/Tests/Privesc.tests.ps1 b/Tests/Privesc.tests.ps1 index 095c946..999d712 100644 --- a/Tests/Privesc.tests.ps1 +++ b/Tests/Privesc.tests.ps1 @@ -74,6 +74,137 @@ Describe 'Get-ModifiableFile' { } } +Describe 'Test-ServiceDaclPermission' { + + if(-not $(Test-IsAdmin)) { + Throw "'Test-ServiceDaclPermission' Pester test needs local administrator privileges." + } + + It "Should fail finding 'sc.exe'." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + $DirectoryName = Get-RandomName + $env:SystemRoot = 'C:\\' + $DirectoryName + { Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' } | Should Throw "sc.exe not found" + + sc.exe delete $ServiceName | Should Match "SUCCESS" + $env:SystemRoot = 'C:\Windows' + } + + It "Should succeed finding 'sc.exe'." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + $DirectoryName = Get-RandomName + New-Item -Path $env:Temp -Name "$DirectoryName\System32" -ItemType Directory + New-Item -Path $env:Temp -Name "$DirectoryName\System32\sc.exe" -ItemType File + $env:SystemRoot = $env:Temp + "\$DirectoryName" + Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' | Should Be $True + + Remove-Item -Recurse -Force "$env:Temp\$DirectoryName" + $env:SystemRoot = 'C:\Windows' + sc.exe delete $ServiceName | Should Match "SUCCESS" + } + + It "Should fail querying WMI for a non-existent service." { + $ServiceName = Get-RandomName + { Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' } | Should Throw "not found on the machine" + } + + It "Should succeed querying WMI for an existenting service." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' | Should Be $True + sc.exe delete $ServiceName | Should Match "SUCCESS" + } + + It "Should fail querying WMI for an existing service due to insufficient DACL permissions." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + $UserSid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.value + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + sc.exe sdset $ServiceName "D:(A;;CCDCSWRPWPDTLOCRSDRCWDWO;;;$UserSid)" | Should Match "SUCCESS" + { Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' } | Should Throw "not found on the machine" + sc.exe delete $ServiceName | Should Match "SUCCESS" + } + + It "Should succeed querying WMI for an existing service due to sufficient DACL permissions." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + $UserSid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.value + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + sc.exe sdset $ServiceName "D:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$UserSid)" | Should Match "SUCCESS" + Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' | Should Be $True + sc.exe delete $ServiceName | Should Match "SUCCESS" + } + + It "Should fail running 'sc.exe sdshow' due to insufficient permissions." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + $UserSid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.value + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + sc.exe sdset $ServiceName "D:(A;;CCDCLCSWRPWPDTLOCRSDWDWO;;;$UserSid)" | Should Match "SUCCESS" + { Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' } | Should Throw "Could not retrieve DACL permissions" + sc.exe delete $ServiceName | Should Match "SUCCESS" + } + + It "Should succeed running 'sc.exe sdshow' due to sufficient permissions." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + $UserSid = [System.Security.Principal.WindowsIdentity]::GetCurrent().User.value + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + sc.exe sdset $ServiceName "D:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$UserSid)" | Should Match "SUCCESS" + Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'DC' | Should Be $True + sc.exe delete $ServiceName | Should Match "SUCCESS" + } + + it "Should fail finding the service DACL value of 'WP' for the current user." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + sc.exe sdset $ServiceName "D:(A;;CCDCLCSWRPDTLOCRSDRCWDWO;;;S-1-5-4)" | Should Match "SUCCESS" + Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'WP' | Should Be $False + sc.exe delete $ServiceName | Should Match "SUCCESS" + } + + it "Should succeed finding the service DACL value of 'WP' for the current user." { + $ServiceName = Get-RandomName + $ServicePath = "C:\Program Files\service.exe" + + sc.exe create $ServiceName binPath= $ServicePath | Should Match "SUCCESS" + Start-Sleep -Seconds 1 + + sc.exe sdset $ServiceName "D:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;S-1-5-4)" | Should Match "SUCCESS" + Test-ServiceDaclPermission -ServiceName $ServiceName -Dacl 'WP' | Should Be $True + sc.exe delete $ServiceName | Should Match "SUCCESS" + } +} ######################################################## # @@ -568,3 +699,133 @@ Describe 'Invoke-AllChecks' { $Null = Remove-Item -Path $HtmlReportFile -Force -ErrorAction SilentlyContinue } } + +Describe 'Get-SiteListPassword' { + BeforeEach { + $Xml = '<?xml version="1.0" encoding="UTF-8"?><ns:SiteLists xmlns:ns="naSiteList" Type="Client"><SiteList Default="1" Name="SomeGUID"><HttpSite Type="fallback" Name="McAfeeHttp" Order="26" Enabled="1" Local="0" Server="update.nai.com:80"><RelativePath>Products/CommonUpdater</RelativePath><UseAuth>0</UseAuth><UserName></UserName><Password Encrypted="1">jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==</Password></HttpSite><UNCSite Type="repository" Name="Paris" Order="13" Server="paris001" Enabled="1" Local="0"><ShareName>Repository$</ShareName><RelativePath></RelativePath><UseLoggedonUserAccount>0</UseLoggedonUserAccount><DomainName>companydomain</DomainName><UserName>McAfeeService</UserName><Password Encrypted="0">Password123!</Password></UNCSite><UNCSite Type="repository" Name="Tokyo" Order="18" Server="tokyo000" Enabled="1" Local="0"><ShareName>Repository$</ShareName><RelativePath></RelativePath><UseLoggedonUserAccount>0</UseLoggedonUserAccount><DomainName>companydomain</DomainName><UserName>McAfeeService</UserName><Password Encrypted="1">jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==</Password></UNCSite></SiteList></ns:SiteLists>' + $Xml | Out-File -FilePath "${Home}\SiteList.xml" -Force + } + AfterEach { + Remove-Item -Force "${Home}\SiteList.xml" + } + + It 'Should correctly parse a SiteList.xml found in a searched path.' { + + $Credentials = Get-SiteListPassword + + $Credentials | Where-Object {$_.Name -eq 'McAfeeHttp'} | ForEach-Object { + # HTTP site + $_.Enabled | Should Be '1' + $_.Server | Should Be 'update.nai.com:80' + $_.Path | Should Be 'Products/CommonUpdater' + $_.EncPassword | Should Be 'jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==' + $_.DecPassword | Should Be 'MyStrongPassword!' + $_.UserName | Should BeNullOrEmpty + $_.DomainName | Should BeNullOrEmpty + } + + + $Credentials | Where-Object {$_.Name -eq 'Paris'} | ForEach-Object { + # UNC site with unencrypted password + $_.Enabled | Should Be '1' + $_.Server | Should Be 'paris001' + $_.Path | Should Be 'Repository$' + $_.EncPassword | Should Be 'Password123!' + $_.DecPassword | Should Be 'Password123!' + $_.UserName | Should Be 'McAfeeService' + $_.DomainName | Should Be 'companydomain' + } + + $Credentials | Where-Object {$_.Name -eq 'Tokyo'} | ForEach-Object { + # UNC site with encrypted password + $_.Enabled | Should Be '1' + $_.Server | Should Be 'tokyo000' + $_.Path | Should Be 'Repository$' + $_.EncPassword | Should Be 'jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==' + $_.DecPassword | Should Be 'MyStrongPassword!' + $_.UserName | Should Be 'McAfeeService' + $_.DomainName | Should Be 'companydomain' + } + } + + It 'Should correctly parse a SiteList.xml on a searched path.' { + + $Credentials = Get-SiteListPassword -SiteListFilePath "${Home}\SiteList.xml" + + $Credentials | Where-Object {$_.Name -eq 'McAfeeHttp'} | ForEach-Object { + # HTTP site + $_.Enabled | Should Be '1' + $_.Server | Should Be 'update.nai.com:80' + $_.Path | Should Be 'Products/CommonUpdater' + $_.EncPassword | Should Be 'jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==' + $_.DecPassword | Should Be 'MyStrongPassword!' + $_.UserName | Should BeNullOrEmpty + $_.DomainName | Should BeNullOrEmpty + } + + + $Credentials | Where-Object {$_.Name -eq 'Paris'} | ForEach-Object { + # UNC site with unencrypted password + $_.Enabled | Should Be '1' + $_.Server | Should Be 'paris001' + $_.Path | Should Be 'Repository$' + $_.EncPassword | Should Be 'Password123!' + $_.DecPassword | Should Be 'Password123!' + $_.UserName | Should Be 'McAfeeService' + $_.DomainName | Should Be 'companydomain' + } + + $Credentials | Where-Object {$_.Name -eq 'Tokyo'} | ForEach-Object { + # UNC site with encrypted password + $_.Enabled | Should Be '1' + $_.Server | Should Be 'tokyo000' + $_.Path | Should Be 'Repository$' + $_.EncPassword | Should Be 'jWbTyS7BL1Hj7PkO5Di/QhhYmcGj5cOoZ2OkDTrFXsR/abAFPM9B3Q==' + $_.DecPassword | Should Be 'MyStrongPassword!' + $_.UserName | Should Be 'McAfeeService' + $_.DomainName | Should Be 'companydomain' + } + } +} + + +Describe 'Get-System' { + + if(-not $(Test-IsAdmin)) { + Throw "'Get-System' Pester test needs local administrator privileges." + } + + AfterEach { + Get-System -RevToSelf + } + + It 'Should not throw with default parameters and should elevate to SYSTEM.' { + { Get-System } | Should Not Throw + "$([Environment]::UserName)" | Should Be 'SYSTEM' + } + + It 'Named pipe impersonation should accept an alternate service and pipe name.' { + { Get-System -Technique NamedPipe -ServiceName 'testing123' -PipeName 'testpipe' } | Should Not Throw + "$([Environment]::UserName)" | Should Be 'SYSTEM' + } + + It 'Should elevate to SYSTEM using token impersonation.' { + { Get-System -Technique Token } | Should Not Throw + "$([Environment]::UserName)" | Should Be 'SYSTEM' + } + + It '-WhoAmI should display the current user.' { + { Get-System -Technique Token } | Should Not Throw + { Get-System -WhoAmI } | Should Match 'SYSTEM' + } + + It 'RevToSelf should revert privileges.' { + { Get-System -Technique Token } | Should Not Throw + { Get-System -RevToSelf } | Should Not Throw + "$([Environment]::UserName)" | Should Not Match 'SYSTEM' + } + + It 'Token impersonation should throw with incompatible parameters.' { + { Get-System -Technique Token -WhoAmI } | Should Throw + } +} |