Last active
March 4, 2024 05:48
-
-
Save LHazy/882bb89c99ac877a77f4ca760b78eb43 to your computer and use it in GitHub Desktop.
Hunting Script for Entra Audit Logs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| enum LogCategory { | |
| Audit | |
| Signin | |
| } | |
| enum Sevirity { | |
| High | |
| Medium | |
| Low | |
| } | |
| $defaultFormatter = { | |
| param( | |
| [object[]] $events, | |
| [string] $title, | |
| [Sevirity] $sevirity | |
| ) | |
| $eventTable = $events | Format-Table | Out-String | |
| return "Title: ${title}`nSevirity: ${sevirity}`nEvents:${eventTable}" | |
| } | |
| class QueryRunner { | |
| static [string] FormatEvents([ | |
| string] $title, | |
| [Sevirity] $sevirity, | |
| [object[]] $events, | |
| [ScriptBlock] $formatter = $defaultFormatter | |
| ) { | |
| return & $formatter -events $events -title $title -sevirity $sevirity | |
| } | |
| static [object] SearchAuditLogs([string]$query) { | |
| return Get-MgAuditLogDirectoryAudit -Filter $query | |
| } | |
| static [object] SearchSigninLogs([string]$query) { | |
| return Get-MgBetaAuditLogSignIn -Filter $query | |
| } | |
| static [object] ExecuteQuery([ | |
| string] $query, | |
| [LogCategory] $category | |
| ) { | |
| $events = @() | |
| switch ($category) { | |
| Audit { | |
| $events = [QueryRunner]::SearchAuditLogs($query) | |
| break | |
| } | |
| Signin { | |
| $events = [QueryRunner]::SearchSigninLogs($query) | |
| break | |
| } | |
| default { | |
| throw "Unknown category: $category" | |
| } | |
| } | |
| return $events | |
| } | |
| } | |
| $queries = @( | |
| @{ | |
| "Title" = "Service Principal Added" | |
| "Category" = [LogCategory]::Audit | |
| "Sevirity" = [Sevirity]::High | |
| "Query" = "category eq 'ApplicationManagement' and activityDisplayName eq 'Add service principal'" | |
| }, | |
| @{ | |
| "Title" = "Device Code Signin" | |
| "Category" = [LogCategory]::Signin | |
| "Sevirity" = [Sevirity]::Low | |
| "Query" = "authenticationProtocol eq 'deviceCode'" | |
| } | |
| ) | |
| Import-Module Microsoft.Graph.Users.Actions | |
| Import-Module Microsoft.Graph.Beta.Reports | |
| # collect necessary scopes and connect to Graph API | |
| $commands = @( | |
| "Get-MgAuditLogDirectoryAudit", | |
| "Get-MgBetaAuditLogSignIn", | |
| "Send-MgUserMail" | |
| ) | |
| $allScopes = @() | |
| foreach ($command in $commands) { | |
| $scopes = Find-MgGraphCommand -command $command | Select-Object -First 1 -ExpandProperty Permissions | %{ $_.Name } | |
| $allScopes += $scopes | |
| } | |
| Connect-MgGraph -Scopes $allScopes -NoWelcome | |
| # execute queries | |
| foreach ($query in $queries) { | |
| $query["Results"] = [QueryRunner]::ExecuteQuery($query.Query, $query.Category) | |
| } | |
| # make a report | |
| $auditReport = "" | |
| foreach ($query in $queries) { | |
| $events = $query["Results"] | |
| # if format is specified, use it | |
| if ($query.Formatter) { | |
| $formatter = $query.Formatter | |
| } else { | |
| $formatter = $defaultFormatter | |
| } | |
| $auditReport += [QueryRunner]::FormatEvents($query.Title, $query.Sevirity, $events, $formatter) + "`n-----------------`n" | |
| } | |
| $params = @{ | |
| Message = @{ | |
| Subject = "Audit Report for $(Get-Date -Format "yyyy-MM-dd")" | |
| Body = @{ | |
| ContentType = "Text" | |
| Content = $auditReport | |
| } | |
| ToRecipients = @( | |
| @{ | |
| EmailAddress = @{ | |
| Address = "[email protected]" | |
| } | |
| } | |
| ) | |
| # CcRecipients = @( | |
| # @{ | |
| # EmailAddress = @{ | |
| # Address = "[email protected]" | |
| # } | |
| # } | |
| # ) | |
| } | |
| SaveToSentItems = "false" | |
| } | |
| Send-MgUserMail -UserId 'XXXXXXXXXXXXXX' -BodyParameter $params |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment