Credential phishing: Generic document sharing

Detects credential phishing attempts using generic document sharing language where the sender claims to have sent a document for review, but the link doesn't point to legitimate file sharing services.

Sublime rule (View on GitHub)

  1name: "Credential phishing: Generic document sharing"
  2description: |
  3  Detects credential phishing attempts using generic document sharing language
  4  where the sender claims to have sent a document for review, but the link
  5  doesn't point to legitimate file sharing services.  
  6type: "rule"
  7severity: "medium"
  8source: |
  9  type.inbound
 10  // exclude if it's a reply to an existing conversation
 11  and not length(body.previous_threads) > 0
 12  and (
 13    // subject contains document sharing language
 14    regex.icontains(subject.subject,
 15                    '\b(has\s+sent\s+you|sent\s+you|shared\s+with\s+you|document\s+to\s+review|file\s+to\s+review|proposal\s+document|new\s+document|document\s+.{0,20}assigned)\b'
 16    )
 17    or strings.icontains(subject.subject, 'document to review')
 18    or strings.icontains(subject.subject, 'file to review')
 19    or strings.icontains(subject.subject, 'sent you')
 20    // or recipient's SLD is the subject
 21    or (
 22      subject.base == sender.email.domain.sld
 23      // account for near-matches
 24      or (
 25        length(subject.base) < length(sender.email.domain.sld)
 26        and any([subject.base], strings.icontains(sender.email.domain.sld, .))
 27      )
 28    )
 29  )
 30  and (
 31    // body contains document sharing language
 32    regex.icontains(body.current_thread.text,
 33                    '\b(document\s+I\s+sent|proposal\s+document|(proposal|documents?)\s+for\s+your\s+(approval|consideration|review|signature)|see\s+the\s+below|document.*review|file.*review|let\s+me\s+know\s+what\s+you\s+think|shared.{0,50}document)\b'
 34    )
 35    or strings.icontains(body.current_thread.text, 'document I sent')
 36    or strings.icontains(body.current_thread.text, 'proposal document')
 37    or strings.icontains(body.current_thread.text, 'let me know what you think')
 38    // account for image-as-content
 39    or (
 40      length(body.current_thread.text) < 10
 41      and (
 42        regex.icontains(beta.ocr(file.message_screenshot()).text,
 43                        '\b(document\s+I\s+sent|proposal\s+document|see\s+the\s+below|document.*review|file.*review|let\s+me\s+know\s+what\s+you\s+think|shared.{0,50}document)\b'
 44        )
 45        or strings.icontains(beta.ocr(file.message_screenshot()).text,
 46                             'document I sent'
 47        )
 48        or strings.icontains(beta.ocr(file.message_screenshot()).text,
 49                             'proposal document'
 50        )
 51        or strings.icontains(beta.ocr(file.message_screenshot()).text,
 52                             'let me know what you think'
 53        )
 54      )
 55    )
 56  )
 57  // has links that look like file attachments but aren't
 58  and any(body.links,
 59          // display text looks like a file
 60          (
 61            regex.icontains(.display_text,
 62                            '\.(pdf|doc|docx|goto|xls|xlsx|ppt|pptx)'
 63            )
 64            or regex.icontains(.display_text, '\d+kb|\d+mb')
 65            or strings.icontains(.display_text, 'document')
 66            or strings.icontains(.display_text, 'proposal')
 67            or strings.icontains(.display_text, 'review')
 68            // account for image-as-content
 69            or (length(body.current_thread.text) < 10 and length(body.links) == 1)
 70          )
 71          // but the URL doesn't point to legitimate file sharing
 72          and .href_url.domain.root_domain not in (
 73            "sharepoint.com",
 74            "google.com",
 75            "drive.google.com",
 76            "dropbox.com",
 77            "box.com",
 78            "onedrive.com",
 79            "1drv.ms",
 80            "aka.ms",
 81            "microsoft.com",
 82            "office.com",
 83            "docusign.com",
 84            "adobesign.com",
 85            "hellosign.com",
 86            "signable.app"
 87          )
 88          // and points to suspicious domains
 89          and (
 90            .href_url.domain.tld in $suspicious_tlds
 91            or .href_url.domain.root_domain in $url_shorteners
 92            or .href_url.domain.domain in $url_shorteners
 93            or .href_url.domain.root_domain in $free_file_hosts
 94            or .href_url.domain.domain in $free_file_hosts
 95            // or it's a forms/survey platform being abused in self_service_creation_platform_domains
 96            or .href_url.domain.root_domain in $self_service_creation_platform_domains
 97            or .href_url.domain.domain in $self_service_creation_platform_domains
 98          )
 99  )
100  // negate highly trusted sender domains unless they fail DMARC authentication
101  and (
102    (
103      sender.email.domain.root_domain in $high_trust_sender_root_domains
104      and not headers.auth_summary.dmarc.pass
105    )
106    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
107  )
108  and (
109    profile.by_sender().solicited == false
110    or profile.by_sender_email().prevalence == "new"
111    or profile.by_sender_email().days_since.last_contact > 30
112    or (
113      profile.by_sender().any_messages_malicious_or_spam
114      and not profile.by_sender().any_messages_benign
115    )
116    // or it's a spoof of the org_domain
117    or (
118      sender.email.domain.domain in $org_domains
119      and not (
120        headers.auth_summary.spf.pass
121        or coalesce(headers.auth_summary.dmarc.pass, false)
122      )
123    )
124  )
125  and not profile.by_sender().any_messages_benign
126    
127attack_types:
128  - "Credential Phishing"
129  - "BEC/Fraud"
130tactics_and_techniques:
131  - "Social engineering"
132  - "Evasion"
133  - "Impersonation: Employee"
134detection_methods:
135  - "Content analysis"
136  - "Natural Language Understanding"
137  - "URL analysis"
138  - "Sender analysis"
139id: "9f0e1d2c-3b4a-5c6d-7e8f-9a0b1c2d3e4f"
to-top