Enumerate-ADSecurityBaseline.ps1


<#PSScriptInfo
 
.VERSION 1.0.1
 
.GUID 24ca6a33-e51f-4d26-b723-97318dec940a
 
.AUTHOR kalichuza
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Enumerates common AD weak point.
 
#>
 

<#
.SYNOPSIS
Performs a comprehensive Active Directory security baseline enumeration with checks for privileged users, password policies, shadow copy permissions, logging configurations, audit policies, and service accounts.
 
.DESCRIPTION
This script conducts various security checks in an Active Directory environment, including:
 
- Enumerating privileged users and groups (Domain Admins, Enterprise Admins, Schema Admins, Administrators)
- Evaluating the domain's password policy
- Checking permissions on shadow copies and critical files
- Gathering logging configurations for system, security, and PowerShell logs
- Extracting Active Directory group policies related to auditing
- Listing service accounts and their associated Service Principal Names (SPNs)
 
The script can display results in the console or save them to a specified output file. It includes color-coded console output for ease of interpretation.
 
.PARAMETER OutputFile
(Optional) Path to a file where the results will be saved. If not specified, the results will only be displayed on the console.
 
.PARAMETER SaveToFile
(Optional) Switch to save results to a file. If enabled, you must provide an OutputFile. If not enabled, results will be output to the console only.
 
.PARAMETER ExpectedUsers
(Optional) An array of expected privileged user accounts. If any unexpected users are found in the privileged groups, a warning will be shown. Defaults to "ExpectedAdmin1" and "ExpectedAdmin2."
 
.EXAMPLE
.\AD-SecurityBaseline.ps1
 
This command runs the script with default settings, displaying the output in the console without saving to a file.
 
.EXAMPLE
.\AD-SecurityBaseline.ps1 -SaveToFile -OutputFile "C:\Reports\SecurityBaseline.txt"
 
This command runs the script and saves the results to the specified file while still displaying them in the console.
 
.EXAMPLE
.\AD-SecurityBaseline.ps1 -ExpectedUsers @("AdminUser1", "AdminUser2")
 
This command runs the script and checks for unexpected users in privileged groups, considering "AdminUser1" and "AdminUser2" as the expected users.
 
.NOTES
- The script requires the `ActiveDirectory` module to be installed and the user must have appropriate permissions to query AD groups and settings.
- Ensure that PowerShell script block logging is configured for best practice monitoring.
#>



[CmdletBinding()]
param (
    [string]$OutputFile = "",
    [switch]$SaveToFile = $false,
    [string[]]$ExpectedUsers 
)

# Function to write output to console or file with color
function Write-OutputData {
    param (
        [string]$Data,
        [string]$ForegroundColor = "White"
    )
    if ($SaveToFile -and $OutputFile) {
        Add-Content -Path $OutputFile -Value $Data
    }
    Write-Host $Data -ForegroundColor $ForegroundColor
}

# Function to display ASCII art in color
function Show-AsciiArt {
    param (
        [string]$Art
    )
    Write-Host $Art -ForegroundColor Cyan
}

# Placeholder for the ASCII art (you can replace this with your own)
$asciiArt = @"
##########################################################
   
 █████╗ ██████╗ ███████╗███╗ ██╗██╗ ██╗███╗ ███╗
██╔══██╗██╔══██╗ ██╔════╝████╗ ██║██║ ██║████╗ ████║
███████║██║ ██║ █████╗ ██╔██╗ ██║██║ ██║██╔████╔██║
██╔══██║██║ ██║ ██╔══╝ ██║╚██╗██║██║ ██║██║╚██╔╝██║
██║ ██║██████╔╝ ███████╗██║ ╚████║╚██████╔╝██║ ╚═╝ ██║
╚═╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝
                                                           
 
##########################################################
"@


# Function to enumerate privileged users and groups with conditional checks
function Get-PrivilegedUsersAndGroups {
    Write-OutputData "`n==== Enumerating Privileged Users and Groups ====" -ForegroundColor Yellow

    # Domain Admins group members
    $domainAdmins = Get-ADGroupMember -Identity 'Domain Admins'
    Write-OutputData "`nDomain Admins:" -ForegroundColor Cyan
    $domainAdmins | ForEach-Object { 
        Write-OutputData $_.SamAccountName
        if ($ExpectedUsers -notcontains $_.SamAccountName) {
            Write-OutputData "Warning: Unexpected member detected in Domain Admins: $($_.SamAccountName)" -ForegroundColor Red
        }
    }

    # Enterprise Admins group members
    $enterpriseAdmins = Get-ADGroupMember -Identity 'Enterprise Admins'
    Write-OutputData "`nEnterprise Admins:" -ForegroundColor Cyan
    $enterpriseAdmins | ForEach-Object { 
        Write-OutputData $_.SamAccountName
        if ($ExpectedUsers -notcontains $_.SamAccountName) {
            Write-OutputData "Warning: Unexpected member detected in Enterprise Admins: $($_.SamAccountName)" -ForegroundColor Red
        }
    }

    # Other admin groups like Schema Admins and Administrators
    $otherAdminGroups = @('Schema Admins', 'Administrators')
    foreach ($group in $otherAdminGroups) {
        $groupOutput = "`n${group}:"
        Write-OutputData $groupOutput -ForegroundColor Cyan
        $members = Get-ADGroupMember -Identity $group
        $members | ForEach-Object { 
            Write-OutputData $_.SamAccountName
            if ($ExpectedUsers -notcontains $_.SamAccountName) {
                Write-OutputData "Warning: Unexpected member detected in ${group}: $($_.SamAccountName)" -ForegroundColor Red
            }
        }
    }
}


# Function to check Password Policies and flag weak settings
function Get-PasswordPolicy {
    Write-OutputData "`n==== Password Policies ====" -ForegroundColor Yellow

    $domainPolicy = Get-ADDefaultDomainPasswordPolicy
    Write-OutputData "`nPassword Policy for the Domain:" -ForegroundColor Cyan
    Write-OutputData "MinimumPasswordLength: $($domainPolicy.MinPasswordLength)"
    Write-OutputData "MaximumPasswordAge: $($domainPolicy.MaxPasswordAge)"
    Write-OutputData "PasswordHistoryCount: $($domainPolicy.PasswordHistoryCount)"
    Write-OutputData "LockoutThreshold: $($domainPolicy.LockoutThreshold)"

    # Flag weak password settings
    if ($domainPolicy.MinPasswordLength -lt 12) {
        Write-OutputData "Warning: Minimum password length is less than 12 characters!" -ForegroundColor Red
    }
}

# Function to check for vulnerable permissions on Shadow Copy and VSS
function Check-ShadowCopyPermissions {
    Write-OutputData "`n==== Checking Shadow Copy Permissions ====" -ForegroundColor Yellow

    $vssPermissions = Get-WmiObject -Class Win32_ShadowCopy | Select-Object DeviceObject,ID,InstallDate
    Write-OutputData "Shadow Copies:" -ForegroundColor Cyan
    $vssPermissions | ForEach-Object {
        Write-OutputData "Shadow Copy ID: $($_.ID), InstallDate: $($_.InstallDate), DeviceObject: $($_.DeviceObject)"
    }

    $shadowCopyAccess = Get-Acl -Path "C:\Windows\System32\config\SYSTEM"
    Write-OutputData "`nPermissions on SYSTEM file (shadow copy target):" -ForegroundColor Cyan
    $shadowCopyAccess.Access | ForEach-Object {
        Write-OutputData "Identity: $($_.IdentityReference), Permissions: $($_.FileSystemRights)"
    }
}

# Function to get Event Log configurations (PowerShell, System, Security)
function Get-LoggingConfiguration {
    Write-OutputData "`n==== Logging Configuration ====" -ForegroundColor Yellow

    $logSettings = @('System', 'Security', 'Application', 'Microsoft-Windows-PowerShell/Operational')
    foreach ($log in $logSettings) {
        $logSize = Get-WinEvent -ListLog $log | Select-Object -ExpandProperty MaximumSizeInBytes
        Write-OutputData "`n$($log) Log:" -ForegroundColor Cyan
        Write-OutputData "Log Size (bytes): $logSize"
    }

    # PowerShell script block logging status
    $scriptBlockLogging = Get-ItemProperty -Path "HKLM:\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -ErrorAction SilentlyContinue
    if ($scriptBlockLogging) {
        Write-OutputData "`nPowerShell ScriptBlock Logging:" -ForegroundColor Cyan
        Write-OutputData "Enabled: $($scriptBlockLogging.EnableScriptBlockLogging)"
    } else {
        Write-OutputData "`nPowerShell ScriptBlock Logging: Not Configured" -ForegroundColor Cyan
    }
}

# Function to get Active Directory Group Policies related to auditing with cleaned-up XML output
function Get-AuditPolicies {
    Write-OutputData "`n==== Auditing Policies ====" -ForegroundColor Yellow
    
    $auditSettings = Get-GPOReport -All -ReportType Xml
    Write-OutputData "Active Directory Auditing Policies (Cleaned):" -ForegroundColor Cyan
    $auditSettings = [xml]$auditSettings
    $auditSettings.GPO.Report.Policy | ForEach-Object { 
        Write-OutputData "Policy Name: $($_.Name), Enabled: $($_.Enabled)" -ForegroundColor Cyan
    }
}

# Function to enumerate Service Accounts and Privileges
function Get-ServiceAccounts {
    Write-OutputData "`n==== Service Accounts Enumeration ====" -ForegroundColor Yellow

    $serviceAccounts = Get-ADUser -Filter {ServicePrincipalName -ne "$null"} -Property SamAccountName,ServicePrincipalName
    Write-OutputData "Service Accounts:" -ForegroundColor Cyan
    $serviceAccounts | ForEach-Object {
        Write-OutputData "Account: $($_.SamAccountName), SPN: $($_.ServicePrincipalName)"
    }
}

# Main enumeration with ASCII art and color
Write-OutputData "`nStarting AD Security Baseline Enumeration..." -ForegroundColor Green

# Display the ASCII art
Show-AsciiArt -Art $asciiArt

# Check if saving to a file is requested
if ($SaveToFile -and $OutputFile) {
    Write-OutputData "Results will be saved to: $OutputFile" -ForegroundColor Green
}

# Run enumeration functions
Get-PrivilegedUsersAndGroups
Get-PasswordPolicy
Check-ShadowCopyPermissions
Get-LoggingConfiguration
Get-AuditPolicies
Get-ServiceAccounts

Write-OutputData "`nEnumeration complete." -ForegroundColor Green