← Back to Explore
elastichighTTP
Google Workspace Object Copied from External Drive with App Consent
Detects when a Workspace user copies a document, spreadsheet, form, or script from an external Drive into their My Drive and, within minutes from the same IP, authorizes a custom web OAuth client that requests an Apps Script scope. `script.container` is the container sidebar or dialog. The check also matches any other `script.*` scope, a `*.currentonly` scope, or a scope containing `scripts` or `container`. Adversaries send spearphishing links with a /copy URI parameter so the victim replicates a malicious object locally. Google names that replica with a "Copy of " prefix. The copy is performed by a domain user rather than a collaborator account, and the consent is not a known Google first-party client.
Detection Query
sequence by source.user.email, source.ip with maxspan=3m
[file where data_stream.dataset == "google_workspace.drive" and event.action == "copy" and
/* External My Drive replica by a domain user, not a collaborator account or shared drive */
google_workspace.drive.owner_is_team_drive == false and
google_workspace.drive.actor_is_collaborator_account == false and
google_workspace.drive.primary_event == true and
google_workspace.drive.copy_type == "external" and
/* Google Script, Forms, Sheets, and Documents can carry container-bound scripts */
google_workspace.drive.file.type : ("script", "form", "spreadsheet", "document") and
/* /copy links name the replica with this English prefix */
file.name : "Copy of*"]
[any where data_stream.dataset == "google_workspace.token" and event.action == "authorize" and
/* Custom web OAuth client, not a numeric GCP service-account client */
google_workspace.token.client.type == "WEB" and
google_workspace.token.client.id : "*apps.googleusercontent.com" and
/* Client IDs are {cloud_project_number}-{oauth_client}.apps.googleusercontent.com. */
not google_workspace.token.client.id : (
"77185425430*.apps.googleusercontent.com",
"32555940559*.apps.googleusercontent.com",
"764086051850*.apps.googleusercontent.com",
"407408718192*.apps.googleusercontent.com",
"857627895310*.apps.googleusercontent.com"
) and
/* script.container is the sidebar or dialog. Also match other script.* scopes,
container-bound *.currentonly, or a scope containing scripts or container */
google_workspace.token.scope.value : (
"*script.*",
"*.currentonly",
"*scripts*",
"*container*"
)]
Author
Elastic
Created
2023/03/07
Data Sources
Google WorkspaceGoogle Workspace Audit Logslogs-google_workspace.*
References
- https://www.elastic.co/security-labs/google-workspace-attack-surface-part-one
- https://www.elastic.co/security-labs/google-workspace-attack-surface-part-two
- https://developers.google.com/apps-script/guides/bound
- https://developers.google.com/identity/protocols/oauth2
- https://support.google.com/a/users/answer/13004165#share_make_a_copy_links
Tags
Domain: CloudData Source: Google WorkspaceData Source: Google Workspace Audit LogsTactic: Initial AccessTactic: ExecutionTactic: PersistenceResources: Investigation GuideNoise: LowPerformance: FastProfile: RecommendedThreat: OAuth App ConsentRule Type: Event Correlation (EQL)Platform: Google WorkspaceDomain: SaaS
Raw Content
[metadata]
creation_date = "2023/03/07"
integration = ["google_workspace"]
maturity = "production"
min_stack_comments = "Changing min stack to 9.3.0, the latest minimum supported version for 9.X releases."
min_stack_version = "9.3.0"
updated_date = "2026/09/24"
[rule]
author = ["Elastic"]
description = """
Detects when a Workspace user copies a document, spreadsheet, form, or script from an external Drive into their My Drive
and, within minutes from the same IP, authorizes a custom web OAuth client that requests an Apps Script scope.
`script.container` is the container sidebar or dialog. The check also matches any other `script.*` scope, a
`*.currentonly` scope, or a scope containing `scripts` or `container`. Adversaries send spearphishing links with a /copy
URI parameter so the victim replicates a malicious object locally. Google names that replica with a "Copy of " prefix.
The copy is performed by a domain user rather than a collaborator account, and the consent is not a known Google
first-party client.
"""
false_positives = [
"""
A user may copy a public template that uses a container-bound script and consent to that add-on within three minutes
from the same IP. Confirm the OAuth client with the template owner before treating the grant as malicious.
""",
"""
The copied-title check looks for the English text "Copy of ". Workspace locales that translate that prefix will not
match.
""",
]
from = "now-130m"
index = ["logs-google_workspace.*"]
interval = "10m"
language = "eql"
license = "Elastic License v2"
name = "Google Workspace Object Copied from External Drive with App Consent"
note = """## Triage and analysis
### Investigating Google Workspace Object Copied from External Drive with App Consent
A `/copy` link replicates a document, spreadsheet, form, or script into the recipient's Drive with a `Copy of` title, and a container-bound Apps Script can then prompt for consent when the object is opened. This rule correlates that external My Drive copy (`copy_type: external`, `actor_is_collaborator_account: false`, `owner_is_team_drive: false`) with a custom web OAuth grant (`client.type: WEB`, client id ending in `apps.googleusercontent.com`) for the same `source.user.email` and `source.ip` within `maxspan=3m`. The grant must include an Apps Script scope: `script.container` (the container sidebar or dialog), any other `script.*` scope, a `*.currentonly` scope, or a scope containing `scripts` or `container`. Known Google first-party clients and Cloud project `857627895310` are excluded. Compare `google_workspace.token.app_name` with `file.name` and review `google_workspace.token.scope.value`. Broader scopes such as `spreadsheets`, `drive`, or `gmail` do not match on their own, and visibility is not filtered.
### Possible investigation steps
- Identify the affected user from `source.user.email` or `user.email`. Note `source.ip` and compare `@timestamp`
(event time) on the copy and the authorize event.
- Drive copy event (`google_workspace.drive`):
- Review `file.name` and `google_workspace.drive.file.type` to identify what was copied. Confirm the title contains
`Copy of`.
- For deeper review, pivot on `google_workspace.drive.file.id` or `file.name` in Drive audit logs and Admin console
Drive investigation.
- OAuth authorize event (`google_workspace.token`):
- Review `google_workspace.token.app_name` and `google_workspace.token.client.id` to identify the application.
Check whether the app name appears in the copied title.
- Review granted scopes in `google_workspace.token.scope.value` to determine which services the token can access
(for example Drive, Gmail, or Calendar scopes beyond the current file).
- Confirm `google_workspace.token.client.type` is `WEB` and that the client is not a known Google first-party client.
- Determine whether the activity is expected:
- Contact the user to confirm they intentionally copied an external template and authorized the application.
- If timing or `source.ip` is unusual for the user, treat as higher priority until validated.
- Search Kibana for related activity:
- Determine whether other users copied the same external object:
```
data_stream.dataset: "google_workspace.drive" and event.action: "copy" and google_workspace.drive.copy_type: "external" and file.name: "<FILE_NAME>"
```
- Correlate with sign-in activity around the same window:
```
data_stream.dataset: "google_workspace.login" and user.email: "<USER_EMAIL>"
```
- Scope for other OAuth grants to the same client across the tenant:
```
data_stream.dataset: "google_workspace.token" and event.action: "authorize" and google_workspace.token.client.id: "<CLIENT_ID>"
```
- If a container-bound script is suspected, locate the copied object in the user's Drive and review Apps Script code
for exfiltration, token harvesting, or persistence logic. Remove the object from affected users' Drives.
### False positive analysis
- Users may legitimately copy public templates (spreadsheets, forms, or documents) from external drives and consent to
a container-bound add-on within three minutes from the same IP. Compare `google_workspace.token.app_name` with
`file.name` and review `google_workspace.token.scope.value` before closing the alert. Grants that do not include an
Apps Script scope (`script.container` or another `script.*` scope, `*.currentonly`, `scripts`, or `container`) do not match.
- OAuth consent does not always follow the copy immediately. Opening the object later can separate the two actions
beyond 180 seconds, which will not match even when the activity is related.
- Non-English Workspace locales translate the `Copy of ` prefix, so those replicas will not match.
### Response and remediation
- Initiate the incident response process based on triage findings.
- If the copy or OAuth grant is not clearly authorized, revoke the application's access for the affected user under
Security > Access and data control > API controls (or remove the user token via admin OAuth reports).
- Remove malicious copied objects from affected users' Drives and report abusive OAuth clients to Google if appropriate.
- If the user account is suspected compromised, reset credentials, revoke active sessions, and review all OAuth grants
for that user.
- Review activity performed with the authorized token based on scopes in `google_workspace.token.scope.value`.
- Identify the possible impact of the incident and prioritize accordingly; the following actions can help you gain context:
- Identify the account role in the cloud environment.
- Assess the criticality of affected services and servers.
- Work with your IT team to identify and minimize the impact on users.
- Identify if the attacker is moving laterally and compromising other accounts, servers, or services.
- Identify any regulatory or legal ramifications related to this activity.
- Investigate credential exposure on systems compromised or used by the attacker to ensure all compromised accounts are identified. Reset passwords or delete API keys as needed to revoke the attacker's access to the environment. Work with your IT teams to minimize the impact on business operations during these actions.
- Review the permissions assigned to the implicated user to ensure that the least privilege principle is being followed.
- Implement security best practices [outlined](https://support.google.com/a/answer/7587183) by Google.
- Determine the initial vector abused by the attacker and take action to prevent reinfection via the same vector.
- Using the incident response data, update logging and audit policies to improve the mean time to detect (MTTD) and the mean time to respond (MTTR).
## Setup
The Google Workspace Fleet integration or similarly structured data is required to be compatible with this rule.
### Important Information Regarding Google Workspace Event Lag Times
- As per Google's documentation, Google Workspace administrators may observe lag times ranging from minutes up to 3 days between the time of an event's occurrence and the event being visible in the Google Workspace admin/audit logs.
- This rule is configured to run every 10 minutes with a lookback time of 130 minutes and uses `timestamp_override: event.ingested` so delayed ingest does not drop events from the execution window. Sequence correlation and `maxspan` still use `@timestamp` event time.
- Drive and token audit events may arrive on different schedules; the token integration polls Google's API on a longer default interval. To reduce false negatives, consider reducing the poll interval for both Drive and token data sources.
- By default, `var.interval` is set to 2 hours (2h). Consider changing this interval to a lower value, such as 10 minutes (10m).
"""
references = [
"https://www.elastic.co/security-labs/google-workspace-attack-surface-part-one",
"https://www.elastic.co/security-labs/google-workspace-attack-surface-part-two",
"https://developers.google.com/apps-script/guides/bound",
"https://developers.google.com/identity/protocols/oauth2",
"https://support.google.com/a/users/answer/13004165#share_make_a_copy_links",
]
risk_score = 73
rule_id = "f33e68a4-bd19-11ed-b02f-f661ea17fbcc"
severity = "high"
tags = [
"Domain: Cloud",
"Data Source: Google Workspace",
"Data Source: Google Workspace Audit Logs",
"Tactic: Initial Access",
"Tactic: Execution",
"Tactic: Persistence",
"Resources: Investigation Guide",
"Noise: Low",
"Performance: Fast",
"Profile: Recommended",
"Threat: OAuth App Consent",
"Rule Type: Event Correlation (EQL)",
"Platform: Google Workspace",
"Domain: SaaS",
]
timestamp_override = "event.ingested"
type = "eql"
query = '''
sequence by source.user.email, source.ip with maxspan=3m
[file where data_stream.dataset == "google_workspace.drive" and event.action == "copy" and
/* External My Drive replica by a domain user, not a collaborator account or shared drive */
google_workspace.drive.owner_is_team_drive == false and
google_workspace.drive.actor_is_collaborator_account == false and
google_workspace.drive.primary_event == true and
google_workspace.drive.copy_type == "external" and
/* Google Script, Forms, Sheets, and Documents can carry container-bound scripts */
google_workspace.drive.file.type : ("script", "form", "spreadsheet", "document") and
/* /copy links name the replica with this English prefix */
file.name : "Copy of*"]
[any where data_stream.dataset == "google_workspace.token" and event.action == "authorize" and
/* Custom web OAuth client, not a numeric GCP service-account client */
google_workspace.token.client.type == "WEB" and
google_workspace.token.client.id : "*apps.googleusercontent.com" and
/* Client IDs are {cloud_project_number}-{oauth_client}.apps.googleusercontent.com. */
not google_workspace.token.client.id : (
"77185425430*.apps.googleusercontent.com",
"32555940559*.apps.googleusercontent.com",
"764086051850*.apps.googleusercontent.com",
"407408718192*.apps.googleusercontent.com",
"857627895310*.apps.googleusercontent.com"
) and
/* script.container is the sidebar or dialog. Also match other script.* scopes,
container-bound *.currentonly, or a scope containing scripts or container */
google_workspace.token.scope.value : (
"*script.*",
"*.currentonly",
"*scripts*",
"*container*"
)]
'''
[[rule.threat]]
framework = "MITRE ATT&CK"
[[rule.threat.technique]]
id = "T1566"
name = "Phishing"
reference = "https://attack.mitre.org/techniques/T1566/"
[[rule.threat.technique.subtechnique]]
id = "T1566.002"
name = "Spearphishing Link"
reference = "https://attack.mitre.org/techniques/T1566/002/"
[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 = "T1204"
name = "User Execution"
reference = "https://attack.mitre.org/techniques/T1204/"
[[rule.threat.technique.subtechnique]]
id = "T1204.001"
name = "Malicious Link"
reference = "https://attack.mitre.org/techniques/T1204/001/"
[rule.threat.tactic]
id = "TA0002"
name = "Execution"
reference = "https://attack.mitre.org/tactics/TA0002/"
[[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.001"
name = "Additional Cloud Credentials"
reference = "https://attack.mitre.org/techniques/T1098/001/"
[rule.threat.tactic]
id = "TA0003"
name = "Persistence"
reference = "https://attack.mitre.org/tactics/TA0003/"
[rule.investigation_fields]
field_names = [
"user.name",
"user.email",
"source.ip",
"file.name",
"google_workspace.drive.file.type",
"google_workspace.token.app_name",
"google_workspace.token.client.id",
"google_workspace.token.client.type",
"google_workspace.token.scope.value",
]