Playbooks
T1078SaaS Account Takeover Response Playbook
A structured playbook for detecting, containing, and investigating SaaS account takeovers — covering MFA bypass, session hijacking, OAuth abuse, and automated credential stuffing across SaaS platforms.
View on Graph
What This Playbook Covers
- SaaS account takeovers occur when an attacker gains unauthorized access to a user’s cloud application account — typically through stolen credentials, session token theft, or MFA fatigue push bombing
- This is distinct from on-prem credential theft. SaaS accounts have different detection surfaces (API logs, cloud audit logs, browser sessions) and different containment mechanisms (session revocation, OAuth token invalidation)
- MITRE ATT&CK maps SaaS account takeover under
T1078(Valid Accounts) andT1556(Modify Authentication Process) for MFA bypass
Common SaaS Takeover Vectors
| Vector | How It Works | SaaS Accounts Affected |
|---|---|---|
| Credential stuffing | Automated login attempts using breached credentials from prior data breaches | Any SaaS with login — most common on O365, Salesforce, GitHub |
| MFA fatigue | Repeated push notification spam until the user approves | All MFA-protected SaaS (Azure AD, Google Workspace, Okta) |
| Session token theft | Steal session cookie/token via malware, proxy, or browser extension | Any SaaS with persistent sessions |
| OAuth abuse | Malicious OAuth app requesting excessive permissions | Google Workspace, Slack, GitHub, Salesforce |
| SIM swapping | Social engineer the carrier to transfer the phone number — reset MFA | Any SaaS using SMS MFA |
| Phishing (credential + session) | Credential harvesting via phishing site that proxies the real login | Any SaaS |
Phase 0: Detect the SaaS Takeover (0-15 minutes)
Detection Indicators by SaaS Platform
Detection — Anomalous sign-in activity: Monitor these signals across your SaaS platforms:
| Signal | What to Check | Examples |
|---|---|---|
| Impossible travel | Two sign-ins from geographically impossible locations within the session window | Login from New York then login from Lagos 15 minutes later |
| Unfamiliar device/browser | First sign-in from a device/browser the user has never used | New device, new OS, new browser family |
| Unfamiliar IP/location | Sign-in from an IP not in the user’s normal range | VPN exit node, TOR exit node, known malicious IP |
| Anomalous sign-in frequency | Failed sign-ins followed by successful sign-in | Credential stuffing pattern: 20 failed MFA attempts, then success |
| New MFA enrollment | MFA device added shortly before the takeover | New device enrolled, then legitimate device removed |
| Mailbox rule creation | New rule forwarding or deleting email | Attacker creates rule to hide compromise notifications |
| OAuth app consent | User grants consent to an OAuth app they have never used | New third-party app with Mail.Read, Files.ReadWrite permissions |
KQL query — Azure AD sign-in anomalies:
SigninLogs
| where TimeGenerated > ago(1h)
| where RiskLevelDuringSignIn in ("medium", "high") or RiskLevelAggregated in ("medium", "high")
| project TimeGenerated, UserPrincipalName, IPAddress, Location, RiskLevelDuringSignIn,
DeviceDetail.browser, DeviceDetail.operatingSystem, Status.failureReason
| order by TimeGenerated desc
Google Workspace — anomalous login detection:
index=google_workspace event_name="login_success" OR event_name="login_failure"
| stats values(event_name) as Events, values(ip_address) as IPs, values(user_agent) as UserAgents by actor_email, _time
| where mvcount(IPs) > 3
| eval alert = "SUSPICIOUS — multiple IPs for " . actor_email . " in one session"
Slack — anomalous workspace access:
index=slack event_type="user_login"
| eval is_new_device = if(match(user_agent, "Mozilla") AND NOT match(user_agent, known_slack_user_agents), 1, 0)
| where is_new_device = 1 AND location NOT IN (known_team_locations)
| eval alert = "SUSPICIOUS — new device login for " . user_name . " from " . location
Phase 1: Immediate Containment (15-30 minutes)
Critical Actions — Do These First
- Force password reset — do not use the user’s last password, and require MFA re-registration
- Revoke all active sessions — sign out of all sessions across the affected SaaS, not just the current session
- Revoke OAuth tokens — revoke all third-party app OAuth tokens granted by the affected user
- Disable the user account — temporarily disable the account in the IdP while investigating
- Check for mailbox rules — if O365 or Google Workspace, check for suspicious forwarding, deletion, or phishing rules
- Cancel pending actions — if the attacker initiated actions (password reset, email forwarding, payment method change), cancel them
Platform-specific session revocation:
| Platform | Revocation Method |
|---|---|
| Azure AD / O365 | Revoke-AzureADUserAllRefreshToken -ObjectId <user> |
| Google Workspace | Admin console → Security → Session control → Sign out all sessions |
| Salesforce | Setup → Users → User detail → Session management → Log out |
| Slack | Workspace settings → Manage members → Deactivate or Force logout |
| GitHub | Settings → Security → Revoke all sessions |
| AWS | IAM → Users → Revoke all active sessions |
What NOT to Do
| Action | Why It’s Dangerous |
|---|---|
| Notify the user immediately | If the user is the attacker (the account was compromised through credential sharing or their own device was compromised), notifying them may tip off the attacker. Verify through a separate channel. |
| Only reset password | The attacker may still have OAuth tokens, active sessions, or mailbox rules that persist after password reset |
| Ignore MFA device enrollment | If the attacker enrolled their own MFA device, a password reset does not - the device persists |
| Assume it’s only one account | Credential stuffing often tests multiple accounts from the same breach database. Check for other recently compromised accounts. |
Phase 2: Evidence Preservation (30-60 minutes)
Evidence to Capture
| Evidence | Source | How to Capture |
|---|---|---|
| Sign-in logs | Azure AD SigninLogs, Google Workspace login audit | Export 7 days of sign-in logs for the affected user |
| OAuth consent logs | Azure AD consent logs, Google Workspace OAuth audit | List all OAuth apps the user has consented to |
| Mailbox audit logs | O365 Mailbox Audit, Gmail audit log | Check for rule creation, message forwarding, message deletion |
| Audit log (all platform activity) | Each SaaS platform’s audit log | Full export of the user’s activity for 7 days before and during the incident |
| MFA enrollment/change logs | IdP audit logs | Check when MFA was enrolled, changed, or removed |
| Password reset logs | IdP audit logs | Check if password reset was initiated by the attacker |
Phase 3: Investigation (1-4 hours)
Questions to Answer
| Question | Evidence Source | How to Determine |
|---|---|---|
| How was the account compromised? | Sign-in log analysis — credential stuffing, phishing, MFA fatigue, session theft, SIM swap | Pattern of failed logins + MFA approvals + device enrollment |
| What data was accessed? | Each platform’s audit log — file access, email read, API calls, repository access | List all data types accessed during the compromise window |
| Was data exfiltrated? | Email forwarding rules, file downloads, API calls to external services | Check for large downloads, email forwarding, external sharing |
| What actions were taken? | Full audit log of the compromise session | List every action: password resets, MFA changes, OAuth consents, mailbox rules |
| Were other accounts affected? | Cross-reference IP, device, and session data across other users | Check if the same IP/device was used against other accounts |
| Is the attacker still active? | Active sessions, OAuth token usage, recent logins | Check active sessions and recent activity |
Phase 4: Recovery and Hardening
Account Recovery
| Action | Detail | Timeline |
|---|---|---|
| Password reset (strong, unique) | 30+ character random password | Immediate |
| MFA re-registration | Require new MFA enrollment with FIDO2 or number-matching push | Immediate |
| Session token revocation | Revoke all active sessions, OAuth tokens, and app passwords | Immediate |
| Mailbox/rule cleanup | Remove any attacker-created rules, forwarding, or delegation | 1 hour |
| OAuth app audit | Review and revoke suspicious OAuth applications | 1-2 hours |
| Restore deleted data | Check recycle bin/deleted items for attacker-deleted data | 2-4 hours |
Long-Term Hardening
| Control | What It Prevents | Implementation |
|---|---|---|
| Conditional Access policies | Anomalous sign-in (impossible travel, unfamiliar device) | Azure AD Conditional Access or Google Workspace Context-Aware Access |
| Number-matching MFA | MFA fatigue push bombing | Require number matching for all MFA approvals |
| FIDO2/Passkeys | Phishing-resistant MFA | Deploy FIDO2 security keys for privileged users |
| Session token protection | Session token theft | Token binding, short-lived sessions, continuous access evaluation |
| OAuth app governance | Malicious OAuth app consent | Restrict OAuth consent to approved app publishers only |
| Credential monitoring | Credential stuffing | Deploy Azure AD Identity Protection or Google Workspace alert center |
| User education | Phishing and social engineering | Regular training on MFA fatigue, phishing, and OAuth risks |
Related
- Credential Theft Incident Response — detection and response for T1558.001, T1003.001, T1134 techniques
- Cloud Incident Response — detection and response for T1525, T1526, T1078, T1530 techniques
- MFA Fatigue — detection and response for T1110.004, T1621 techniques
- Phishing — detection and response for T1566 techniques
- Suspicious Authentication — detection and response for T1078 techniques
