diff --git a/PowerHuntShares.psm1 b/PowerHuntShares.psm1
index f64f4c0..d39c603 100644
--- a/PowerHuntShares.psm1
+++ b/PowerHuntShares.psm1
@@ -1,55 +1,75 @@
-
-#Requires -Version 5.1
+#Requires -Version 5.1
#--------------------------------------
-# Function: Analyze-HuntSMBShares
+# Function: Invoke-HuntSMBShares
#--------------------------------------
# Author: Scott Sutherland, 2024 NetSPI
# License: 3-clause BSD
-# Version: v1.46
+# 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.
-function Analyze-HuntSMBShares
+function Invoke-HuntSMBShares
{
<#
.SYNOPSIS
- This function can be used to analyze data collected by Invoke-HuntSMBShares offline, analyze data, and generate the report.
- It's goal in life is to expedite development.
+ This function can be used to inventory to SMB shares on the current Active Directory domain and identify potentially high risk exposures.
+ It will automatically generate csv files and html summary report.
.PARAMETER Threads
Number of concurrent tasks to run at once.
.PARAMETER Output Directory
- File path report will be exported.
+ File path where all csv and html report will be exported.
.EXAMPLE
- PS C:\> Analyze-HuntSMBShares -TargetDirectory c:\temp\SmbShareHunt-06132024085736\ -OutputDirectory c:\temp
+ PS C:\temp\test> Invoke-HuntSMBShares -Threads 20 -OutputDirectory c:\temp\test -DomainController 10.1.1.1 -ExportFindings -Username domain\user -Password password
+ .EXAMPLE
+ C:\temp\test> runas /netonly /user:domain\user PowerShell.exe
+ PS C:\temp\test> Import-Module Invoke-HuntSMBShares.ps1
+ PS C:\temp\test> Invoke-HuntSMBShares -Threads 20 -RunSpaceTimeOut 10 -OutputDirectory c:\folder\ -DomainController 10.1.1.1 -ExportFindings -Username domain\user -Password password
+ .EXAMPLE
+ PS C:\temp\test> Invoke-HuntSMBShares -Threads 20 -ExportFindings -OutputDirectory c:\temp\test
+
---------------------------------------------------------------
- Analyze-HuntSMBShares
+ INVOKE-HUNTSMBSHARES
---------------------------------------------------------------
This function automates the following tasks:
+ o Determine current computer's domain
+ o Enumerate domain computers
+ o Check if computers respond to ping requests
+ o Filter for computers that have TCP 445 open and accessible
+ o Enumerate SMB shares
+ o Enumerate SMB share permissions
o Identify shares with potentially excessive privileges
o Identify shares that provide read or write access
o Identify shares thare are high risk
o Identify common share owners, names, & directory listings
o Generate last written & last accessed timelines
- o Generate html summary report and detailed csv files
+ o Generate html summary report and detailed csv files
+
+ Note: This can take hours to run in large environments.
---------------------------------------------------------------
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---------------------------------------------------------------
- [*][07/03/2024 11:20] IMPORT DATA
+ SHARE DISCOVERY
---------------------------------------------------------------
- [*][07/03/2024 11:20] Importing computer data...
- [*][07/03/2024 11:20] - acme.com is the target domain.
- [*][07/03/2024 11:20] - 11724 computers found.
- [*][07/03/2024 11:20] - 282 Active Directory subnets found.
- [*][07/03/2024 11:20] - 5733 computers responded to ping requests.
- [*][07/03/2024 11:20] - 5567 computers have TCP port 445 open.
- [*][07/03/2024 11:20] Importing share data...
- [*][07/03/2024 11:21] - 25949 SMB shares were found across 4886 computers.
- [*][07/03/2024 11:21] Importing acl data...
- [*][07/03/2024 11:21] - 41923 share permissions were enumerated.
- [*][07/03/2024 11:21] Importing excessive privilege data...
- [*][07/03/2024 11:21] - 4633 acls were found configured with potentially excess
- ive privileges on 1839 shares across 808 computers.
+ [*][03/01/2021 09:35] Scan Start
+ [*][03/01/2021 09:35] Output Directory: c:\temp\smbshares\SmbShareHunt-03012021093504
+ [*][03/01/2021 09:35] Successful connection to domain controller: dc1.demo.local
+ [*][03/01/2021 09:35] Performing LDAP query for computers associated with the demo.local domain
+ [*][03/01/2021 09:35] - 245 computers found
+ [*][03/01/2021 09:35] Pinging 245 computers
+ [*][03/01/2021 09:35] - 55 computers responded to ping requests.
+ [*][03/01/2021 09:35] Checking if TCP Port 445 is open on 55 computers
+ [*][03/01/2021 09:36] - 49 computers have TCP port 445 open.
+ [*][03/01/2021 09:36] Getting a list of SMB shares from 49 computers
+ [*][03/01/2021 09:36] - 217 SMB shares were found.
+ [*][03/01/2021 09:36] Getting share permissions from 217 SMB shares
+ [*][03/01/2021 09:37] - 374 share permissions were enumerated.
+ [*][03/01/2021 09:37] Getting directory listings from 33 SMB shares
+ [*][03/01/2021 09:37] - Targeting up to 3 nested directory levels
+ [*][03/01/2021 09:37] - 563 files and folders were enumerated.
+ [*][03/01/2021 09:37] Identifying potentially excessive share permissions
+ [*][03/01/2021 09:37] - 33 potentially excessive privileges were found across 12 systems..
+ [*][03/01/2021 09:37] Scan Complete
---------------------------------------------------------------
- SHARE DATA ANALYSIS
+ SHARE ANALYSIS
---------------------------------------------------------------
[*][03/01/2021 09:37] Analysis Start
[*][03/01/2021 09:37] - 14 shares can be read across 12 systems.
@@ -110,21 +130,45 @@ function Analyze-HuntSMBShares
#>
[CmdletBinding()]
Param(
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'Domain user to authenticate with domain\user. For computer lookup.')]
+ [string]$Username,
+
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'Domain password to authenticate with domain\user. For computer lookup.')]
+ [string]$Password,
+
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'Credentials to use when connecting to a Domain Controller. For computer lookup.')]
+ [System.Management.Automation.PSCredential]
+ [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
+
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'Domain controller for Domain and Site that you want to query against. For computer lookup.')]
+ [string]$DomainController,
[Parameter(Mandatory = $false,
HelpMessage = 'Number of threads to process at once.')]
[int]$Threads = 20,
- [Parameter(Mandatory = $false,
+ [Parameter(Mandatory = $true,
HelpMessage = 'Directory to output files to.')]
[string]$OutputDirectory,
- [Parameter(Mandatory = $true,
- HelpMessage = 'The PowerHuntShare output folder.')]
- [string]$TargetDirectory,
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'Export to CSV file format to support importing into other tools.')]
+ [switch]$ExportFindings,
[Parameter(Mandatory = $false,
- HelpMessage = 'Number of items to sample for summary report. Typically something like: SmbShareHunt-06132024085403')]
+ HelpMessage = 'Convert the export to the NOVA file format.')]
+ [switch]$ExportNova,
+
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'This is the path to a host list. One per line.')]
+ [string] $HostList,
+
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'Number of items to sample for summary report.')]
[int]$SampleSum = 200,
[Parameter(Mandatory = $false,
@@ -147,10 +191,6 @@ function Analyze-HuntSMBShares
HelpMessage = 'Show runspace errors if they occur.')]
[switch] $ShowRunpaceErrors,
- [Parameter(Mandatory = $false,
- HelpMessage = 'Import all data from files vs analyzing raw import data. Mostly used when making code changes.')]
- [switch] $ImportAll,
-
[Parameter(Mandatory = $false,
HelpMessage = 'Supress timeline report generation.')]
[switch] $SupressTimelineRpt,
@@ -158,19 +198,31 @@ function Analyze-HuntSMBShares
[Parameter(Mandatory = $false,
HelpMessage = 'Number of directory levels to capture file list.')]
[int] $DirLevel = 3,
-
+
[Parameter(Mandatory = $false,
HelpMessage = 'Path to interesting files template to import file keywords to search for.')]
- [string] $FileKeywordsPath
+ [string] $FileKeywordsPath,
+
+ [Parameter(Mandatory = $false,
+ HelpMessage = 'Do not perform ping scan.')]
+ [switch] $NoPing
+
)
Begin
{
Write-Output " ==============================================================="
- Write-Output " Analyze-HuntSMBShares "
+ Write-Output " INVOKE-HUNTSMBSHARES "
Write-Output " ==============================================================="
Write-Output " This function automates the following tasks: "
+ Write-Output " "
+ Write-Output " o Determine current computer's domain "
+ Write-Output " o Enumerate domain computers "
+ Write-Output " o Check if computers respond to ping requests "
+ Write-Output " o Filter for computers that have TCP 445 open and accessible "
+ Write-Output " o Enumerate SMB shares "
+ Write-Output " o Enumerate SMB share permissions "
Write-Output " o Identify shares with potentially excessive privielges "
Write-Output " o Identify shares that provide read or write access "
Write-Output " o Identify shares thare are high risk "
@@ -181,34 +233,49 @@ function Analyze-HuntSMBShares
Write-Output " Note: This can take hours to run in large environments. "
Write-Output " ---------------------------------------------------------------"
Write-Output " |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
- Write-Output " ---------------------------------------------------------------"
+ Write-Output " ---------------------------------------------------------------"
+ Write-Output " SHARE DISCOVERY "
+ Write-Output " ---------------------------------------------------------------"
+
# Get start time
$StartTime = Get-Date
$StopWatch = [system.diagnostics.stopwatch]::StartNew()
$Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Scan Start"
- # Set target directory
- if(-not $TargetDirectory){
- $TargetDirectory = ".\Results"
+ # Nova format
+ If ($Nova) {
+ Write-Verbose " [*][$Time] The results will be export to the NOVA format as well."
+ $rMasterFindingId = "FindingTemplateSourceIdentifier"
+ $rFindingName = "FindingName"
+ $rAssetName = "AssetName" # This could eventually be updated to reflect a different Nova asset, e.g. 'AD Domain'.
}else{
- $TargetDirectory = "$TargetDirectory\Results"
- $TargetDirectory = $TargetDirectory.Replace('\\','\')
- }
- Write-Output " [*] Target directory: $TargetDirectory"
-
- # Set output directory
- if(-not $OutputDirectory){
- $OutputDirectory = $TargetDirectory
- }
- Write-Output " [*] Output directory: $OutputDirectory"
+ $rMasterFindingId = "MasterFindingSourceIdentifier"
+ $rFindingName = "InstanceName"
+ $rAssetName = "AssetName" # R7 only has one option.
+ }
- # Check for target directory
- if(Test-Path $TargetDirectory){
- #Write-Output " [x]The target directory exists."
+
+ # ----------------------------------------------------------------------
+ # Create output directory
+ # ----------------------------------------------------------------------
+ if(Test-Path $OutputDirectory){
+
+ # Verify output directory path
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ $FolderDateTime = Get-Date -Format "MMddyyyyHHmmss"
+ $OutputDirectoryBase = "$OutputDirectory\SmbShareHunt-$FolderDateTime"
+
+ # Create sub directories
+ mkdir $OutputDirectoryBase | Out-Null
+ $SubDir = "Results"
+ mkdir "$OutputDirectoryBase\Results" | Out-Null
+ $OutputDirectory = "$OutputDirectoryBase\Results"
+ Write-Output " [*][$Time] Output Directory: $OutputDirectoryBase"
}else{
- Write-Output " [x] The $TargetDirectory did not exist."
- Write-Output " [!] Aborting operation."
+ Write-Output " [x][$Time] The $OutputDirectory was not writable."
+ Write-Output " [!][$Time] Aborting operation."
break
}
@@ -224,253 +291,612 @@ function Analyze-HuntSMBShares
}
}
- # Check for output directory
- if(Test-Path $OutputDirectory){
- #Write-Output " [x][$Time] The output directory exists."
+ # ----------------------------------------------------------------------
+ # Import computers from file
+ # ----------------------------------------------------------------------
+ if($HostList){
+
+ if(test-path $HostList){
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Importing computer targets from $HostList"
+ $HostListContent = gc $HostList
+ $DomainComputers = $HostListContent |
+ foreach {
+ $object = New-Object psobject
+ $Object | Add-Member Noteproperty ComputerName $_
+ $Object
+ }
+ $TargetDomain = "SmbHunt"
+ $ComputerCount = $DomainComputers | measure | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] $ComputerCount systems will be targeted"
+ }else{
+ Write-Output " [!][$Time] The host list was not accessible: $HostList"
+ break
+ }
+ }
+
+ # Set variables
+ $GlobalThreadCount = $Threads
+
+ # ----------------------------------------------------------------------
+ # Enumerate domain computers
+ # ----------------------------------------------------------------------
+
+ if(-not $HostList){
+
+ # Create PS Credential object
+ if($Username -and $Password)
+ {
+ $secpass = ConvertTo-SecureString $Password -AsPlainText -Force
+ $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ($Username, $secpass)
+ }
+
+ # Set target domain
+ $DCRecord = Get-LdapQuery -LdapFilter "(&(objectCategory=computer)(userAccountControl:1.2.840.113556.1.4.803:=8192))" -DomainController $DomainController -Credential $Credential | select -first 1 | select properties -expand properties -ErrorAction SilentlyContinue
+ [string]$DCHostname = $DCRecord.dnshostname
+ [string]$DCCn = $DCRecord.cn
+ [string]$TargetDomain = $DCHostname -replace ("$DCCn\.","")
+
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ if($DCHostname)
+ {
+ Write-Output " [*][$Time] Successful connection to domain controller: $DCHostname"
+ }else{
+ Write-Output " [*][$Time] There appears to have been an error connecting to the domain controller."
+ Write-Output " [*][$Time] Aborting."
+ break
+ }
+
+ # Status user
+ Write-Output " [*][$Time] Performing LDAP query for computers associated with the $TargetDomain domain"
+
+ # Get domain computers
+ $DomainComputersRecord = Get-LdapQuery -LdapFilter "(objectCategory=Computer)" -DomainController $DomainController -Credential $Credential
+ $DomainComputers = $DomainComputersRecord |
+ foreach{
+
+ $DnsHostName = [string]$_.Properties['dnshostname']
+ if($DnsHostName -notlike ""){
+ $object = New-Object psobject
+ $Object | Add-Member Noteproperty ComputerName $DnsHostName
+ $Object
+ }
+ }
+
+ # Status user
+ $ComputerCount = $DomainComputers.count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $ComputerCount computers found"
+
+ # Save results
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Domain-Computers.csv"
+ $DomainComputers | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Domain-Computers.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $DomainComputers -Outfile "$OutputDirectory\$TargetDomain-Domain-Computers.html" -Title "Domain Computers" -Description "This page shows the domain computers discovered for the $TargetDomain Active Directory domain."
+ $DomainComputersFile = "$TargetDomain-Domain-Computers.csv"
+ $DomainComputersFileH = "$TargetDomain-Domain-Computers.html"
+
+ # Get subnet info
+ $DomainSubnets = Get-DomainSubnet -DomainController $DomainController -Credential $Credential
+ $DomainSubnetsCount = $DomainSubnets | measure | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $DomainSubnetsCount subnets found"
+ $DomainSubnets | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Domain-Subnets.csv"
+
+ }
+
+ # ----------------------------------------------------------------------
+ # Identify computers that respond to ping reqeusts
+ # ----------------------------------------------------------------------
+
+ if($NoPing){
+ Write-Output " [*][$Time] - Skipping ping scan."
+ $ComputerPingableCount = 0
}else{
- Write-Output " [x] The $OutputDirectory did not exist."
- Write-Output " [!] Aborting operation."
+
+ # Status user
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Pinging $ComputerCount computers"
+
+ # Ping computerss
+ $PingResults = $DomainComputers | Invoke-Ping -Throttle $GlobalThreadCount
+
+ # select computers that respond
+ $ComputersPingable = $PingResults |
+ foreach {
+
+ $computername = $_.address
+ $status = $_.status
+ if($status -like "Responding"){
+ $object = new-object psobject
+ $Object | add-member Noteproperty ComputerName $computername
+ $Object | add-member Noteproperty status $status
+ $Object
+ }
+ }
+
+ # Status user
+ $ComputerPingableCount = $ComputersPingable.count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $ComputerPingableCount computers responded to ping requests."
+
+ # Save results
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Domain-Computers-Pingable.csv"
+ if($ComputersPingable){
+ $ComputersPingable | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Domain-Computers-Pingable.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $ComputersPingable -Outfile "$OutputDirectory\$TargetDomain-Domain-Computers-Pingable.html" -Title "Domain Computers: Ping Response" -Description "This page shows the domain computers for the $TargetDomain Active Directory domain that responded to ping requests."
+ }
+ $ComputersPingableFile = "$TargetDomain-Domain-Computers-Pingable.csv"
+ $ComputersPingableFileH = "$TargetDomain-Domain-Computers-Pingable.html"
+ }
+
+ # ----------------------------------------------------------------------
+ # Identify computers that have TCP 445 open and accessible
+ # ----------------------------------------------------------------------
+
+ # Status user
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Checking if TCP Port 445 is open on $ComputerCount computers"
+
+ # Create script block to port scan tcp 445
+ $MyScriptBlock = {
+ $ComputerName = $_.ComputerName
+ try{
+ $Socket = New-Object System.Net.Sockets.TcpClient($ComputerName,"445")
+
+ if($Socket.Connected)
+ {
+ $Status = "Open"
+ $Socket.Close()
+ }
+ else
+ {
+ $Status = "Closed"
+ }
+ }
+ catch{
+ $Status = "Closed"
+ }
+
+ if($Status -eq "Open")
+ {
+ $object = new-object psobject
+ $Object | add-member Noteproperty ComputerName $computername
+ $Object | add-member Noteproperty 445status $status
+ $Object
+ }
+ }
+
+ # Perform port scan of tcp 445 threaded
+ $Computers445Open = $DomainComputers | Invoke-Parallel -ScriptBlock $MyScriptBlock -ImportSessionFunctions -ImportVariables -Throttle $GlobalThreadCount -RunspaceTimeout $RunSpaceTimeOut -ErrorAction SilentlyContinue
+
+ # Status user
+ $Computers445OpenCount = $Computers445Open.count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $Computers445OpenCount computers have TCP port 445 open."
+
+
+ # Stop if no ports are accessible
+ If ($Computers445OpenCount -eq 0)
+ {
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - Aborting."
break
}
- Write-Output " ---------------------------------------------------------------"
- Write-Output " [*][$Time] IMPORT SHARE DATA"
- Write-Output " ---------------------------------------------------------------"
- Write-Output " [*][$Time] Importing computer data..."
-
- $TargetDomain = "Testing"
-
- # Get all computers
- try{
- $DomainComputers = import-csv "$TargetDirectory\*-Domain-Computers.csv"
- $ComputerCount = $DomainComputers | Measure-Object | select count -ExpandProperty count
-
- # Get domain
- $DomainNamePrep = $DomainComputers | select computername -first 1 -expandproperty computername
- $TargetDomain = Get-ADDomainFromFQDN -FQDN $DomainNamePrep
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $TargetDomain is the target domain."
- Write-Output " [*][$Time] - $ComputerCount computers found."
- }catch{
- $DomainComputers = ""
- $ComputerCount = 0
- Write-Output " [*][$Time] - Computers file could not be imported."
+ # Save results
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Domain-Computers-Open445.csv"
+ if($Computers445Open){
+ $Computers445Open | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Domain-Computers-Open445.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $Computers445Open -Outfile "$OutputDirectory\$TargetDomain-Domain-Computers-Open445.html" -Title "Domain Computers: Port 445 Open" -Description "This page shows the domain computers for the $TargetDomain Active Directory domain with port 445 open."
}
-
- # Get all pingable
- try{
- $ComputersPingable = import-csv "$TargetDirectory\*-Domain-Computers-Pingable.csv"
- $ComputerPingableCount = $ComputersPingable | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $ComputerPingableCount computers responded to ping requests."
- }catch{
- $ComputersPingable = ""
- $ComputersPingableCount = 0
- Write-Output " [*][$Time] - Computers that were pingable file could not be imported."
- }
-
- # Get all open ports
- try{
- $Computers445Open = import-csv "$TargetDirectory\*-Domain-Computers-Open445.csv"
- $Computers445OpenCount = $Computers445Open | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $Computers445OpenCount computers have TCP port 445 open."
- }catch{
- $Computers445Open = ""
- $Computers445OpenCount = 0
- Write-Output " [*][$Time] - Computers with open port 445 file could not be imported."
- }
-
- # Get Subnets
- try{
- $DomainSubnets = import-csv "$TargetDirectory\*-Domain-Subnets.csv"
- $DomainSubnetsCount = $DomainSubnets | measure | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $DomainSubnetsCount Active Directory subnets found."
- }catch{
- $DomainSubnets = ""
- $DomainSubnetsCount = 0
- Write-Output " [*][$Time] - Subnets file could not be imported."
- }
-
- # Get all shares
- Write-Output " [*][$Time] Importing share data..."
- try{
- $AllSMBShares = import-csv "$TargetDirectory\*-Shares-Inventory-All.csv"
- $AllSMBSharesCount = $AllSMBShares | Measure-Object | select count -ExpandProperty count
-
- # Get all computers with shares
- $AllComputersWithShares = $AllSMBShares | Select-Object ComputerName -Unique
- $AllComputersWithSharesCount = $AllComputersWithShares | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $AllSMBSharesCount SMB shares were found across $AllComputersWithSharesCount computers."
- }catch{
- $AllSMBShares = ""
- $AllComputersWithShares = ""
- $AllSMBSharesCount = 0
- $AllComputersWithSharesCount = 0
- Write-Output " [*][$Time] - Shares file could not be imported."
- }
-
- # Get all acls
- Write-Output " [*][$Time] Importing acl data..."
- try{
- $ShareACLs = import-csv "$TargetDirectory\*-Shares-Inventory-All-ACL.csv"
- $ShareACLsCount = $ShareACLs | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $ShareACLsCount share permissions were enumerated."
- }catch{
- $ShareACLs = ""
- $ShareACLsCount = 0
- Write-Output " [*][$Time] - Share ACL file could not be imported."
- }
-
- # Get acls with excessive privileges
- Write-Output " [*][$Time] Importing excessive privilege data..."
- try{
- $ExcessiveSharePrivs = import-csv "$TargetDirectory\*-Shares-Inventory-Excessive-Privileges.csv"
- $ExcessiveSharePrivsCount = $ExcessiveSharePrivs | Measure-Object | select count -ExpandProperty count
- $ExcessiveAclCount = $ExcessiveSharePrivs | Measure-Object | select count -ExpandProperty count #sloppy patch
- }catch{
- Write-Output " [*][$Time] - Excessive privileges file could not be imported - aborted."
- }
-
- # Get shares with excessive privileges
- $ExcessiveShares = $ExcessiveSharePrivs | Select-Object ComputerName,ShareName -unique
- $ExcessiveSharesCount = $ExcessiveShares | Measure-Object | select count -ExpandProperty count
-
- # Get computers with excessive privileges
- $ComputerWithExcessive = $ExcessiveSharePrivs | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
-
- Write-Output " [*][$Time] - $ExcessiveSharePrivsCount acls were found configured with potentially excessive privileges on $ExcessiveSharesCount shares across $ComputerWithExcessive computers."
-
- Write-Output " ---------------------------------------------------------------"
- Write-Output " [*][$Time] ANALYZE SHARE DATA"
- Write-Output " ---------------------------------------------------------------"
-
- # Get non default share access
- Write-Output " [*][$Time] Identifying non-default share access..."
- try{
- if($ImportAll){
- Write-Output " [*][$Time] - Importing from file..."
- $SharesNonDefault = import-csv "$TargetDirectory\*-Shares-Inventory-Excessive-Privileges-NonDefault.csv"
- } else {
- Write-Output " [*][$Time] - Parsing excessive privileges..."
- $SharesNonDefault = $ShareACLs |
- Foreach {
-
- if(($_.ShareName -notlike 'admin$') -or ($_.ShareName -notlike 'c$') -or ($_.ShareName -notlike 'd$') -or ($_.ShareName -notlike 'e$') -or ($_.ShareName -notlike 'f$'))
- {
- $_ # out to file
- }
- }
- }
- $AclNonDefaultCount = $SharesNonDefault | measure | select count -ExpandProperty count
- $SharesNonDefaultCount = $SharesNonDefault | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
- $ComputerwithNonDefaultCount = $SharesNonDefault | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $SharesNonDefaultCount shares are considered non-default across $ComputerwithNonDefaultCount systems."
- }catch{
- $AclNonDefaultCount = 0
- $SharesNonDefaultCount = 0
- $ComputerwithNonDefaultCount = 0
- Write-Output " [*][$Time] - Non default shares file could not be imported."
- }
-
- # Get shares that provide read access
- Write-Output " [*][$Time] Identifying excessive read access..."
- try{
- if($ImportAll){
- Write-Output " [*][$Time] - Importing from file..."
- $SharesWithread = import-csv "$TargetDirectory\*-Shares-Inventory-Excessive-Privileges-Read.csv"
- } else {
- Write-Output " [*][$Time] - Parsing excessive privileges..."
- $SharesWithread = $ExcessiveSharePrivs |
- Foreach {
-
- if(($_.FileSystemRights -like "*read*"))
- {
- $_ # out to file
- }
- }
- }
- $AclWithReadCount = $SharesWithread | Measure-Object | select count -ExpandProperty count
- $SharesWithReadCount = $SharesWithread | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
- $ComputerWithReadCount = $SharesWithread | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $SharesWithReadCount shares can be read across $ComputerWithReadCount computers."
- }catch{
- $AclWithReadCount = 0
- $SharesWithReadCount = 0
- $ComputerWithReadCount = 0
- Write-Output " [*][$Time] - Read shares file could not be imported."
- }
-
- # Get shares that provide write access
- Write-Output " [*][$Time] Identifying excessive write access..."
- try{
- if($ImportAll){
- Write-Output " [*][$Time] - Importing from file..."
- $SharesWithWrite = import-csv "$TargetDirectory\*-Shares-Inventory-Excessive-Privileges-Write.csv"
- }else{
- Write-Output " [*][$Time] - Parsing excessive privileges..."
- $SharesWithWrite = $ExcessiveSharePrivs |
- Foreach {
-
- if(($_.FileSystemRights -like "*GenericAll*") -or ($_.FileSystemRights -like "*Write*"))
- {
- $_ # out to file
- }
- }
- }
- $AclWithWriteCount = $SharesWithWrite | Measure-Object | select count -ExpandProperty count
- $SharesWithWriteCount = $SharesWithWrite | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
- $ComputerWithWriteCount = $SharesWithWrite | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $SharesWithWriteCount shares can be written to across $ComputerWithWriteCount systems."
- }catch{
- $AclWithWriteCount = 0
- $SharesWithWriteCount = 0
- $ComputerWithWriteCount = 0
- Write-Output " [*][$Time] - Write shares file could not be imported."
- }
-
- # Get high risk share access
- try{
- Write-Output " [*][$Time] Identifying high risk access..."
- if($ImportAll){
- Write-Output " [*][$Time] - Importing from file..."
- $SharesHighRisk = import-csv "$TargetDirectory\*-Shares-Inventory-Excessive-Privileges-HighRisk.csv"
- }else{
- Write-Output " [*][$Time] - Parsing excessive privileges..."
- $SharesHighRisk = $ExcessiveSharePrivs |
- Foreach {
-
- if(($_.ShareName -like 'c$') -or ($_.ShareName -like 'admin$') -or ($_.ShareName -like "*wwwroot*") -or ($_.ShareName -like "*inetpub*") -or ($_.ShareName -like 'c') -or ($_.ShareName -like 'C') -or ($_.ShareName -like 'c_share'))
- {
- $_ # out to file
- }
- }
- }
- $AclHighRiskCount = $SharesHighRisk | Measure-Object | select count -ExpandProperty count
- $SharesHighRiskCount = $SharesHighRisk | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
- $ComputerwithHighRisk = $SharesHighRisk | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
- $Time = Get-Date -UFormat "%m/%d/%Y %R"
- Write-Output " [*][$Time] - $SharesHighRiskCount shares are considered high risk across $ComputerwithHighRisk systems."
- }catch{
- $AclHighRiskCount = 0
- $SharesHighRiskCount = 0
- $ComputerwithHighRisk = 0
- Write-Output " [*][$Time] - High risk shares file could not be imported."
- }
-
- Write-Output " [*][$Time] Identifying trends..."
+ $Computers445OpenFile = "$TargetDomain-Domain-Computers-Open445.csv"
+ $Computers445OpenFileH ="$TargetDomain-Domain-Computers-Open445.html"
# ----------------------------------------------------------------------
- # Identify common excessive share owners
- # ----------------------------------------------------------------------
+ # Enumerate computer SMB shares
+ # ----------------------------------------------------------------------
+ # Status user
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Getting a list of SMB shares from $Computers445OpenCount computers"
+
+ # Create script block to query for SMB shares
+ $MyScriptBlock = {
+ Get-MySMBShare -ComputerName $_.ComputerName
+ }
+
+ # Get smb shares threaded
+ $AllSMBShares = $Computers445Open | Invoke-Parallel -ScriptBlock $MyScriptBlock -ImportSessionFunctions -ImportVariables -Throttle $GlobalThreadCount -RunspaceTimeout $RunSpaceTimeOut -ErrorAction SilentlyContinue
+
+ # Computer computers with shares
+ $AllComputersWithShares = $AllSMBShares | Select-Object ComputerName -Unique
+ $AllComputersWithSharesCount = $AllComputersWithShares.count
+
+ # Status user
+ $AllSMBSharesCount = $AllSMBShares.count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $AllSMBSharesCount SMB shares were found."
+
+ # Stop if no shares
+ If ($AllSMBSharesCount -eq 0)
+ {
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - Aborting."
+ break
+ }
+
+ # Save results
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Shares-Inventory-All.csv"
+ $AllSMBShares | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Inventory-All.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $AllSMBShares -Outfile "$OutputDirectory\$TargetDomain-Shares-Inventory-All.html" -Title "Domain Shares" -Description "This page shows the all enumerated shares for the $TargetDomain Active Directory domain."
+ $AllSMBSharesFile = "$TargetDomain-Shares-Inventory-All.csv"
+ $AllSMBSharesFileH = "$TargetDomain-Shares-Inventory-All.html"
+
+ # ----------------------------------------------------------------------
+ # Enumerate computer SMB share permissions
+ # ----------------------------------------------------------------------
+
+ # Status user
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Getting share permissions from $AllSMBSharesCount SMB shares"
+
+ # Create script block to query for SMB permissions
+ $MyScriptBlock = {
+
+ $CurrentShareName = $_.ShareName
+ $CurrentComputerName = $_.ComputerName
+ $CurrentIP = $_.IpAddress
+ $ShareDescription = $_.ShareDesc
+ $Sharetype = $_.sharetype
+ $Shareaccess = $_.shareaccess
+
+ if($CurrentComputerName -eq ""){
+ $TargetAsset = $CurrentIP
+ }else{
+ $TargetAsset = $CurrentComputerName
+ }
+
+ $currentaacl = Get-PathAcl "\\$TargetAsset\$CurrentShareName" -ErrorAction SilentlyContinue
+ $currentaacl |
+ foreach{
+
+ # Get file listing
+ $FullFileList = Get-ChildItem -Path "\\$TargetAsset\$CurrentShareName"
+
+ # Get file count
+ $FileCount = $FullFileList.Count
+
+ # Get top 5 files list
+ $FileList = $FullFileList | Select-Object Name -ExpandProperty Name | Out-String
+
+ # Get File listing hash
+ $FileListGroup = Get-FolderGroupMd5 -FolderList $FileList
+ $FileListGroup
+
+ # Audit Settings
+ $AuditSettings = Get-ACL "\\$TargetAsset\$CurrentShareName" -ErrorAction SilentlyContinue | Select-Object AuditToString -ExpandProperty AuditToString
+
+ # Creation date
+ $CreationdDateObject = Get-Item "\\$TargetAsset\$CurrentShareName" -ErrorAction SilentlyContinue | Select CreationTime
+ $CreationdDate = $CreationdDateObject.CreationTime.ToString()
+ $CreationdDateYear = $CreationdDateObject.CreationTime.Year.ToString()
+
+ # Last modified date
+ $TargetPath = $_.Path
+ $LastModifiedDateObject = Get-Item "\\$TargetAsset\$CurrentShareName" -ErrorAction SilentlyContinue | Select-Object LastWriteTime
+ $LastModifiedDate = $LastModifiedDateObject.LastWriteTime.ToString()
+ $LastModifiedDateYear = $LastModifiedDate.split(' ')[0].split('/')[2]
+
+ # Last accessed date
+ $TargetPath = $_.Path
+ $LastAccessDateObject = Get-Item "\\$TargetAsset\$CurrentShareName" -ErrorAction SilentlyContinue | Select-Object LastAccessTime
+ $LastAccessDate = $LastAccessDateObject.LastAccessTime.ToString()
+ $LastAccessDateYear = $LastAccessDate.split(' ')[0].split('/')[2]
+
+ $aclObject = new-object psobject
+ $aclObject | add-member Noteproperty ComputerName $CurrentComputerName
+ $aclObject | add-member Noteproperty IpAddress $CurrentIP
+ $aclObject | add-member Noteproperty ShareName $CurrentShareName
+ $aclObject | add-member Noteproperty SharePath $_.Path
+ $aclObject | add-member Noteproperty ShareDescription $ShareDescription
+ $aclObject | add-member Noteproperty ShareOwner $_.PathOwner
+ $aclObject | add-member Noteproperty ShareType $ShareType
+ $aclObject | add-member Noteproperty ShareAccess $ShareAccess
+ $aclObject | add-member Noteproperty FileSystemRights $_.FileSystemRights
+ $aclObject | add-member Noteproperty IdentityReference $_.IdentityReference
+ $aclObject | add-member Noteproperty IdentitySID $_.IdentitySID
+ $aclObject | add-member Noteproperty AccessControlType $_.AccessControlType
+ $aclObject | add-member Noteproperty CreationDate $CreationdDate
+ $aclObject | add-member Noteproperty CreationDateYear $CreationdDateYear
+ $aclObject | add-member Noteproperty LastModifiedDate $LastModifiedDate
+ $aclObject | add-member Noteproperty LastModifiedDateYear $LastModifiedDateYear
+ $aclObject | add-member Noteproperty LastAccessDate $LastAccessDate
+ $aclObject | add-member Noteproperty LastAccessDateYear $LastAccessDateYear
+ $aclObject | add-member Noteproperty FileCount $FileCount
+ $aclObject | add-member Noteproperty FileList $FileList
+ $aclObject | add-member Noteproperty FileListGroup $FileListGroup
+ $aclObject | add-member Noteproperty AuditSettings $AuditSettings
+ $aclObject
+ }
+ }
+
+ # Get SMB permissions threaded
+ $ShareACLs = $AllSMBShares | Invoke-Parallel -ScriptBlock $MyScriptBlock -ImportSessionFunctions -ImportVariables -Throttle $GlobalThreadCount -RunspaceTimeout $RunSpaceTimeOut -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | where ShareName -notlike ""
+
+ # Status user
+ $ShareACLsCount = $ShareACLs | measure | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $ShareACLsCount share permissions were enumerated."
+
+ # Stop if no shares ACLs were enumerated
+ If ($ShareACLsCount -eq 0)
+ {
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - Aborting."
+ break
+ }
+
+ # Save results
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Shares-Inventory-All-ACL.csv"
+ $ShareACLs | where ShareName -notlike "" | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Inventory-All-ACL.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $ShareACLs -Outfile "$OutputDirectory\$TargetDomain-Shares-Inventory-All-ACL.html" -Title "Domain Shares: All ACL Entries" -Description "This page shows all share ACL entries discovered on computers associated with the $TargetDomain Active Directory domain."
+ $ShareACLsFile = "$TargetDomain-Shares-Inventory-All-ACL.csv"
+ $ShareACLsFileH = "$TargetDomain-Shares-Inventory-All-ACL.html"
+
+
+ # ----------------------------------------------------------------------
+ # Get potentially excessive share permissions
+ # ----------------------------------------------------------------------
+
+ # Status user
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Identifying potentially excessive share permissions"
+
+ # Check for share that provide read/write access to common user groups
+ $ExcessiveSharePrivs = foreach ($line in $ShareACLs){
+
+ # Filter for basic user ACLs
+ if (($line.IdentityReference -eq "Everyone") -or ($line.IdentityReference -eq "BUILTIN\Users") -or ($line.IdentityReference -eq "Authenticated Users") -or ($line.IdentityReference -like "*Domain Users*") ){
+
+ if($line.ShareAccess -like "Yes"){
+
+ if(($line.ShareName -notlike "print$") -and ($line.ShareName -notlike "prnproc$") -and ($line.ShareName -notlike "*printer*") -and ($line.ShareName -notlike "sysvol") -and ($line.ShareName -notlike "netlogon"))
+ {
+ $line
+ }
+ }
+ }
+ }
+
+ # Status user
+ $ExcessiveAclCount = $ExcessiveSharePrivs.count
+ $ExcessiveShares = $ExcessiveSharePrivs | Select-Object ComputerName,ShareName -unique
+ $ExcessiveSharesCount = $ExcessiveShares.count
+ $ExcessiveSharePrivsCount = $ExcessiveSharePrivs.count
+ $ComputerWithExcessive = $ExcessiveSharePrivs | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $ExcessiveSharePrivsCount potentially excessive privileges were found on $ExcessiveSharesCount shares across $ComputerWithExcessive systems."
+
+ # Save results
+ if($ExcessiveSharesCount -ne 0){
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges.csv"
+ $ExcessiveSharePrivs | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $ExcessiveSharePrivs -Outfile "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges.html" -Title "Domain Shares: ACL Entries - Excessive Privileges" -Description "This page shows all share ACL entries discovered on computers associated with the $TargetDomain Active Directory domain that appear to be configured with excessive privileges."
+ $ShareACLsExFile = "$TargetDomain-Shares-Inventory-Excessive-Privileges.csv"
+ $ShareACLsExFileH = "$TargetDomain-Shares-Inventory-Excessive-Privileges.html"
+ }else{
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [!][$Time] 0 excessive privileges found."
+ break
+ }
+
+ $ExcessiveSharePrivsFile = "$TargetDomain-Shares-Inventory-Excessive-Privileges.csv"
+
+
+ # ----------------------------------------------------------------------
+ # Get Recursive Directory Listings
+ # ----------------------------------------------------------------------
+ # Default depth is 3 by default
+
+ # Status user
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Getting directory listings from $ExcessiveSharesCount SMB shares"
+ Write-Output " [*][$Time] - Targeting up to $DirLevel nested directory levels"
+
+ # Create script block to query for directory listing
+ $MyScriptBlock = {
+
+ # Get share context
+ $CurrentComputerName = $_.ComputerName
+ $CurrentIP = $_.IpAddress
+ $ShareDescription = $_.ShareDesc
+ $CurrentShareName = $_.ShareName
+ $SharePath = $_.SharePath
+
+ # Get file listing from non system directories
+ #$FullFileList = Get-ChildItem -Path $SharePath -Exclude "c:\windows" | Select FullName
+ $FullFileList = Get-ChildItem -Depth $DirLevel -Path "$SharePath" | select fullname | where {$_.fullname -NotLike "$SharePath\Windows*" -and $_.fullname -notlike "$SharePath\WINNT"}
+
+ $FullFileList |
+ Foreach{
+ $aclObject = new-object psobject
+ $aclObject | add-member Noteproperty ComputerName $CurrentComputerName
+ $aclObject | add-member Noteproperty IpAddress $CurrentIP
+ $aclObject | add-member Noteproperty ShareName $CurrentShareName
+ $aclObject | add-member Noteproperty SharePath $SharePath
+ $aclObject | add-member Noteproperty ShareDescription $ShareDescription
+ $aclObject | add-member Noteproperty FilePath $_.fullname
+ $aclObject
+ }
+ }
+
+ # Get SMB directory listing threaded
+ $ShareDirListing = $ExcessiveSharePrivs | select computername,ipaddress,sharedesc,sharename,sharepath -Unique | Invoke-Parallel -ScriptBlock $MyScriptBlock -ImportSessionFunctions -ImportVariables -Throttle $GlobalThreadCount -RunspaceTimeout $RunSpaceTimeOut -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | where ShareName -notlike "" #| select * -Unique
+
+ # Status user
+ $ShareDirListingCount = $ShareDirListing | measure | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $ShareDirListingCount files and folders were enumerated."
+
+ # Write output
+ # Write-Output " [*] Saving results to $OutputDirectory\$TargetDomain-Shares-Directory-Listings-Depth-$DirLevel.csv"
+ $ShareDirListing | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Directory-Listings-Depth-$DirLevel.csv"
+
+
+ # ----------------------------------------------------------------------
+ # Get File Listings from Shares
+ # ----------------------------------------------------------------------
+ #$FindFiles # hardcoded array
+ #$FindFilesList # file
+ # combine
+ # create where statement
+ #$ShareDirListing | Where
+ #count
+ #export
+
+ # End of scanning
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] Scan Complete"
+
+ Write-Output " ---------------------------------------------------------------"
+ Write-Output " SHARE ANALYSIS "
+ Write-Output " ---------------------------------------------------------------"
+ Write-Output " [*][$Time] Analysis Start"
+
+ # ----------------------------------------------------------------------
+ # Identify shares that provide read access
+ # ----------------------------------------------------------------------
+
+ # Get shares that provide read access
+ $SharesWithread = $ExcessiveSharePrivs |
+ Foreach {
+
+ if(($_.FileSystemRights -like "*read*"))
+ {
+ $_ # out to file
+ }
+ }
+
+ # Status user
+ $AclWithReadCount = $SharesWithread.count
+ $SharesWithReadCount = $SharesWithread | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
+ $ComputerWithReadCount = $SharesWithread | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $SharesWithReadCount shares can be read across $ComputerWithReadCount systems."
+
+ # Save results
+ if($SharesWithReadCount -ne 0){
+ #Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Read.csv"
+ $SharesWithRead | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Read.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $SharesWithRead -Outfile "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Read.html" -Title "Domain Shares: ACL Allow Read Entries" -Description "This page shows all share ACL entries discovered on computers associated with the $TargetDomain Active Directory domain that are readable."
+ $ShareACLsReadFile = "$TargetDomain-Shares-Inventory-Excessive-Privileges-Read.csv"
+ $ShareACLsReadFileH = "$TargetDomain-Shares-Inventory-Excessive-Privileges-Read.html"
+ }
+
+ $SharesWithReadFile = "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Read.csv"
+
+ # ----------------------------------------------------------------------
+ # Identify shares that provide write access
+ # ----------------------------------------------------------------------
+
+ # Get shares that provide write access
+ $SharesWithWrite = $ExcessiveSharePrivs |
+ Foreach {
+
+ if(($_.FileSystemRights -like "*GenericAll*") -or ($_.FileSystemRights -like "*Write*"))
+ {
+ $_ # out to file
+ }
+ }
+
+ # Status user
+ $AclWithWriteCount = $SharesWithWrite | Measure-Object | select count -ExpandProperty count
+ $SharesWithWriteCount = $SharesWithWrite | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
+ $ComputerWithWriteCount = $SharesWithWrite | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $SharesWithWriteCount shares can be written to across $ComputerWithWriteCount systems."
+
+ # Save results
+ if($SharesWithWriteCount -ne 0){
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Write.csv"
+ $SharesWithWrite | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Write.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $SharesWithWrite -Outfile "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Write.html" -Title "Domain Shares: ACL Allow Write Entries" -Description "This page shows all share ACL entries discovered on computers associated with the $TargetDomain Active Directory domain that are writable."
+ $ShareACLsWriteFile = "$TargetDomain-Shares-Inventory-Excessive-Privileges-Write.csv"
+ $ShareACLsWriteFileH = "$TargetDomain-Shares-Inventory-Excessive-Privileges-Write.html"
+ }
+
+ $SharesWithWriteFile = "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-Write.csv"
+
+ # ----------------------------------------------------------------------
+ # Identify shares that are non-default
+ # ----------------------------------------------------------------------
+
+ # Get high risk share access
+ $SharesNonDefault = $ShareACLs |
+ Foreach {
+
+ if(($_.ShareName -notlike 'admin$') -or ($_.ShareName -notlike 'c$') -or ($_.ShareName -notlike 'd$') -or ($_.ShareName -notlike 'e$') -or ($_.ShareName -notlike 'f$'))
+ {
+ $_ # out to file
+ }
+ }
+
+ # Status user
+ $AclNonDefaultCount = $SharesNonDefault | measure | select count -ExpandProperty count
+ $SharesNonDefaultCount = $SharesNonDefault | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
+ $ComputerwithNonDefaultCount = $SharesNonDefault | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $SharesNonDefaultCount shares are considered non-default across $ComputerwithNonDefaultCount systems."
+
+ # Save results
+ if($SharesNonDefaultCount-ne 0){
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-NonDefault.csv"
+ $SharesNonDefault | where ShareName -notlike "" | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-NonDefault.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $SharesNonDefault -Outfile "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-NonDefault.html" -Title "Domain Shares: Non-Default" -Description "This page shows all share ACL entries discovered on computers associated with the $TargetDomain Active Directory domain that are non-default."
+ $ShareACLsNonDefaultFile = "$TargetDomain-Shares-Inventory-Excessive-Privileges-NonDefault.csv"
+ $ShareACLsNonDefaultFileH = "$TargetDomain-Shares-Inventory-Excessive-Privileges-NonDefault.html"
+ }
+
+ $SharesNonDefaultFile = "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-NonDefault.csv"
+
+ # ----------------------------------------------------------------------
+ # Identify shares that are high risk
+ # ----------------------------------------------------------------------
+
+ # Get high risk share access
+ $SharesHighRisk = $ExcessiveSharePrivs |
+ Foreach {
+
+ if(($_.ShareName -like 'c$') -or ($_.ShareName -like 'admin$') -or ($_.ShareName -like "*wwwroot*") -or ($_.ShareName -like "*inetpub*") -or ($_.ShareName -like 'c') -or ($_.ShareName -like 'c_share'))
+ {
+ $_ # out to file
+ }
+ }
+
+ # Status user
+ $AclHighRiskCount = $SharesHighRisk.count
+ $SharesHighRiskCount = $SharesHighRisk | Select-Object SharePath -Unique | Measure-Object | select count -ExpandProperty count
+ $ComputerwithHighRisk = $SharesHighRisk | Select-Object ComputerName -Unique | Measure-Object | select count -ExpandProperty count
+ $Time = Get-Date -UFormat "%m/%d/%Y %R"
+ Write-Output " [*][$Time] - $SharesHighRiskCount shares are considered high risk across $ComputerwithHighRisk systems."
+
+ # Save results
+ if($SharesHighRiskCount -ne 0){
+ # Write-Output " [*] - Saving results to $OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-HighRisk.csv"
+ $SharesHighRisk | Export-Csv -NoTypeInformation "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-HighRisk.csv"
+ $null = Convert-DataTableToHtmlTable -DataTable $SharesHighRisk -Outfile "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-HighRisk.html" -Title "Domain Shares: ACL High Risk Entries" -Description "This page shows all share ACL entries discovered on computers associated with the $TargetDomain Active Directory domain that are considered to be high risk."
+ $ShareACLsHRFile = "$TargetDomain-Shares-Inventory-Excessive-Privileges-HighRisk.csv"
+ $ShareACLsHRFileH = "$TargetDomain-Shares-Inventory-Excessive-Privileges-HighRisk.html"
+ }
+
+ $SharesHighRiskFile = "$OutputDirectory\$TargetDomain-Shares-Inventory-Excessive-Privileges-HighRisk.csv"
+
+
+ # ----------------------------------------------------------------------
+ # Identify common excessive share owners
+ # ----------------------------------------------------------------------
+
# Get share owner list
$CommonShareOwners = $ExcessiveSharePrivs | Select SharePath,ShareOwner -Unique |
Select-Object ShareOwner |
@@ -527,14 +953,14 @@ function Analyze-HuntSMBShares
}
}
- # Get percent of shared covered by top n
+ # Get percent of shared covered by top 5
# If very weighted this indicates if the shares are part of a deployment process, image, or app
# Get top five share name
$CommonShareNamesCount = $CommonShareNames.count
$CommonShareNamesTop5 = $CommonShareNames | Select-Object count,name -First $SampleSum
- # Get count of share name if in the top n
+ # Get count of share name if in the top 5
$Top5ShareCountTotal = 0
$CommonShareNamesTop5 |
foreach{
@@ -1043,7 +1469,6 @@ function Analyze-HuntSMBShares
#Write-Output " [*][$Time] - Summary report data generated."
#Write-Output " [*][$Time] - $Top5ShareCountTotal of $AllAccessibleSharesCount ($DupPercent) shares are associated with the top $SampleSum share names."
-
# ----------------------------------------------------------------------
# Create Interesting Files Table
# ----------------------------------------------------------------------
@@ -1062,26 +1487,20 @@ function Analyze-HuntSMBShares
$FileNamePatternsAll.Columns.Add("SampleRegex") | Out-Null # Used to parse sample data from file matches.
# Add rows to data table - Sensitive data
- $FileNamePatternsAll.Rows.Add("*credit*","Credit card number and/or PII.","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*pci*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*social*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*ssn*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("human*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("finance*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*medical*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("Health*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("Billing*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*payment*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("patient*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("HR*","","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*nessus*","This is a vulnerability scanner.","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*nexpose*","This is a vulnerability scanner.","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*qualys*","This is a vulnerability scanner.","None.","Sensitive","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*tripwire*","This is a vulnerability scanner.","None.","Sensitive","") | Out-Null
-
+ $FileNamePatternsAll.Rows.Add("*credit*","Credit card number and/or PII.","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*pci*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*social*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*ssn*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("human*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("finance*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("Health*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("Billing*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("patient*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("HR*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*ftp*","","None.","Sensitive","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*Program Files*","","None.","Sensitive","") | Out-Null
+
# Add rows to data table - Files containing passwords
- $FileNamePatternsAll.Rows.Add("Bootstrap.ini*","Used for Windows Deployment services (WDS) PXE installation and may contain credentials.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add(".bcd*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("context.xml*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("db2cli.ini*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("ftpd.*","","None.","Secret","") | Out-Null
@@ -1098,9 +1517,6 @@ function Analyze-HuntSMBShares
$FileNamePatternsAll.Rows.Add("*ntds.dit*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("pg_hba.conf*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("php.ini*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.pfx*","Private key.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("policy.xml*","May be associated with SCCM/ConfigMgr and contain credentials to support PXE that can be recovered, base64 decoded, or decrypted using PXEThief or https://github.com/1njected/CMvarDecrypt.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add(".pol*","May contain credentials to support PXE or other things.","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("putty.reg*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("postgresql.conf*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("SAM","","None.","Secret","") | Out-Null
@@ -1114,14 +1530,28 @@ function Analyze-HuntSMBShares
$FileNamePatternsAll.Rows.Add("tomcat-users.xml*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("sitemanager.xml*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("users.*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*variable*.dat*","This file is used for SCCM/ConfigMgr PXE deployments. It may contain passwords that can be recovered, base64 decoded, or decrypted using PXEThief or https://github.com/1njected/CMvarDecrypt.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.var*","Often contain credentials. May be assocaited with SCCM/MECM","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmx*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmdk*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.nvram*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmsd*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmsn*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmss*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vmem*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vhd*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vhdx*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.avhd*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.avhdx*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vsv*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vbox*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vbox-prev*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.vdi*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.hdd*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.sav*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*setting.ini*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.pvm*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.pvs*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.qcow*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.qcow2*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.qcow2*","","None.","Secret","") | Out-Null
+ $FileNamePatternsAll.Rows.Add("*.img*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*vcenter*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*vault*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*DefaultAppPool*","","None.","Secret","") | Out-Null
@@ -1130,36 +1560,6 @@ function Analyze-HuntSMBShares
$FileNamePatternsAll.Rows.Add("wp-config.php*","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.config","","None.","Secret","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.dtsx*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.rdp*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.aws*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*vnc.ini*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*DataSource.xml*","Group policy file that may contain passwords.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*ScheduledTasks.xml*","Group policy file that may contain passwords.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*Groups.xml*","Group policy file that may contain passwords.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*Drives.xml*","Group policy file that may contain passwords.","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*unattend*","","None.","Secret","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*sysprep*","","None.","Secret","") | Out-Null
-
- # Add rows to data table - System/VM Images
- $FileNamePatternsAll.Rows.Add("*.img*","","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.iso*","This is system image.It may contain passwords in Variables.dat, unattend.xml, and policy.xml files.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.wmi*","This is system image.It may contain passwords in Variables.dat, unattend.xml, and policy.xml files.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vmx*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vmdk*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.nvram*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vmsd*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vmsn*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vmss*","This is a virtual memory file that could be used to recover data or System Images.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vmem*","This is a virtual memory file that could be used to recover data or System Images.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vhd*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vhdx*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.avhd*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.avhdx*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vsv*","This is a virtual memory file that could be used to recover data or SystemImages.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vbox*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vbox-prev*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.vdi*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.hdd*","This is a virtual machine image file.","None.","SystemImage","") | Out-Null
# Add rows to data table - Database files
$FileNamePatternsAll.Rows.Add("*database*","","None.","Database","") | Out-Null
@@ -1167,8 +1567,6 @@ function Analyze-HuntSMBShares
$FileNamePatternsAll.Rows.Add("*.sqlite*","","None.","Database","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.idf*","","None.","Database","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.mdf*","","None.","Database","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*.ora*","","None.","Database","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*oracle*","","None.","Database","") | Out-Null
# Add rows to data table - Backup files
$FileNamePatternsAll.Rows.Add("*.bak*","","None.","Backup","") | Out-Null
@@ -1176,7 +1574,6 @@ function Analyze-HuntSMBShares
$FileNamePatternsAll.Rows.Add("*backup*","","None.","Backup","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.tar*","","None.","Backup","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.zip*","","None.","Backup","") | Out-Null
- $FileNamePatternsAll.Rows.Add("IT*","May contain IT department files","None.","Backup","") | Out-Null
# Add rows to data table - Scripts
$FileNamePatternsAll.Rows.Add("*.ps1*","","None.","Script","") | Out-Null
@@ -1192,7 +1589,6 @@ function Analyze-HuntSMBShares
$FileNamePatternsAll.Rows.Add("*.dll","","None.","Binaries","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.exe","","None.","Binaries","") | Out-Null
$FileNamePatternsAll.Rows.Add("*.msi","","None.","Binaries","") | Out-Null
- $FileNamePatternsAll.Rows.Add("*Program Files*","This is an application directory.","None.","Binaries","") | Out-Null
# Use keyword from define file instead
if($FileKeywordsPath){
@@ -1695,7 +2091,7 @@ function Analyze-HuntSMBShares
$RiskLevelCountLow = $ExcessiveSharePrivsFinal | where RiskLevel -eq 'Low' | measure | select count -ExpandProperty count
$RiskLevelCountMedium = $ExcessiveSharePrivsFinal | where RiskLevel -eq 'Medium' | measure | select count -ExpandProperty count
$RiskLevelCountHigh = $ExcessiveSharePrivsFinal | where RiskLevel -eq 'High' | measure | select count -ExpandProperty count
- $RiskLevelCountCritical = $ExcessiveSharePrivsFinal | where RiskLevel -eq 'Critical' | measure | select count -ExpandProperty count
+ $RiskLevelCountCritical = $ExcessiveSharePrivsFinal | where RiskLevel -eq 'Critical' | measure | select count -ExpandProperty count
# ----------------------------------------------------------------------
# Create Timeline Reports
@@ -1771,7 +2167,7 @@ function Analyze-HuntSMBShares
Write-Output " [*][$Time] - $ComputerwithHighRisk ($PercentComputerHighRiskP) domain computers had shares that are HIGH RISK."
Write-Output " [*][$Time] "
Write-Output " [*][$Time] SHARE SUMMARY"
- Write-Output " [*][$Time] - $AllSMBSharesCount shares were found. We expected a minimum of $MinExpectedShareCount shares"
+ Write-Output " [*][$Time] - $AllSMBSharesCount shares were found. We expect a minimum of $MinExpectedShareCount shares"
Write-Output " [*][$Time] because $Computers445OpenCount systems had open ports and there are typically two default shares."
Write-Output " [*][$Time] - $SharesNonDefaultCount ($PercentSharesNonDefaultP) shares across $ComputerwithNonDefaultCount systems were non-default."
Write-Output " [*][$Time] - $ExcessiveSharesCount ($PercentSharesExPrivP) shares across $ComputerWithExcessive systems are configured with $ExcessiveSharePrivsCount potentially excessive ACLs."
@@ -1787,15 +2183,15 @@ function Analyze-HuntSMBShares
Write-Output " [*][$Time] - $AclWithWriteCount ($PercentAclWriteP) ACLs were found that allowed WRITE access."
Write-Output " [*][$Time] - $AclHighRiskCount ($PercentAclHighRiskP) ACLs were found that are associated with HIGH RISK share names."
Write-Output " [*][$Time] "
- Write-Output " [*][$Time] - The $SampleSum most common share names are:"
+ Write-Output " [*][$Time] - The 5 most common share names are:"
Write-Output " [*][$Time] - $Top5ShareCountTotal of $AllAccessibleSharesCount ($DupPercent) discovered shares are associated with the top $SampleSum share names."
$CommonShareNamesTop5 |
foreach {
$ShareCount = $_.count
- $ShareName = $_.name
+ $ShareName = $_.name
Write-Output " [*][$Time] - $ShareCount $ShareName"
}
-
+
# Estimate report generation time
$ReportGenTimeEstimate = "Unknown"
If($AllSMBSharesCount -le 500 ) {$ReportGenTimeEstimate = "1 minute or less" }
@@ -1806,8 +2202,7 @@ function Analyze-HuntSMBShares
If($AllSMBSharesCount -ge 15000 ) {$ReportGenTimeEstimate = "25 minutes or less" }
If($AllSMBSharesCount -ge 30000 ) {$ReportGenTimeEstimate = "30 minutes or less" }
-
- Write-Output " [*] -----------------------------------------------"
+ Write-Output " [*] -----------------------------------------------"
Write-Output " [*][$Time] - Generating HTML Report"
Write-Output " [*][$Time] - Estimated generation time: $ReportGenTimeEstimate"
@@ -1825,13 +2220,13 @@ function Analyze-HuntSMBShares
$ThisFileBars = Get-GroupFileBar -DataTable $ExcessiveSharePrivs -Name $FileGroupName -AllComputerCount $ComputerCount -AllShareCount $AllSMBSharesCount -AllAclCount $ShareACLsCount
$ComputerBarF = $ThisFileBars.ComputerBar
$ShareBarF = $ThisFileBars.ShareBar
- $AclBarF = $ThisFileBars.AclBar
+ $AclBarF = $ThisFileBars.AclBar
$ThisFileListPrep = $ThisFileBars.FileList
$ThisFileList = $ThisFileListPrep -replace "`n", " "
$ThisFileCount = $ThisFileBars.FileCount
$ThisFileShareCount = $ThisFileBars.Sharecount
$ThisFileShareNameList = $ExcessiveSharePrivs | where FileListGroup -eq $FileGroupName | select ShareName -unique -expandproperty sharename | foreach { "$_ "}
- $ThisFileShareNameListUniqueCount = $ThisFileShareNameList | measure | select count -ExpandProperty count
+ $ThisFileShareNameListUniqueCount = $ThisFileShareNameList | measure | select count -ExpandProperty count
$ShareFileShareUnc = $ExcessiveSharePrivs | where FileListGroup -eq $FileGroupName | select SharePath -unique -expandproperty SharePath | foreach { "$_ "}
$ThisRow = @"
@@ -1860,7 +2255,7 @@ function Analyze-HuntSMBShares
$AclBarF
-"@
+"@
$ThisRow
}
@@ -2622,12 +3017,98 @@ function Analyze-HuntSMBShares
# Set default
$ShareRowCountInteresting = "No"
+ # Define common image and other formats to filter out later
+ $ImageFormats = @("*.jpg", "*.jpeg", "*.png", "*.gif", "*.bmp", "*.ico", "*.svg", "*.webp", "*.mif", "*.heic", "*.msi")
+
# Check if interesting files - Secrets
# Files that may contain passwords, key, or other authentication tokens
$ShareRowInterestingFileListSecrets = ""
$ShareRowInterestingFileListSecretsCount = 0
$ShareRowCountInterestingSecrets = "No"
-
+ $FileNamePatternsSecrets = @(
+ "*.bacpac*",
+ "*.bat*",
+ "*.config*",
+ "*.dtsx*",
+ "*.json*",
+ "*.ps1*",
+ "*.psm1*",
+ "*.UDL*",
+ "*config.php*",
+ "*Credentials*",
+ "*Creds*",
+ "*keys*",
+ "*pass*",
+ "*private*",
+ "*secret*",
+ "*secure*",
+ "*security*",
+ "*web.conf*",
+ "*htaccess*",
+ "*htpasswd*",
+ "*inetpub*",
+ "applicationhost.config*",
+ "auth*",
+ "config.xml*",
+ "context.xml*",
+ "db2cli.ini*",
+ "ftpd.*",
+ "ftpusers*",
+ "httpd.conf*",
+ "hudson.security.HudsonPrivateSecurityRealm.*",
+ "jboss-cli.xml*",
+ "jboss-logmanager.properties*",
+ "jenkins.model.JenkinsLocationConfiguration.*",
+ "machine.config*",
+ "my.*",
+ "mysql.user*",
+ "nginx.conf*",
+ "*ntds.dit*",
+ "pg_hba.conf*",
+ "php.ini*",
+ "putty.reg*",
+ "postgresql.conf*",
+ "SAM",
+ "SAM-*",
+ "SAM_*",
+ "SYSTEM",
+ "server.xml*",
+ "shadow*",
+ "standalone.xml*",
+ "tnsnames.ora*",
+ "tomcat-users.xml*",
+ "sitemanager.xml*",
+ "users.*",
+ "*.vmx*",
+ "*.vmdk*",
+ "*.nvram*",
+ "*.vmsd*",
+ "*.vmsn*",
+ "*.vmss*",
+ "*.vmem*",
+ "*.vhd*",
+ "*.vhdx*",
+ "*.avhd*",
+ "*.avhdx*",
+ "*.vsv*",
+ "*.vbox*",
+ "*.vbox-prev*",
+ "*.vdi*",
+ "*.hdd*",
+ "*.sav*",
+ "*.pvm*",
+ "*.pvs*",
+ "*.qcow*",
+ "*.qcow2*",
+ "*.img*",
+ "*vcenter*",
+ "*vault*",
+ "*DefaultAppPool*",
+ "*WinSCP.ini*",
+ "*.kdbx",
+ "wp-config.php*"
+ )
+
# Check for matches
$ShareRowInterestingFileListSecrets = foreach ($pattern in $FileNamePatternsSecrets) {
@@ -2676,6 +3157,29 @@ function Analyze-HuntSMBShares
$ShareRowInterestingFileListData = ""
$ShareRowInterestingFileListDataCount = 0
$ShareRowCountInterestingData = "No"
+ $FileNamePatternsData = @(
+ "*credit*",
+ "*card*",
+ "*pci*",
+ "*social*",
+ "*ssn*",
+ "*database*",
+ "human*",
+ "finance*",
+ "Health*",
+ "Billing*",
+ "patient*",
+ "*.bak*",
+ "*backup*",
+ "*.sql",
+ "*.mdb",
+ "*.mdf",
+ "*.idf",
+ "*.sqlite",
+ "*ftp",
+ "*Program Files*",
+ "HR*"
+ )
# Check for matches
$ShareRowInterestingFileListData = foreach ($pattern in $FileNamePatternsData) {
@@ -3058,7 +3562,7 @@ function Analyze-HuntSMBShares
-"@
+"@
$ThisRow
}
@@ -3134,8 +3638,8 @@ $NewHtmlReport = @"
Report
-
@@ -4344,8 +4845,8 @@ input[type="checkbox"]:checked::before {
Share Names
Folder Groups
Affected Subnets
- Share Owners
- Group ACL Summary
+ Share Owners
+ Group ACL Summary
Recommendations
Exploit Share Access
Detect Share Scans
@@ -4731,7 +5232,7 @@ Below is a summary of the domain computers that were targeted, connectivity to t
100.00%
$ComputerCount
- CSV | HTML
+ CSV | HTML
PING RESPONSE
@@ -4803,8 +5304,8 @@ Below is a summary of the domain computers that were targeted, connectivity to t
Share Summary
Below is a summary of the SMB shares discovered on domain computers that may provide excessive privileges to standard domain users.
-
+