SaveMyCert
Log in
5 of 5 free questions left today·for 10 a day
Respond to security incidents

SC-200 Microsoft 365 Investigations: Purview Audit, Content Search and Graph Activity Logs

19 min readSC-200 · Respond to security incidentsUpdated

Investigating Microsoft 365 activities for SC-200 means using three evidence sources to find out what an attacker did: Microsoft Purview Audit for activity records, Content search in Microsoft Purview eDiscovery for the content itself, and Microsoft Graph activity logs for API calls made against your tenant. This lesson covers who can search the audit log and how long records last, how to run and scope audit searches, how MailItemsAccessed scopes a mailbox compromise, how to pull audit data programmatically, how to build KeyQL content searches and purge malicious email, and how to turn on and query Graph activity logs.

What you’ll learn
  • Choose between Purview Audit, eDiscovery Content search and Microsoft Graph activity logs for a given investigation question
  • Assign least-privileged audit and eDiscovery roles and confirm that unified audit log ingestion is on
  • Predict how long an audit record is kept from the user's licence, the workload and any custom retention policy
  • Run and scope Purview audit searches within their limits, and use MailItemsAccessed to scope a mailbox compromise
  • Pick the right programmatic route for audit data: Search-UnifiedAuditLog, the Graph audit log query or the Office 365 Management Activity API
  • Write correct KeyQL queries and remove malicious email with search and purge
  • Turn on Microsoft Graph activity logs and query them in Log Analytics or Defender XDR advanced hunting

Which Microsoft 365 investigation tool answers which question

SC-200 names three Microsoft 365 investigation sources: Microsoft Purview Audit records what people and apps did, Content search in Microsoft Purview eDiscovery finds what content exists, and Microsoft Graph activity logs record which Graph API calls were made against your tenant. Choosing the wrong one is the commonest mistake: an audit search can't tell you whether a message body contains a phrase, and a content search can't tell you who downloaded a file.

SourceWhat it holdsTypical SOC questionWhere you query it
Microsoft Purview Audit (unified audit log)Activity records from Exchange, SharePoint, OneDrive, Teams, Microsoft Entra ID and other servicesWho downloaded this file? Did the attacker create an inbox rule? Which messages did they read?Audit search in the Purview portal, Search-UnifiedAuditLog, the Graph audit log query, the Office 365 Management Activity API
Content search (eDiscovery)The content itself: mailbox items, OneDrive and SharePoint documents, Teams messagesWhich mailboxes received this phishing message? Where does the leaked file name appear?A search in an eDiscovery case or the Content Search case; search and purge for email
Microsoft Graph activity logsEvery HTTP request made to Microsoft Graph for resources in your tenantWhich API calls did this compromised app or service principal make, and were any refused?The MicrosoftGraphActivityLogs table in Log Analytics or Microsoft Sentinel; GraphAPIAuditEvents in Defender XDR advanced hunting

The three are complementary. A typical business email compromise investigation uses audit search to find the attacker's sign-in session and inbox rules, MailItemsAccessed records to scope which mail was read, content search to find every copy of the phishing message, and search and purge to remove it. Alert triage in the Defender workloads belongs to the sibling topic on Defender alerts; this lesson is about the Microsoft 365 evidence behind them.

Turning on Purview Audit and getting search access

To search the audit log you need the Audit Logs or View-Only Audit Logs role in the Microsoft Purview portal, and auditing must be on for the tenant. Both roles allow searching and exporting; Audit Logs also allows turning auditing on or off, so View-Only Audit Logs is the least-privileged choice for analysts who only search.

Two places to assign the same roles

The portal and the cmdlets use different role systems. A role assigned in the Purview portal lets you search in the portal; to run Search-UnifiedAuditLog and the other audit cmdlets, the user needs Audit Logs or View-Only Audit Logs assigned in the Exchange admin center (Exchange Online RBAC). Portal access doesn't carry over to PowerShell: each role system needs its own assignment.

Checking and changing whether auditing is on

Auditing is on by default in Microsoft 365 organisations, but it can be turned off. Check and change it in Exchange Online PowerShell:

Get-AdminAuditLogConfig | Format-List UnifiedAuditLogIngestionEnabled
Set-AdminAuditLogConfig -UnifiedAuditLogIngestionEnabled $true

The same Get- cmdlet exists in Security & Compliance PowerShell, but there its UnifiedAuditLogIngestionEnabled value is always False, even when auditing is on. If portal searches return recent records, auditing is on; read the value in Exchange Online PowerShell before raising a change. Turning ingestion on captures activity from that moment; earlier activity is not backfilled.

How long audit records are kept: Standard, Premium and retention policies

Audit (Standard) keeps records for 180 days; Audit (Premium) keeps Exchange, SharePoint, OneDrive and Microsoft Entra ID records of E5-licensed users for one year by default, and custom audit log retention policies can set other durations, up to ten years with an add-on licence. (The Standard default rose from 90 to 180 days in October 2023.)

Who gets the one-year default

Two conditions must both hold. The user who performed the activity needs an Office 365 or Microsoft 365 E5 licence (or an E5 Compliance, Purview suite or eDiscovery and Audit add-on), and the record must come from one of the four workloads in the default policy: AzureActiveDirectory, Exchange, OneDrive, SharePoint. Records from other workloads, such as Teams, keep 180 days even for E5 users, and activity by non-E5 users and guest users keeps 180 days. So for the same E5 user, a OneDrive record outlives a Power BI record created the same day by about six months. The default policy can't be edited.

Custom audit log retention policies

  • Role: creating or changing a policy needs the Organization Configuration role in the Purview portal. The audit search roles don't include it.
  • Criteria: record types, activities and users; an empty Users field means every user. The Activities field appears only when you select a single record type; with several record types the policy covers all their activities.
  • Priority: from 1 (highest) to 10000 (lowest). When several policies match a record, the one with the highest priority (lowest number) wins, regardless of how specific or how long it is. An organisation can have up to 50 policies.
  • Custom beats default: any custom policy takes precedence over the default policy, even when it is shorter. For example, a 90-day SharePoint policy covering all users cuts the SharePoint records of E5 users from one year to 90 days.
  • Not retroactive: a record's lifetime is set when it enters the audit pipeline, so a new or changed policy affects only records created afterwards.
  • Ten years: needs the 10-Year Audit Log Retention add-on on the user who generates the record (not on the analysts who search), plus a ten-year policy covering that user. Licensing only the users in scope keeps the cost down. Any duration beyond one year (three, five, seven or ten years) needs that add-on, and every custom duration, including short ones such as 7 or 30 days, needs E5-level licensing.

Mailbox access records (MailItemsAccessed) use the record type ExchangeItemAggregated; SharePoint and OneDrive file activities such as FileDownloaded use SharePointFileOperation.

Running an audit search in the Purview portal

An audit search in the Purview portal is an asynchronous search job: you set a date range and filters, start it, and read the results from the search job dashboard when it completes. Jobs keep running after you close the browser, and completed jobs are kept for 30 days, so a long search can be started at the end of a shift and opened the next morning.

Limits that shape an investigation

LimitBehaviour
Concurrent jobsUp to 10 running per user, but only one unfiltered job (no workload, record type, user or activity filter). A second all-blank search won't start; add any filter or wait.
Date rangeUp to 180 days per search; what you can find also depends on retention.
LatencyMicrosoft doesn't guarantee a time. For core services (Exchange, SharePoint, OneDrive, Teams) records typically appear 60 to 90 minutes after the event, so an empty result for the last half hour usually means "not yet". Defender XDR advanced hunting is the faster source for near-real-time signals.
ExportUp to 50,000 rows for Audit (Standard) and up to 1,000,000 for Audit (Premium). For larger Standard result sets, run several narrower searches (for example, shorter date ranges). Copying a search reproduces the same result set.

Search criteria

  • Activities - operations names must be the exact operation name, such as New-InboxRule or FileDownloaded. A description such as "New inbox rule" returns nothing. The Activities - friendly names list lets you pick activities by description instead.
  • Record types and Workloads narrow by source; a workload filter on its own is tenant-wide.
  • File, folder, or site takes part or all of a name or URL, with * as a wildcard at the end. https://fabrikam.sharepoint.com/sites/Projects* returns that site and everything beneath it.
  • Keyword Search searches only the indexed common schema of the record, not the audit data content. Values that sit in an operation's parameters (an inbox rule's ForwardTo address, for example) are not found by keyword; filter on the operation, then read the parameters in the record details or export.

Administrative units

An admin assigned one or more Purview administrative units is a restricted admin: they can search and export only user-generated records within their units. Some operations, including Exchange Set-Mailbox, Set-MailboxPlan and SupervisionBulkEmailExclusion, are visible only to unrestricted admins (no unit assignment).

Scoping mailbox compromise with MailItemsAccessed

MailItemsAccessed is the mailbox audit action that records when mail is read or synced, and it is part of Audit (Standard): it is on by default for users with Office 365 or Microsoft 365 E3/E5 licences. An E3 organisation can therefore scope which messages an attacker accessed without buying an upgrade. Audit (Premium) adds intelligent insights such as extra properties (for example SensitivityLabel) on the records, not the event itself. The records are in the unified audit log, so portal search, Search-UnifiedAuditLog and the APIs all return them.

Sync versus Bind

MailAccessTypeWhen it is writtenHow to scope exposure
SyncDesktop Outlook downloads a folder's items to the local computer; one record per folder, not per itemAssume every item in the synced folder is compromised; once synced it can be read offline with no further audit record
BindAn individual message is accessed (for example in Outlook on the web); records list each message's InternetMessageId, aggregated over two-minute windowsTreat the messages named by InternetMessageId as exposed

De-duplication and separating attacker from owner

To control volume, duplicate records for the same bind within an hour are filtered out, unless the context differs: ClientIPAddress, ClientInfoString, ParentFolder, Logon_type, MailAccessType, MailboxUPN, User or SessionId. For example, a user who opens a message in Outlook on the web and, 40 minutes later, in the Outlook mobile app produces two records, because ClientInfoString and SessionId differ; opening it again in the same browser session within the hour adds nothing. The audit trail shows when each context first touched a message, not every repeat.

In a compromised account the attacker signs in as the owner, so the identity fields can't tell them apart. To separate them, compare SessionId (the sign-in session) and ClientIPAddress (the network), helped by ClientInfoString. Find the attacker's session in the sign-in data first, then filter MailItemsAccessed records to it.

Other mailbox evidence comes from the same audit log: inbox rules created with New-InboxRule or changed with Set-InboxRule, and mailbox forwarding set with Set-Mailbox.

Getting audit data out programmatically

Use Search-UnifiedAuditLog for ad hoc scripted searches, the Microsoft Graph audit log query for filtered searches over REST, and the Office 365 Management Activity API for a continuous feed into a SIEM. Microsoft's guidance for programmatically downloading audit data is the Management Activity API rather than a PowerShell script.

MethodShapeUse it when
Search-UnifiedAuditLogExchange Online cmdlet; run in Exchange Online PowerShell (Connect-ExchangeOnline), not Security & Compliance, Entra or Azure PowerShellAn analyst scripts a one-off pull, such as the last day's records for a list of accounts
Microsoft Graph auditLogQuery (security API)Create a query with filters (date range, record types, services, operations, user principal names, IP addresses, object IDs, administrative units), poll its status, then read its recordsA filtered historical search from code, without PowerShell
Office 365 Management Activity APISubscriptions per content type; the collector lists available content and downloads content blobsA SIEM ingests audit data continuously, for correlation and retention beyond Purview's

Management Activity API windows

When listing content, startTime and endTime must be no more than 24 hours apart, and the start no more than seven days in the past; older content can't be retrieved (error AF20051). Restarting a subscription gives access only to content from then on, it doesn't replay the past. A gap in the feed is therefore recoverable from the API only for its most recent seven days, in windows of 24 hours or less; anything older has to come from the audit log itself, which still holds it for at least 180 days. Audit (Premium) raises the API's bandwidth allocation.

Graph activity logs, covered below, are a different source: they describe calls made to Microsoft Graph, not Microsoft 365 workload activity.

Content search in Microsoft Purview eDiscovery

Content search now means a search in the unified eDiscovery experience, either inside a case or in the organisation's built-in Content Search case, which is meant for searches not tied to a legal matter. Microsoft retired the classic eDiscovery experiences, including classic Content search, on 31 August 2025, so there is no standalone classic search page to use.

Permissions

To create and run searches, a user needs membership of the eDiscovery Manager role group or the Compliance Search role. Deleting messages is a separate right (see search and purge), so an organisation can control who searches mailboxes separately from who deletes. Audit roles and Organization Configuration belong to Purview Audit, not eDiscovery.

Building and checking a search

  • Data sources: choose the mailboxes, OneDrive accounts, SharePoint sites and Teams locations to search, or tenant-wide sources.
  • Condition builder or KeyQL editor: the condition builder adds condition cards (keywords, date, sender and so on). The KeyQL editor takes a written query; existing conditions are converted to KeyQL when you switch, and a KeyQL condition must stand alone, so further criteria such as a date range go into the KeyQL text joined with AND.
  • Choose search results: Statistics shows estimated hit counts arranged by top indicators, optionally with the query keywords report (hits per term); Sample shows a representative selection with a chosen number of items per location. Together they let you check a query before you add results to a review set or export.

KeyQL syntax that changes the result set

Keyword Query Language (KeyQL) is the query syntax for eDiscovery searches, and a few rules decide whether a query returns exactly the intended set or thousands of unrelated items.

RuleEffectExample
A space between terms means ORfrom:"Priya Shah" subject:budget returns everything from Priya plus everything with that subjectWrite from:"Priya Shah" AND subject:budget
Operators must be uppercase (AND, OR, NOT, NEAR)Lowercase and is treated as a keywordkind:email AND from:"Lee Gu"
Quote multi-word property valuessubject:Quarterly forecast matches "Quarterly" in the subject and "forecast" anywheresubject:"Quarterly forecast"
No space after the colonsubject: invoice no longer filters on the propertysubject:invoice
Wildcards are prefix onlySuffix (*voice), infix (in*oice) and substring (*invoic*) searches aren't supportedsubject:invoic*
Email has separate datesreceived is when a message arrived; sent is when it was sentreceived:2026-10-01..2026-10-31
Item kindskind:email and kind:microsoftteams separate mail from Teams chatskind:microsoftteams AND invoice
Site-only paths need a trailing /Without it, sites with a similar path (HR-Old) also matchpath:"https://fabrikam.sharepoint.com/sites/HR/"
ProximityNEAR(n) allows n or fewer words between terms; bare NEAR defaults to 8acquisition NEAR(3) Fabrikam

Date ranges use two dots between the start and end dates. When a query returns far more than expected, check first for a missing uppercase AND and for unquoted multi-word values; the query keywords report shows which term is responsible.

Removing malicious email with search and purge

Search and purge deletes the email found by an eDiscovery search from users' mailboxes, using New-ComplianceSearchAction -Purge in Security & Compliance PowerShell (or Microsoft Graph in a premium case). Purge actions need a search-only session: connect with Connect-IPPSSession -EnableSearchOnlySession using Exchange Online PowerShell module 3.9.0 or later, or the action fails. Where Microsoft Defender for Office 365 Plan 2 is available, Microsoft recommends its remediation (for example from Threat Explorer) instead; search and purge is the route for organisations without it.

Permissions

Purging needs the Search And Purge role or the Organization Management role group in the Microsoft Purview portal. Membership of Organization Management in Exchange Online doesn't count. Without the right, the cmdlet simply has no -Purge parameter, producing the error "A parameter can't be found that matches parameter name 'Purge'". Creating the search itself needs eDiscovery Manager or Compliance Search.

Soft delete or hard delete

PurgeTypeWhere the message goesCan the user recover it?
SoftDeleteThe Recoverable Items folder (Deletions)Yes, for the deleted item retention period; use it when some matches may be legitimate
HardDeleteMarked for permanent removal; moved to the Purges folderNo; even with single item recovery or a hold it is kept only for the organisation

Limits

  • Items per location: in a case without premium features only PowerShell can purge, up to 10 items per mailbox per action; rerun the action to remove more. Premium (E5) cases can purge up to 100 items per location through Microsoft Graph (purgeData). Don't mix PowerShell and Graph purges for the same search.
  • Mailboxes per search: a search used for a purge can cover at most 50,000 mailboxes, and the purge fails if it covers more, even when fewer contain matches. In larger tenants, split the mailboxes with temporary search permissions filters (by department, location and so on) and purge each subset.
  • Scope: mailboxes and public folders only. Teams chat messages are removed through a separate process, and SharePoint or OneDrive files aren't purged this way. Unindexed items aren't purged, and when a mailbox is on litigation hold, purged items are kept in Recoverable Items rather than permanently deleted.

Investigating with Microsoft Graph activity logs

Microsoft Graph activity logs are an audit trail of every HTTP request made to Microsoft Graph for resources in your tenant, delivered through a Microsoft Entra diagnostic setting as the MicrosoftGraphActivityLogs category. They show what a compromised app, service principal or user token did through the API, which sign-in logs alone can't.

Turning them on

  • Licence: Microsoft Entra ID P1 or P2 for the tenant. Purview Audit licensing plays no part.
  • Role: Security Administrator is the least-privileged role that can create the diagnostic setting; Global Administrator works but is broader.
  • Destination: a Log Analytics workspace (analysis in Azure Monitor or Microsoft Sentinel), an Azure Storage account (archive), or an event hub (streaming to a third-party SIEM), in an Azure subscription where the admin has permission to use it (for a storage account, the right to list its keys).
  • No filtering in the diagnostic setting. To cut cost in a workspace, apply a workspace transformation to the table to drop rows (for example an internal inventory tool's routine reads) or columns. The Basic plan also lowers cost but limits how the table can be queried, so it suits tables kept for occasional investigation rather than ones that detections run against.
  • Delivery and scope: most events arrive within 30 minutes, some take up to two hours. Logs exist only from when the setting is configured (no backfill), and they cover the resource tenant: calls a multitenant app makes into a customer's tenant appear in that customer's logs, not the publisher's.

Querying the logs

Key columns are AppId, ServicePrincipalId, UserId, RequestUri, RequestMethod, ResponseStatusCode, IPAddress, Roles, Scopes, ClientAuthMethod and SignInActivityId.

  • Permission probing: refused requests show ResponseStatusCode 401 or 403; 429 is throttling and 5xx are service errors.
  • App-only versus delegated: a call with application permissions has an empty UserId and its app roles in Roles; a delegated call carries the user's UserId and delegated permissions in Scopes. ClientAuthMethod is 0 for a public client, 1 for a client secret and 2 for a certificate.
  • Linking a request to its sign-in: join SignInActivityId to UniqueTokenIdentifier in the sign-in table that matches the actor: SigninLogs or AADNonInteractiveUserSignInLogs for users, AADServicePrincipalSignInLogs for service principals, AADManagedIdentitySignInLogs for managed identities.

This query lists which apps and users changed service principals (for example by adding credentials) over the last week:

MicrosoftGraphActivityLogs
| where TimeGenerated >= ago(7d)
| where RequestUri has "/servicePrincipals"
| where RequestMethod in ("POST", "PATCH", "DELETE")
| where ResponseStatusCode between (200 .. 299)
| summarize Calls = count() by AppId, UserId, RequestMethod
| order by Calls desc

In Defender XDR advanced hunting, the equivalent data is the GraphAPIAuditEvents table (columns such as RequestUri, RequestMethod, ResponseStatusCode, ApplicationId, ServicePrincipalId and IpAddress). MicrosoftGraphActivityLogs exists only in a Log Analytics workspace, so an analyst without a workspace uses GraphAPIAuditEvents.

Tip. Questions on this topic set a Microsoft 365 investigation scenario, with the organisation's licences, roles and tooling, and ask what to use, assign, run or expect. Expect to pick the right evidence source or API, the least-privileged role, the correct PowerShell session or cmdlet, and the right search criterion; to predict how long a record survives given the user's licence, workload and retention policies; to scope mailbox exposure from MailItemsAccessed records; to choose or complete KeyQL and KQL queries; and to explain why a search, purge or log pipeline returned nothing or failed.

Key takeaways
  • Audit records activity, Content search finds content, Graph activity logs record Graph API calls: match the tool to the question.
  • View-Only Audit Logs is least privilege for audit search; assign it in the Exchange admin center too for Search-UnifiedAuditLog.
  • UnifiedAuditLogIngestionEnabled is reliable only in Exchange Online PowerShell; Security & Compliance PowerShell always shows False.
  • Audit (Standard) keeps 180 days; the one-year default needs an E5 user and an Entra ID, Exchange, OneDrive or SharePoint record.
  • Custom retention policies beat the default even when shorter, lower priority numbers win, and changes are never retroactive.
  • Audit search jobs run on after the browser closes, last 30 days, allow one unfiltered job, and usually lag 60 to 90 minutes.
  • MailItemsAccessed is in Audit (Standard); a Sync record means assume the whole folder was taken, and SessionId plus ClientIPAddress separate attacker from owner.
  • SIEM feed = Office 365 Management Activity API (7-day content window); REST search = Graph auditLogQuery; scripts = Search-UnifiedAuditLog in Exchange Online PowerShell.
  • KeyQL: space is OR, operators uppercase, quote multi-word values, prefix-only wildcards, trailing slash for site-only paths.
  • Search and purge needs Search And Purge in Purview, removes 10 items per mailbox per run (100 via Graph in premium cases), and fails over 50,000 searched mailboxes.

Frequently asked questions

What is the difference between Purview Audit and Content search?

Microsoft Purview Audit records activities, such as who downloaded a file, created an inbox rule or read a message, in the unified audit log. Content search in Purview eDiscovery searches the content itself, such as the text of email, documents and Teams messages. Use Audit to reconstruct what an attacker did and Content search to find every copy of a malicious message or leaked file.

How long does Microsoft Purview keep audit records?

Audit (Standard) keeps audit records for 180 days. With Audit (Premium), records from Exchange, SharePoint, OneDrive and Microsoft Entra ID generated by E5-licensed users are kept for one year by default, while other workloads, non-E5 users and guests keep 180 days. Custom audit log retention policies can set other durations, and ten-year retention needs the 10-Year Audit Log Retention add-on on the users who generate the records.

Does MailItemsAccessed require Audit (Premium)?

No. MailItemsAccessed is part of Audit (Standard) and is on by default for users with Office 365 or Microsoft 365 E3 or E5 licences. It records both Sync access, where desktop Outlook downloads a folder, and Bind access to individual messages. Audit (Premium) adds extra properties to the records but is not needed to see which mail an attacker accessed.

Why does my Purview audit search return nothing for recent activity?

Audit records are not instant. Microsoft doesn't guarantee a time, but for core services such as Exchange, SharePoint, OneDrive and Teams, records typically become searchable 60 to 90 minutes after the event. Other causes of empty results are an operation name that isn't typed exactly, a keyword that sits only in the record's data content, or records that have passed their retention period.

How do I send Microsoft 365 audit logs to a SIEM?

Use the Office 365 Management Activity API, which Microsoft recommends over PowerShell scripts for programmatic download. The SIEM's collector subscribes to content types, lists available content in windows of up to 24 hours and downloads the content blobs. Content older than seven days can't be retrieved from the API, so gaps longer than that are filled from an audit search.

What permissions do I need to purge email in Microsoft Purview?

Searching needs the eDiscovery Manager role group or the Compliance Search role, and purging needs the Search And Purge role or the Organization Management role group in the Microsoft Purview portal. Organization Management in Exchange Online doesn't grant purge rights. Without them, New-ComplianceSearchAction has no Purge parameter and returns a parameter-not-found error.

How do I turn on Microsoft Graph activity logs?

Create a Microsoft Entra diagnostic setting that sends the MicrosoftGraphActivityLogs category to a Log Analytics workspace, a storage account or an event hub. The tenant needs Microsoft Entra ID P1 or P2, and Security Administrator is the least-privileged role that can create the setting. The setting can't filter the logs, so use a workspace transformation to drop unwanted rows, and expect most events within 30 minutes.

Can I query Microsoft Graph activity logs in Defender XDR advanced hunting?

Yes, through the GraphAPIAuditEvents table, which holds Microsoft Graph API requests for resources in the tenant with columns such as RequestUri, RequestMethod, ResponseStatusCode, ApplicationId and ServicePrincipalId. The MicrosoftGraphActivityLogs table is a separate Log Analytics table created by the Entra diagnostic setting, queried in a workspace or Microsoft Sentinel.

Source

This lesson covers the "Respond to security incidents" domain of the official SC-200 exam guide. Vendors revise their guides — check the source for the current version.

Test yourself on this topic
Practice now

Sign up free to mark lessons complete, bookmark topics and track your exam readiness.

Spotted a mistake in this lesson?