TL;DR
Advanced persistent threats didn’t disappear; they moved closer to identity. In 2025, the most effective actors don’t always drop exotic malware - they live off the land inside your cloud tenant, harvest tokens, grant OAuth consents, and hide in mailboxes and service principals long enough to finish their objective. This field guide meets that reality head-on: it focuses on identity and SaaS-centric tradecraft, provides ATT&CK-mapped detections you can deploy, and lays out a pragmatic 90-day rollout your SecOps team can execute starting now.
What changed since 2023 (and why your defenses must, too)
Over the last 18–24 months, the center of gravity for serious intrusions shifted to identity and SaaS. Microsoft’s public write-ups of Midnight Blizzard (APT29) document the actor creating and consenting malicious OAuth apps to grant mailbox-wide access - persistence without a noisy implant. In one case, the actor used a legacy test app to obtain full_access_as_app (Exchange Online / Office 365) permissions across mailboxes, exemplifying the new playbook: compromise → consent → live quietly inside identity fabric.
Meanwhile, Volt Typhoon campaigns highlighted how nation-state actors burrow into critical infrastructure using valid accounts and living-off-the-land (LOTL) techniques to maintain long-term, low-noise persistence - often in places with thin logging. U.S. government guidance explicitly calls LOTL a hallmark of Volt Typhoon’s tradecraft and provides operational mitigations defenders can adopt. And this isn’t unique to Volt Typhoon: a Bitdefender analysis of 700,000 incidents found 84% of high-severity attacks involved LOTL binaries, underscoring how widespread these tactics have become.
On the destructive side, Sandworm/APT44 activity continued to blend espionage, sabotage, and information ops, with 2024–2025 reporting underscoring its integrated playbook and critical-infrastructure targeting. That matters because your tabletop scenarios should assume multi-vector pressure, not a tidy “single incident.”
Bottom line: the APT of 2025 is identity-centric, cloud-aware, and patient. Your defense must treat identity signals, Software-as-a-Service (SaaS) posture, and detections as first-class citizens alongside Endpoint Detection and Response (EDR) and Extended Detection and Response (XDR.)
APT lifecycle - rewritten for the identity era
The classic phases still apply, but each step now has an identity/SaaS flavor:
- Initial access: password spray, consent phishing, supplier compromise, or token replay.
- Establish persistence: OAuth application grants, service principals with excessive app roles, mailbox rules that hide replies. (No binary, no beacon - just platform features.)
- Discovery & lateral movement: enumerate tenants, mailboxes, SharePoint/Drive, cloud roles; pivot across test/production or subsidiaries via OAuth apps.
- Privilege escalation: abuse conditional access gaps, legacy auth, unmanaged device joins, or dormant high-privilege accounts.
- Collection & exfiltration: mailbox search/export, staged file syncing, exfil via sanctioned apps to look “normal.”
- Action on objectives: espionage, prepositioning for disruption, or financial fraud.
If your program still frames APTs as “EDR + patch” problems, you’ll miss the quiet parts.
Defender’s map: ATT&CK × identity & SaaS (high-value techniques)
Below are some examples and what to watch. Use them as seeds for your own coverage map.
The combination of malicious OAuth apps and LOTL is the signature of modern APT persistence. Build detections where your adversaries actually live - your IdP and SaaS logs.
Detection engineering you can actually ship
For each detection you get (a) the objective, (b) primary signals no matter your vendor, (c) where to pull those signals on Windows/macOS/Linux, and (d) an IdP/SaaS angle. Snippets use Sigma-style fields (generic) - translate to your SIEM syntax.
1) Suspicious OAuth consent spike (new app + high-privilege scopes)
Objective: Catch consent-phishing/token-based persistence that bypasses endpoint controls.
Primary signals (any stack): New OAuth app registration or enterprise app install; high-scope grants; unusual granter; bursty approvals.
- Windows/macOS/Linux: Mostly N/A (identity layer), but correlate with first-seen device or headless browser use on the approving host (EDR telemetry).
- IdP/SaaS:
- Entra/Okta/Google: Service/app creation, admin/user consent, high scopes (mail/files/all, offline_access, repo_admin, etc.).
- GitHub/Slack/Atlassian: New OAuth apps, token grants with org-wide scopes.
- Entra/Okta/Google: Service/app creation, admin/user consent, high scopes (mail/files/all, offline_access, repo_admin, etc.).
Sigma-style sketch
title: OAuth Consent Spike With High-Risk Scopes
logsource: identity
detection:
selection:
event.category: ["iam","application"]
event.action: ["app_consent_granted","oauth_app_installed","service_principal_created"]
oauth.scopes|contains_any:
- "Files.ReadWrite.All"
- "Mail.ReadWrite"
- "offline_access"
- "repo"
- "admin:*"
timeframe: 30m
condition: selection | count() by user.id > 2
fields: [user.id, app.id, oauth.scopes, source.ip, user.agent]
level: high
2) Mass mailbox rule creation/changes (multi-platform mail)
Objective: Find stealthy mail forwarding/hiding used for collection or BEC.
Primary signals: New/modified inbox rules, forwarding to external, “move to RSS/Archive,” auto-delete.
- Windows/macOS/Linux: If using Outlook/Apple Mail/Thunderbird local rules, watch for changes in client config files + EDR network beacons immediately after.
- IdP/SaaS (any email provider): Unified audit/mailbox audit logs: New-InboxRule/Update-InboxRule, external forward enabled, auto-forward policy violations, Gmail filters API changes.
Sigma-style sketch
title: Burst Of Suspicious Mailbox Rules
logsource: email
detection:
selection:
event.action: ["mailbox_rule_created","mailbox_rule_updated"]
rule.actions|contains_any: ["forward_external","delete","move_to_archive","mark_read"]
timeframe: 30m
condition: selection | count() by mailbox.address >= 3
fields: [mailbox.address, rule.name, rule.conditions, rule.actions, actor.user, source.ip]
level: high
3) High-risk token use (impossible travel + privileged action)
Objective: Tie an anomalous sign-in to a sensitive admin/API action shortly after.
Primary signals: Geo/ASN/device anomalies; privileged API calls (create user, change roles, modify SSO/SCIM, rotate keys).
- Windows: Event logs for new device sign-in + subsequent directory/privileged tooling (e.g., PowerShell Graph/AD modules).
- macOS: Unified Logging entries for new browser/device; EDR network telemetry to IdP endpoints followed by admin APIs.
- Linux: journald/auth logs for first-seen user-agent; CLI SDK calls (aws, gcloud, az) with admin actions.
- IdP/SaaS: Correlate sign-in risk or impossible travel with “role_assignment,” “policy_update,” “admin_consent,” “SCIM_provision.”
Sigma-style sketch
title: Impossible Travel Followed By Privileged Action
logsource: identity
detection:
signin_anom:
event.action: "login_success"
auth.risk: "impossible_travel"
admin_action:
event.action|contains_any: ["role_assignment","policy_update","key_rotation","create_service_principal"]
timeframe: 15m
condition: signin_anom by user.id then admin_action by user.id within 15m
fields: [user.id, source.geo, source.asn, target.resource, action.name]
level: critical
4) New service principal / robot identity with broad roles
Objective: Detect non-human identities gaining powerful org/tenant roles (hard to notice, very durable).
Primary signals: Creation of app/service account; assignment of org-wide roles or app roles; escalation of existing SP/robot.
- Windows/macOS/Linux: Track local credential stores/CLI profiles (e.g., ~/.aws/credentials, ~/.config/gcloud/, Azure CLI token cache) created right after SP creation.
- IdP/Cloud:
- Entra/Okta/Google/AWS/IAM: create_app, create_service_principal, attach_role_policy, UpdateAssumeRolePolicy, iam.serviceAccount.addKey.
- Kubernetes: ServiceAccount with ClusterRoleBinding.
- Entra/Okta/Google/AWS/IAM: create_app, create_service_principal, attach_role_policy, UpdateAssumeRolePolicy, iam.serviceAccount.addKey.
Sigma-style sketch
title: Newly Created Non-Human Identity With Broad Privileges
logsource: cloud
detection:
create_id:
event.action|contains_any: ["create_service_principal","iam.createUser","iam.createRole","projects.serviceAccounts.create"]
high_priv:
privileges|contains_any: ["*","Owner","Administrator","ClusterAdmin","iam:*","ec2:*","s3:*"]
condition: create_id and high_priv within 10m
fields: [actor.user, principal.id, privileges, source.ip]
level: high
5) Exfiltration via sanctioned SaaS (endpoint + SaaS together)
Objective: Catch “looks-legit” data staging/sync to approved tools at abnormal volume or timing.
Primary signals: Abnormal download/sync size or rate; creation of public links on sensitive libraries; off-hours spikes.
- Windows/macOS/Linux (endpoint): EDR network flows to sanctioned SaaS domains with unusual byte counts; filesystem events indicating bulk reads of labeled files before sync.
- SaaS: SharePoint/Google Drive/Box/Dropbox/Confluence: file download/create-link/audit events; DLP hits; sudden permission changes to “anyone with link.”
Sigma-style sketch
title: Sanctioned SaaS Data Exfil Pattern
logsource: saas
detection:
burst_downloads:
event.action|contains_any: ["file_download","file_sync"]
bytes_out > 500000000 # 500MB (tune per org)
public_link:
event.action: "link_created"
link.visibility: "public"
timeframe: 1h
condition: burst_downloads by user.id and public_link by user.id within 1h
fields: [user.id, saas.app, bytes_out, file.labels, link.url]
level: high
Platform signal cheat-sheet
- Windows: Security/Event Logs (4624/4625/4648), PowerShell logs, Sysmon, EDR process + network trees.
- macOS: Unified Logging (log show), EndpointSecurity/EDR events, keychain/launchd changes, new configuration profiles.
- Linux: auditd/auditbeat, journald (_SYSTEMD_UNIT, SYSLOG_IDENTIFIER), shell history anomalies, package manager logs.
- Identity/SSO: Okta System Log, Entra/Azure AD Audit/Sign-in, Google Workspace Admin, PingFederate, Duo, Auth0.
- Cloud/IaC: AWS CloudTrail, Azure Activity/Graph, GCP Admin Activity, Kubernetes audit, GitHub/Azure DevOps/GitLab audit.
- SaaS apps: M365/Google Drive/Box/Dropbox/Slack/Atlassian/GitHub audit streams; DLP/SSPM findings.
- Email: Microsoft 365/Exchange Online, Gmail audit, Proofpoint/Mimecast logs, DMARC aggregate/forensic where available.
Tuning & deployment tips (non-Microsoft)
- If you’re Okta-first, replace “consent events” with: app.oauth2.client.application.created, system.api_token.create, user.mfa.factor.deactivate, app.oauth2.scope.grant.
- If you’re Google Workspace-first, monitor: CREATE_DATA_ACCESS_LEVEL, AUTHORIZE_API_CLIENT_ACCESS, Gmail CREATE_FILTER with forward/external actions.
- On macOS fleets, lean on your EDR for network + process lineage around identity events and profile installs; add Configuration Profiles monitoring to flag unexpected SSO/MDM changes.
- On Linux servers, add CLI SDK telemetry (aws/gcloud/az) and watch for first-seen credentials files + subsequent high-priv API calls.
- Wherever possible, join identity + endpoint + SaaS: most of these detections “light up” when you correlate cross-source within short windows.
Control stack by maturity (choose your next step, not all steps)
You don’t need everything on day one. Build upward in deliberate stages, starting where the biggest gains come fastest - identity and detections - and then graduate to deeper coverage as your team and telemetry mature.
Level 1: Baselines that bite.
Get the fundamentals working for you every single day. Enforce MFA, moving to phishing-resistant methods where practical. Block legacy protocols that bypass modern protections. Use Conditional Access to evaluate user, device, and session risk before granting entry. Turn on audit logging across your identity provider, email, and core SaaS platforms, and light up alerts for mailbox-rule changes and new OAuth grants. Make reporting suspicious prompts a one-click action in mail and chat. Treat CISA’s living-off-the-land guidance as your minimum operating floor for configuration and hygiene.
Level 2: Identity-aware telemetry.
Once the basics hold, deepen visibility where today’s intrusions actually live: identity and SaaS. Stream IdP, email, and SaaS audit logs into your SIEM/XDR and add ITDR so you can reason about users, tokens, app grants, and privileged actions—not just endpoints. Deploy SSPM to surface risky OAuth consents and SaaS misconfigurations, and use EASM/CAASM to discover exposed assets and shadow IT. Prioritize quiet-signal detections: unusual OAuth scopes on new apps, bursts of mailbox rules, replayed tokens tied to admin API calls, newly created service principals gaining powerful roles, and anomalous downloads from labeled repositories. Pair detections with automatic containment steps—revoke tokens, disable suspect app grants, force re-auth—so response is measured in minutes.
Level 3: Operate like a hunter.
With telemetry in place, set explicit ATT&CK coverage goals and hunt the techniques that matter in your environment. Replace standing admin rights with tiered administration and just-in-time elevation so privileged sessions are rare, short, and heavily logged. Monitor service principals like crown jewels: owner verification, scope reviews, and alerting on privilege changes. Add targeted deception around high-value apps and identities to raise the cost of lateral movement. Run regular tabletop exercises that stress identity abuse paths, and feed what you learn back into detections and access policy.
Treat traditional endpoint controls and network monitoring as necessary - but recognize they’re not sufficient on their own for long-dwell, identity-centric campaigns. The combination that keeps pace in 2025 is an identity-first control plane, ITDR-driven detections, and disciplined operations with owners, SLAs, and audit-ready evidence.
A 90-day execution plan
Days 0–15: Instrument & baseline
Name the three human-plus-identity risks you actually see. Pipe IdP, email, and cloud audit logs into your SIEM/XDR. Turn on mailbox-rule/OAuth-consent alerts. Record a 60-second exec kickoff so managers carry the message.
Days 16–45: Enforce & detect
Enforce Conditional Access baselines (block legacy, step-up for risky sign-ins). Publish the first two detections above and tune. Inventory OAuth apps and service principals; disable unused, review privileged ones with owners. Hold a 2-hour tabletop: consent phishing + mailbox rule abuse + exfil tasking.
Days 46–75: Hunt & harden
Add detections 3 - 5. Introduce JIT for admin roles. Enable DLP/SSPM policies for sensitive stores. Run a phishing drill focused on consent prompts; remediate kindly but quickly.
Days 76–90: Report & iterate
Ship a one-page brief: what detections fired, what you tuned, what identity posture improved (fewer privileged SPs, fewer risky OAuth grants), and what changed in MTTD/containment. Capture artifacts (screenshots/exports) into your audit pack.
Are we already in an APT? Read the room through identity and SaaS
Forget generic “symptom” lists. In long-dwell intrusions today, the tells are quiet and identity-shaped and they’re all visible if you collect the right logs. Start with application consents and service principals: a newly registered OAuth app that requests sweeping Graph scopes (think mail or files at tenant scale), or a service principal that appears with broad roles and no clear owner. That’s not hygiene; that’s a foothold.
Pivot to mail telemetry. Bursts of inbox rules that silently move or delete messages, sudden forwarding to external recipients, and eDiscovery or export activity that no one recalls initiating are classic signs of mailbox harvesting and staging for exfiltration. Correlate sign-ins with admin actions as well: a “valid account” login from an impossible location followed minutes later by privileged API calls is the living-off-the-land pattern in miniature - credentials first, admin work second.
Watch dormant privilege waking up. A long-idle global admin, app registration permission, or powerful service principal springing to life for a short window and then going quiet again often marks hands on a backdoor rather than a routine task. Finally, follow the data. In sanctioned SaaS like SharePoint, OneDrive, Google Drive, or Box, look for spikes in downloads or syncs from sensitive libraries - especially when they happen at odd hours or from unfamiliar networks. Network tools may shrug at this traffic; your SaaS and DLP logs will not.
If you can describe these signals with timestamps, actors, scopes/roles, and follow-on actions, and you can’t find a legitimate change ticket, you don’t just have “weirdness.” You have a high-confidence APT lead, and your next move is containment: revoke tokens, disable the suspect app grant, lock or rotate impacted accounts and service principals, and begin a wider hunt for the same patterns across tenants.
People and process: training that shrinks the blast radius
Technology alone won’t hold. The people closest to identity and SaaS must recognize and report the quiet indicators APTs produce. Teach everyone how consent prompts work, what a suspicious OAuth screen looks like, and where to report it immediately. For IT, cloud, and engineering, go beyond concepts: practice hardening identity providers, reviewing OAuth apps, locking down service principals, and responding to mailbox rule abuse in hands-on labs. For SOC, practice the detections above until response times drop.
Cybrary fits as your role-based learning and practice engine: enroll IT/cloud/dev/SOC personas in the paths and labs that mirror their jobs, pair phishing/tabletop exercises with relevant lessons as pre-work or remediation, and export completion/lab outcomes into your evidence pack.
Build Your Quarterly Cyber Risk Snapshot
Make your quarterly update a crisp narrative that a director can absorb in two minutes. Start with what changed: describe how identity posture improved - fewer always-on admins, a smaller set of privileged service principals, and a reduction in risky OAuth consents. Note the expansion of detection coverage by naming the ATT&CK techniques you can now see reliably, and add one human signal that matters, such as a higher first-hour phishing-report rate.
Then translate that movement into operational risk. Explain, in plain language, that fewer valid-account intrusions are progressing to mailbox or data-access stages, and that the ones that do are being contained faster because alerts arrive earlier and with better context.
Close with what happens next. Commit to a small, concrete set of actions for the coming quarter - two new detections you’ll ship, one access-policy change you’ll enforce, and one exercise you’ll run - and give each an owner and a date.
Attach concise evidence, not a data dump: a link to your consent-log review, a screenshot of a tuned detection firing and being triaged, and the updated ATT&CK-by-identity matrix that shows coverage at a glance. Presented the same way every quarter, this single page becomes a trustworthy record of progress for both the board / auditors and it keeps your program focused on outcomes rather than activity.
Appendix: five starter detections (pseudocode to adapt)
New app consent with risky scopes
What it does: Flags users granting OAuth consent to a new application that requests powerful scopes (e.g., full mailbox/file access) within the last hour, excluding known privileged admin accounts.
Why it matters: Consent phishing and malicious app registration are common APT persistence paths that bypass MFA and endpoint tools.
How to read it:
- Filters for “ConsentToApp” events and checks if requested scopes include high-risk permissions.
- Excludes a safelisted admin group to reduce noise from legitimate admin activity.
- Buckets by 1-hour windows and surfaces who approved what app and scopes.
Tuning tips: Maintain an allowlist of known apps/scopes; consider alerting only on new apps or first-time consents per user.
Investigate next: Validate the app publisher, review all granted scopes, revoke consent if suspicious, and hunt for token refresh activity from unfamiliar IPs/devices.
where Event == "ConsentToApp"
and Scopes has_any ("full_access_as_app","Mail.ReadWrite","Files.ReadWrite.All")
and Actor not_in (PrivilegedAdmins)
| summarize count() by Actor, AppId, Scopes, bin(TimeGenerated, 1h)
Mailbox rule storm
What it does: Detects bursts of inbox rule creation or changes on a single mailbox in a short period (e.g., >3 rules in 30 minutes).
Why it matters: Attackers often create rules to hide or forward messages (collection/BEC staging) without tripping login alerts.
How to read it:
- Looks for “New-InboxRule” or “Set-InboxRule” operations.
- Counts rule changes per user within a 30-minute window and flags unusually high activity.
Tuning tips:
- Add rule-content filters (forward to external, move to RSS/Archive, delete) for higher fidelity.
- Suppress during known migrations or when admins are bulk-standardizing rules.
- Investigate next: List new/changed rules, destinations (external domains), and who/what performed the action (user vs service). Disable suspicious rules and review concurrent sign-ins.
where Operation in ("New-InboxRule","Set-InboxRule")
| summarize RuleCount = count() by UserId, bin(TimeGenerated, 30m)
| where RuleCount > 3
Impossible travel + privileged action
What it does: Detects bursts of inbox rule creation or changes on a single mailbox in a short period (e.g., >3 rules in 30 minutes).
Why it matters: Attackers often create rules to hide or forward messages (collection/BEC staging) without tripping login alerts.
How to read it:
- Looks for “New-InboxRule” or “Set-InboxRule” operations.
- Counts rule changes per user within a 30-minute window and flags unusually high activity.
Tuning tips:
- Add rule-content filters (forward to external, move to RSS/Archive, delete) for higher fidelity.
- Suppress during known migrations or when admins are bulk-standardizing rules.
- Investigate next: List new/changed rules, destinations (external domains), and who/what performed the action (user vs service). Disable suspicious rules and review concurrent sign-ins.
let risky_signins = (SigninLogs | where RiskLevel >= "medium" | project UserId, TimeGenerated);
AdminActions
| lookup risky_signins on UserId
| where AdminActions.TimeGenerated between (risky_signins.TimeGenerated .. risky_signins.TimeGenerated + 15m)
New service principal with elevated role
What it does: Surfaces creation or modification events where a new application/service principal (non-human identity) is granted high-privilege roles or app permissions.
Why it matters: Robot identities with tenant-wide rights are stealthy persistence; they can access mail, files, or directories without interactive logins.
How to read it:
- Watches directory audit logs for app role assignments.
- Flags when the assigned role is powerful (e.g., Exchange.ManageAsApp, Directory.ReadWrite.All).
Tuning tips:
- Maintain a registry of approved service principals and expected roles; alert only on new SPs or new high-priv grants.
- Include who granted the role and from where to assist triage.
- Investigate next: Validate business justification with the owner/team, rotate app secrets, and revoke the role if unapproved. Review follow-on API usage by that SP.
DirectoryAudit
| where Operation == "AddAppRoleAssignment"
and AppRole in ("Exchange.ManageAsApp","Directory.ReadWrite.All", "Mail.Read")
Exfil pattern via sanctioned SaaS
What it does: Detects potential data exfiltration through approved cloud storage by looking for unusually high download/sync volume of labeled-sensitive content in short windows.
Why it matters: APTs often use “allowed” apps (SharePoint/Drive/Box) to blend in while staging or exfiltrating data.
How to read it:
- Aggregates file operations by user and sensitivity label over 1 hour.
- Alerts when volume exceeds a threshold on “Confidential/Restricted” sites/libraries.
Tuning tips:
- Calibrate the byte/volume threshold per team (engineering vs HR will differ).
- Add conditions for public link created or sharing to external domains to increase fidelity.
- Investigate next: Identify which files were accessed, sharing changes, time of day, and destination links. Temporarily suspend external sharing for the user/library and review endpoint activity leading up to the burst.
SharePointFileOperation
| summarize Downloads = count() by UserId, SiteSensitivityLabel, bin(TimeGenerated, 1h)
| where SiteSensitivityLabel in ("Confidential","Restricted") and Downloads > threshold
Tune thresholds, add allow-lists for known automations, and wire pages to analyst runbooks.
Conclusion
APTs are not a malware genre; they are an operational style. In 2025, that style is defined by identity: consent prompts, tokens, service principals, and SaaS admin APIs - plus the old LOTL discipline that keeps noise low. If you log where the adversary lives, ship detections that fit your tenant, harden identity in 90 days, and train the people nearest the blast radius to spot the quiet tells, you’ll make serious intrusions expensive again.
Ready to help your team level up? Find out how Cybrary can get you there. Request a demo, today.





