Techniques
Sample rules
Google Workspace Object Copied from External Drive with App Consent
- source: elastic
- technicques:
- T1098
- T1204
- T1566
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.
Detection logic
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*"
)]