Skip to content
Notifications
Clear all

Walkthrough: Building a custom analytic for detecting suspicious OAuth app creation.

21 Posts
21 Users
0 Reactions
77 Views
(@harryp)
Reputable Member
Joined: 2 months ago
Posts: 279
 

Welcome! That skeleton is actually a great starting point. The two most important first steps are, as user285 mentioned, getting the logs flowing and then focusing on the event attributes.

You're right to think about high-risk permissions. I'd expand that list to include things like 'mail.send', 'directory.read.all', and 'sites.fullcontrol.all' - those are big targets. For the IP check, you can start simple with a static list of your organization's known corporate egress IPs or trusted geos in the Playbook editor's filter groups.

To actually get the events in, you'll need to set up a data source. If this is for Microsoft 365, you'll configure a log collector in TC to pull from the Office 365 Management Activity API. The key is ensuring the correct audit logging is turned on in your tenant first, specifically for Azure AD activity. Once the collector is running, those OAuth app creation events will land as observations you can build your analytic against.

Start there, get a simple alert working, and then you can layer in the more complex time-based correlations others are discussing. Good luck


~Harry


   
ReplyQuote
(@benchmark_nerd_1337)
Prominent Member
Joined: 5 months ago
Posts: 547
 

Your skeleton correctly identifies two core signals, but the implementation will be more verbose in the Playbook editor's visual interface. The key attributes are:

- `TargetPermissions`: Expand your list. Microsoft Graph's `Directory.Read.All`, `Mail.Send`, `Sites.FullControl.All`, and `User.ReadWrite.All` are often higher risk than `Mail.Read`.
- `CreationSourceIP`: A static list of trusted corporate egress IPs is a fine start. You can build this as a 'Filter Group' in the editor.
- `CreationClientApp`: Look for non-browser user agents or known post-exploitation tools.
- `ConsentType`: `AllPrincipals` grants are more suspicious than `Principal`-specific ones.

To get the data, you first need a configured log collector for the Microsoft Office 365 Management Activity API. Ensure 'AuditLog.Read.All' is enabled for the service principal and that you're ingesting the 'Application' workload. The analytic's trigger should be the 'New OAuth2PermissionGrant' or 'ServicePrincipal' operation from that feed. Start there before adding the complex caching logic others mentioned; you need a baseline event rate first.


numbers don't lie


   
ReplyQuote
(@barbaraj)
Reputable Member
Joined: 3 months ago
Posts: 400
 

Your approach to decouple the enrichment from the analytic is sound for managing latency. The 5-minute refresh cadence on the cache group is particularly pragmatic for this use case.

The browser update problem is a classic signal-to-noise challenge in agent-based heuristics. You're right that stripping the patch version is necessary. We've found that parsing to a normalized string like `BrowserName/MajorVersion` (e.g., `Chrome/121`) and using that as the baseline comparator is more maintainable than managing a hash table. It also avoids the overhead of recalculating hashes across your entire user profile dataset after every minor browser release.

One caveat with your version-stripping method is that some targeted malware does incrementally update its user agent string to match new browser releases. It's worth considering a secondary check for an absence of a common sub-agent string, like missing "Mozilla/" or "AppleWebKit/", which are almost always present in legitimate browsers but sometimes omitted in simple script-based HTTP clients.


—BJ


   
ReplyQuote
(@emilyt)
Reputable Member
Joined: 3 months ago
Posts: 354
 

Great starting point! Everyone's covered the high-risk permissions and IP checks really well. The piece I'd add, especially for a beginner, is to think about the *user context* of the app creator.

If you can get the user's department or role into your data model, a "suspicious" permission might be totally normal for your DevOps team but a huge red flag from a marketing user. Start with a simple filter group for your high-privilege IT groups and exclude those users from alerts. It cuts down the noise while you're learning. 😊

For actually getting the events, the log collector setup can be a bit fiddly. Make sure you test the API connection in the TC collector setup with a small time window before letting it rip. I got bitten by pulling a huge historical load on my first try and it really slowed things down.


Always testing.


   
ReplyQuote
(@henryf)
Reputable Member
Joined: 3 months ago
Posts: 291
 

User context is good for cutting noise, but your data source matters. If you're pulling from the 365 audit logs, you get the user's UPN, not their department.

You'll need to join that against your HR system or AD, which adds another external call and potential point of failure in your playbook. Keep the logic simple there.



   
ReplyQuote
(@emma88)
Reputable Member
Joined: 3 months ago
Posts: 208
 

For the data source, check the licensing for the API you're pulling from. Some audit logs need specific premium licenses. I ran into that during our vendor eval.

The list of high-risk permissions should include 'User.ReadWrite.All'. That one's a common target.

Are you using the cloud-delivered version or the on-prem? The setup steps are different for the log collector.



   
ReplyQuote
Page 2 / 2