LoFP LoFP / the copied-title check looks for the english text \"copy of \". workspace locales that translate that prefix will not match.

Techniques

Sample rules

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*"
    )]