Advanced hunting for Microsoft Purview Data Loss Prevention - mattnovitsch/M365 GitHub Wiki

Summary

If you are looking to query your Purview data using KQL, good news that data is sent using the Cloud App connector. What I will be covering is the reporting of files with Sensitive Information Types(SIT) being access, printed, and copied to removeable media.

Prerequisites

  • Purview Deployed
  • Microsoft Defender for Cloud Apps Deployed

Hunting

  1. This query fill identify all files that have a SIT assigned to them.

Query: let AppEvents = (CloudAppEvents | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) | mv-expand sit | extend UserId = tolower(RawEventData.UserId) | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName) | extend document = tostring(RawEventData.ObjectId) ); AppEvents | extend ObjectId = tostring(RawEventData.ObjectId) | extend DeviceName = tostring(RawEventData.DeviceName) | extend Application = tostring(RawEventData.Application) | summarize count = count() by document,Application,SensitiveInfoTypeName,ActionType,DeviceName

image


  1. This query will list all the files that were copied to removable media.

Query: //Files that were copied to Removable Media with SIT data let FileswithSITLabel=CloudAppEvents | where ActionType contains "FileCopiedToRemovableMedia" | extend RawEventDataObject = parse_json(RawEventData) | extend SourceFileName = RawEventDataObject.ObjectId | extend UserName = RawEventDataObject.UserId | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) | mv-expand sit | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName) | project Timestamp, ActionType,SourceFileName,SensitiveInfoTypeName; CloudAppEvents | where ActionType contains "FileCopiedToRemovableMedia" | extend RawEventDataObject = parse_json(RawEventData) | extend SourceFileName = RawEventDataObject.ObjectId | extend SourceFileName = tostring(SourceFileName) | extend UserName = RawEventDataObject.UserId | extend DestinationFilePath = RawEventDataObject.TargetFilePath | where parse_json(tostring(RawEventData.RemovableMediaDeviceAttributes)) != "" | where parse_json(tostring(RawEventData.RemovableMediaDeviceAttributes)) != "[]" | extend RemovableMediaDeviceAttributes = parse_json(tostring(RawEventData.RemovableMediaDeviceAttributes)) | extend RemovableMediaDeviceAttributes = parse_json(RemovableMediaDeviceAttributes) | extend MediaManufacturer = RemovableMediaDeviceAttributes.Manufacturer | extend MediaModel = RemovableMediaDeviceAttributes.Model | extend MediaSerialNumber = RemovableMediaDeviceAttributes.SerialNumber | join kind=leftouter (FileswithSITLabel | extend SourceFileName = tostring(SourceFileName) | project Timestamp, SourceFileName, SensitiveInfoTypeName ) on Timestamp, SourceFileName | project Timestamp, ActionType,SourceFileName,DestinationFilePath,SensitiveInfoTypeName, MediaManufacturer, MediaModel, MediaSerialNumber,UserName, City, CountryCode, IPAddress image


  1. This query will let you know what files have been printed.

Query: let FileswithSITLabel=CloudAppEvents | where ActionType contains "FilePrinted" | extend RawEventDataObject = parse_json(RawEventData) | extend SourceFileName = RawEventDataObject.ObjectId | extend UserName = RawEventDataObject.UserId | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "" | where parse_json(tostring(RawEventData.SensitiveInfoTypeData)) != "[]" | extend sit = parse_json(tostring(RawEventData.SensitiveInfoTypeData)) | mv-expand sit | extend SensitiveInfoTypeName = tostring(sit.SensitiveInfoTypeName) | project Timestamp, ActionType,SourceFileName,SensitiveInfoTypeName; CloudAppEvents | where ActionType contains "FilePrinted" | extend RawEventDataObject = parse_json(RawEventData) | extend SourceFileName = RawEventDataObject.ObjectId | extend SourceFileName = tostring(SourceFileName) | where parse_json(tostring(RawEventData.PolicyMatchInfo)) != "" | where parse_json(tostring(RawEventData.PolicyMatchInfo)) != "[]" | extend PolicyMatchInfo = parse_json(tostring(RawEventData.PolicyMatchInfo)) | extend PolicyMatchInfo = parse_json(PolicyMatchInfo) | extend PolicyName = PolicyMatchInfo.RuleName | extend UserName = RawEventDataObject.UserId | extend TargetPrinterName = RawEventData.TargetPrinterName | join kind=leftouter (FileswithSITLabel | extend SourceFileName = tostring(SourceFileName) | project Timestamp, SourceFileName, SensitiveInfoTypeName ) on Timestamp, SourceFileName | project Timestamp, ActionType,SourceFileName,SensitiveInfoTypeName, PolicyName,TargetPrinterName,UserName, City, CountryCode, IPAddress image

References