Windows Security Event Triage
Triage Windows authentication events with PowerShell and publish sanitized reports.
Introduction
30 Second Summary
You'll turn a crowded record of computer sign-ins into clear evidence you can explain to a recruiter. The finished report protects your personal details while highlighting activity that deserves attention.
In this project, you will use Windows PowerShell to review Windows Security logs. Your investigation will include sanitized CSV and HTML evidence within a public GitHub portfolio repository.
What You'll Build
One script transforms recent sign-in activity into a sanitized report you can open in a browser and walk through with a recruiter.
By the end of this project, you'll have:
- Readable triage results: Run a script and see recent authentication activity in a focused table.
- Sanitized evidence: Inspect event types and account categories without exposing personal identifiers.
- A recruiter-ready case study: Show your investigation method and reasoned conclusion through a public repository.
- Secret Mission: Complete an optional challenge to push your investigation skills further.
Are there any prerequisites?
You need a Windows 10 Pro 64-bit computer with administrator access.
You also need internet access plus a Gmail address.
Before We Start
Before you begin, commit to building a repeatable PowerShell workflow that turns Windows security activity into sanitized evidence. Your goal is to demonstrate SOC analyst judgment to recruiters.
Set Up Your Analyst Workspace
A credible investigation needs a secure publishing identity. It also needs a readable editor.
You will prepare a local workspace for your evidence. You will also confirm that Windows PowerShell can read the Security log.
In this step, get ready to:
- Create a verified GitHub account with two-factor authentication.
- Install Visual Studio Code and create the local project folders.
- Confirm Windows PowerShell 5.1 can read the Windows Security log.
Create and secure your GitHub account
Your public repository will eventually hold sanitized evidence. A verified personal account gives that work a publishing identity.
- Visit https://github.com/signup in Google Chrome.
- Select Continue with Google if you prefer to use your Gmail address.
- Complete the account creation prompts.
- Verify your Gmail address from the message GitHub sends you.
Why Verify Your Account?
GitHub requires a verified email address before you can create a repository. Verification prepares your account for the portfolio step.
Two-factor authentication adds a second sign-in check. This protects the account that will publish your analyst work.
- Click your profile picture in the upper-right corner of GitHub.
- Select Settings.
- Select Password and authentication from the Access section.
- Click Enable two-factor authentication.
- Choose an available authentication method.
- Complete the verification prompts for that method.
- Download your recovery codes when GitHub displays them.
- Store the recovery codes somewhere private.
Having Trouble Securing GitHub?
Confirm that your Gmail address is verified before opening the authentication settings.
Use Help me secure my GitHub account without sharing private recovery codes. for guided troubleshooting.
Install Visual Studio Code and create the workspace
Visual Studio Code gives you a readable place to build the investigation files. The User setup runs under your Windows account without requiring the editor to run as Administrator.
- Press the Windows key to open search.
- Type Visual Studio Code into the search field.
✔️ I See Version 1.134 or Higher
- Open Visual Studio Code from the search result.
- Select Help from the top menu.
- Select About.
The About dialog shows version 1.134 or higher. Keep Visual Studio Code open normally.
ⓧ I See an Older Version
- Open Visual Studio Code from the search result.
- Select Help from the top menu.
- Select Check for Updates.
- Allow Visual Studio Code to install the available update.
- Restart Visual Studio Code after the update completes.
- Return to Help.
- Select About.
The About dialog now shows version 1.134 or higher.
ⓧ It Is Not Installed Yet
The User setup installs Visual Studio Code for your Windows account. The installer guides you through the required choices.
- Visit the Visual Studio Code download page in Google Chrome.
- Select the Windows x64 User Installer.
- Run the downloaded installer.
- Accept the license terms when prompted.
- Complete the installation with the default options.
- Press the Windows key after installation.
- Type Visual Studio Code into the search field.
- Open Visual Studio Code normally from the search result.
The Visual Studio Code welcome screen confirms that the editor opens under your standard Windows account.
Visual Studio Code Won't Open?
Confirm that you downloaded the Windows x64 User setup. Rerun the installer if Windows search cannot find the editor.
Use Help me troubleshoot my Visual Studio Code User setup. for environment-specific help.
Your project needs separate locations for generated evidence and sanitized screenshots. A predictable folder structure keeps those artifacts easy to review.
- Press the Windows key to open search.
- Type File Explorer into the search field.
- Open File Explorer from the search result.
- Select Documents in the left sidebar.
- Create a folder named windows-security-event-triage inside Documents.
- Open the windows-security-event-triage folder.
- Create an output folder inside it.
- Create a screenshots folder inside it.
File Explorer now shows the empty output folder plus the empty screenshots folder.
- Switch back to Visual Studio Code.
- Select File from the top menu.
- Select Open Folder.
- Choose C:\Users\<your-username>\Documents\windows-security-event-triage.
- Click Select Folder.
The Explorer sidebar now lists output plus screenshots inside your project workspace.
Confirm Security-log access
Windows PowerShell can query the local Security log through Get-WinEvent. An elevated session supplies the access that some Windows logs require.
- Press the Windows key to open search.
- Type Windows PowerShell into the search field.
- Right-click Windows PowerShell in the search results.
- Select Run as administrator.
- Click Yes if Windows asks for permission.
- Check the PowerShell version by running this command:
$PSVersionTable.PSVersion
What Does This Command Do?
The command displays the version of the current Windows PowerShell session. This project uses version 5.1.
✔️ I See Version 5.1
Windows PowerShell 5.1 is ready. Keep this elevated session open for the Security-log check.
ⓧ I See a Different Version
- Close the current PowerShell window.
- Press the Windows key.
- Search for Windows PowerShell.
- Right-click the result named Windows PowerShell.
- Select Run as administrator.
Run the version check again in this session. The major and minor values should begin with 5.1.
ⓧ I Cannot Find Windows PowerShell
- Confirm that your computer is running Windows 10 Pro.
- Restart Windows.
- Search again for Windows PowerShell.
Still Cannot Find It?
Use Help me locate Windows PowerShell 5.1 on Windows 10 Pro. for guided help.
The final query tests your actual access to the Security log. Form a prediction before checking the result.
- Predict whether one readable Security event will appear.
- Test Security-log access by running this command:
Get-WinEvent -LogName Security -MaxEvents 1
What Does This Command Do?
The command requests one event from the Windows Security log. PowerShell returns the newest matching event by default.
One event appears in the terminal. Its columns include TimeCreated plus Id.
Security Log Access Failed?
Confirm that the window title identifies an Administrator session. Reopen Windows PowerShell with Run as administrator if access is denied.
Use Help me diagnose my Get-WinEvent Security-log query. if the query still fails.
Your secure account and local workspace are ready. Next, you will compare a noisy Security-log sample with a focused authentication query.
Filter Authentication Events
Your elevated Windows PowerShell session can already read the Windows Security log. You can now examine the activity recorded there.
The Security log mixes authentication records with unrelated activity. A broad query exposes this noise before you apply efficient filtering.
In this step, get ready to:
- Experience the noise in a broad Security-log sample.
- Filter the log for authentication events from the previous seven days.
- Interpret the selected event IDs using their surrounding context.
Inspect a broad Security-log sample
A broad query retrieves recent records without limiting their event IDs. The result shows why raw event streams are difficult to triage.
- Predict whether the first 30 records will show one event ID or a mix of IDs.
- Reveal the broad sample in the elevated Windows PowerShell session from earlier by running this command:
Get-WinEvent -LogName Security -MaxEvents 30
What Does This Command Do?
- The Security value selects the Windows Security log.
- The MaxEvents value limits the output to 30 recent records.
- The query leaves event IDs unrestricted, so unrelated activity appears together.
You should see mixed event IDs with records serving different purposes. This noisy result is intentional.
Can't Read the Security Log?
Confirm that you are using the elevated Windows PowerShell session from earlier. Security-log access can require Administrator privileges.
Check the log name for typing differences. Help me diagnose my Security-log query.
Interpret the authentication event IDs
An event ID identifies the type of activity Windows recorded. Its meaning gives you a starting point for investigation.
- Use the Microsoft event 4624 documentation to confirm what event 4624 records.
- Use the Microsoft event 4625 documentation to confirm what event 4625 records.
- Use the Microsoft event 4672 documentation to confirm what event 4672 records.
What Do These Event IDs Mean?
- Event 4624 records a successful logon.
- Event 4625 records a failed logon.
- Event 4672 records sensitive privileges assigned to a new logon.
Each record supplies context for an investigation. Patterns across frequency, account category, source, timing, or related activity provide stronger evidence.
Filter the authentication events
A FilterHashtable limits records while Windows retrieves them. This is more efficient than retrieving every event before filtering the results.
- Predict which event IDs will remain after the focused query runs.
- Retrieve the focused seven-day sample by running this command:
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624,4625,4672; StartTime=(Get-Date).AddDays(-7)} -MaxEvents 30
How Does the Filter Reduce Noise?
- The filter keeps records from the Security log.
- The event ID list keeps successful logons, failed logons, plus privileged-logon activity.
- The start time limits the search to the previous seven days.
- The event limit returns at most 30 matching records.
The broad output contains mixed IDs. The focused output contains only 4624, 4625, or 4672 records from the selected window.
No Focused Records Returned?
Confirm that the command uses the Security log with the three selected event IDs. A quiet system can have few matching records in the seven-day window.
Keep a zero-result observation accurate if no matching activity exists. Help me check my focused event query.
You have reduced a noisy Security log to authentication-focused evidence. Next, you will turn these records into reusable sanitized reports.
Generate Sanitized Evidence
Your focused Windows Security log sample contains useful evidence. However, console output remains difficult to share safely because event records can expose local identity data.
In this step, you will turn that sample into a reusable PowerShell script. The script produces sanitized CSV and HTML evidence for your investigation.
In this step, get ready to:
- Build a script that queries selected Security events.
- Categorize identifying event fields before export.
- Generate sanitized evidence and capture the HTML report.
Create the event collection pipeline
The script begins by defining consistent paths and a seven-day investigation window. It then retrieves up to 300 relevant events for processing.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Visual Studio Code into the search bar.
- Press Enter to open Visual Studio Code.
Visual Studio Code opens with your normal user permissions. Your elevated PowerShell session remains separate for Security-log access.
- Click File in the top menu bar.
- Click Open Folder.
- Select C:\Users\<your-username>\Documents\windows-security-event-triage.
- Click Select Folder.
- Click the New File icon in the Explorer sidebar.
- Enter Analyze-WindowsSecurity.ps1 as the file name.
- Press Enter to create the file.
- Add the path definitions and event query by copying this first section into Analyze-WindowsSecurity.ps1:
$ErrorActionPreference = 'Stop'
$ProjectRoot = Join-Path $env:USERPROFILE 'Documents\windows-security-event-triage'
$OutputDirectory = Join-Path $ProjectRoot 'output'
$CsvPath = Join-Path $OutputDirectory 'security-findings.csv'
$HtmlPath = Join-Path $OutputDirectory 'security-report.html'
New-Item -Path $OutputDirectory -ItemType Directory -Force | Out-Null
$StartTime = (Get-Date).AddDays(-7)
$EventIds = 4624, 4625, 4672
$Events = Get-WinEvent -FilterHashtable @{
LogName = 'Security'
Id = $EventIds
StartTime = $StartTime
} -MaxEvents 300
What does this section do?
- The path variables keep both exports inside the existing output folder.
- The filtered query limits collection to event IDs 4624, 4625, and 4672 from the previous seven days.
- Save Analyze-WindowsSecurity.ps1.
- Confirm the final visible line contains -MaxEvents 300.
- Continue the same file by copying this event-parsing section directly below the query:
$Findings = $Events | ForEach-Object {
$Record = $_
[xml]$EventXml = $Record.ToXml()
$EventData = @{}
foreach ($Node in $EventXml.Event.EventData.Data) {
$EventData[[string]$Node.Name] = [string]$Node.'#text'
}
How does XML parsing help?
- Each event becomes XML so the script can address named fields such as logon type and status.
- The EventData hashtable turns those named fields into values that the later rules can classify.
- Save Analyze-WindowsSecurity.ps1.
- Confirm the new section ends with the closing brace for the inner foreach loop.
- Add the account sanitization rules by copying this section directly below the XML loop:
$AccountName = if ($EventData.ContainsKey('TargetUserName')) {
$EventData['TargetUserName']
}
elseif ($EventData.ContainsKey('SubjectUserName')) {
$EventData['SubjectUserName']
}
else {
''
}
$AccountCategory = if (
$AccountName -eq 'SYSTEM' -or
$AccountName -eq 'LOCAL SERVICE' -or
$AccountName -eq 'NETWORK SERVICE' -or
$AccountName.EndsWith('$')
) {
'System or computer account'
}
elseif ([string]::IsNullOrWhiteSpace($AccountName)) {
'Not recorded'
}
else {
'User account (name redacted)'
}
How are account names protected?
- The script reads an available account field privately during processing.
- The export receives a broad category such as System or computer account instead of the raw account name.
- Save Analyze-WindowsSecurity.ps1.
- Confirm the account section ends with User account (name redacted).
Does the script structure look misaligned?
Keep the indentation shown in each section so the account rules remain inside ForEach-Object. Use Help me check the structure of my PowerShell event-processing pipeline. if a brace appears misplaced.
Classify events and protect source data
Raw event IDs need readable meanings before they become useful evidence. Source addresses also need sanitization before the findings can leave your computer.
- Add readable event meanings and analyst guidance by copying this section below the account rules:
$EventMeaning = switch ($Record.Id) {
4624 { 'Successful logon' }
4625 { 'Failed logon' }
4672 { 'Sensitive privileges assigned' }
default { 'Other selected event' }
}
$AnalystGuidance = switch ($Record.Id) {
4624 { 'Review logon type and account category for expected activity.' }
4625 { 'Review frequency and failure context before escalating.' }
4672 { 'Correlate the logon ID with a related successful logon.' }
default { 'Review context.' }
}
Why add analyst guidance?
- The event meaning converts each numeric ID into a readable activity label.
- The guidance states the next analytical question without declaring that an incident occurred.
- Save Analyze-WindowsSecurity.ps1.
- Confirm each selected event ID has one meaning and one guidance statement.
- Add the source categorization rules by copying this section below the guidance rules:
$SourceCategory = if (
$EventData.ContainsKey('IpAddress') -and
$EventData['IpAddress'] -and
$EventData['IpAddress'] -ne '-' -and
$EventData['IpAddress'] -ne '127.0.0.1' -and
$EventData['IpAddress'] -ne '::1'
) {
'Remote address present (redacted)'
}
elseif (
$EventData.ContainsKey('IpAddress') -and
($EventData['IpAddress'] -eq '127.0.0.1' -or $EventData['IpAddress'] -eq '::1')
) {
'Localhost'
}
else {
'Not recorded'
}
How are source addresses protected?
- Remote addresses become Remote address present (redacted) before export.
- Loopback addresses become Localhost because that category preserves useful context without publishing a raw address.
- Save Analyze-WindowsSecurity.ps1.
- Confirm the source section contains categories for a remote address, localhost, and an unrecorded source.
- Complete each finding by copying this projection and sorting section below the source rules:
[pscustomobject]@{
TimeCreated = $Record.TimeCreated
EventId = $Record.Id
EventMeaning = $EventMeaning
AccountCategory = $AccountCategory
LogonType = $EventData['LogonType']
SourceCategory = $SourceCategory
Status = $EventData['Status']
AnalystGuidance = $AnalystGuidance
}
}
$Findings = $Findings | Sort-Object -Property TimeCreated -Descending
What enters the findings table?
- Each finding contains only the eight fields required for triage and reporting.
- The closing brace completes the event-processing pipeline before the findings are sorted from newest to oldest.
- Save Analyze-WindowsSecurity.ps1.
- Confirm the finding fields end with AnalystGuidance before the pipeline closes.
Seeing an unexpected field or raw identifier?
Compare the object properties with the code above. The finding must exclude account names, computer names, full messages, and raw addresses.
Use Help me check whether my finding object exports identifying Windows event data. for a privacy-focused review.
Export and inspect the sanitized reports
The final sections write the same findings into two formats. The CSV supports structured review while the HTML report provides a readable table for your portfolio evidence.
- Add the CSV export and HTML styling by copying this section below the sorting line:
$Findings |
Export-Csv -Path $CsvPath -NoTypeInformation -Encoding UTF8
$Head = @'
<style>
body { font-family: Segoe UI, Arial, sans-serif; margin: 32px; color: #172033; }
h1 { color: #173f73; }
p { max-width: 900px; }
table { border-collapse: collapse; width: 100%; font-size: 14px; }
th { background: #173f73; color: white; text-align: left; }
th, td { border: 1px solid #ccd5e0; padding: 8px; vertical-align: top; }
tr:nth-child(even) { background: #f3f6f9; }
</style>
'@
What does this export section do?
- The first pipeline writes the sanitized findings to security-findings.csv.
- The Head value gives the HTML report a readable table layout without changing its evidence.
- Save Analyze-WindowsSecurity.ps1.
- Confirm the style section ends with the closing '@ marker.
- Complete the report export and console summary by copying this final section below the styling section:
$PreContent = @"
<h1>Windows Security Event Triage</h1>
<p>Window start: $StartTime</p>
<p>Events reviewed: 4624, 4625, and 4672. Account names, computer names, raw messages, and raw remote addresses are not exported.</p>
"@
$Findings |
ConvertTo-Html -Head $Head -Title 'Windows Security Event Triage' -PreContent $PreContent |
Out-File -FilePath $HtmlPath -Encoding UTF8
Write-Host "Created: $CsvPath"
Write-Host "Created: $HtmlPath"
Write-Host "Total findings: $($Findings.Count)"
Write-Host "Failed logons: $(($Findings | Where-Object EventId -eq 4625).Count)"
How does the script finish?
- The report introduction states its time window, selected events, and privacy boundary.
- The final lines print both output paths and two investigation counts after the files are created.
- Save Analyze-WindowsSecurity.ps1.
- Confirm the file ends with the failed-logon count.
The complete script is longer than 30 lines. Use these tabs to confirm that every section appears once in the correct order.
✔️ Awesome, I've got everything!
Great. Confirm that Analyze-WindowsSecurity.ps1 is saved before you run it.
ⓧ I'd like to double check the full code
Scroll through the code chunks above and confirm that your file contains these sections in order:
- Path and query setup.
- XML parsing pipeline.
- Account sanitization.
- Event interpretation.
- Source sanitization.
- Finding projection and sorting.
- CSV export and HTML styling.
- HTML export and console summary.
Before you run the script, what four summary lines do you expect it to print?
- Switch back to the elevated Windows PowerShell session from earlier.
- Return to C:\Users\<your-username>\Documents\windows-security-event-triage in that session.
- Generate both evidence files by running this command:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\Analyze-WindowsSecurity.ps1
What does this command do?
The command starts a separate PowerShell process without loading a profile. Its execution-policy setting applies only to that launched process.
The console displays two created file paths, the total finding count, and the failed-logon count. A zero failed-logon count is a valid result for the selected window.
- Return to the Explorer sidebar in Visual Studio Code.
- Expand the output folder.
- Open security-findings.csv.
The CSV contains TimeCreated, EventId, EventMeaning, AccountCategory, LogonType, SourceCategory, Status, and AnalystGuidance. It contains no raw usernames, computer names, full messages, or raw IP addresses.
- Open output\security-report.html in Chrome.
- Confirm the page heading reads Windows Security Event Triage.
- Confirm the page shows the report window start time.
- Confirm the findings table contains only categorized account and source values.
- Capture the sanitized report with your usual Windows screenshot method.
- Save the image as C:\Users\<your-username>\Documents\windows-security-event-triage\screenshots\security-report.png.
Did the script fail or produce no files?
Confirm you ran the command from the windows-security-event-triage folder in the elevated session. Also check that every opening brace and here-string marker has its matching closing marker.
Use Help me diagnose why my PowerShell triage script did not create its CSV and HTML files. for guided debugging.
Your noisy event records are now reusable, sanitized evidence. Next, you will turn these findings into clear case notes and a recruiter-readable portfolio.
Publish Your Investigation
Your sanitized evidence proves that the collection workflow works. A recruiter also needs to see how you interpret that evidence.
In this step, you will document your judgment in Markdown. You will publish the complete investigation through GitHub so anyone can review it without signing in.
In this step, get ready to:
- Write a cautious investigation report using your sanitized findings.
- Create a README that explains how the investigation works.
- Publish the complete project in a public GitHub repository.
Write the investigation report
A SOC report connects evidence to a defensible conclusion. It records the investigation question before explaining what the available data supports.
- Switch back to Visual Studio Code from earlier.
- Create investigation-report.md inside the windows-security-event-triage folder using the Explorer sidebar.
- Add the report introduction by copying this first section into the file:
# Windows Security Event Triage Report
## Executive Summary
I reviewed up to 300 Windows Security events from the previous seven days, limited to successful logons, failed logons, and sensitive privileges assigned to new logons. The exported evidence was sanitized before publication.
## Investigation Question
What authentication and privileged-logon activity is visible on this Windows endpoint, and does the available evidence justify escalation?
## Data Scope
- Host type: Windows 10 Pro workstation
- Time window: Previous seven days
- Event IDs reviewed: 4624, 4625, 4672
- Collection method: Windows PowerShell and Get-WinEvent
- Publication rule: No raw usernames, computer names, raw IP addresses, full messages, or EVTX files
What does this section establish?
- The executive summary defines the reviewed time window.
- The investigation question keeps the analysis focused on escalation.
- The data scope records what the evidence includes.
- The publication rule makes the privacy boundary explicit.
- Save investigation-report.md.
- Open the Markdown preview from the editor toolbar.
The preview should show the report title followed by the executive summary, investigation question, and data scope.
Is the Markdown preview incomplete?
Confirm that investigation-report.md is saved inside the project folder. Check that every heading begins with the same number of # characters shown above.
Ask for help checking the structure without sharing raw event data: Help me diagnose why my Markdown report headings are not rendering correctly.
The findings section turns your sanitized report into an evidence summary. Your classification must reflect the records you actually observed.
- Add a ## Findings heading below the data scope.
- Record your successful-logon count from the sanitized report.
- Record your failed-logon count from the sanitized report.
- Record your sensitive-privilege event count from the sanitized report.
- Describe the most common logon type shown in the evidence.
- Describe one accurate sanitized pattern from the evidence.
- Add an ## Assessment heading below the findings.
- Classify the activity as expected, suspicious, or inconclusive.
- Explain which evidence supports your classification.
- Save investigation-report.md.
- Refresh the Markdown preview.
The preview should now show five locally observed findings followed by a cautious classification and its reasoning.
Keep the conclusion defensible
One failed logon or one privileged-logon event does not establish an attack. Frequency, account context, source context, timing, and related activity determine whether escalation is justified.
- Complete the report by adding the remaining sections below your assessment:
## MITRE ATT&CK Context
Authentication-failure telemetry can support investigation of Brute Force activity, including technique T1110. Event evidence must be evaluated as a pattern and with environmental context.
## Limitations
- This is a single Windows endpoint, not an enterprise SIEM.
- The query is limited to three event IDs and a seven-day window.
- Event availability depends on local audit configuration and log retention.
- Sanitization removes identifiers that would normally support deeper enterprise correlation.
- The available events alone may not prove intent or compromise.
## Recommended Next Actions
1. Establish a normal authentication baseline over a longer period.
2. Correlate repeated failures by account, source, and time window in an authorized lab or SIEM.
3. Add endpoint process and network telemetry in a later project.
4. Escalate only when frequency, account value, source, timing, or related behavior increases risk.
Why include limitations?
- The MITRE ATT&CK section connects authentication failures to Brute Force technique T1110.
- The limitations define what this endpoint evidence cannot prove.
- The recommended actions show how an analyst would deepen the investigation.
- Save investigation-report.md.
- Refresh the Markdown preview.
The complete report should end with four numbered next actions. No placeholder text should remain in the findings or assessment.
Does the report still contain placeholders?
Compare every finding with output/security-findings.csv or the sanitized HTML report. Replace each unfinished observation with a count or pattern you can support.
Ask for help reviewing the wording without sharing private identifiers: Help me make my SOC assessment cautious and evidence-based.
✔️ Awesome, I've got everything!
Great. Confirm that investigation-report.md is saved with your own sanitized findings and assessment.
ⓧ I'd like to double check the full code
Scroll up and confirm that the file contains the report introduction, your personalized findings, your assessment, the MITRE ATT&CK context, the limitations, and the recommended next actions in that order.
Create the project README
The README gives a recruiter a two-minute path through the project. It explains the problem, the outputs, the run process, and the privacy decisions.
- Create README.md inside the windows-security-event-triage folder using the Explorer sidebar.
- Add the project overview by copying this section into the file:
# Windows Security Event Triage with PowerShell
A beginner SOC portfolio project that turns noisy Windows Security logs into sanitized, recruiter-readable evidence.
## What This Demonstrates
- Windows event-log triage with PowerShell
- Efficient filtering with Get-WinEvent
- Interpretation of event IDs 4624, 4625, and 4672
- XML event-field extraction
- Evidence sanitization before public sharing
- CSV and HTML reporting
- SOC-style assessment, limitations, and next actions
## Project Output
Running `Analyze-WindowsSecurity.ps1` creates:
- `output/security-findings.csv`
- `output/security-report.html`
The repository also includes an investigation report and a sanitized screenshot of the HTML output.
What does this overview communicate?
- The opening sentence states the practical result.
- The skills list highlights filtering, interpretation, sanitization, and reporting.
- The output section tells reviewers which evidence files the script creates.
- Save README.md.
- Open the Markdown preview from the editor toolbar.
The preview should show the project title, seven demonstrated skills, and two generated output paths.
Are the output paths rendering incorrectly?
Check that each path uses one pair of backticks. Confirm that both output files remain inside the output folder.
Ask for help checking the README formatting: Help me fix the Markdown formatting in my project overview.
- Add the run instructions and privacy sections below the project output:
## How to Run
1. Open Windows PowerShell as Administrator.
2. Change to the project directory.
3. Run:
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\Analyze-WindowsSecurity.ps1
```
4. Open `output/security-report.html` in a browser.
The execution-policy setting applies only to the launched PowerShell process. Review scripts before running them.
## Events Reviewed
- 4624: successful logon
- 4625: failed logon
- 4672: sensitive privileges assigned to a new logon
## Privacy and Safety
This public repository does not include raw EVTX files, raw usernames, computer names, full event messages, passwords, tokens, or raw remote addresses. The script exports categories instead of identifying values.
## Analyst Takeaway
A single event is not automatically an incident. Useful triage combines event meaning, frequency, account context, logon type, source context, related activity, and known limitations.
Why these sections matter
- The run instructions make the analysis reproducible.
- The event list defines the authentication evidence being reviewed.
- The privacy section identifies the data excluded from publication.
- The analyst takeaway shows that triage depends on context.
- Save README.md.
- Refresh the Markdown preview.
The preview should show the PowerShell run command, three event meanings, the privacy protections, and the analyst takeaway.
Is the PowerShell command missing?
Confirm that the opening and closing code fences each use three backticks. Keep powershell immediately after the opening fence.
Ask for help repairing the fenced block: Help me fix the PowerShell code block in my README.
- Complete the README by adding its references:
## References
- Microsoft Get-WinEvent documentation: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.diagnostics/get-winevent
- Microsoft event 4624 documentation: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4624
- Microsoft event 4625 documentation: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4625
- Microsoft event 4672 documentation: https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-10/security/threat-protection/auditing/event-4672
- MITRE ATT&CK Brute Force T1110: https://attack.mitre.org/techniques/T1110/
What do the references provide?
These links let reviewers verify the query method, event meanings, and Brute Force context. They separate documented facts from your local observations.
- Save README.md.
- Refresh the Markdown preview.
The complete README should end with five references. Its preview should contain no raw personal event data.
Do the references appear as plain text?
Confirm that each reference starts with a hyphen followed by a space. Keep each URL on the same line as its label.
Ask for help checking the list: Help me diagnose why my Markdown reference list is not rendering.
✔️ Awesome, I've got everything!
Great. Confirm that README.md is saved with the overview, run instructions, event meanings, privacy rules, analyst takeaway, and references.
ⓧ I'd like to double check the full code
Scroll up and confirm that the file contains the project overview, the run and privacy sections, and the references in that order.
Publish and review the repository
A public repository turns the local investigation into evidence that another person can inspect. The upload must preserve reproducibility without exposing raw Security-log data.
- Return to GitHub in Google Chrome.
- Choose New repository from the GitHub repository menu.
- Select your personal account in the Owner field.
- Enter windows-security-event-triage as the repository name.
- Enter Sanitized Windows Security event triage with PowerShell as the description.
- Select Public as the visibility.
- Enable the option to add a README.
- Click Create repository.
The repository page should show the name windows-security-event-triage with public visibility.
- Click Add file on the repository page.
- Select Upload files.
- Use choose your files to select Analyze-WindowsSecurity.ps1.
- Add investigation-report.md to the upload.
- Add the local README.md to the upload.
- Drag the output folder onto the upload area.
- Drag the screenshots folder onto the upload area.
- Use the page's commit control to publish the upload.
Protect your evidence
Publish only the sanitized CSV, sanitized HTML report, and sanitized screenshot. Keep raw EVTX files, usernames, computer names, full messages, raw remote addresses, passwords, and tokens outside the repository.
Before opening the repository privately, what files do you expect an unsigned visitor to see?
- Open an incognito Chrome window.
- Paste the public repository URL into the address bar.
- Review the repository without signing in.
- Open README.md from the repository file list.
- Open investigation-report.md from the repository file list.
- Open screenshots/security-report.png from the repository file list.
You should see the PowerShell script, both sanitized outputs, the sanitized screenshot, the investigation report, and the README without signing in. The report should contain your local observations with no unfinished placeholders.
Is a file missing or private?
Return to the signed-in repository page to upload any missing sanitized file. Confirm that the repository visibility is public before repeating the incognito review.
Ask for help without sharing the repository contents if they contain sensitive data: Help me check why my GitHub repository is incomplete or inaccessible.
Secret mission
Correlate a Privileged Logon
Connect one privileged-logon event to the successful session that received those privileges. You will publish a sanitized correlation note while keeping the shared identifier private.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources available, pause your work, or delete them entirely. This project has no ongoing costs.
Resources you used:
- A local windows-security-event-triage folder in your Documents folder.
- A public GitHub repository named windows-security-event-triage.
Keep everything running
No action is needed. Choose this if you want to keep improving your investigation.
- Keep the local windows-security-event-triage folder for future analysis.
- Keep the public repository available as your sanitized portfolio evidence.
Pause - I'll come back to this later
Close your analysis tools while keeping your files available. This frees your workspace without removing your evidence.
- Close the elevated Windows PowerShell window.
- Close Visual Studio Code.
- Leave the local project folder in your Documents folder.
- Leave the public repository available for future updates.
Delete - I don't want to use this again
Remove all project resources if you want to start fresh. This permanently removes your local evidence and public portfolio repository.
Delete the local copy
- Press the Windows key to open the search bar.
- Type File Explorer into the search bar.
- Press Enter to open File Explorer.
- Open your Documents folder.
- Select the windows-security-event-triage folder.
- Press Shift+Delete to request permanent deletion.
- Confirm the deletion when Windows asks.
The project folder should no longer appear in your Documents folder.
Delete the public copy
- Return to the windows-security-event-triage repository in Chrome.
- Open the repository settings page.
- Scroll to the repository deletion area at the bottom of the page.
- Use the repository deletion control.
- Enter the repository name when prompted.
- Confirm the permanent deletion.
- Return to the repository address in the incognito Chrome window.
The repository should no longer be publicly available.
Nice Work!
Nice Work!
Nice work! You built a Windows security investigation workflow with PowerShell. You published sanitized evidence in a recruiter-readable GitHub repository.
You've learned how to:
- Filter noisy telemetry into focused authentication findings for event IDs 4624, 4625, and 4672.
- Sanitize security evidence before exporting findings as CSV and HTML reports.
- Communicate SOC judgment through an evidence-based assessment with limitations and recommended next actions.
- Secret Mission: Correlate a privileged logon with its related successful session while keeping the shared Logon ID private.
Ready to quiz yourself?