Phishing accounts for over 36% of all data breaches. Understanding exactly how a SOC team responds — from the first alert to final remediation — is one of the most valuable skills in cybersecurity. This guide walks through a complete phishing incident using real tools and decisions made at each stage.
The Scenario
At 9:14 AM, a user in the finance department calls the helpdesk: “I got an email from our CEO asking me to wire $50,000 urgently. I clicked a link and it asked for my Microsoft login. I think I made a mistake.” This is a Business Email Compromise (BEC) phishing attack — and the clock is now ticking.
Phase 1: Triage (0-15 Minutes)
The Level 1 analyst receives the ticket and begins immediate triage. The goal: understand the scope and severity before escalating.
Step 1: Preserve Evidence
Ask the user to NOT close or delete the email. Forward the email as an attachment (not inline) to the security mailbox so headers are preserved.
# In Outlook: Select email > More options > Forward as attachment
# In Gmail: Three dots > Forward as attachment
# Or ask user to save as .eml file
# This preserves full headers needed for investigationStep 2: Analyze Email Headers
Email headers reveal the true origin of the message. Check:
- Return-Path: Does it match the From address?
- Received: What servers did it pass through?
- SPF/DKIM/DMARC: Did authentication pass or fail?
- X-Originating-IP: What’s the sender’s real IP?
# Parse email headers with Python
python3 -c "
import email
with open('phishing.eml', 'rb') as f:
msg = email.message_from_bytes(f.read())
for key, value in msg.items():
print(f'{key}: {value}')
"
# Check SPF, DKIM, DMARC with mxtoolbox CLI or API
curl "https://api.mxtoolbox.com/api/v1/lookup/spf/attacker-domain.com"
# Use mail-parser Python library
pip3 install mail-parser
mailparser -f phishing.eml --json | jq '.received_spf, .authentication_results'
# Check the sender IP in threat intel sources
curl "https://www.virustotal.com/api/v3/ip-addresses/185.220.101.45" -H "x-apikey: YOUR_VT_KEY"
# AbuseIPDB check
curl "https://api.abuseipdb.com/api/v2/check?ipAddress=185.220.101.45&maxAgeInDays=90" -H "Key: YOUR_KEY"Step 3: Check SIEM for Scope
Query the SIEM to find out if other users received the same email. In a Wazuh or Elastic environment:
# Elastic/Kibana KQL query
# Find all emails from the malicious sender in Exchange logs
event.category: email AND email.from.address: "ceo@attacker-domain.com"
# Or search in Microsoft 365 via PowerShell
Connect-ExchangeOnline
Get-MessageTrace -SenderAddress "fake.ceo@attacker.com" -StartDate (Get-Date).AddDays(-7) -EndDate (Get-Date) | Select RecipientAddress, Received, Subject
# Count recipients
Get-MessageTrace -SenderAddress "fake.ceo@attacker.com" | Group-Object RecipientAddress | Measure-ObjectPhase 2: Containment (15-60 Minutes)
Step 4: Block the Phishing Domain and URLs
# Add malicious domain to DNS sinkhole
# On pfSense/OPNsense: Firewall > Aliases > Add domain
# In Pi-hole:
echo "0.0.0.0 attacker-phish-domain.com" >> /etc/pihole/custom.list
pihole restartdns
# Block URL in Microsoft Defender for Endpoint
# Settings > Endpoints > Indicators > Add indicator (URL)
# Block in Cisco Umbrella via API
curl -X POST "https://management.api.umbrella.com/v1/organizations/YOUR_ORG_ID/blocklistdomains" -H "Authorization: Bearer TOKEN" -d '{"domains": ["attacker-phish-domain.com"]}'
# Add to Palo Alto URL filtering category via API
curl -k -X POST "https://PA_IP/api/?type=config&action=set&xpath=/config/devices/entry/vsys/entry/profiles/url-filtering&element=attacker-phish-domain.com " --header "X-PAN-KEY: YOUR_KEY"Step 5: Pull and Block the Phishing Email from All Mailboxes
# Microsoft 365 - soft-delete phishing email from ALL mailboxes
New-ComplianceSearchAction -SearchName "Phishing-Hunt-001" -Purge -PurgeType SoftDelete
# First, create the search:
New-ComplianceSearch -Name "Phishing-Hunt-001" -ExchangeLocation All -ContentMatchQuery "Subject:'Urgent Wire Transfer' AND From:'fake.ceo@attacker.com'"
Start-ComplianceSearch -Identity "Phishing-Hunt-001"
# Check search status
Get-ComplianceSearch "Phishing-Hunt-001" | Select Status, Items, SizeStep 6: Assess Credential Compromise
Did the user enter credentials on the fake login page? Check Azure AD / Entra ID sign-in logs immediately:
# Azure AD sign-in logs via PowerShell
Connect-MgGraph -Scopes "AuditLog.Read.All"
Get-MgAuditLogSignIn -Filter "userPrincipalName eq 'finance.user@company.com'" |
Select CreatedDateTime, AppDisplayName, IPAddress, Location, Status | Format-Table
# Look for:
# - Sign-ins from unusual countries
# - Sign-ins at unusual hours (e.g., 3 AM)
# - Successful auth after failed MFA
# Check OAuth app grants (attackers may have added persistent access)
Get-MgUserOauth2PermissionGrant -UserId "finance.user@company.com" | Select ClientId, ScopePhase 3: Eradication (1-4 Hours)
Step 7: Reset Credentials and Revoke Sessions
# Force password reset
Set-MgUserPassword -UserId "finance.user@company.com" -ForceChangePasswordNextSignIn $true
# Revoke ALL active sessions (forces re-login everywhere)
Revoke-MgUserSignInSession -UserId "finance.user@company.com"
# Disable the account temporarily if compromise confirmed
Update-MgUser -UserId "finance.user@company.com" -AccountEnabled $falseStep 8: Hunt for Persistence
Sophisticated attackers set up persistence before you lock them out — mailbox rules, OAuth apps, new admin accounts:
# Check inbox rules (attackers use these to hide replies/auto-forward)
Get-InboxRule -Mailbox "finance.user@company.com" | Select Name, ForwardTo, DeleteMessage
# Check for new admin accounts created recently
Get-MgDirectoryRole -Filter "displayName eq 'Global Administrator'" |
Get-MgDirectoryRoleMember | Select DisplayName, UserPrincipalName
# Check Exchange transport rules (could be forwarding all email out)
Get-TransportRule | Select Name, RedirectMessageTo, BlindCopyToPhase 4: Recovery & Lessons Learned
Step 9: User Communication
Send a company-wide security notice (without causing panic) alerting staff about the phishing campaign, providing indicators to watch for, and reminding them to report suspicious emails.
Step 10: Build a YARA Rule to Detect Future Variants
rule Phishing_BEC_Finance_2024 {
meta:
description = "Detects BEC phishing email patterns"
author = "PlainlySec SOC"
date = "2024-01-15"
strings:
$subj1 = "Urgent Wire Transfer" nocase
$subj2 = "Wire Transfer Request" nocase
$subj3 = "Confidential Transfer" nocase
$domain = "attacker-domain.com"
$urgency = "as soon as possible" nocase
condition:
any of ($subj*) and ($domain or $urgency)
}Free vs. Paid SOC Tools for Phishing Response
| Task | Free Tool | Paid Tool |
|---|---|---|
| Email gateway | SpamAssassin, Rspamd | Proofpoint, Mimecast |
| URL detonation | VirusTotal (free tier), URLhaus | Palo Alto WildFire, CrowdStrike |
| SIEM | Wazuh, ELK Stack | Splunk, Microsoft Sentinel |
| SOAR/Case Mgmt | TheHive, n8n | Splunk SOAR, ServiceNow SecOps |
| Threat Intel | MISP, OpenCTI, OTX | Recorded Future, Intel 471 |
| EDR | Wazuh, Velociraptor | CrowdStrike Falcon, SentinelOne |
The free tools in this table handle the vast majority of phishing incidents effectively. Most enterprise tools add automation and scale — but the core investigation skills remain identical.