Hardening SMB on Domain Controllers, Step 1: Reporting on SMBv1 connections , SMBv2 connections and SMB null sessions

Reading Time: 3 minutes

Server Message Block

Server Message Block (SMB) is a critical component for any Microsoft-oriented networking environment. That’s why hardening SMB is one of the critical steps in securing Active Directory Domain Controllers.

In this blog post series, I’ll share my approach on hardening SMB on Domain Controllers.

Tip!
I apply this approach to Active Directory Domain Controllers, but you can reuse this approach on any Windows Server installation.

Many admins struggle with following Microsoft’s documentation to detect, enable and disable SMBv1, SMBv2, and SMBv3. Microsoft’s method is based on detecting the role and not on detecting sessions. I feel this method is incomplete and inadequate.

With the PowerShell script below, you can create a report of all SMB connections to an Active Directory Domain Controller running Windows Server 2016. Then, you have the information that you need to disable SMBv1, potentially disable SMBv2 and rule out SMB null sessions.

Note:
SMBv2 is currently not as problematic as SMBv1 and thus as urgent as disabling SMBv1.

My definition of reporting on SMB is that you know:

  • If there are connections using SMBv1 and/or SMBv2
  • If there are connections using these protocols, you know from what hosts these connections are made and what account is making these connections (where applicable)
  • If there are connections using these protocols, you know how often are these connections made
  • If there are connections without credentials (‘null sessions’).

Because reporting in organizations is often through Microsoft Excel, I’ve made the decision to export the data to a comma-separated values (*.csv) file.

 

How to report on SMBv1 and SMBv2 connections

Reporting on SMBv1 and SMBv2 sessions is threefold:

Script to gather incoming SMB sessions

The following Windows PowerShell script is a wrapper around the Get-SmbSession cmdlet. It interprets the output of this cmdlet. That way we get information on the incoming SMB connections to the Domain Controller. We then interpret this information and filter out any duplicates. If a duplicate is found, an occurrence value is upped. This way, you know how many connections are made and when the last date was the connection was made.

[array]$ResultArray = Import-Csv C:\Scripts\IncomingSMBConnections.csv

$ServerConnections = Get-SmbSession
foreach ($Connection in $ServerConnections) {
$Date = Get-Date -Format 'yyyy-MM-dd'
$ServerObject = [PSCustomObject]@{
  ClientComputerName = $Connection.ClientComputerName
  ClientUserName     = $Connection.ClientUserName
  Dialect            = $Connection.Dialect
  Date               = $Date
  Occurence          = 1
  }
  $ResultArray += $ServerObject
}

$Groups = $ResultArray | Group-Object ClientComputerName,ClientUserName,Dialect | where { $_.count -gt 1 }

foreach ($Group in $Groups) {
  for ($i = 0; $i -lt $Group.Count; $i++) {
   $Object = $ResultArray | where { $_ -eq $Group.Group[$i] }
   $object.Occurence = $Group.Count
  }
}

$ResultArray | Export-Csv C:\Scripts\IncomingSMBConnections.csv

 

Place the script on the local server in a location like C:\Scripts and create an empty file named IncomingSMBConnections.csv next to it.

 

Scheduled task to run the script

This script can be scheduled to run every 5 minutes. Use the following lines of Windows PowerShell to schedule the script:

$Script = 'C:\Scripts\Gather-IncomingSMBSessions.ps1'
$TaskName
= 'Gather Incoming SMB Sessions'
$Description
= 'This task gathers incoming SMB connections'
$User = "NT AUTHORITY\SYSTEM"
$Executable
= "PowerShell.exe"

$Action
= New-ScheduledTaskAction -execute $Executable -Argument "-file $Script"

$Trigger
= New-ScheduledTaskTrigger -Once -At (Get-Date).Date -RepetitionInterval (New-TimeSpan -Minutes 5)

$Settings
= New-ScheduledTaskSettingsSet –StartWhenAvailable

Register-ScheduledTask -TaskName $TaskName -Trigger $Trigger -Action $Action -Setting $Settings -description $Description -User $User -RunLevel Highest

 

Excel skills to report on logged connections

The script provides a comma-separated values (*.csv) file. When you open the file in Microsoft Excel, you can convert the text to columns. Then, you can sort, etc.

  • Through the Dialect column, you can quickly identify any SMB 1.0 sessions: The value in the column would start with 1.
  • You can also quickly identify any SMB null sessions. For these sessions, the ClientUserName column would be empty.

 

Concluding

If you are unsure if you can disable SMBv1, SMBv2 and/or SMB null sessions on your Active Directory Domain Controllers, than this script helps you gathering the information you need.

In the next parts of this blog post series, we’ll look at disabling the default SMB configuration to meet our security requirements.

When done, simply delete the scheduled task and remove the Gather-IncomingSMBConnections.ps1 and IncomingSMBConnections.csv from the Domain Controller.

2 Responses to Hardening SMB on Domain Controllers, Step 1: Reporting on SMBv1 connections , SMBv2 connections and SMB null sessions

  1.  

    I wanted to keep a log of one unique record per connection, updated with the most recent connection datetime and with the total number of connections found in all the script runs (minute precision to help us track clients down).

    The original script seems to be exporting duplicates of each occurrence, each updated with the total Occurrences number – not sure if that's deliberate.

    I only wanted lower SMB versions as well, so I added a filter and something to skip the rest of the script if no there are no results in that run:

    $ServerConnections = Get-SmbSession | where {$_.Dialect -lt 3}
    If (-not $ServerConnections) {
    write-output "No results"
    Break
    }

    For the Group-Object subroutine, each group's member objects are sorted by Date and the most recent is selected (obviously it can be a bit random if the precision is only by day). That object's Occurrence property is updated with the sum of all the Group's objects' Occurrence values before it's added to the $Results array for exporting.

    $Groups = $ResultArray | Group-Object ClientComputerName,ClientUserName,Dialect
    $Results = foreach ($Group in $Groups) {
    $g = ($Group.Group |sort Date -Descending)[0]
    $g.Occurrence = ($Group.Group | measure-object -Sum Occurrence).sum
    $g
    }
    $Results | Export-Csv $resultFile -NoTypeInformation

    This also helps keep the output file size down when running it fairly frequently over a few days.

  2.  

    thanks, good script.
    appreciate publishing it.

leave your comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.