Script Guide: Automate Rogue DHCP Server Detection with PowerShell

Key takeaways

  • Automated rogue DHCP detection: The script automates the process of detecting unauthorized DHCP servers, enhancing network security.
  • Nmap integration: Utilizes nmap for comprehensive network scanning, requiring its prior installation.
  • Customizable parameters: Allows for customization through parameters like allowed DHCP servers and output fields.
  • Subnet-focused scanning: Extracts and scans subnets, ensuring targeted and efficient network analysis.
  • Real-time security maintenance: Ideal for regular network checks, helping maintain real-time security and operational integrity.
  • Easy comparison with allowed list: Automatically compares detected servers against a pre-defined list of authorized DHCP servers.
  • Automated output and reporting: Outputs findings in a user-friendly format and integrates with network management tools like NinjaOne.
  • Enhanced network management: Streamlines network management, especially for IT professionals and MSPs handling large networks.
  • Risk minimization: Significantly reduces the risk of network issues and security breaches caused by rogue DHCP servers.
  • Administrative rights required: Requires administrative privileges to run effectively.

Understanding and managing network security is a cornerstone of efficient IT operations, especially in today’s interconnected environment. Identifying rogue DHCP servers, which can cause serious network issues and security vulnerabilities, is a critical task for IT professionals and Managed Service Providers (MSPs). This blog post delves into a PowerShell script designed for this purpose, outlining its functionality and importance in maintaining network integrity.

Background

Rogue DHCP servers are unauthorized DHCP servers on a network. They can lead to a range of problems, from IP address conflicts to severe security risks like man-in-the-middle attacks. This PowerShell script automates the process of finding such servers using nmap, a renowned network scanning tool, enhancing network security and operational efficiency. It’s particularly useful for IT professionals and MSPs who manage large, dynamic networks where manual monitoring is impractical.

The script:

#Requires -Version 4.0

<#
.SYNOPSIS
    Runs an nmap scan to find rogue dhcp servers on a network. This script will not install nmap and nmap is required for this script to work.
.DESCRIPTION
    Runs an nmap scan to find rogue dhcp servers on a network. This script will not install nmap and nmap is required for this script to work.
.EXAMPLE
    (No Parameters)
    
    DHCP Servers found.

    Mac Address       IP Address    
    -----------       ----------    
    00:15:5D:FF:93:C3 172.17.240.1  
                      172.17.242.16 
    00:15:5D:45:D5:07 172.17.251.231



    Checking allowed servers list...
    C:\ProgramData\NinjaRMMAgent\scripting\customscript_gen_14.ps1 : Rogue DHCP Server Found! 172.17.240.1 is not on the 
    list of allowed DHCP Servers.
        + CategoryInfo          : NotSpecified: (:) [Write-Error], WriteErrorException
        + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,customscript_gen_14.ps1

PARAMETER: -AllowedServers "172.17.240.1"
    Lists 172.17.240.1 as an allowed dhcp server.

PARAMETER: -CustomField "ReplaceMeWithAnyMultilineCustomField"
    Output results to a custom field of your choice.

PARAMETER: -AllowedServersField "ReplaceMeWithAnyTextCustomField"
    Will retrieve a list of allowed servers from a custom field.
    
.OUTPUTS
    None
.NOTES
    Minimum Supported OS: Windows 8, Server 2012
    Release Notes: Initial Release
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use.
    Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. 
    Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. 
    Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. 
    Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. 
    Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. 
    Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. 
    EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
#>

[CmdletBinding()]
param (
    [Parameter()]
    [String[]]$AllowedServers,
    [Parameter()]
    [String]$CustomField = "rogueDHCPServers",
    [Parameter()]
    [String]$AllowedServersField = "allowedDHCPServers"
)

begin {

    # If script variables are used set them here
    if($env:allowedServersCustomField -and $env:allowedServersCustomField -notlike "null"){
        $AllowedServersField = $env:allowedServersCustomField
    }

    if($AllowedServersField -and -not ($AllowedServers)){
        $AllowedServers = (Ninja-Property-Get $AllowedServersField) -split ',' | ForEach-Object { ($_).trim() }
    }

    if($env:allowedServers -and $env:allowedServers -notlike "null"){
        $AllowedServers = $env:AllowedServers -split ',' | ForEach-Object { ($_).trim() }
    }

    if($env:customFieldName -and $env:customFieldName -notlike "null"){
        $CustomField = $env:customFieldName 
    }

    # Parses out the subnet info into cidr format
    function Get-Subnet {
        $DefaultGateways = (Get-NetIPConfiguration).IPv4DefaultGateway

        $Subnets = $DefaultGateways | ForEach-Object {
            $Index = $_.ifIndex
            $PrefixLength = (Get-NetIPAddress | Where-Object { $_.AddressFamily -eq 'IPv4' -and $_.PrefixOrigin -ne 'WellKnown' -and $Index -eq $_.InterfaceIndex } | Select-Object -ExpandProperty PrefixLength)
            if ($_.NextHop -and $PrefixLength) {
                "$($_.NextHop)/$PrefixLength"
            }
        }

        if ($Subnets) {
            $Subnets | Select-Object -Unique
        }
    }

    # Handy uninstall string finder
    function Find-UninstallKey {
        [CmdletBinding()]
        param (
            [Parameter(ValueFromPipeline = $True)]
            [String]$DisplayName,
            [Parameter()]
            [Switch]$UninstallString
        )
        process {
            $UninstallList = New-Object System.Collections.Generic.List[Object]

            $Result = Get-ChildItem HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Get-ItemProperty | Where-Object { $_.DisplayName -like "*$DisplayName*" }
            if ($Result) { $UninstallList.Add($Result) }

            $Result = Get-ChildItem HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Get-ItemProperty | Where-Object { $_.DisplayName -like "*$DisplayName*" }
            if ($Result) { $UninstallList.Add($Result) }

            # Programs don't always have an uninstall string listed here so to account for that I made this optional.
            if ($UninstallString) {
                $UninstallList | Select-Object -ExpandProperty UninstallString -ErrorAction SilentlyContinue
            }
            else {
                $UninstallList
            }
        }
    }

    $Nmap = (Find-UninstallKey -DisplayName "Nmap" -UninstallString) -replace '"' -replace 'uninstall.exe', 'nmap.exe'
    if (-not $Nmap) {
        Write-Error "Nmap is not installed! Please install nmap prior to running this script. https://nmap.org/download.html"
        exit 1
    }
}
process {

    # Get's a list of subnets
    $Subnets = Get-Subnet
    if (-not $Subnets) {
        Write-Error "Unable to get list of subnets?"
        exit 1
    }

    # nmap arguments
    $Arguments = @(
        "-sU"
        "-p"
        "67"
        "-d"
        $Subnets
        "--open"
        "-oX"
        "$env:TEMP\nmap-results.xml"
    )
    try {
        Start-Process -FilePath $Nmap -ArgumentList $Arguments -WindowStyle Hidden -Wait
        [xml]$result = Get-Content -Path "$env:Temp\nmap-results.xml"
    }
    catch {
        Write-Error "Nmap scan failed to run! Ensure nmap is installed prior to running this script."
        exit 1
    }

    # Parse the xml results
    if ($result) {
        $resultObject = $result.DocumentElement.host | ForEach-Object {
            New-Object psobject -Property @{
                "IP Address"  = ($_.address | Where-Object { $_.addrtype -match "ip" } | Select-Object -ExpandProperty "addr")
                "Mac Address" = ($_.address | Where-Object { $_.addrtype -match "mac" } | Select-Object -ExpandProperty "addr")
            }
        }
    }
    else {
        Write-Error "Nmap results are empty?"
        exit 1
    }

    # Check if the dhcp servers found are on the list. If so simply report back what were found otherwise indicate that they're Rogue DHCP Servers.
    if ($resultObject) {
        Write-Host "DHCP Servers found."
        $resultObject | Sort-Object -Property "IP Address" -Unique | Format-Table | Out-String | Write-Host
        Remove-Item -Path "$env:Temp\nmap-results.xml" -Force

        Write-Host "Checking allowed servers list..."
        $ErrorOut = $False
        $resultObject | ForEach-Object {
            if ($AllowedServers -notcontains $_."IP Address") {
                Write-Error "Rogue DHCP Server Found! $($_.'IP Address') is not on the list of allowed DHCP Servers."
                $ErrorOut = $True
            }
        }

        Ninja-Property-Set -Name $CustomField -Value ($resultObject | Where-Object { $AllowedServers -notcontains $_."IP Address" } | Format-List | Out-String)

        if($ErrorOut -eq $True){
            exit 1
        }

        Write-Host "No rogue dhcp servers found."
    }
}
end {
    
    
    
}

 

Access over 300+ scripts in the NinjaOne Dojo

Get Access

Detailed breakdown

The script functions in several stages:

  • Initialization: It begins by setting parameters like allowed DHCP servers and custom fields for output, allowing for customization according to specific network environments.
  • Subnet identification: It employs a function to extract subnet information from the network, crucial for targeting the scan.
  • Nmap integration: The script checks for nmap installation, which is essential for scanning. It then executes an nmap scan on identified subnets, looking for active DHCP servers.
  • Result parsing: After scanning, the script parses the XML output from nmap, extracting IP and MAC addresses of DHCP servers found.
  • Validation against allowed list: It compares found DHCP servers against a list of authorized servers, flagging any unauthorized (rogue) servers.
  • Output and cleanup: The results are then outputted, and any temporary files created by the script are cleaned up.

A visual diagram accompanying this explanation could illustrate the flow from initialization to result output, enhancing understanding.

Potential use cases

Consider a large enterprise with multiple subnets managed by an IT department. This script could be scheduled to run periodically, ensuring no unauthorized DHCP servers appear on the network, thus maintaining network integrity and preventing potential security breaches.

Comparisons

Manual checks or basic network monitoring tools might miss rogue DHCP servers or require extensive manpower. In contrast, this script automates the process, is more thorough, and integrates with existing tools like NinjaOne for enhanced management capabilities.

FAQs

  • How often should I run this script?
    • Regular execution, such as weekly or after any major network changes, is recommended.
  • Do I need special permissions to run this script?
    • Yes, administrative rights are typically required for network scanning.

Implications

Unidentified rogue DHCP servers can lead to significant security risks. Automating their detection minimizes these risks, contributing to overall network security and operational efficiency.

Recommendations

  • Regularly update the allowed DHCP servers list.
  • Integrate this script with broader network monitoring and management tools.
  • Ensure that nmap is properly installed and updated.

Final thoughts

In the realm of network security and management, tools like NinjaOne, complemented with scripts like this, offer robust solutions for maintaining network integrity. By automating critical tasks, such as finding rogue DHCP servers, NinjaOne helps IT professionals focus on strategic initiatives while ensuring the security and reliability of their networks.

Next Steps

Building an efficient and effective IT team requires a centralized solution that acts as your core service deliver tool. NinjaOne enables IT teams to monitor, manage, secure, and support all their devices, wherever they are, without the need for complex on-premises infrastructure.

Learn more about NinjaOne Remote Script Deployment, check out a live tour, or start your free trial of the NinjaOne platform.

Categories:

You might also like

Watch Demo×
×

See NinjaOne in action!

By submitting this form, I accept NinjaOne's privacy policy.

NinjaOne Terms & Conditions

By clicking the “I Accept” button below, you indicate your acceptance of the following legal terms as well as our Terms of Use:

  • Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms.
  • Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party.
  • Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library belonging to or under the control of any other software provider.
  • Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations.
  • Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks.
  • Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script.
  • EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).