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