EXPLORE
← Back to Explore
sublimemediumRule

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.

MITRE ATT&CK

initial-accessdefense-evasion

Detection Query

type.inbound
// exclude if it's a reply to an existing conversation
and not length(body.previous_threads) > 0
and (
  // subject contains document sharing language
  regex.icontains(subject.base,
                  '\b(has\s+sent\s+you|sent\s+you|shared\s+with\s+you|document\s+to\s+review|document\s*(number|num|#)|file\s+to\s+review|proposal\s+document|new\s+document|document\s+.{0,20}(assigned|available)|(complete|review|shared?).{0,20}agreement.{0,20}|document\s+(?:transfer|shared))\b'
  )
  or strings.icontains(subject.subject, 'document to review')
  or strings.icontains(subject.subject, 'file to review')
  or strings.icontains(subject.subject, 'sent you')
  or strings.icontains(subject.subject, 'eDocuments Notification')
  // or recipient's SLD is the subject
  or (
    subject.base == sender.email.domain.sld
    // account for near-matches
    or (
      length(subject.base) < length(sender.email.domain.sld)
      and any([subject.base], strings.icontains(sender.email.domain.sld, .))
    )
  )
  // blank subject with recipient SLD in message body
  or (
    (length(subject.base) == 0 or subject.base is null)
    and any(recipients.to,
            strings.istarts_with(body.current_thread.text, .email.domain.sld)
    )
  )
)
and (
  // body contains document sharing language
  regex.icontains(body.current_thread.text,
                  '\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|posted)|file.*review|let\s+me\s+know\s+what\s+you\s+think|shared.{0,50}document)\b'
  )
  or strings.icontains(body.current_thread.text, 'document I sent')
  or strings.icontains(body.current_thread.text, 'proposal document')
  or strings.icontains(body.current_thread.text, 'let me know what you think')
  // account for image-as-content
  or (
    length(body.current_thread.text) < 10
    and (
      regex.icontains(beta.ocr(file.message_screenshot()).text,
                      '\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'
      )
      or strings.icontains(beta.ocr(file.message_screenshot()).text,
                           'document I sent'
      )
      or strings.icontains(beta.ocr(file.message_screenshot()).text,
                           'proposal document'
      )
      or strings.icontains(beta.ocr(file.message_screenshot()).text,
                           'let me know what you think'
      )
    )
  )
)
// has links that look like file attachments but aren't
and any(filter(body.links,
               // display text looks like a file
               (
                 regex.icontains(.display_text,
                                 '\.(pdf|doc|docx|goto|xls|xlsx|ppt|pptx)'
                 )
                 or regex.icontains(.display_text, '\d+kb|\d+mb')
                 or strings.icontains(.display_text, 'document')
                 or strings.icontains(.display_text, 'proposal')
                 or strings.icontains(.display_text, 'review')
                 // account for image-as-content
                 or (
                   length(body.current_thread.text) < 10
                   and length(body.links) == 1
                 )
               )
               // but the URL doesn't point to legitimate file sharing
               and .href_url.domain.root_domain not in (
                 "sharepoint.com",
                 "google.com",
                 "dropbox.com",
                 "box.com",
                 "onedrive.com",
                 "1drv.ms",
                 "aka.ms",
                 "microsoft.com",
                 "office.com",
                 "docusign.com",
                 "adobesign.com",
                 "hellosign.com",
                 "signable.app"
               )
               and .href_url.domain.domain not in ("drive.google.com")
        ),
        // and points to suspicious domains
        .href_url.domain.tld in $suspicious_tlds
        or .href_url.domain.root_domain in $url_shorteners
        or .href_url.domain.domain in $url_shorteners
        or .href_url.domain.root_domain in $free_file_hosts
        or .href_url.domain.domain in $free_file_hosts
        // or it's a forms/survey platform being abused in self_service_creation_platform_domains
        or .href_url.domain.root_domain in $self_service_creation_platform_domains
        or .href_url.domain.domain in $self_service_creation_platform_domains
        // bulk mailer abuse has been observed
        or (
          (
            .href_url.domain.root_domain in $bulk_mailer_url_root_domains
            or (
              .href_url.rewrite.original is not null
              and 'mandrill' in .href_url.rewrite.encoders
            )
          )
          and .href_url.domain.sld not in $org_slds
        )
        // or the page redirects to common website, observed when evasion happens
        or (
          length(ml.link_analysis(., mode="aggressive").redirect_history) > 0
          and ml.link_analysis(., mode="aggressive").effective_url.domain.root_domain in $tranco_10k
        )
        // or common email marketing/tracking patterns
        or regex.match(.href_url.url, 'url\d+\..*\.com/ls/click')
        or regex.match(.href_url.path, '/ls/click|/click|/c/')
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and not headers.auth_summary.dmarc.pass
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)
and (
  profile.by_sender().solicited == false
  or profile.by_sender_email().prevalence == "new"
  or profile.by_sender_email().days_since.last_contact > 30
  or (
    profile.by_sender().any_messages_malicious_or_spam
    and not profile.by_sender().any_messages_benign
  )
  // or it's a spoof of the org_domain
  or (
    sender.email.domain.domain in $org_domains
    and not (
      headers.auth_summary.spf.pass
      or coalesce(headers.auth_summary.dmarc.pass, false)
    )
  )
)
and not profile.by_sender().any_messages_benign

Data Sources

Email MessagesEmail HeadersEmail Attachments

Platforms

email
Raw Content
name: "Credential phishing: Generic document sharing"
description: |
  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.
type: "rule"
severity: "medium"
source: |
  type.inbound
  // exclude if it's a reply to an existing conversation
  and not length(body.previous_threads) > 0
  and (
    // subject contains document sharing language
    regex.icontains(subject.base,
                    '\b(has\s+sent\s+you|sent\s+you|shared\s+with\s+you|document\s+to\s+review|document\s*(number|num|#)|file\s+to\s+review|proposal\s+document|new\s+document|document\s+.{0,20}(assigned|available)|(complete|review|shared?).{0,20}agreement.{0,20}|document\s+(?:transfer|shared))\b'
    )
    or strings.icontains(subject.subject, 'document to review')
    or strings.icontains(subject.subject, 'file to review')
    or strings.icontains(subject.subject, 'sent you')
    or strings.icontains(subject.subject, 'eDocuments Notification')
    // or recipient's SLD is the subject
    or (
      subject.base == sender.email.domain.sld
      // account for near-matches
      or (
        length(subject.base) < length(sender.email.domain.sld)
        and any([subject.base], strings.icontains(sender.email.domain.sld, .))
      )
    )
    // blank subject with recipient SLD in message body
    or (
      (length(subject.base) == 0 or subject.base is null)
      and any(recipients.to,
              strings.istarts_with(body.current_thread.text, .email.domain.sld)
      )
    )
  )
  and (
    // body contains document sharing language
    regex.icontains(body.current_thread.text,
                    '\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|posted)|file.*review|let\s+me\s+know\s+what\s+you\s+think|shared.{0,50}document)\b'
    )
    or strings.icontains(body.current_thread.text, 'document I sent')
    or strings.icontains(body.current_thread.text, 'proposal document')
    or strings.icontains(body.current_thread.text, 'let me know what you think')
    // account for image-as-content
    or (
      length(body.current_thread.text) < 10
      and (
        regex.icontains(beta.ocr(file.message_screenshot()).text,
                        '\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'
        )
        or strings.icontains(beta.ocr(file.message_screenshot()).text,
                             'document I sent'
        )
        or strings.icontains(beta.ocr(file.message_screenshot()).text,
                             'proposal document'
        )
        or strings.icontains(beta.ocr(file.message_screenshot()).text,
                             'let me know what you think'
        )
      )
    )
  )
  // has links that look like file attachments but aren't
  and any(filter(body.links,
                 // display text looks like a file
                 (
                   regex.icontains(.display_text,
                                   '\.(pdf|doc|docx|goto|xls|xlsx|ppt|pptx)'
                   )
                   or regex.icontains(.display_text, '\d+kb|\d+mb')
                   or strings.icontains(.display_text, 'document')
                   or strings.icontains(.display_text, 'proposal')
                   or strings.icontains(.display_text, 'review')
                   // account for image-as-content
                   or (
                     length(body.current_thread.text) < 10
                     and length(body.links) == 1
                   )
                 )
                 // but the URL doesn't point to legitimate file sharing
                 and .href_url.domain.root_domain not in (
                   "sharepoint.com",
                   "google.com",
                   "dropbox.com",
                   "box.com",
                   "onedrive.com",
                   "1drv.ms",
                   "aka.ms",
                   "microsoft.com",
                   "office.com",
                   "docusign.com",
                   "adobesign.com",
                   "hellosign.com",
                   "signable.app"
                 )
                 and .href_url.domain.domain not in ("drive.google.com")
          ),
          // and points to suspicious domains
          .href_url.domain.tld in $suspicious_tlds
          or .href_url.domain.root_domain in $url_shorteners
          or .href_url.domain.domain in $url_shorteners
          or .href_url.domain.root_domain in $free_file_hosts
          or .href_url.domain.domain in $free_file_hosts
          // or it's a forms/survey platform being abused in self_service_creation_platform_domains
          or .href_url.domain.root_domain in $self_service_creation_platform_domains
          or .href_url.domain.domain in $self_service_creation_platform_domains
          // bulk mailer abuse has been observed
          or (
            (
              .href_url.domain.root_domain in $bulk_mailer_url_root_domains
              or (
                .href_url.rewrite.original is not null
                and 'mandrill' in .href_url.rewrite.encoders
              )
            )
            and .href_url.domain.sld not in $org_slds
          )
          // or the page redirects to common website, observed when evasion happens
          or (
            length(ml.link_analysis(., mode="aggressive").redirect_history) > 0
            and ml.link_analysis(., mode="aggressive").effective_url.domain.root_domain in $tranco_10k
          )
          // or common email marketing/tracking patterns
          or regex.match(.href_url.url, 'url\d+\..*\.com/ls/click')
          or regex.match(.href_url.path, '/ls/click|/click|/c/')
  )
  // negate highly trusted sender domains unless they fail DMARC authentication
  and (
    (
      sender.email.domain.root_domain in $high_trust_sender_root_domains
      and not headers.auth_summary.dmarc.pass
    )
    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
  )
  and (
    profile.by_sender().solicited == false
    or profile.by_sender_email().prevalence == "new"
    or profile.by_sender_email().days_since.last_contact > 30
    or (
      profile.by_sender().any_messages_malicious_or_spam
      and not profile.by_sender().any_messages_benign
    )
    // or it's a spoof of the org_domain
    or (
      sender.email.domain.domain in $org_domains
      and not (
        headers.auth_summary.spf.pass
        or coalesce(headers.auth_summary.dmarc.pass, false)
      )
    )
  )
  and not profile.by_sender().any_messages_benign
attack_types:
  - "Credential Phishing"
  - "BEC/Fraud"
tactics_and_techniques:
  - "Social engineering"
  - "Evasion"
  - "Impersonation: Employee"
detection_methods:
  - "Content analysis"
  - "Natural Language Understanding"
  - "URL analysis"
  - "Sender analysis"
id: "9f0e1d2c-3b4a-5c6d-7e8f-9a0b1c2d3e4f"