PowerShell Quick Guide: Creating Your First Security Audit Script

PowerShell Quick Guide: Creating Your First Security Audit Script
Hey there, fellow threat hunters! 👋 Today we're going to create your first PowerShell security audit script. Tired of running individual commands every time you need to check a system? Let's build something reusable that will make your life easier! You can find the full repository here:
SecurityScriptographer/PowerShell-Quick-Guide

Setting Up Our Script

First, let's create our basic script structure. We'll build this step by step:
param(
    [Parameter(Mandatory=$false)]
    [string]$OutputPath = ".\SecurityAudit_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt",
    
    [Parameter(Mandatory=$false)]
    [switch]$ExportToCSV
)

# Initialize our report
$report = @()
$startTime = Get-Date
Write-Host "Starting security audit at $startTime" -ForegroundColor Green

System Information Module

Let's start with basic system information - always good to know what you're dealing with:
function Get-SystemInfo {
    Write-Host "Collecting system information..." -ForegroundColor Yellow
    
    $os = Get-WmiObject -Class Win32_OperatingSystem
    $computerSystem = Get-WmiObject -Class Win32_ComputerSystem
    
    return @{
        'Hostname' = $env:COMPUTERNAME
        'OS Version' = $os.Caption
        'OS Architecture' = $os.OSArchitecture
        'Last Boot Time' = $os.ConvertToDateTime($os.LastBootUpTime)
        'Total Memory (GB)' = [math]::Round($computerSystem.TotalPhysicalMemory/1GB, 2)
        'Domain' = $computerSystem.Domain
    }
}

Security Settings Check

Now, let's add a function to check important security settings:
function Get-SecuritySettings {
    Write-Host "Checking security settings..." -ForegroundColor Yellow
    
    $firewallStatus = Get-NetFirewallProfile | Select-Object Name, Enabled
    $antivirusProduct = Get-WmiObject -Namespace root\SecurityCenter2 -Class AntiVirusProduct -ErrorAction SilentlyContinue
    
    return @{
        'Firewall Status' = ($firewallStatus | ForEach-Object { "$($_.Name): $($_.Enabled)" }) -join '; '
        'Antivirus Status' = if ($antivirusProduct) { $antivirusProduct.displayName } else { "No AV detected" }
        'PowerShell Version' = $PSVersionTable.PSVersion.ToString()
        'UAC Enabled' = (Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System).EnableLUA -eq 1
        'SecureBoot Enabled' = Confirm-SecureBootUEFI -ErrorAction SilentlyContinue
    }
}

User and Group Analysis

Let's add some user account auditing:
function Get-UserAudit {
    Write-Host "Auditing user accounts..." -ForegroundColor Yellow
    
    $localUsers = Get-LocalUser | Where-Object Enabled -eq $true
    $adminGroup = Get-LocalGroupMember -Group "Administrators" -ErrorAction SilentlyContinue
    
    return @{
        'Enabled Local Users' = ($localUsers | Select-Object Name).Name -join ', '
        'Local Admins' = ($adminGroup | Select-Object Name).Name -join ', '
        'Last 5 Created Users' = (Get-LocalUser | Sort-Object Created -Descending | 
            Select-Object -First 5 Name, Created | ForEach-Object { 
                "$($_.Name) (Created: $($_.Created))" 
            }) -join '; '
    }
}

Running Services and Network Connections

Time to check what's running and connecting:
function Get-RunningServices {
    Write-Host "Analyzing services and connections..." -ForegroundColor Yellow
    
    $suspiciousServices = Get-WmiObject win32_service | 
        Where-Object {$_.PathName -like "*temp*" -or $_.PathName -like "*appdata*"}
    
    $externalConnections = Get-NetTCPConnection -State Established |
        Where-Object {$_.RemoteAddress -notmatch "^10\.|^172\.|^192\.168\."}
    
    return @{
        'Suspicious Service Paths' = if ($suspiciousServices) {
            ($suspiciousServices | Select-Object DisplayName, PathName).DisplayName -join ', '
        } else { "None found" }
        'External Connections' = ($externalConnections | Measure-Object).Count
    }
}

Putting It All Together

Now for our main execution block:
try {
    # Create our report object
    $report = [ordered]@{
        'ScanTime' = Get-Date
        'SystemInformation' = Get-SystemInfo
        'SecuritySettings' = Get-SecuritySettings
        'UserAudit' = Get-UserAudit
        'ServiceAnalysis' = Get-RunningServices
    }
    
    # Export results based on format preference
    if ($ExportToCSV) {
        $reportPath = $OutputPath -replace '\.json$', '.csv'
        $report | ConvertTo-Json | 
            ConvertFrom-Json | 
            Export-Csv -Path $reportPath -NoTypeInformation
        Write-Host "Audit complete! Results saved to $reportPath" -ForegroundColor Green
    } else {
        $report | ConvertTo-Json -Depth 10 | 
            Out-File -FilePath $OutputPath -Encoding UTF8
        Write-Host "Audit complete! Results saved to $OutputPath" -ForegroundColor Green
        
        # Optionally display a summary in console
        Write-Host "`nQuick Summary:" -ForegroundColor Yellow
        Write-Host "- Hostname: $($report.SystemInformation.Hostname)"
        Write-Host "- OS Version: $($report.SystemInformation.OSVersion)"
        Write-Host "- External Connections Found: $($report.ServiceAnalysis.'External Connections')"
        Write-Host "- Enabled Local Users: $($report.UserAudit.'Enabled Local Users'.Split(',').Count)"
    }
} catch {
    Write-Host "Error during audit: $($_.Exception.Message)" -ForegroundColor Red
}

Running the Script

Save this as `Security-Audit.ps1` and run it like this:
.\Security-Audit.ps1 -ExportToCSV
Or for JSON output:
.\Security-Audit.ps1

Pro Tips

  1. Always run this with administrative privileges - many checks require elevated access.
  2. Consider adding error handling for each function to prevent one failure from stopping the entire audit.
  3. Feel free to customize the checks based on your organization's security requirements.
  4. Remember to sanitize any output before sharing - you don't want to accidentally leak sensitive information!

Room for Improvement

This is a basic script, but you could enhance it by:

  • Adding checks for installed software and patches
  • Implementing compliance checks against a baseline
  • Adding remote system scanning capabilities
  • Including scheduled task analysis
  • Adding registry checks for common malware persistence locations

Wrapping Up

There you have it - your first security audit script! It's not perfect (what is?), but it's a solid foundation that you can build upon. Remember, automation is your friend in security, but always verify your results. A script can only tell you what you programmed it to look for! Stay safe, and happy hunting! 🕵️‍♂️ P.S. Want to learn more about PowerShell security tools? Check out the other PowerShell Quick Guides.

0 comments:

Post a Comment