PowerShell Windows Host Security Audit Script Generator
Before you can harden plant and ERP servers you need to know who is a local administrator, what is listening and when each host last patched. This generator builds a read-only script that collects exactly that into CSV files.
Fill in
Hosts reachable with WinRM from your admin workstation.
Setup and inventory
# Read-only audit. Run from an admin workstation with WinRM access. $servers = 'ERP-APP01,MES-DB01,HMI-SRV02' -split ',' $outDir = 'C:\SecAudit' New-Item -ItemType Directory -Force -Path $outDir | Out-Null $stamp = Get-Date -Format 'yyyyMMdd-HHmm'
Local administrators
$admins = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-LocalGroupMember -Group 'Administrators' | Select-Object Name, ObjectClass, PrincipalSource
}
$admins | Select-Object PSComputerName, Name, ObjectClass, PrincipalSource |
Export-Csv "$outDir\local-admins-$stamp.csv" -NoTypeInformationListening ports and owning process
$ports = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-NetTCPConnection -State Listen | ForEach-Object {
$p = Get-Process -Id $_.OwningProcess -ErrorAction SilentlyContinue
[pscustomobject]@{ Port = $_.LocalPort; Address = $_.LocalAddress; Process = $p.ProcessName }
}
}
$ports | Select-Object PSComputerName, Port, Address, Process |
Export-Csv "$outDir\listening-ports-$stamp.csv" -NoTypeInformationInstalled updates and staleness
$hotfixes = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-HotFix | Sort-Object InstalledOn -Descending | Select-Object -First 1 HotFixID, InstalledOn
}
$hotfixes | ForEach-Object {
$age = if ($_.InstalledOn) { (New-TimeSpan -Start $_.InstalledOn -End (Get-Date)).Days } else { -1 }
[pscustomobject]@{ Server = $_.PSComputerName; LastKB = $_.HotFixID; Installed = $_.InstalledOn; AgeDays = $age; Stale = ($age -gt 60) }
} | Export-Csv "$outDir\last-update-$stamp.csv" -NoTypeInformationNon-Microsoft scheduled tasks
$tasks = Invoke-Command -ComputerName $servers -ScriptBlock {
Get-ScheduledTask | Where-Object { $_.TaskPath -notlike '\Microsoft\*' } |
Select-Object TaskName, TaskPath, State, @{n='RunAs';e={$_.Principal.UserId}}
}
$tasks | Select-Object PSComputerName, TaskName, TaskPath, State, RunAs |
Export-Csv "$outDir\scheduled-tasks-$stamp.csv" -NoTypeInformation
Write-Host "Audit files written to $outDir"Read-only commands, but test on one non-production host first. Requires PowerShell remoting enabled for the target hosts and an account with local administrator rights. Get-LocalGroupMember can fail when an orphaned domain SID is in the group, so review errors. Check the script with your change process before running it on plant servers.
Host hardening review
Optional review of your audit output and a prioritized fix list.
Optional. The tool and every export work without this. No spam.
How to use it
Enter your server names, an output folder and the age in days at which an update should be treated as stale. Copy the blocks into one script, review it, and run it from an admin workstation that has WinRM access. The script writes four time-stamped CSV files you can open in Excel and attach to an audit record or a risk register entry.
- Start with three to five hosts
- Keep CSVs in a restricted folder
- Re-run monthly and compare to the last file
What to look for
In the administrator list, look for personal accounts, shared service accounts and domain groups that nobody remembers adding. In listening ports, look for remote management services, old FTP or Telnet, and database ports reachable from places they should not be. In the update file, a host months behind is a finding. In scheduled tasks, look for tasks running as high-privilege accounts from user-writable paths.
Fit for OT hosts
HMI and historian servers may run vendor-certified builds where patching follows a vendor schedule. A stale flag there is a prompt to check the vendor bulletin, not an instruction to patch immediately. Document the compensating controls, such as segmentation and application allow lists, next to the finding.
Common mistakes
Running a new script against a production line server without a change window is risky even when it only reads. Another error is leaving output CSVs on a shared drive: they are a map of your attack surface. Finally, do not treat a clean report as proof of security. It shows four facts about each host, nothing more.
Frequently Asked Questions
Is the script safe to run?
It only reads information and writes CSV files to the folder you name. Still test on a non-production host and follow your change process. Remoting and local admin rights are required, which is itself a sensitive permission.
Why use Invoke-Command?
It runs the block on each remote host through WinRM in parallel and returns objects tagged with PSComputerName, which keeps the exported CSV tidy and avoids installing anything on the targets.
What if WinRM is not enabled?
Enable it through group policy on managed servers, or run the script locally on each host with the server list reduced to localhost. Do not open WinRM broadly just to run an audit.
Can I extend it?
Yes. Add blocks for local users, installed software from the registry uninstall keys, or firewall profile status. Keep each block read-only and write its own CSV for easy comparison over time.
If you want the output of audits like this fed into a single risk register or ERP-linked asset record, Netray can help build that pipeline.
Related Tools
Windows Security Event ID Reference for Threat Hunting
The event IDs a small security team should log and alert on, from failed logons and new services to cleared logs and PowerShell script blocks.
Developer ToolsCommon OT and ICS Protocol Ports Reference
Default TCP and UDP ports used by industrial protocols and the IT services that sit beside them, with a firewall risk note for each.
Compliance & ContractsCyber Risk Register Worksheet for Manufacturers
Score IT and OT cyber risks by likelihood and impact, compare inherent and residual risk and track the treatment owner.
Developer ToolsSIEM Failed Logon Detection KQL Query Generator
Fill in a time window and thresholds and get ready-to-paste KQL for Microsoft Sentinel or Log Analytics covering password guessing and common tampering events.
More Developer Tools tools
See all- Excel Timesheet and Overtime Formula Generator
- Environmental Permit Expiry Alert SQL Generator
- SAP Sales Order ABAP SELECT Generator (VBAK, VBAP, VBFA)
- SAP Sales Order Create BAPI ABAP Generator (BAPI_SALESORDER_CREATEFROMDAT2)
- SAP ABAP Open Items SELECT Generator
- SAP ACDOCA SQL Query Generator
- SAP QM Inspection Lot ABAP SELECT Generator
- SAP Quality Notification Pareto SQL Query Generator
- SAP QM Usage Decision BAPI Skeleton