Chapter 23

Phishing Response Playbook

From "user reported a suspicious email" to credential reset — triage, identifying who else received it, retracting the message, and converting the phishing investigation into a scope determination for possible post-exploitation activity.

Scenario

9:47 AM. A user calls the help desk: "I got a weird email saying my password expired, I clicked the link, it asked me to log in, so I did, and now it says my account is locked." Classic AiTM (Adversary-in-the-Middle) phishing: the user was sent to a credential harvesting proxy that intercepted both the user's credentials and the MFA token. The attacker now has a live, MFA-authenticated session — your MFA policy didn't protect you. You have minutes to revoke that session before the attacker pivots to BEC, lateral movement, or data exfiltration. And the user who clicked it isn't necessarily the only recipient.

Immediate Triage Actions (T+0 to T+15 min)

  Phishing Response: First 15 Minutes
  ═══════════════════════════════════════════════════════════════════

  User reports suspicious email
       │
       ▼
  Determine what happened:
    Q: Did the user click a link?
    Q: Did the user enter credentials?
    Q: Did the user open an attachment?
    Q: Did the user see any MFA prompt after entering credentials?
       │
       ├── "I entered my credentials" (with or without MFA) →
       │   IMMEDIATE: Revoke all sessions, reset password
       │   → Treat as credential compromise (Ch09)
       │   → Check Azure AD sign-in logs for session activity
       │
       ├── "I opened an attachment" →
       │   IMMEDIATE: Isolate the machine via EDR
       │   → Check EDR for process executions from the document
       │   → Typical: macro execution → PowerShell download
       │
       ├── "I just clicked a link, nothing happened" →
       │   MEDIUM urgency: analyze the link, check endpoint for
       │   drive-by exploitation, review browser history
       │
       └── "I'm not sure what I did" →
           Treat as worst case: both credential and endpoint compromise

Identifying All Recipients

PowerShellphishing-scope.ps1
# Exchange Online: find all recipients of a phishing email and purge it
Connect-ExchangeOnline

# 1. Search for the phishing email by subject or sender
$sender   = "legit-sounding@evil-domain.com"
$subject  = "Your password will expire soon"

# Content search (requires Security & Compliance role)
# In Microsoft 365 Compliance Center → Content Search is the most powerful method
# Via PowerShell:
$search = New-ComplianceSearch -Name "PhishHunt_$(Get-Date -Format yyyyMMdd_HHmmss)" `
    -ExchangeLocation All `
    -ContentMatchQuery "(From:$sender) OR (Subject:""$subject"")"
Start-ComplianceSearch -Identity $search.Name

# Wait for results
do {
    Start-Sleep -Seconds 10
    $status = Get-ComplianceSearch $search.Name
    Write-Host "Status: $($status.Status)"
} while ($status.Status -ne "Completed")

# View results (shows number of mailboxes and messages found)
$search | Select-Object Items, Size, SuccessResults

# 2. Purge the message from all mailboxes (soft delete — goes to Deleted Items)
New-ComplianceSearchAction -SearchName $search.Name `
    -Purge -PurgeType SoftDelete

# For hard delete (permanently removes — requires additional permissions):
# New-ComplianceSearchAction -SearchName $search.Name -Purge -PurgeType HardDelete

# 3. Check who clicked the link (if you have email security gateway link click tracking)
# Products like Mimecast, Proofpoint, or Defender for Office 365 Safe Links log click events

AiTM Phishing Credential Harvest Response

AiTM phishing intercepts both credentials and the session cookie. A password reset alone is insufficient — the attacker's active session (using the session cookie) remains valid until explicitly revoked.

PowerShellaitm-response.ps1
# AiTM phishing credential harvest response

# 1. Revoke ALL sessions for the affected user IMMEDIATELY
# (This invalidates the stolen session cookie even though it's still "valid" from Azure's perspective)
Connect-MgGraph -Scopes "User.ReadWrite.All"
Invoke-MgUserInvalidateAllRefreshToken -UserId "jsmith@corp.com"

# 2. Reset the password
Set-MgUserPassword -UserId "jsmith@corp.com" `
    -PasswordProfile @{
        Password = [System.Web.Security.Membership]::GeneratePassword(24, 4)
        ForceChangePasswordNextSignIn = $true
    }

# 3. Check Azure AD sign-in logs for what was done with the stolen session
# Look for: mail access, rule creation, lateral movement to other resources
Connect-MgGraph -Scopes "AuditLog.Read.All"
$since = (Get-Date).AddHours(-4).ToString("yyyy-MM-ddTHH:mm:ssZ")
Get-MgAuditLogSignIn -Filter "userPrincipalName eq 'jsmith@corp.com' and createdDateTime gt $since" |
    Select-Object CreatedDateTime, IpAddress, Location, ClientAppUsed, IsInteractive |
    Sort-Object CreatedDateTime | Format-Table

# 4. Check for inbox rules created via the stolen session (BEC setup)
Get-InboxRule -Mailbox "jsmith@corp.com" |
    Where-Object { $_.ForwardTo -or $_.RedirectTo -or $_.DeleteMessage } |
    Format-List

# 5. Block legacy authentication for this user (prevents IMAP fallback)
# Conditional Access policy: block legacy auth for affected user

Malicious Attachment Response

Attachment typeCommon payloadDetection sourceResponse
Office document with macro (docm, xlsm)VBA macro → PowerShell download → Cobalt StrikeEDR: Word.exe / Excel.exe spawning cmd.exe or powershell.exeIsolate endpoint; collect memory before process kill; full IR workflow
PDF with exploitReader exploit → shellcode → dropperEDR: AcroRd32.exe spawning child processesSame as above
ISO/LNK (ZIP + shortcut)LNK executes mshta or wscript pointing to malicious payloadSysmon: mshta.exe or wscript.exe spawned with LOLBin patternIsolate; collect process tree artifacts
HTML attachment (HTML smuggling)HTML creates a malicious file locally via JavaScript BlobEDR: browser process writing executable to Downloads folderCheck Downloads folder for dropped files; isolate; full IR workflow if executed

Q & A

Q: 500 users received the phishing email. You don't know how many clicked it. How do you prioritize who to investigate first?

Prioritize by: (1) Who clicked the link — check email security gateway link click logs, Azure AD sign-in logs for authentication from the phishing kit's IP/domain in the relevant time window. Users who authenticated to the phishing kit are confirmed compromised and need immediate attention. (2) Who opened an attachment — EDR process creation events showing Office/PDF process spawning suspicious children. (3) High-privilege account holders (admin, finance, HR) regardless of whether you have evidence they clicked — a phishing email to a DA is higher priority than one to a junior developer. (4) Users who didn't click, for awareness notification — lower priority but still needed. The compliance notification requires notifying all recipients that a phishing email was identified.

Q: You want to quarantine the phishing email from all 500 mailboxes. But some users may need their email accessible for an investigation (evidence). How do you handle this?

Preserve before purge: the compliance search shows you which mailboxes have the message. Before running the purge action, export the message content (headers, body, attachments) from one mailbox as a reference copy and preserve the sender, subject, all embedded links, and attachments in your case documentation. The purge removes the message from production mailboxes but does not remove it from compliance holds — if mailboxes are on litigation hold, the purged messages remain in the hold for the hold's retention period. For the investigation mailboxes specifically: use the "soft delete" purge type, which moves the message to Deleted Items rather than removing it permanently — an investigator can still access it there while it's removed from the main inbox of the remaining users.