Link: Multistage landing - Abused Google Drive

The detection rule matches on message groups which make use of Google Drive as a landing page. The landing page contains links which are newly registered, use free file or subdomain hosts, url shortners or when visited are phishing pages, lead to a captcha or redirect to a common website.

Sublime rule (View on GitHub)

  1name: "Link: Multistage landing - Abused Google Drive"
  2description: "The detection rule matches on message groups which make use of Google Drive as a landing page. The landing page contains links which are newly registered, use free file or subdomain hosts, url shortners or when visited are phishing pages, lead to a captcha or redirect to a common website."
  3type: "rule"
  4severity: "high"
  5source: |
  6  type.inbound
  7  
  8  //
  9  // This rule makes use of a beta feature and is subject to change without notice
 10  // using the beta feature in custom rules is not suggested until it has been formally released
 11  //
 12  // the reply-to address is new or unsolicited
 13  and (
 14    // reply-to address has never sent an email to the org
 15    beta.profile.by_reply_to().prevalence == "new"
 16  
 17    // reply-to email address has never been sent an email by the org
 18    or not beta.profile.by_reply_to().solicited
 19  )
 20  
 21  // message is from google actual
 22  and sender.email.domain.domain == 'google.com'
 23  and (
 24    sender.email.local_part == "drive-shares-noreply"
 25    or sender.email.local_part == "drive-shares-dm-noreply"
 26  )
 27  and headers.auth_summary.spf.pass
 28  and strings.ends_with(headers.auth_summary.spf.details.designator,
 29                        'doclist.bounces.google.com'
 30  )
 31  and headers.auth_summary.dmarc.pass
 32  
 33  // not where the reply_to address is within org_domains
 34  and not any(headers.reply_to, .email.domain.domain in $org_domains)
 35  
 36  // not where the sender display name is within org_display_names
 37  and not any(regex.iextract(sender.display_name,
 38                             '^(?P<sender_display_name>.*)\((?:via )?Google'
 39              ),
 40              .named_groups["sender_display_name"] in~ $org_display_names
 41  )
 42  
 43  // threat actors dont want others to edit the share
 44  and not strings.icontains(body.current_thread.text, 'invited you to edit')
 45  and (
 46    // check the shared filed name for suspicious indicators
 47    // alerting keywords
 48    regex.icontains(strings.replace_confusables(subject.subject),
 49                    ': \".*(?:Immediate|Urgent|Critical|Alert|Warning|Urgent|Important|Critical Alert|Security Notice)[!:\-]?[^\"]*\"'
 50    )
 51    // account issues
 52    or regex.icontains(strings.replace_confusables(subject.subject),
 53                       ': \".*(?:Online|Bank(?:ing)?|User|Account|Access|[[:punct:]\s]?(?:ID)|Transactions)\b.*\b(?:Security|Recover|Blocked|Suspen(?:ded|sion)|Restricted|Locked|Disabled|Frozen|Closed)[^\"]*\"'
 54    )
 55    // keywords themed as Suspicious
 56    or regex.icontains(strings.replace_confusables(subject.subject),
 57                       ': \".*(Suspicious|Unauthorized|Unrecognized|Fraudulent|Scam)\b.*\b(Activity|Transaction|Log[- ]?In|Access|Entry|Sign[- ]?In|Detected)[^\"]*\"'
 58    )
 59    // account/identify verification keywords
 60    or regex.icontains(strings.replace_confusables(subject.subject),
 61                       ': \".*(?:(?:Verify|Confirm|Update|Review|Complete)\b.*\b(Your (Identity|Account|Online[- ]?ID|Billing Information))|(?:(?:Action|Attention|Verification|Review)[[:punct:]\s](?:Needed|Required)))[^\"]*\"'
 62    )
 63    or ( // filenames that in References/ID keywords
 64      regex.icontains(strings.replace_confusables(subject.subject),
 65                      ': \".*[[:punct:]\s]+\w+[[:punct:]\s]*[a-zA-Z]*[0-9][a-zA-Z0-9]*\"$'
 66      )
 67      // the above regex is a bit "open", so close it by checking it with a more specific "ending" pattern.
 68      and regex.icontains(strings.replace_confusables(subject.subject),
 69                          '[[:punct:]]\s*[a-z0-9]{5,}\"$'
 70      )
 71    )
 72  
 73    // finally get ready to do link analysis
 74    // filter out all the links, keeping only the links of interest
 75    or any(filter(body.links,
 76                  // target the "Open" link
 77                  (
 78                    .href_url.domain.domain == "drive.google.com"
 79                    and strings.icontains(.href_url.path, '/view')
 80                    // this isn't controlled by the actor
 81                    and .display_text == "Open"
 82                  )
 83           ),
 84           // the Google Drive page has been taken down due to TOS violations
 85           strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
 86                             "You can't access this item because it is in violation of our Terms of Service"
 87           )
 88           // if not taken down
 89           // inspect the links on the page
 90           or any(filter(ml.link_analysis(., mode="aggressive").additional_responses,
 91                         .url.path == "/viewerng/presspage"
 92                  ),
 93                  any(.json,
 94                      any(.,
 95                          any(., // this gets us to the array that contains the links embedded in the PDF
 96                              network.whois(strings.parse_url(.).domain).days_old < 30
 97                              or strings.parse_url(.).domain.tld in $suspicious_tlds
 98                              or (
 99                                strings.parse_url(.).domain.root_domain in $free_subdomain_hosts
100                                and strings.parse_url(.).domain.subdomain is not null
101                                and strings.parse_url(.).domain.subdomain != "www"
102                              )
103                              or strings.parse_url(.).domain.domain in $free_file_hosts
104                              or strings.parse_url(.).domain.root_domain in $free_file_hosts
105                              or strings.parse_url(.).domain.domain in $url_shorteners
106                              or strings.parse_url(.).domain.domain in $social_landing_hosts
107                              or strings.parse_url(.).domain.root_domain in $url_shorteners
108                              or strings.parse_url(.).domain.root_domain in $social_landing_hosts
109                          )
110                      )
111                  )
112           )
113           // if not taken down
114           // filter down the links on the google drive page to those that are external to google
115           or any(filter(ml.link_analysis(., mode="aggressive").final_dom.links,
116                         .href_url.domain.root_domain != 'google.com'
117                         // relative links (no domains)
118                         and .href_url.domain.domain is not null
119                  ),
120                  (
121                    // any of those links domains are new
122                    network.whois(.href_url.domain).days_old < 30
123                    // go to free file hosts
124                    or .href_url.domain.root_domain in $free_file_hosts
125                    or .href_url.domain.domain in $free_file_hosts
126  
127                    // go to free subdomains hosts
128                    or (
129                      .href_url.domain.root_domain in $free_subdomain_hosts
130                      // where there is a subdomain
131                      and .href_url.domain.subdomain is not null
132                      and .href_url.domain.subdomain != "www"
133                    )
134                    // go to url shortners
135                    or .href_url.domain.root_domain in $url_shorteners
136                    or .href_url.domain.root_domain in $social_landing_hosts
137                    or .href_url.domain.domain in $url_shorteners
138                    or .href_url.domain.domain in $social_landing_hosts
139                    or (
140                      // find any links that mention common "action" words
141                      regex.icontains(.display_text,
142                                      '(?:view|click|show|access|download|continue|goto|Validate|Va[il]idar|login|verify|account)'
143                      )
144                      and (
145                        // and when visiting those links, are phishing
146                        ml.link_analysis(., mode="aggressive").credphish.disposition == "phishing"
147  
148                        // hit a captcha page
149                        or ml.link_analysis(., mode="aggressive").credphish.contains_captcha
150  
151                        // or the page redirects to common website, observed when evasion happens
152                        or (
153                          length(ml.link_analysis(., mode="aggressive").redirect_history
154                          ) > 0
155                          and ml.link_analysis(., mode="aggressive").effective_url.domain.root_domain in $tranco_10k
156                        )
157                      )
158                    )
159                  )
160           )
161    )
162  )  
163attack_types:
164  - "Credential Phishing"
165tactics_and_techniques:
166  - "Evasion"
167  - "Free email provider"
168  - "Free file host"
169detection_methods:
170  - "Content analysis"
171  - "Sender analysis"
172  - "URL analysis"
173  - "Whois"
174  - "HTML analysis"
175id: "c86288b4-98f3-5d71-850e-c001a628600a"
to-top