Skip to content

Commit

Permalink
Improvement to HTML Report
Browse files Browse the repository at this point in the history
Added info to HTML Report:
-Blocked Senders
-Mailbox Audit Feedback
-added O365Troubleshooters logo
-other minor code fixes
  • Loading branch information
Alexandru Liviu Nita committed Jul 30, 2020
1 parent ee92969 commit 815d38d
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 50 deletions.
140 changes: 90 additions & 50 deletions ActionPlans/Start-CompromisedInvestigation.ps1
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
Function Get-BlockedSenderReasons
{
###Get Blocked Senders and Create Hashtable Array with SenderAddress & Reasons
###ToDo clarify what to return to MainMenu
{param([bool][Parameter(Mandatory=$true)] $isFormatted)
$blockedSenders = Get-BlockedSenderAddress

if($null -ne $blockedSenders)
{
$blockedSenders|Export-Csv -NoTypeInformation -Path "$ExportPath\BlockedOutboundSenders.csv"

$blockedSenderReasons = @()
{
if($isFormatted)
{
$blockedSenders|Export-Csv -NoTypeInformation -Path "$ExportPath\BlockedOutboundSenders.csv"

$blockedSenderReasons = @()

foreach($blockedSender in $blockedSenders)
foreach($blockedSender in $blockedSenders)
{
$Reason = $blockedSender.Reason.Replace(";","`n")
$Reason = ConvertFrom-StringData $Reason.Replace(":","=")
$Reason["SenderAddress"] = $blockedSender.SenderAddress
[hashtable[]]$blockedSenderReasons += $Reason
}
}
else
{
$Reason = $blockedSender.Reason.Replace(";","`n")
$Reason = ConvertFrom-StringData $Reason.Replace(":","=")
$Reason["SenderAddress"] = $blockedSender.SenderAddress
$blockedSenderReasons += $Reason
$blockedSenderReasons = $blockedSenders
}
return $blockedSenderReasons
return $BlockedSenderReasons
}
else
{
Expand Down Expand Up @@ -67,9 +71,8 @@ Audit 14

Function Get-SuspiciousTransportRules
{
#ToDo - only notify about recent rules
$SuspiciousTransportRules = @()
$TransportRules = Get-TransportRule -ResultSize unlimited
$TransportRules = Get-TransportRule -ResultSize unlimited | Sort-Object -Descending WhenChanged

foreach($TransportRule in $TransportRules)
{
Expand Down Expand Up @@ -98,7 +101,6 @@ Function Get-SuspiciousTransportRules

Function Get-SuspiciousJournalRule
{
#ToDo - only notify about recent Journal Rules
$JournalRules = Get-JournalRule
if($JournalRules.count -eq 0)
{
Expand Down Expand Up @@ -150,7 +152,7 @@ Function Test-ProvisionedMailbox
try
{
$i++
$GAExoMailbox = Get-EXOMailbox $EmailAddresses[$i-1] -ErrorAction Stop
$GAExoMailbox = Get-Mailbox $EmailAddresses[$i-1] -ErrorAction Stop
[string[]]$ProvisionedMailboxSMTPs += $GAExoMailbox.PrimarySmtpAddress
}
catch {continue}
Expand All @@ -165,45 +167,42 @@ Function Get-SuspiciousInboxRules
$InboxRules += Get-InboxRule -Mailbox $EmailAddress
Start-Sleep -Seconds 0.5
}
#ToDo - check which Admins have Inbox Rules with Forward/Redirect
#ToDo - check which Admins have Inbox Rules with Forward/Redirect/Delete/MoveToFolder
$InboxRules | Export-Csv -NoTypeInformation -Path "$ExportPath\GAInboxRules.csv"
return $InboxRules
}

#region GA audit disable & audit bypass
Function Get-EXOAuditBypass
{param([string[]][Parameter(Mandatory=$true)] $EmailAddresses)
<#ToDo
Return Object from Get-MailboxAuditBypassAssociation with properties:
PrimarySMTPAddress
WhenChangedUTC
AuditBypassEnabled
#>

if ((Get-OrganizationConfig).AuditDisabled -eq $true)
{
Write-Warning "Automatic AuditEnabled at organization level is turned off"
return $null
return $true, $null, $null
}

else
{
Write-Host "Automatic AuditEnabled at organization level is turned on" -ForegroundColor Green

foreach($GASMTP in $GASMTPs)
{
if ((Get-Mailbox $GASMTP -ErrorAction SilentlyContinue).AuditEnabled -eq $false)
{
$GAMailbox = Get-Mailbox $GASMTP -ErrorAction SilentlyContinue
if (($GAMailbox).AuditEnabled -eq $false)
{
Write-Warning "The following Global Administrator $($GASMTP) has mailbox audit disabled"
[string[]]$MailboxAuditDisabledGAs += $GASMTP
[Object[]]$MailboxAuditDisabledGAs += $GAMailbox
}

if ((Get-MailboxAuditBypassAssociation -Identity $GASMTP).AuditByPassEnabled -eq $true)

$GAMailboxAuditBypass = Get-MailboxAuditBypassAssociation -Identity $GASMTP
if (($GAMailboxAuditBypass).AuditByPassEnabled -eq $true)
{
Write-Warning "The following administrator's ($GASMTP) actions on other mailboxes are not audited"
[string[]]$MailboxAuditBypassGAs += $GASMTP
[Object[]]$MailboxAuditBypassGAs += $GAMailboxAuditBypass
}
}
return $MailboxAuditDisabledGAs, $MailboxAuditBypassGAs
return $false, $MailboxAuditDisabledGAs, $MailboxAuditBypassGAs
}
}
#endregion GA audit disable & audit bypass
Expand Down Expand Up @@ -280,7 +279,11 @@ Function Export-CompromisedHTMLReport
[Object[]][Parameter(Mandatory=$false)] $InboundConnectors,
[Object[]][Parameter(Mandatory=$false)] $OutboundConnectors,
[Object[]][Parameter(Mandatory=$false)] $JournalRules,
[Object[]][Parameter(Mandatory=$true)] $GlobalAdminsWithIssues
[Object[]][Parameter(Mandatory=$false)] $GlobalAdminsWithIssues,
[Object[]][Parameter(Mandatory=$false)] $BlockedSenderReasons,
[Object[]][Parameter(Mandatory=$false)] $MailboxAuditDisabledGAs,
[Object[]][Parameter(Mandatory=$false)] $MailboxAuditBypassGAs,
[bool][Parameter(Mandatory=$false)] $OrganizationMailboxAuditDisabled
)
#Export Info to HTML
$header = @"
Expand Down Expand Up @@ -344,13 +347,13 @@ Function Export-CompromisedHTMLReport
font-size: 12px;
}
</style>
<a href="https://www.powershellgallery.com/packages/O365Troubleshooters" target="_blank">
<img src="$script:modulePath\Resources\O365Troubleshooters-Logo.png" alt="O365Troubleshooters" width="173" height="128">
</a>
<img src=>
"@
#ToDo - validate if any Param null -> PreContent with Message that we have no Suspicious Entries for that.

$ReportTitle = "<h1>Compromised Investigation</h1>"

if($TransportRules)
Expand Down Expand Up @@ -412,14 +415,51 @@ Function Export-CompromisedHTMLReport
$GlobalAdminsWithIssues = $GlobalAdminsWithIssues | ConvertTo-Html -PreContent "<h2 class=`"ResultOk`">No Global Admin configuration security concerns</h2>"
}

if($BlockedSenderReasons)
{
$BlockedSenderReasons = $BlockedSenderReasons | ConvertTo-Html -Property SENDERADDRESS, REASON, CREATEDDATETIME -PreContent "<h2 class=`"ResultNotOk`">Restricted Users found</h2>"
}
else
{
$BlockedSenderReasons = $BlockedSenderReasons | ConvertTo-Html -PreContent "<h2 class=`"ResultOk`">No Restricted Users found</h2>"
}

$HiddenInboxRulesWarningString = "This Script does not currently check for Hidden Inbox Rules.
To identify and delete such rules, perform the steps from the following article:
https://docs.microsoft.com/en-us/archive/blogs/hkong/how-to-delete-corrupted-hidden-inbox-rules-from-a-mailbox-using-mfcmapi"
$HiddenInboxRulesWarning = New-Object -TypeName psobject
$HiddenInboxRulesWarning | Add-Member -MemberType NoteProperty -Name "Warning" -Value $HiddenInboxRulesWarningString
$HiddenInboxRulesWarning = $HiddenInboxRulesWarning | ConvertTo-Html -Property Warning -PreContent "<h2 class=`"ResultNotOk`">Hidden Inbox Rules</h2>"
<a href=`"https://docs.microsoft.com/en-us/archive/blogs/hkong/how-to-delete-corrupted-hidden-inbox-rules-from-a-mailbox-using-mfcmapi`" target=`"_blank`">How To Check and Delete Corrupted or Hidden Inbox Rules</a>"
<# $HiddenInboxRulesWarning = New-Object -TypeName psobject
$HiddenInboxRulesWarning | Add-Member -MemberType NoteProperty -Name "Warning" -Value $HiddenInboxRulesWarningString #>
$HiddenInboxRulesWarning = $null | ConvertTo-Html -PostContent $HiddenInboxRulesWarningString -PreContent "<h2 class=`"ResultNotOk`">Hidden Inbox Rules</h2>"

$Report = ConvertTo-Html -Head $header -Body "$ReportTitle $GlobalAdminsWithIssues $HiddenInboxRulesWarning $InboxRules $TransportRules $InboundConnectors $OutboundConnectors $JournalRules" `
if(!$OrganizationMailboxAuditDisabled)
{
if($MailboxAuditDisabledGAs)
{
$MailboxAuditDisabledGAs = $MailboxAuditDisabledGAs | ConvertTo-Html -Property DisplayName, PrimarySmtpAddress, AuditEnabled `
-PreContent "<h2 class=`"ResultNotOk`">Global Admin Mailboxes with Audit Disabled</h2>"
}
else
{
$MailboxAuditDisabledGAs = $MailboxAuditDisabledGAs | ConvertTo-Html -PreContent "<h2 class=`"ResultOk`">No Global Admin Mailboxes have Audit Disabled</h2>"
}

if($MailboxAuditBypassGAs)
{
$MailboxAuditBypassGAs = $MailboxAuditBypassGAs|Select-Object Identity,@{Name="PrimarySmtpAddress";expression={(Get-Recipient -Identity $_.DistinguishedName).PrimarySmtpAddress}}, AuditBypassEnabled | `
ConvertTo-Html -PreContent "<h2 class=`"ResultNotOk`">Global Admin with Audit Bypass on other Mailboxes</h2>"
}
else
{
$MailboxAuditBypassGAs = $MailboxAuditBypassGAs | ConvertTo-Html -PreContent "<h2 class=`"ResultOk`">No Global Admin with Audit Bypass on other Mailboxes found</h2>"
}
$OrganizationMailboxAuditDisabledWarning = $null | ConvertTo-Html -PreContent "<h2 class=`"ResultOk`">Mailbox Audit Enabled Organization Wide</h2>"
}
else
{
$OrganizationMailboxAuditDisabledWarning = $null | ConvertTo-Html -PreContent "<h2 class=`"ResultNotOk`">Mailbox Audit Disabled Organization Wide, check via Get-OrganizationConfig|select AuditDisabled</h2>"
}
$Report = ConvertTo-Html -Head $header -Body "$ReportTitle $GlobalAdminsWithIssues $HiddenInboxRulesWarning $InboxRules $OrganizationMailboxAuditDisabledWarning `
$MailboxAuditBypassGAs $MailboxAuditDisabledGAs $BlockedSenderReasons $TransportRules $InboundConnectors $OutboundConnectors $JournalRules" `
-Title "Compromised Investigation" -PreContent "<p>Creation Date: $now</p>"

$Report | Out-File "$ExportPath\CompromisedReport_$ts.htm"
Expand All @@ -429,7 +469,7 @@ Function Start-CompromisedMain
Clear-Host

#Connect to O365 Workloads
$Workloads = "Exo2", "MSOL", "AzureADPreview"#, "AAD", "SCC"
$Workloads = "Exo", "MSOL", "AzureADPreview"#, "AAD", "SCC"

Connect-O365PS $Workloads

Expand Down Expand Up @@ -466,21 +506,21 @@ Function Start-CompromisedMain

$SuspiciousTransportRules = Get-SuspiciousTransportRules

#Todo : Add BlockedSenderReasons to Report
$BlockSenderReasons = Get-BlockedSenderReasons
$BlockedSenderReasonsObject = Get-BlockedSenderReasons -isFormatted $false

$InboundConnectorAdminAudit,$OutboundConnectorAdminAudit,$TransportRuleAdminAudit,$InboxRuleAdminAudit = Get-CompromisedAdminAudit

Get-GAAzureSignInLogs -EmailAddresses $GASMTPs

$GlobalAdminsWithIssues = Get-GlobalAdminsWithIssues -GlobalAdminList $GlobalAdminList

#ToDo : Add Audit Bypass feedback to Report
$MailboxAuditDisabledGAs, $MailboxAuditBypassGAs = Get-EXOAuditBypass -EmailAddresses $GASMTPs
$OrganizationMailboxAuditDisabled, $MailboxAuditDisabledGAs, $MailboxAuditBypassGAs = Get-EXOAuditBypass -EmailAddresses $GASMTPs

Export-CompromisedHTMLReport -InboundConnectors $InboundConnectors -OutboundConnectors $OutboundConnectors `
-InboxRules $GAInboxRules -TransportRules $SuspiciousTransportRules -GlobalAdminsWithIssues $GlobalAdminsWithIssues `
-JournalRules $JournalRules
-JournalRules $JournalRules -BlockedSenderReasons $BlockedSenderReasonsObject `
-OrganizationMailboxAuditDisabled $OrganizationMailboxAuditDisabled -MailboxAuditDisabledGAs $MailboxAuditDisabledGAs `
-MailboxAuditBypassGAs $MailboxAuditBypassGAs

Write-Host "Exported logs to $ExportPath, you will be returned to O365Troubleshooters Main Menu" -ForegroundColor Green

Expand Down
Binary file added Resources/O365Troubleshooters-Logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 815d38d

Please sign in to comment.