Google presentation open redirect phishing

Detects emails containing links to Google Document Presentations that either have a single page with a single external link, have been removed for Terms of Service violations, or have been deleted.

Sublime rule (View on GitHub)

  1name: "Google presentation open redirect phishing"
  2description: "Detects emails containing links to Google Document Presentations that either have a single page with a single external link, have been removed for Terms of Service violations, or have been deleted."
  3type: "rule"
  4severity: "medium"
  5source: |
  6  type.inbound
  7  and not strings.icontains(body.current_thread.text, 'invited you to edit')
  8  and any(body.links,
  9          // body link is to a google doc presentation
 10          .href_url.domain.domain == "docs.google.com"
 11          and strings.istarts_with(.href_url.path, '/presentation/')
 12  
 13          // prefilter some to avoid clicking on _every_ google presentation link
 14          and (
 15            (
 16              // make sure the display text is in the current thread and not a previous one.
 17              strings.icontains(body.current_thread.text, .display_text)
 18              // the display_text ends with a word that is 4-10 long
 19              and regex.icontains(.display_text, '[[:punct:]\s][a-z0-9]{5,9}$')
 20              // that word has to include a letter AND a number
 21              and regex.icontains(.display_text,
 22                                  '[[:punct:]\s](?:[a-z0-9]*[a-z][0-9][a-z0-9]*|[a-z0-9]*[0-9][a-z][a-z0-9]*)$'
 23              )
 24              and strings.iends_with(.href_url.path, '/pub')
 25            )
 26            or 
 27            // finally send the link to link analysis that presentation...
 28            (
 29              // contains a single link
 30              length(filter(ml.link_analysis(., mode="aggressive").final_dom.links,
 31                            .href_url.domain.root_domain != "google.com"
 32                     )
 33              ) == 1
 34  
 35              // cannot be edited via link provided
 36              and strings.contains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 37                                   'canEdit:  false'
 38              )
 39  
 40              // and a single page
 41              and strings.contains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 42                                   'slidePageCount:  1.0'
 43              )
 44  
 45              // where we have links which have been written via a google open redirect
 46              and any(ml.link_analysis(., mode="aggressive").final_dom.links,
 47                      // links are not in thhe org_domains
 48                      .href_url.domain.domain not in $org_domains
 49                      and (
 50                        (
 51                          // don't include high rep domains
 52                          .href_url.domain.domain not in $tranco_1m
 53                          and .href_url.domain.domain not in $umbrella_1m
 54                        )
 55                        // if it's in Tranco or Umbrella, still include it if it's one of these
 56                        or .href_url.domain.domain in $free_file_hosts
 57                        or .href_url.domain.root_domain in $free_file_hosts
 58                        or .href_url.domain.root_domain in $free_subdomain_hosts
 59                        // or it's a url shortner
 60                        or .href_url.domain.root_domain in $url_shorteners
 61                        or .href_url.domain.root_domain in $social_landing_hosts
 62                      )
 63                      // which have been "unrolled" by the google_open_redirect rule
 64                      and any(.href_url.rewrite.encoders,
 65                              . == "google_open_redirect"
 66                      )
 67              )
 68            )
 69            // or the presentation has been removed for violation of terms of service
 70            or strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
 71                                 "We're sorry. You can't access this item because it is in violation of our Terms of Service."
 72            )
 73          )
 74  )
 75  // when the sender is not google, the sender should not be a common prevalence
 76  and (
 77    ( // the message is not from google actual
 78      sender.email.email not in (
 79        'comments-noreply@docs.google.com',
 80        'drive-shares-dm-noreply@google.com',
 81        'drive-shares-noreply@google.com',
 82        'calendar-notification@google.com'
 83      )
 84      // ensure the sender prevalence is not common
 85      and profile.by_sender().prevalence != "common"
 86    )
 87    // or the message is from google actual
 88    or (
 89      sender.email.email in (
 90        'comments-noreply@docs.google.com',
 91        'drive-shares-dm-noreply@google.com',
 92        'drive-shares-noreply@google.com',
 93        'calendar-notification@google.com'
 94      )
 95    )
 96  )
 97  
 98  // not where the sender display name of the message is within org_display_names
 99  and not (
100    // the message is from google actual
101    sender.email.email in (
102      'comments-noreply@docs.google.com',
103      'drive-shares-dm-noreply@google.com',
104      'drive-shares-noreply@google.com',
105      'calendar-notification@google.com'
106    )
107    and headers.auth_summary.dmarc.pass
108  
109    // but the sender display name is within org_display_names
110    and any($org_display_names,
111            strings.istarts_with(sender.display_name,
112                                 strings.concat(., " (via Google ")
113            )
114            or strings.istarts_with(sender.display_name,
115                                    strings.concat(., " (Google ")
116            )
117    )
118  )
119  // negate highly trusted sender domains unless they fail DMARC authentication
120  // but ignore high_trust if the sender is one of the google actual senders
121  and (
122    (
123      (
124        sender.email.domain.root_domain in $high_trust_sender_root_domains
125        and not headers.auth_summary.dmarc.pass
126      )
127      or (
128        sender.email.domain.root_domain in $high_trust_sender_root_domains
129        and sender.email.email in (
130          'comments-noreply@docs.google.com',
131          'drive-shares-dm-noreply@google.com',
132          'drive-shares-noreply@google.com',
133          'calendar-notification@google.com'
134        )
135      )
136      or sender.email.domain.root_domain not in $high_trust_sender_root_domains
137    )
138  )  
139attack_types:
140  - "Credential Phishing"
141tactics_and_techniques:
142  - "Evasion"
143  - "Open redirect"
144  - "Social engineering"
145detection_methods:
146  - "URL analysis"
147  - "HTML analysis"
148id: "5d01ee3a-9426-5a8b-bde3-328d6780af6f"
to-top