-
Notifications
You must be signed in to change notification settings - Fork 659
[New Rule] Google Workspace User Sign-in from Atypical Device Type #6153
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
terrancedejesus
wants to merge
6
commits into
main
Choose a base branch
from
new-rule/google-workspace-atypical-device-registration
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
9367280
[New Rule] Google Workspace User Sign-in from Atypical Device Type
terrancedejesus 0236027
[New Rule] Google Workspace Device Registration Burst for Single User
terrancedejesus 541c452
Merge branch 'main' into new-rule/google-workspace-atypical-device-re…
terrancedejesus d0a2f93
Merge branch 'main' into new-rule/google-workspace-atypical-device-re…
terrancedejesus 57c696d
Merge branch 'main' into new-rule/google-workspace-atypical-device-re…
terrancedejesus 4195065
Merge branch 'main' into new-rule/google-workspace-atypical-device-re…
terrancedejesus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
160 changes: 160 additions & 0 deletions
160
...ns/google_workspace/persistence_google_workspace_device_registration_atypical_device.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,160 @@ | ||
| [metadata] | ||
| creation_date = "2026/05/15" | ||
| integration = ["google_workspace"] | ||
| maturity = "production" | ||
| updated_date = "2026/05/15" | ||
|
|
||
| [rule] | ||
| author = ["Elastic"] | ||
| description = """ | ||
| Detects the first time a Google Workspace user is observed authenticating from a device of a given type (e.g., WINDOWS, | ||
| MAC, ANDROID, IOS, LINUX) within a historical window. Note that `DEVICE_REGISTER_UNREGISTER_EVENT` events do not | ||
| represent one-time physical device enrollments; the Google Reports API emits a fresh `google_workspace.device.id` on | ||
| each event, and the same physical device may produce multiple events per day as sessions/sync renewals occur. The rule | ||
| therefore surfaces a user authenticating from a new device type, not a new physical device. This is still high-fidelity | ||
| because adversaries who compromise a Workspace identity via AiTM kits or stolen OAuth refresh tokens frequently relay | ||
| sessions from device types that diverge from the legitimate user's baseline (e.g., a WINDOWS session appearing for a | ||
| known macOS user, or simultaneous WINDOWS+MAC sessions within minutes), which is the canonical kit fingerprint. Because | ||
| the underlying token retains access after password rotation, treat unexpected device-type divergence as a compromise | ||
| indicator and revoke tokens, not just credentials. | ||
| """ | ||
| false_positives = [ | ||
| """ | ||
| A user legitimately enrolling a new personal or corporate device (new laptop, replacement phone, BYOD enrollment). | ||
| Validate by confirming the device registration timing aligns with a known device refresh, IT hardware ticket, or | ||
| onboarding event. | ||
| """, | ||
| """ | ||
| Bulk device enrollment campaigns (e.g., MDM rollout, fleet refresh) where many users register the same new device | ||
| type in a short window. Consider suppressing during planned rollouts. | ||
| """, | ||
| ] | ||
| from = "now-9m" | ||
| index = ["logs-google_workspace.device*"] | ||
| language = "kuery" | ||
| license = "Elastic License v2" | ||
| name = "Google Workspace User Sign-in from Atypical Device Type" | ||
| note = """## Triage and analysis | ||
|
|
||
| ### Investigating Google Workspace User Sign-in from Atypical Device Type | ||
|
|
||
| This rule emits when a user authenticates from a device whose type (`google_workspace.device.type`) has not been observed for that user in the prior 14 days. | ||
|
|
||
| **Important: this is not a true "device enrollment" event.** Google's Reports API emits `DEVICE_REGISTER_UNREGISTER_EVENT` from the `mobile` provider on every session/sync registration, with a fresh `google_workspace.device.id` each time. A single physical device can produce many such events per day. The rule therefore identifies a *device-type-per-user* anomaly: a session originating from a class of device the user has not been seen on in the prior 14 days, not a one-time physical device join. | ||
|
|
||
| The detection value remains high because adversaries who relay sessions via AiTM kits (Tycoon2FA Google variant, EvilGinx phishlets) or who replay stolen OAuth refresh tokens typically egress from device fingerprints that diverge from the victim's baseline. Two patterns are especially diagnostic: | ||
|
|
||
| - A device type appearing for a user that does not match the user's known OS (e.g., WINDOWS sessions for a user whose corporate laptop is macOS). | ||
| - Simultaneous WINDOWS+MAC (or similar cross-type) sessions for the same user within a short window, indicating the kit and the victim are active at the same time. | ||
|
|
||
| Because the underlying OAuth refresh token continues to grant access after a password reset, password rotation alone does not remediate this; only token revocation does. | ||
|
|
||
| ### Possible investigation steps | ||
|
|
||
| - Identify the user (`user.email`), the device type (`google_workspace.device.type`), and the device model and OS (`google_workspace.device.model`, `host.os.version`). | ||
| - Compare the registered device type to the user's known device baseline. A WINDOWS device for a known macOS user, or an ANDROID device for a known iOS user, is a high-confidence adversary signal. | ||
| - Pull all `logs-google_workspace.login` events for the same `user.email` in the 24 hours leading up to the device registration. Inspect `source.geo.country_name`, `source.as.organization.name`, and `user_agent.original` for each sign-in. A device registration immediately following a sign-in from a non-baseline ASN (hosting providers, cheap VPS, AiTM kit egress like Clouvider or Host Telecom) is the kit-driven persistence signature. | ||
| - Cross-reference `logs-google_workspace.token` for `event.action: "authorize"` events from the same user near the same time. OAuth grants minted around the device registration window indicate the kit has minted additional tokens for the attacker-controlled device. | ||
| - Inspect `google_workspace.device.id` and `google_workspace.device.resource.id` for the registered device. Capture both, since `device.id` is required for the device removal API call during remediation. | ||
| - Confirm with the user whether the device registration is theirs (new hardware, BYOD enrollment) or unexpected. | ||
|
|
||
| ### False positive analysis | ||
|
|
||
| - Legitimate first-time device enrollment for new hardware, BYOD onboarding, or device refresh cycles. Validate by checking IT hardware tickets, onboarding records, or HR. | ||
| - Planned MDM rollouts that register many users' devices in a short window. Consider a temporary rule suppression during scheduled rollouts. | ||
| - Users who legitimately use multiple device types and happened to first enroll a given type outside the lookback window (e.g., always had a personal Android but only just enrolled it in Workspace). | ||
|
|
||
| ### Response and remediation | ||
|
|
||
| - If the device registration is unexpected: treat as compromise. Immediately suspend the user, revoke all OAuth tokens (`DELETE /admin/directory/v1/users/<email>/tokens/<clientId>`), reset the password, and clear recovery email/phone. | ||
| - Remove the attacker-controlled device via the Admin SDK Directory API: `POST /admin/directory/v1/customer/<customerId>/devices/chromeos/<deviceId>/action` (or the mobile device variant) to wipe / remove the device. | ||
| - Audit any post-registration mailbox, Drive, and Calendar activity for adversary data access or exfiltration. | ||
| - Cross-check `logs-gcp.audit-*` if the tenant exposes GCP resources to the user: look for `authenticationInfo.principalEmail` matching the user from a non-baseline `callerIp` in the same window, since token theft frequently extends to cross-cloud access. | ||
| """ | ||
| references = [ | ||
| "https://developers.google.com/workspace/admin/reports/v1/appendix/activity/mobile", | ||
| "https://www.elastic.co/security-labs/google-workspace-attack-surface-part-one", | ||
| "https://any.run/malware-trends/tycoon/", | ||
| ] | ||
| risk_score = 47 | ||
| rule_id = "e0916edd-ea8c-49d2-882e-2cf6af161dd7" | ||
| severity = "medium" | ||
| tags = [ | ||
| "Domain: Cloud", | ||
| "Domain: Identity", | ||
| "Data Source: Google Workspace", | ||
| "Data Source: Google Workspace Device Logs", | ||
| "Use Case: Threat Detection", | ||
| "Use Case: Identity and Access Audit", | ||
| "Tactic: Persistence", | ||
| "Tactic: Initial Access", | ||
| "Resources: Investigation Guide", | ||
| ] | ||
| timestamp_override = "event.ingested" | ||
| type = "new_terms" | ||
|
|
||
| query = ''' | ||
| data_stream.dataset: "google_workspace.device" and | ||
| event.action: "DEVICE_REGISTER_UNREGISTER_EVENT" and | ||
| google_workspace.device.account_state: "REGISTERED" and | ||
| google_workspace.device.type: * and | ||
| user.email: * | ||
| ''' | ||
|
|
||
|
|
||
| [[rule.threat]] | ||
| framework = "MITRE ATT&CK" | ||
| [[rule.threat.technique]] | ||
| id = "T1098" | ||
| name = "Account Manipulation" | ||
| reference = "https://attack.mitre.org/techniques/T1098/" | ||
| [[rule.threat.technique.subtechnique]] | ||
| id = "T1098.005" | ||
| name = "Device Registration" | ||
| reference = "https://attack.mitre.org/techniques/T1098/005/" | ||
|
|
||
|
|
||
|
|
||
| [rule.threat.tactic] | ||
| id = "TA0003" | ||
| name = "Persistence" | ||
| reference = "https://attack.mitre.org/tactics/TA0003/" | ||
| [[rule.threat]] | ||
| framework = "MITRE ATT&CK" | ||
| [[rule.threat.technique]] | ||
| id = "T1078" | ||
| name = "Valid Accounts" | ||
| reference = "https://attack.mitre.org/techniques/T1078/" | ||
| [[rule.threat.technique.subtechnique]] | ||
| id = "T1078.004" | ||
| name = "Cloud Accounts" | ||
| reference = "https://attack.mitre.org/techniques/T1078/004/" | ||
|
|
||
|
|
||
|
|
||
| [rule.threat.tactic] | ||
| id = "TA0001" | ||
| name = "Initial Access" | ||
| reference = "https://attack.mitre.org/tactics/TA0001/" | ||
|
|
||
| [rule.investigation_fields] | ||
| field_names = [ | ||
| "@timestamp", | ||
| "user.email", | ||
| "google_workspace.device.type", | ||
| "google_workspace.device.model", | ||
| "google_workspace.device.id", | ||
| "google_workspace.device.resource.id", | ||
| "google_workspace.device.account_state", | ||
| "host.os.version", | ||
| "event.provider", | ||
| ] | ||
|
|
||
| [rule.new_terms] | ||
| field = "new_terms_fields" | ||
| value = ["google_workspace.device.type", "user.email"] | ||
| [[rule.new_terms.history_window_start]] | ||
| field = "history_window_start" | ||
| value = "now-14d" | ||
|
|
||
|
|
||
190 changes: 190 additions & 0 deletions
190
...integrations/google_workspace/persistence_google_workspace_device_registration_burst.toml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,190 @@ | ||
| [metadata] | ||
| creation_date = "2026/05/15" | ||
| integration = ["google_workspace"] | ||
| maturity = "production" | ||
| updated_date = "2026/05/15" | ||
|
|
||
| [rule] | ||
| author = ["Elastic"] | ||
| description = """ | ||
| Detects bursts of Google Workspace device registration events for the same user, where three or more distinct | ||
| `google_workspace.device.id` values are emitted in a one-minute window. Although `DEVICE_REGISTER_UNREGISTER_EVENT` | ||
| fires routinely on session/sync registration and is not a true physical device enrollment, legitimate user activity | ||
| typically produces fewer than three distinct device IDs in a single minute. A high-cardinality burst is the fingerprint | ||
| behavior of AiTM phishing-kit relays (Tycoon2FA Google variant, EvilGinx phishlets) and stolen-OAuth-token replay | ||
| tooling, both of which mint a new session attestation per relay or replay attempt. | ||
| """ | ||
| false_positives = [ | ||
| """ | ||
| A user simultaneously enrolling multiple Workspace-aware apps on a new device (e.g., first-time setup of Gmail, | ||
| Drive, Calendar, and Meet on a new laptop in a short window) may produce three or more distinct device IDs in a | ||
| minute. Validate by checking whether the burst is tied to a fresh device or onboarding event. | ||
| """, | ||
| """ | ||
| Major OS upgrades or Workspace client refreshes that re-attest several apps concurrently may also produce a burst. | ||
| Cross-reference against the user's known device OS transitions. | ||
| """, | ||
| ] | ||
| from = "now-9m" | ||
| language = "esql" | ||
| license = "Elastic License v2" | ||
| name = "Google Workspace Device Registration Burst for Single User" | ||
| note = """## Triage and analysis | ||
|
|
||
| ### Investigating Google Workspace Device Registration Burst for Single User | ||
|
|
||
| `DEVICE_REGISTER_UNREGISTER_EVENT` from the Google Workspace `mobile` provider does not represent a one-time physical device enrollment. The Reports API emits a fresh `google_workspace.device.id` on every session/sync registration, and a single physical device can produce multiple events per day as Workspace-aware apps independently attest. Legitimate activity, however, very rarely concentrates three or more distinct device IDs into a one-minute window for a single user. A burst of that shape is the fingerprint of either: | ||
|
|
||
| - An AiTM phishing-kit relay session: the kit completes the victim's sign-in against Google, then attests one or more device contexts of its own, all from the same kit infrastructure within seconds. | ||
| - Token-replay tooling driving multiple sessions in quick succession against a stolen OAuth refresh token. | ||
|
|
||
| In both cases the device fingerprint (OS, model) typically converges on a single value distinct from the victim's baseline (e.g., all "Windows" attestations for a known macOS user), and the burst events fire within a few seconds of each other rather than spread across minutes. | ||
|
|
||
| ### Possible investigation steps | ||
|
|
||
| - Identify the user (`user.email`, `user.id`) and inspect `Esql.host_os_version_values`, `Esql.device_type_values`, `Esql.device_model_values`. A homogeneous fingerprint (single OS, single model) across multiple device IDs in the burst window is highly suspicious. | ||
| - Cross-reference `logs-google_workspace.login` for `event.action: "login_success"` events from the same `user.email` in the 30 minutes preceding the burst. The kit-relay sign-ins should appear there. Inspect each sign-in's `source.geo.country_name`, `source.as.organization.name`, and `user_agent.original` for divergence from the user's baseline. Hosting-provider ASNs (Clouvider, Host Telecom, OVH, Alibaba, Vultr, DigitalOcean, M247) for interactive sign-ins are high-fidelity suspicious. | ||
| - Cross-reference `logs-google_workspace.token` for `event.action: "authorize"` events for the same user near the burst window. Each kit relay normally fires a corresponding OAuth grant within seconds, often to Google Chrome (`77185425430.apps.googleusercontent.com`) or another long-lived first-party client. | ||
| - Pull all `logs-google_workspace.device` events for the user across the 24 hours preceding the burst to characterize the user's normal device-event rate. A user who typically produces less than 1 event per hour suddenly emitting 3+ in a minute is a strong anomaly even before considering device fingerprints. | ||
| - Confirm with the user whether they were performing a new device setup, OS upgrade, or onboarding activity during the burst window. | ||
|
|
||
| ### False positive analysis | ||
|
|
||
| - New device setup where a user simultaneously enrolls multiple Workspace-aware apps (Gmail, Drive, Calendar, Meet) on first boot can produce a burst. Validate by checking whether the burst coincides with a known device refresh or onboarding event. | ||
| - Major OS upgrades that re-attest several apps concurrently can also produce a burst. The host OS version values will reflect the upgrade transition. | ||
| - Bulk MDM rollouts or fleet refreshes may produce bursts across many users at the same time. Consider rule suppression during planned rollouts. | ||
|
|
||
| ### Response and remediation | ||
|
|
||
| - Treat as likely AiTM compromise or token-replay activity until proven otherwise. Suspend the user, revoke all OAuth tokens (`DELETE /admin/directory/v1/users/<email>/tokens/<clientId>`), reset the password, clear recovery email/phone, sign out all sessions. | ||
| - Audit `logs-google_workspace.token: authorize` events for kit-issued or replay-issued OAuth grants. Each grant maps to an independently replayable refresh token; revoking via the consent removes them all at once. | ||
| - Audit the device IDs surfaced in the burst via the Admin SDK Directory API and remove any that are confirmed adversary-controlled. | ||
| - If the tenant exposes GCP resources to the user, cross-check `logs-gcp.audit-*` for `authenticationInfo.principalEmail` matching the user from a non-baseline `callerIp` in the same window; token theft frequently extends to cross-cloud access. | ||
| """ | ||
| references = [ | ||
| "https://developers.google.com/workspace/admin/reports/v1/appendix/activity/mobile", | ||
| "https://any.run/malware-trends/tycoon/", | ||
| "https://www.elastic.co/security-labs/google-workspace-attack-surface-part-one", | ||
| ] | ||
| risk_score = 47 | ||
| rule_id = "bea0589d-c7a4-4dc6-a931-9fecaa8689fb" | ||
| severity = "medium" | ||
| tags = [ | ||
| "Domain: Cloud", | ||
| "Domain: Identity", | ||
| "Data Source: Google Workspace", | ||
| "Data Source: Google Workspace Device Logs", | ||
| "Use Case: Threat Detection", | ||
| "Use Case: Identity and Access Audit", | ||
| "Tactic: Persistence", | ||
| "Tactic: Initial Access", | ||
| "Tactic: Credential Access", | ||
| "Resources: Investigation Guide", | ||
| ] | ||
| timestamp_override = "event.ingested" | ||
| type = "esql" | ||
|
|
||
| query = ''' | ||
| from logs-google_workspace.device-* | ||
| | where event.dataset == "google_workspace.device" | ||
| and event.action == "DEVICE_REGISTER_UNREGISTER_EVENT" | ||
| and google_workspace.device.account_state == "REGISTERED" | ||
| and user.email is not null | ||
| and google_workspace.device.id is not null | ||
|
|
||
| | eval Esql.bucket_minute = date_trunc(1 minute, @timestamp) | ||
|
|
||
| | stats | ||
| Esql.count_distinct_device_id = count_distinct(google_workspace.device.id), | ||
| Esql.device_id_values = values(google_workspace.device.id), | ||
| Esql.device_resource_id_values = values(google_workspace.device.resource.id), | ||
| Esql.device_type_values = values(google_workspace.device.type), | ||
| Esql.device_model_values = values(google_workspace.device.model), | ||
| Esql.device_account_state_values = values(google_workspace.device.account_state), | ||
| Esql.host_os_version_values = values(host.os.version), | ||
| Esql.event_provider_values = values(event.provider), | ||
| Esql.event_id_values = values(event.id), | ||
| Esql.google_workspace_actor_type_values = values(google_workspace.actor.type), | ||
| Esql.google_workspace_event_type_values = values(google_workspace.event.type), | ||
| Esql.organization_id_values = values(organization.id), | ||
| Esql.user_domain_values = values(user.domain), | ||
| Esql.timestamp_first_seen = min(@timestamp), | ||
| Esql.timestamp_last_seen = max(@timestamp), | ||
| Esql.event_count = count(*) | ||
| by user.id, user.email, user.name, Esql.bucket_minute | ||
|
|
||
| | where Esql.count_distinct_device_id >= 3 | ||
|
|
||
| | keep user.id, | ||
| user.email, | ||
| user.name, | ||
| Esql.bucket_minute, | ||
| Esql.timestamp_first_seen, | ||
| Esql.timestamp_last_seen, | ||
| Esql.count_distinct_device_id, | ||
| Esql.event_count, | ||
| Esql.device_id_values, | ||
| Esql.device_resource_id_values, | ||
| Esql.device_type_values, | ||
| Esql.device_model_values, | ||
| Esql.device_account_state_values, | ||
| Esql.host_os_version_values, | ||
| Esql.event_provider_values, | ||
| Esql.event_id_values, | ||
| Esql.google_workspace_actor_type_values, | ||
| Esql.google_workspace_event_type_values, | ||
| Esql.organization_id_values, | ||
| Esql.user_domain_values | ||
| ''' | ||
|
|
||
|
|
||
| [[rule.threat]] | ||
| framework = "MITRE ATT&CK" | ||
| [[rule.threat.technique]] | ||
| id = "T1098" | ||
| name = "Account Manipulation" | ||
| reference = "https://attack.mitre.org/techniques/T1098/" | ||
| [[rule.threat.technique.subtechnique]] | ||
| id = "T1098.005" | ||
| name = "Device Registration" | ||
| reference = "https://attack.mitre.org/techniques/T1098/005/" | ||
|
|
||
|
|
||
|
|
||
| [rule.threat.tactic] | ||
| id = "TA0003" | ||
| name = "Persistence" | ||
| reference = "https://attack.mitre.org/tactics/TA0003/" | ||
| [[rule.threat]] | ||
| framework = "MITRE ATT&CK" | ||
| [[rule.threat.technique]] | ||
| id = "T1078" | ||
| name = "Valid Accounts" | ||
| reference = "https://attack.mitre.org/techniques/T1078/" | ||
| [[rule.threat.technique.subtechnique]] | ||
| id = "T1078.004" | ||
| name = "Cloud Accounts" | ||
| reference = "https://attack.mitre.org/techniques/T1078/004/" | ||
|
|
||
|
|
||
|
|
||
| [rule.threat.tactic] | ||
| id = "TA0001" | ||
| name = "Initial Access" | ||
| reference = "https://attack.mitre.org/tactics/TA0001/" | ||
| [[rule.threat]] | ||
| framework = "MITRE ATT&CK" | ||
| [[rule.threat.technique]] | ||
| id = "T1557" | ||
| name = "Adversary-in-the-Middle" | ||
| reference = "https://attack.mitre.org/techniques/T1557/" | ||
|
|
||
|
|
||
| [rule.threat.tactic] | ||
| id = "TA0006" | ||
| name = "Credential Access" | ||
| reference = "https://attack.mitre.org/tactics/TA0006/" | ||
|
|
||
| [rule.investigation_fields] | ||
| field_names = ["@timestamp", "user.email", "user.id", "user.name"] | ||
|
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why aren't you using
user.idfield? Just curious on your choice of email since I don't typically see us using this field for new terms.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@imays11 good question. Honestly subjective. Emails are typically the universally accepted "ID" for Google. The
user.idis unique to each user, but I am unsure if it translates to GCP or data sources. If you happen to notice any inconsistencies, we can update.