|
| 1 | +# Microsoft Entra Infrequent Suspicious OData Client Requests |
| 2 | + |
| 3 | +--- |
| 4 | + |
| 5 | +## Metadata |
| 6 | + |
| 7 | +- **Author:** Elastic |
| 8 | +- **Description:** Identifies infrequent OData client requests in Microsoft Entra ID. This behavior may indicate an adversary using a custom or Azure-managed app ID to authenticate on behalf of a user. This is a rare event and may indicate an attempt to bypass conditional access policies (CAP) and multi-factor authentication (MFA) requirements. The app ID specified may not be commonly used by the user based on their historical sign-in activity. The OData client is used in ROADTools, a toolset leveraged by threat actors to automate OAuth and OIDC workflows in Microsoft Entra ID following phishing or token theft. |
| 9 | + |
| 10 | +- **UUID:** `0d3d2254-2b4a-11f0-a019-f661ea17fbcc` |
| 11 | +- **Integration:** [azure](https://docs.elastic.co/integrations/azure) |
| 12 | +- **Language:** `[ES|QL]` |
| 13 | +- **Source File:** [Microsoft Entra Infrequent Suspicious OData Client Requests](../queries/entra_suspicious_odata_client_requests.toml) |
| 14 | + |
| 15 | +## Query |
| 16 | + |
| 17 | +```sql |
| 18 | +FROM logs-azure.auditlogs* METADATA _id, _index |
| 19 | + |
| 20 | +// Only Microsoft Entra ID audit logs |
| 21 | +| WHERE event.dataset == "azure.auditlogs" |
| 22 | + |
| 23 | +// Identify logs with the known suspicious OData user agent |
| 24 | + AND azure.auditlogs.properties.additional_details.value LIKE "Microsoft.OData.Client/*" |
| 25 | + AND azure.auditlogs.identity != "Device Registration Service" |
| 26 | + |
| 27 | +// Extract time window for pattern analysis |
| 28 | +| EVAL time_window = DATE_TRUNC(1d, @timestamp) |
| 29 | + |
| 30 | +// Normalize actor: prefer user UPN if available, else fallback to app name |
| 31 | +| EVAL actor = COALESCE( |
| 32 | + azure.auditlogs.properties.initiated_by.user.userPrincipalName, |
| 33 | + azure.auditlogs.properties.initiated_by.app.displayName, |
| 34 | + "unknown" |
| 35 | +) |
| 36 | + |
| 37 | +// Keep core fields |
| 38 | +| KEEP @timestamp, actor, source.ip, azure.auditlogs.operation_name, azure.auditlogs.properties.activity_display_name, azure.auditlogs.identity, azure.auditlogs.properties.tenantId, azure.auditlogs.properties.initiated_by.app.servicePrincipalId, azure.auditlogs.properties.category, azure.auditlogs.properties.additional_details.value, time_window |
| 39 | + |
| 40 | +// Group by actor per day |
| 41 | +| STATS |
| 42 | + count = COUNT(), |
| 43 | + unique_ips = COUNT_DISTINCT(source.ip), |
| 44 | + operations = VALUES(azure.auditlogs.operation_name), |
| 45 | + identities = VALUES(azure.auditlogs.identity), |
| 46 | + ips = VALUES(source.ip), |
| 47 | + categories = VALUES(azure.auditlogs.properties.category), |
| 48 | + clients = VALUES(azure.auditlogs.properties.additional_details.value) |
| 49 | + BY actor, time_window |
| 50 | + |
| 51 | +// Optional: prioritize less frequent actors |
| 52 | +| SORT count ASC |
| 53 | +``` |
| 54 | + |
| 55 | +## Notes |
| 56 | + |
| 57 | +- Review `azure.auditlogs.properties.additional_details.value` for `Microsoft.OData.Client/*` User-Agent strings. This is uncommon for legitimate first-party Microsoft applications and may indicate use of ROADTools or custom automation to register a device and obtain a PRT. |
| 58 | +- Check `azure.auditlogs.properties.initiated_by` for both `user` and `app` fields. The presence of both may suggest an OAuth on-behalf-of (OBO) flow, where the app is acting with delegated permissions from a phished user token. |
| 59 | +- Review `azure.auditlogs.properties.activity_display_name` and `operation_name` for device registration operations like `Add device` or `Add registered owner to device`. When combined with suspicious user-agents, this may indicate unauthorized device registration. |
| 60 | +- Review `azure.auditlogs.identity` for operations performed by `Device Registration Service`. This service name is commonly associated with device join flows that, if abused, may enable persistence via PRT acquisition. |
| 61 | +- Correlate with `azure.signinlogs` for sign-ins using the same `correlation_id` or `userPrincipalName`. Look for signs of previous OAuth token issuance or multi-geo IP behavior surrounding the device registration. |
| 62 | +- Investigate whether the device registered (under `azure.auditlogs.properties.target_resources`) corresponds to known or authorized endpoints. Devices with names like `DESKTOP-ATTACKER1` or unexpected OS versions may indicate rogue joins. |
| 63 | +- The source IP is likely to be Microsoft-managed infrastructure as requests are proxied through Azure services. Pivoting into which user principal the request is targeting and events leading up to the request may provide additional context. |
| 64 | + |
| 65 | +## MITRE ATT&CK Techniques |
| 66 | + |
| 67 | +- [T1078.004](https://attack.mitre.org/techniques/T1078/004) |
| 68 | +- [T1550.001](https://attack.mitre.org/techniques/T1550/001) |
| 69 | +- [T1098.005](https://attack.mitre.org/techniques/T1098/005) |
| 70 | +- [T1071.001](https://attack.mitre.org/techniques/T1071/001) |
| 71 | +- [T1556.006](https://attack.mitre.org/techniques/T1556/006) |
| 72 | + |
| 73 | +## References |
| 74 | + |
| 75 | +- https://www.volexity.com/blog/2025/04/22/phishing-for-codes-russian-threat-actors-target-microsoft-365-oauth-workflows/ |
| 76 | + |
| 77 | +## License |
| 78 | + |
| 79 | +- `Elastic License v2` |
0 commit comments