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