PowerShell Security Automation

PowerShell Security Automation

PowerShell provides comprehensive Windows automation capabilities with deep OS integration. Modern PowerShell Core extends these capabilities cross-platform, enabling unified automation across Windows and Linux systems. Understanding PowerShell's security features and best practices ensures safe, effective automation implementation.

Implement automated security baseline configuration:

# Comprehensive Windows security baseline script
[CmdletBinding()]
param(
    [Parameter(Mandatory=$false)]
    [string]$ConfigFile = ".\security_baseline.json",
    
    [Parameter(Mandatory=$false)]
    [switch]$ValidateOnly
)

# Load configuration
$Config = Get-Content $ConfigFile | ConvertFrom-Json

# Logging function
function Write-SecurityLog {
    param(
        [string]$Message,
        [string]$Level = "INFO"
    )
    $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $LogEntry = "$Timestamp [$Level] $Message"
    Add-Content -Path ".\security_automation.log" -Value $LogEntry
    
    switch ($Level) {
        "ERROR" { Write-Error $Message }
        "WARNING" { Write-Warning $Message }
        default { Write-Information $Message -InformationAction Continue }
    }
}

# Security configuration functions
function Set-PasswordPolicy {
    param($PolicyConfig)
    
    try {
        Write-SecurityLog "Configuring password policy"
        
        # Set domain password policy
        Set-ADDefaultDomainPasswordPolicy -Identity (Get-ADDomain).DistinguishedName `
            -MinPasswordLength $PolicyConfig.MinLength `
            -PasswordHistoryCount $PolicyConfig.HistoryCount `
            -MaxPasswordAge (New-TimeSpan -Days $PolicyConfig.MaxAgeDays) `
            -MinPasswordAge (New-TimeSpan -Days $PolicyConfig.MinAgeDays) `
            -ComplexityEnabled:$PolicyConfig.ComplexityEnabled
        
        # Configure fine-grained password policies if needed
        foreach ($Policy in $PolicyConfig.FineGrainedPolicies) {
            New-ADFineGrainedPasswordPolicy -Name $Policy.Name `
                -Precedence $Policy.Precedence `
                -MinPasswordLength $Policy.MinLength `
                -PasswordHistoryCount $Policy.HistoryCount `
                -ComplexityEnabled:$Policy.ComplexityEnabled `
                -AppliesTo $Policy.AppliesTo
        }
        
        Write-SecurityLog "Password policy configuration completed"
    }
    catch {
        Write-SecurityLog "Failed to configure password policy: $_" -Level ERROR
        throw
    }
}

function Set-AuditPolicy {
    param($AuditConfig)
    
    try {
        Write-SecurityLog "Configuring audit policy"
        
        foreach ($Category in $AuditConfig.PSObject.Properties) {
            $CategoryName = $Category.Name
            $Settings = $Category.Value
            
            if ($Settings -contains "Success" -and $Settings -contains "Failure") {
                auditpol /set /subcategory:"$CategoryName" /success:enable /failure:enable
            }
            elseif ($Settings -contains "Success") {
                auditpol /set /subcategory:"$CategoryName" /success:enable /failure:disable
            }
            elseif ($Settings -contains "Failure") {
                auditpol /set /subcategory:"$CategoryName" /success:disable /failure:enable
            }
        }
        
        Write-SecurityLog "Audit policy configuration completed"
    }
    catch {
        Write-SecurityLog "Failed to configure audit policy: $_" -Level ERROR
        throw
    }
}

# Main execution
try {
    if ($ValidateOnly) {
        Write-SecurityLog "Running in validation mode"
        # Perform validation checks
        exit 0
    }
    
    # Create system restore point
    Checkpoint-Computer -Description "Pre-Security-Automation" -RestorePointType MODIFY_SETTINGS
    
    # Apply configurations
    Set-PasswordPolicy -PolicyConfig $Config.PasswordPolicy
    Set-AuditPolicy -AuditConfig $Config.AuditPolicy
    
    Write-SecurityLog "Security automation completed successfully"
}
catch {
    Write-SecurityLog "Security automation failed: $_" -Level ERROR
    # Attempt rollback
    Get-ComputerRestorePoint | Where-Object {$_.Description -eq "Pre-Security-Automation"} | Restore-Computer
}

Automate threat hunting with PowerShell:

# Automated threat hunting script
function Hunt-SecurityThreats {
    [CmdletBinding()]
    param(
        [datetime]$StartTime = (Get-Date).AddHours(-24),
        [string[]]$ComputerName = $env:COMPUTERNAME
    )
    
    $Threats = @()
    
    foreach ($Computer in $ComputerName) {
        # Check for suspicious PowerShell activity
        $SuspiciousPS = Get-WinEvent -ComputerName $Computer -FilterHashtable @{
            LogName = 'Microsoft-Windows-PowerShell/Operational'
            ID = 4104
            StartTime = $StartTime
        } | Where-Object {
            $_.Message -match 'IEX|Invoke-Expression|DownloadString|EncodedCommand|bypass|hidden'
        }
        
        if ($SuspiciousPS) {
            $Threats += [PSCustomObject]@{
                Computer = $Computer
                Type = "Suspicious PowerShell"
                Count = $SuspiciousPS.Count
                Details = $SuspiciousPS | Select-Object -First 5
            }
        }
        
        # Check for unusual network connections
        $UnusualConnections = Invoke-Command -ComputerName $Computer -ScriptBlock {
            Get-NetTCPConnection | Where-Object {
                $_.State -eq 'Established' -and
                $_.RemotePort -in @(4444, 5555, 8080, 8888) -and
                $_.OwningProcess -ne 0
            }
        }
        
        if ($UnusualConnections) {
            $Threats += [PSCustomObject]@{
                Computer = $Computer
                Type = "Unusual Network Connection"
                Count = $UnusualConnections.Count
                Details = $UnusualConnections
            }
        }
        
        # Check for persistence mechanisms
        $Persistence = @()
        
        # Scheduled tasks
        $SuspiciousTasks = Get-ScheduledTask -CimSession $Computer | Where-Object {
            $_.Actions.Execute -match 'powershell|cmd|wscript|cscript' -and
            $_.Principal.UserId -eq 'SYSTEM'
        }
        
        # Registry run keys
        $RunKeys = Invoke-Command -ComputerName $Computer -ScriptBlock {
            Get-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Run*',
                                   'HKCU:\Software\Microsoft\Windows\CurrentVersion\Run*' -ErrorAction SilentlyContinue
        }
        
        if ($SuspiciousTasks -or $RunKeys) {
            $Threats += [PSCustomObject]@{
                Computer = $Computer
                Type = "Persistence Mechanism"
                Count = ($SuspiciousTasks.Count + $RunKeys.Count)
                Details = @{Tasks = $SuspiciousTasks; Registry = $RunKeys}
            }
        }
    }
    
    # Generate report
    if ($Threats) {
        $Report = @{
            Timestamp = Get-Date
            ThreatCount = $Threats.Count
            Threats = $Threats
        }
        
        $Report | ConvertTo-Json -Depth 5 | Out-File "ThreatHunt_$(Get-Date -Format yyyyMMdd_HHmmss).json"
        
        # Send alert
        Send-MailMessage -To "[email protected]" `
                         -Subject "Threat Hunting Alert: $($Threats.Count) threats detected" `
                         -Body ($Threats | Format-Table | Out-String) `
                         -Priority High
    }
    
    return $Threats
}

# Schedule automated threat hunting
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" `
    -Argument "-NoProfile -ExecutionPolicy Bypass -Command `"& 'C:\Scripts\Hunt-SecurityThreats.ps1'`""
$Trigger = New-ScheduledTaskTrigger -Daily -At 2AM
Register-ScheduledTask -TaskName "AutomatedThreatHunt" -Action $Action -Trigger $Trigger -RunLevel Highest