mirror of
https://github.com/NetSPI/PowerHuntShares.git
synced 2025-05-05 11:48:40 +02:00
Update Analyze-HuntSMBShares.ps1
Fixed node parsing bug.
This commit is contained in:
parent
127e62f054
commit
77a06d54c0
@ -5,7 +5,7 @@
|
|||||||
#--------------------------------------
|
#--------------------------------------
|
||||||
# Author: Scott Sutherland, 2024 NetSPI
|
# Author: Scott Sutherland, 2024 NetSPI
|
||||||
# License: 3-clause BSD
|
# License: 3-clause BSD
|
||||||
# Version: v1.91
|
# Version: v1.92
|
||||||
# References: This script includes custom code and code taken and modified from the open source projects PowerView, Invoke-Ping, and Invoke-Parrell.
|
# References: This script includes custom code and code taken and modified from the open source projects PowerView, Invoke-Ping, and Invoke-Parrell.
|
||||||
function Analyze-HuntSMBShares
|
function Analyze-HuntSMBShares
|
||||||
{
|
{
|
||||||
@ -2338,82 +2338,102 @@ function Analyze-HuntSMBShares
|
|||||||
$addedNodes = @{}
|
$addedNodes = @{}
|
||||||
$addedEdges = @{}
|
$addedEdges = @{}
|
||||||
|
|
||||||
|
# Function to perform case-sensitive check for node existence
|
||||||
|
function NodeExists {
|
||||||
|
param($nodeId)
|
||||||
|
return $addedNodes.Keys | Where-Object { $_ -ceq $nodeId } | ForEach-Object { return $true }
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to perform case-sensitive check for edge existence
|
||||||
|
function EdgeExists {
|
||||||
|
param($edgeId)
|
||||||
|
return $addedEdges.Keys | Where-Object { $_ -ceq $edgeId } | ForEach-Object { return $true }
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to escape single quotes in a string
|
||||||
|
function EscapeSingleQuotes {
|
||||||
|
param($inputString)
|
||||||
|
return $inputString -replace "'", "\'"
|
||||||
|
}
|
||||||
|
|
||||||
# Iterate through each row in the CSV
|
# Iterate through each row in the CSV
|
||||||
foreach ($row in $ExcessiveSharePrivsFinal) {
|
foreach ($row in $ExcessiveSharePrivsFinal) {
|
||||||
|
|
||||||
# Replace single backslashes with double backslashes for SharePath, ShareName, ShareOwner, and IdentityReference
|
# Replace single backslashes with double backslashes for SharePath, ShareName, ShareOwner, and IdentityReference
|
||||||
$escapedSharePath = $row.SharePath -replace '\\', '\\'
|
$escapedSharePath = EscapeSingleQuotes($row.SharePath -replace '\\', '\\')
|
||||||
$escapedShareName = $row.ShareName -replace '\\', '\\'
|
$escapedShareName = EscapeSingleQuotes($row.ShareName -replace '\\', '\\')
|
||||||
$escapedShareOwner = $row.ShareOwner -replace '\\', '\\'
|
$escapedShareOwner = EscapeSingleQuotes($row.ShareOwner -replace '\\', '\\')
|
||||||
$escapedIdentityReference = $row.IdentityReference -replace '\\', '\\'
|
$escapedIdentityReference = EscapeSingleQuotes($row.IdentityReference -replace '\\', '\\')
|
||||||
|
|
||||||
# Create and add nodes if they don't exist
|
# Create and add nodes if they don't exist
|
||||||
$ownerNode = "{ data: { id: '$escapedShareOwner', label: '$escapedShareOwner', type: 'owner', IdentitySID: '$($row.IdentitySID)' } },"
|
$ownerNode = "{ data: { id: '$escapedShareOwner', label: '$escapedShareOwner', type: 'owner', IdentitySID: '" + (EscapeSingleQuotes($row.IdentitySID)) + "' } },"
|
||||||
if (-not $addedNodes.ContainsKey($escapedShareOwner)) {
|
if (-not (NodeExists $escapedShareOwner)) {
|
||||||
$ShareGraphNodes += $ownerNode
|
$ShareGraphNodes += $ownerNode
|
||||||
$addedNodes[$escapedShareOwner] = $true
|
$addedNodes[$escapedShareOwner] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
$userNode = "{ data: { id: '$escapedIdentityReference', label: '$escapedIdentityReference', type: 'user', IdentitySID: '$($row.IdentitySID)' } },"
|
$userNode = "{ data: { id: '$escapedIdentityReference', label: '$escapedIdentityReference', type: 'user', IdentitySID: '" + (EscapeSingleQuotes($row.IdentitySID)) + "' } },"
|
||||||
if (-not $addedNodes.ContainsKey($escapedIdentityReference)) {
|
if (-not (NodeExists $escapedIdentityReference)) {
|
||||||
$ShareGraphNodes += $userNode
|
$ShareGraphNodes += $userNode
|
||||||
$addedNodes[$escapedIdentityReference] = $true
|
$addedNodes[$escapedIdentityReference] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
$computerNode = "{ data: { id: '$($row.ComputerName)', label: '$($row.ComputerName)', type: 'computer', ipaddress: '$($row.IpAddress)' } },"
|
$computerNode = "{ data: { id: '" + (EscapeSingleQuotes($row.ComputerName)) + "', label: '" + (EscapeSingleQuotes($row.ComputerName)) + "', type: 'computer', ipaddress: '" + (EscapeSingleQuotes($row.IpAddress)) + "' } },"
|
||||||
if (-not $addedNodes.ContainsKey($row.ComputerName)) {
|
if (-not (NodeExists $row.ComputerName)) {
|
||||||
$ShareGraphNodes += $computerNode
|
$ShareGraphNodes += $computerNode
|
||||||
$addedNodes[$row.ComputerName] = $true
|
$addedNodes[$row.ComputerName] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
$folderGroupNode = "{ data: { id: '$($row.FileListGroup)', label: '$($row.FileListGroup)', type: 'Folder Group' } },"
|
$folderGroupNode = "{ data: { id: '" + (EscapeSingleQuotes($row.FileListGroup)) + "', label: '" + (EscapeSingleQuotes($row.FileListGroup)) + "', type: 'Folder Group' } },"
|
||||||
if (-not $addedNodes.ContainsKey($row.FileListGroup)) {
|
if (-not (NodeExists $row.FileListGroup)) {
|
||||||
$ShareGraphNodes += $folderGroupNode
|
$ShareGraphNodes += $folderGroupNode
|
||||||
$addedNodes[$row.FileListGroup] = $true
|
$addedNodes[$row.FileListGroup] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if the ShareName node already exists
|
# Check if the ShareName node already exists
|
||||||
if (-not $addedNodes.ContainsKey($escapedShareName)) {
|
if (-not (NodeExists $escapedShareName)) {
|
||||||
$shareNameNode = "{ data: { id: '$escapedShareName', label: '$escapedShareName', type: 'sharename' } },"
|
$shareNameNode = "{ data: { id: '$escapedShareName', label: '$escapedShareName', type: 'sharename' } },"
|
||||||
$ShareGraphNodes += $shareNameNode
|
$ShareGraphNodes += $shareNameNode
|
||||||
$addedNodes[$escapedShareName] = $true
|
$addedNodes[$escapedShareName] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check if SharePath node already exists
|
# Check if SharePath node already exists
|
||||||
if (-not $addedNodes.ContainsKey($escapedSharePath)) {
|
if (-not (NodeExists $escapedSharePath)) {
|
||||||
$sharePathNode = "{ data: { id: '$escapedSharePath', label: '$escapedSharePath', type: 'sharepath', RiskLevel: '$($row.RiskLevel)', RiskScore: '$($row.RiskScore)', creationDate: '$($row.CreationDate)', lastModifiedDate: '$($row.LastModifiedDate)', fileCount: $($row.FileCount), owner: '$escapedShareOwner', IsDefault: '$($row.IsDefault)', IsEmpty: '$($row.IsEmpty)', IsStale: '$($row.IsStale)', IsHR: '$($row.HasHR)', HasWrite: '$($row.HasWrite)', HasRead: '$($row.HasRead)', HasRCE: '$($row.HasRCE)', InterestingFiles: '$($row.HasIF)', ShareName: '$escapedShareName', ShareDescription: '$($row.ShareDescription)' } },"
|
$sharePathNode = "{ data: { id: '$escapedSharePath', label: '$escapedSharePath', type: 'sharepath', RiskLevel: '" + (EscapeSingleQuotes($row.RiskLevel)) + "', RiskScore: '" + (EscapeSingleQuotes($row.RiskScore)) + "', creationDate: '" + (EscapeSingleQuotes($row.CreationDate)) + "', lastModifiedDate: '" + (EscapeSingleQuotes($row.LastModifiedDate)) + "', fileCount: $($row.FileCount), owner: '$escapedShareOwner', IsDefault: '" + (EscapeSingleQuotes($row.IsDefault)) + "', IsEmpty: '" + (EscapeSingleQuotes($row.IsEmpty)) + "', IsStale: '" + (EscapeSingleQuotes($row.IsStale)) + "', IsHR: '" + (EscapeSingleQuotes($row.HasHR)) + "', HasWrite: '" + (EscapeSingleQuotes($row.HasWrite)) + "', HasRead: '" + (EscapeSingleQuotes($row.HasRead)) + "', HasRCE: '" + (EscapeSingleQuotes($row.HasRCE)) + "', InterestingFiles: '" + (EscapeSingleQuotes($row.HasIF)) + "', ShareName: '$escapedShareName', ShareDescription: '" + (EscapeSingleQuotes($row.ShareDescription)) + "' } },"
|
||||||
$ShareGraphNodes += $sharePathNode
|
$ShareGraphNodes += $sharePathNode
|
||||||
$addedNodes[$escapedSharePath] = $true
|
$addedNodes[$escapedSharePath] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure the edge between ShareName and SharePath exists
|
# Ensure the edge between ShareName and SharePath exists
|
||||||
$shareNameEdge = "{ data: { source: '$escapedShareName', target: '$escapedSharePath', label: 'child_of' } },"
|
$shareNameEdge = "{ data: { source: '$escapedShareName', target: '$escapedSharePath', label: 'child_of' } },"
|
||||||
if (-not $addedEdges.ContainsKey("child_of_$escapedShareName_$escapedSharePath")) {
|
if (-not (EdgeExists "child_of_$escapedShareName_$escapedSharePath")) {
|
||||||
$ShareGraphEdges += $shareNameEdge
|
$ShareGraphEdges += $shareNameEdge
|
||||||
$addedEdges["child_of_$escapedShareName_$escapedSharePath"] = $true
|
$addedEdges["child_of_$escapedShareName_$escapedSharePath"] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Create and add other edges if they don't exist
|
# Create and add other edges if they don't exist
|
||||||
$ownerEdge = "{ data: { source: '$escapedShareOwner', target: '$escapedSharePath', label: 'owner_of' } },"
|
$ownerEdge = "{ data: { source: '$escapedShareOwner', target: '$escapedSharePath', label: 'owner_of' } },"
|
||||||
if (-not $addedEdges.ContainsKey("owner_of_$escapedShareOwner_$escapedSharePath")) {
|
if (-not (EdgeExists "owner_of_$escapedShareOwner_$escapedSharePath")) {
|
||||||
$ShareGraphEdges += $ownerEdge
|
$ShareGraphEdges += $ownerEdge
|
||||||
$addedEdges["owner_of_$escapedShareOwner_$escapedSharePath"] = $true
|
$addedEdges["owner_of_$escapedShareOwner_$escapedSharePath"] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
$privilegeEdge = "{ data: { source: '$escapedIdentityReference', target: '$escapedSharePath', label: 'has_privilege_on', filesystemrights: '$($row.FileSystemRights)' } },"
|
$privilegeEdge = "{ data: { source: '$escapedIdentityReference', target: '$escapedSharePath', label: 'has_privilege_on', filesystemrights: '" + (EscapeSingleQuotes($row.FileSystemRights)) + "' } },"
|
||||||
if (-not $addedEdges.ContainsKey("has_privilege_on_$escapedIdentityReference_$escapedSharePath")) {
|
if (-not (EdgeExists "has_privilege_on_$escapedIdentityReference_$escapedSharePath")) {
|
||||||
$ShareGraphEdges += $privilegeEdge
|
$ShareGraphEdges += $privilegeEdge
|
||||||
$addedEdges["has_privilege_on_$escapedIdentityReference_$escapedSharePath"] = $true
|
$addedEdges["has_privilege_on_$escapedIdentityReference_$escapedSharePath"] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
$folderGroupEdge = "{ data: { source: '$($row.FileListGroup)', target: '$escapedSharePath', label: 'hosted_on' } },"
|
$folderGroupEdge = "{ data: { source: '" + (EscapeSingleQuotes($row.FileListGroup)) + "', target: '$escapedSharePath', label: 'hosted_on' } },"
|
||||||
if (-not $addedEdges.ContainsKey("hosted_on_$($row.FileListGroup)_$escapedSharePath")) {
|
if (-not (EdgeExists "hosted_on_$($row.FileListGroup)_$escapedSharePath")) {
|
||||||
$ShareGraphEdges += $folderGroupEdge
|
$ShareGraphEdges += $folderGroupEdge
|
||||||
$addedEdges["hosted_on_$($row.FileListGroup)_$escapedSharePath"] = $true
|
$addedEdges["hosted_on_$($row.FileListGroup)_$escapedSharePath"] = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
$computerEdge = "{ data: { source: '$escapedSharePath', target: '$($row.ComputerName)', label: 'hosted_on' } },"
|
$computerEdge = "{ data: { source: '$escapedSharePath', target: '" + (EscapeSingleQuotes($row.ComputerName)) + "', label: 'hosted_on' } },"
|
||||||
if (-not $addedEdges.ContainsKey("hosted_on_$escapedSharePath_$($row.ComputerName)")) {
|
if (-not (EdgeExists "hosted_on_$escapedSharePath_$($row.ComputerName)")) {
|
||||||
$ShareGraphEdges += $computerEdge
|
$ShareGraphEdges += $computerEdge
|
||||||
$addedEdges["hosted_on_$escapedSharePath_$($row.ComputerName)"] = $true
|
$addedEdges["hosted_on_$escapedSharePath_$($row.ComputerName)"] = $true
|
||||||
}
|
}
|
||||||
@ -2423,6 +2443,7 @@ function Analyze-HuntSMBShares
|
|||||||
$ShareGraphNodesFinal = $ShareGraphNodes | select -Unique
|
$ShareGraphNodesFinal = $ShareGraphNodes | select -Unique
|
||||||
$ShareGraphEdgesFinal = $ShareGraphEdges | select -Unique
|
$ShareGraphEdgesFinal = $ShareGraphEdges | select -Unique
|
||||||
|
|
||||||
|
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
# Create Timeline Reports
|
# Create Timeline Reports
|
||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
Loading…
x
Reference in New Issue
Block a user