274 lines
8.9 KiB
Markdown
274 lines
8.9 KiB
Markdown
# Project: Syncro Security Event Monitor
|
|
|
|
## Summary
|
|
|
|
A single self-contained PowerShell script for Syncro RMM that monitors selected Windows Security audit events, verifies the required audit-policy prerequisites, optionally auto-remediates missing audit subcategories, and creates de-duplicated Syncro alerts only for newly observed matching events.
|
|
|
|
The script is intentionally stateful:
|
|
|
|
- it reads the Windows `Security` log
|
|
- filters for specific `Microsoft-Windows-Security-Auditing` events
|
|
- stores the last processed `RecordId`
|
|
- alerts only on newly observed matching events
|
|
|
|
This gives Cybertek a lightweight way to surface meaningful local security activity without repeatedly alerting on the same event every time the script runs.
|
|
|
|
---
|
|
|
|
## Current Scope
|
|
|
|
The current script focuses on account activity, authentication activity, and local group membership changes.
|
|
|
|
It currently monitors:
|
|
|
|
- `4624` interactive logon (`LogonType = 2`)
|
|
- `4624` remote interactive / RDP logon (`LogonType = 10`)
|
|
- `4625` failed logon
|
|
- `4634` logoff
|
|
- `4647` logoff initiated by user
|
|
- `4648` logon attempted with explicit credentials
|
|
- `4720` local user created
|
|
- `4729` user removed from group
|
|
- `4732` user added to group
|
|
- `4740` account locked out
|
|
|
|
The script parses structured event XML instead of relying on fragile message-text spacing in Syncro custom event query filters.
|
|
|
|
---
|
|
|
|
## Why This Exists
|
|
|
|
Syncro's built-in custom event log queries can work well, but they are sensitive to exact message formatting and spacing, especially for Security audit events like `4624` logons where the same event ID represents multiple different scenarios.
|
|
|
|
This script moves that logic into PowerShell so we can:
|
|
|
|
- inspect event fields directly
|
|
- distinguish `4624` interactive logons from other `4624` records
|
|
- reduce duplicate alerting across scheduled runs
|
|
- expand logic over time without rebuilding Syncro query filters manually
|
|
|
|
---
|
|
|
|
## Goals
|
|
|
|
### Primary Goals
|
|
|
|
1. Detect high-value local Windows Security audit events through a recurring Syncro script.
|
|
2. Alert only on newly observed matching events.
|
|
3. Make `4624` logon monitoring reliable by filtering on structured `LogonType`.
|
|
4. Keep the script lightweight enough for recurring execution.
|
|
5. Provide a clean foundation for future Cybertek security monitoring scripts.
|
|
|
|
### Secondary Goals
|
|
|
|
1. Write a local report file for technician review.
|
|
2. Keep alert content short but actionable.
|
|
3. Allow easy expansion to more Security event IDs later.
|
|
|
|
### Non-Goals
|
|
|
|
1. Full SIEM-style retention or analytics.
|
|
2. Historical correlation across all Windows logs.
|
|
3. Replacing proper advanced auditing / centralized logging platforms.
|
|
4. Full enterprise audit-policy management beyond the required subcategories for this script.
|
|
|
|
---
|
|
|
|
## Architecture
|
|
|
|
### Execution Model
|
|
|
|
- **Language:** PowerShell 5.1+
|
|
- **Runtime:** Syncro Windows script runner
|
|
- **Run Context:** SYSTEM
|
|
- **Alert Method:** `Rmm-Alert`
|
|
|
|
### Data Source
|
|
|
|
- Windows Event Log: `Security`
|
|
- Provider: `Microsoft-Windows-Security-Auditing`
|
|
|
|
### Local Storage
|
|
|
|
| Path | Purpose |
|
|
|------|---------|
|
|
| `C:\ProgramData\Cybertek\SecurityEventMonitor\state.json` | Stores the last processed `RecordId` |
|
|
| `C:\ProgramData\Cybertek\SecurityEventMonitor\last_report.txt` | Full alert report from the most recent matching run |
|
|
|
|
---
|
|
|
|
## How Detection Works
|
|
|
|
On each run, the script:
|
|
|
|
1. Loads the last processed `RecordId` from local state.
|
|
2. Queries recent Security log events within the configured lookback window.
|
|
3. Filters down to the configured event IDs.
|
|
4. Parses event XML and checks structured fields such as `LogonType`.
|
|
5. Keeps only events newer than the last processed `RecordId`.
|
|
6. Sends one aggregated Syncro alert if new matching events are found.
|
|
7. Saves the newest seen `RecordId` so the next run does not re-alert on the same records.
|
|
|
|
This is why the script behaves more like a small event-monitoring worker than a simple one-shot event search.
|
|
|
|
---
|
|
|
|
## Alerting Strategy
|
|
|
|
### Alert Category
|
|
|
|
- `security_event_monitor`
|
|
|
|
### Error Category
|
|
|
|
- `security_event_monitor_error`
|
|
|
|
### Audit Policy Category
|
|
|
|
- `security_event_monitor_audit_policy`
|
|
|
|
### Alert Content
|
|
|
|
Each alert includes:
|
|
|
|
- host name
|
|
- scan timestamp
|
|
- number of matching events
|
|
- summary counts grouped by event type
|
|
- per-event summary including:
|
|
- title
|
|
- plain-language description of what happened
|
|
- event ID
|
|
- record ID
|
|
- event time
|
|
- user
|
|
- source
|
|
- logon type where applicable
|
|
|
|
The full alert report is also written locally to:
|
|
|
|
- `C:\ProgramData\Cybertek\SecurityEventMonitor\last_report.txt`
|
|
|
|
---
|
|
|
|
## Auditing Requirements
|
|
|
|
This script depends on Windows Security auditing being enabled for the event categories it monitors, and it now attempts to correct missing required subcategories by default.
|
|
|
|
Important:
|
|
|
|
- the script attempts to enable missing audit-policy prerequisites by default with `AutoEnableMissingAuditPolicy = $true`
|
|
- the script **does** perform a preflight audit-policy check before querying events
|
|
- if required auditing is missing, the script raises a separate audit-policy alert category and continues with event monitoring
|
|
- if remediation succeeds, the audit-policy alert category is closed automatically when configured to do so
|
|
- if the required Security auditing categories are disabled on an endpoint, the event query may still return no matching events even though the monitored activity occurred
|
|
|
|
For example:
|
|
|
|
- `4624`, `4625`, `4634`, `4647`, and `4648` generally depend on **Logon/Logoff** auditing
|
|
- `4720`, `4729`, `4732`, and `4740` depend on **Account Management** auditing
|
|
|
|
Current preflight coverage includes:
|
|
|
|
- `Logon`
|
|
- `Logoff`
|
|
- `Other Logon/Logoff Events`
|
|
- `User Account Management`
|
|
- `Security Group Management`
|
|
- `Account Lockout`
|
|
|
|
Optional remediation:
|
|
|
|
- when `AutoEnableMissingAuditPolicy = $true`, the script attempts to enable missing subcategories with `auditpol /set`
|
|
- this is best suited for Cybertek-managed endpoints where local policy changes are expected and acceptable
|
|
- domain Group Policy may still overwrite local audit policy later
|
|
- the script logs whether the endpoint was already compliant, remediated successfully, or failed remediation for one or more subcategories
|
|
|
|
Future improvement:
|
|
|
|
- add a stronger mapping document for exact audit subcategories by event family
|
|
- optionally add auto-remediation guidance when auditing is missing
|
|
|
|
---
|
|
|
|
## Feature Notes
|
|
|
|
### State Tracking
|
|
|
|
The `RecordId` state file is what prevents duplicate alerts from recurring scheduled runs.
|
|
|
|
### Lookback Window
|
|
|
|
The lookback window protects the first run and short scheduling gaps. After the first run, duplicate suppression is primarily handled by the saved `RecordId`.
|
|
|
|
### Aggregated Alerts
|
|
|
|
The script currently aggregates all newly matched events from a run into one alert body rather than firing a separate Syncro alert for each event.
|
|
|
|
---
|
|
|
|
## Known Limitations
|
|
|
|
1. The script only sees what Windows Security auditing is configured to log.
|
|
2. If the state file is deleted, previously seen events inside the lookback window may alert again.
|
|
3. The script monitors only the local Security log, not forwarded events or centralized logs.
|
|
4. The initial event set is intentionally focused; many useful Security event IDs are not yet included.
|
|
5. Audit-policy remediation can still be overridden later by domain Group Policy or other configuration management.
|
|
|
|
---
|
|
|
|
## Future Enhancements
|
|
|
|
### Detection Enhancements
|
|
|
|
1. Expand audit-policy validation coverage and reporting.
|
|
2. Add optional monitoring for privilege escalation and sensitive policy changes.
|
|
3. Add per-event include/exclude tuning via Syncro script variables.
|
|
4. Add username filtering or allowlists for expected service/admin activity.
|
|
5. Add better post-remediation verification after auto-enabling audit policy.
|
|
|
|
### Response Enhancements
|
|
|
|
1. Open tickets automatically for especially sensitive events.
|
|
2. Write summary data into Syncro asset fields.
|
|
3. Split high-severity events into their own alert category.
|
|
|
|
### Management Enhancements
|
|
|
|
1. Add a companion documentation matrix showing which audit policy settings are required.
|
|
2. Build separate variants for:
|
|
- user sign-in monitoring
|
|
- account management monitoring
|
|
- high-risk administrative activity
|
|
|
|
---
|
|
|
|
## Success Criteria
|
|
|
|
This project is successful when:
|
|
|
|
1. The script runs repeatedly in Syncro without duplicate alert spam.
|
|
2. Interactive and RDP logons are detected reliably using structured `LogonType` filtering.
|
|
3. New user creation, group membership changes, lockouts, and failed logons surface as actionable alerts.
|
|
4. Quiet endpoints complete cleanly without generating error alerts.
|
|
|
|
---
|
|
|
|
## Files
|
|
|
|
### `event_log_monitor.ps1`
|
|
|
|
Production script for monitoring selected Windows Security audit events in Syncro.
|
|
|
|
### `mock_syncro_module.psm1`
|
|
|
|
Local testing stub for `Rmm-Alert`, `Close-Rmm-Alert`, `Log-Activity`, and `Set-Asset-Field`.
|
|
|
|
### `test_local.ps1`
|
|
|
|
Local test runner for executing the script outside Syncro.
|
|
|
|
### `project.md`
|
|
|
|
This design and scope document.
|