Detection rules › Sublime MQL

Link: Multistage landing - Abused Google Drive

Severity
high
Type
rule
Source
github.com/sublime-security/sublime-rules

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.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, Free email provider, Free file host

Event coverage

Rule body MQL

type.inbound

//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
// the reply-to address is new or unsolicited
and (
  // reply-to address has never sent an email to the org
  beta.profile.by_reply_to().prevalence == "new"

  // reply-to email address has never been sent an email by the org
  or not beta.profile.by_reply_to().solicited
)

// message is from google actual
and sender.email.domain.domain == 'google.com'
and (
  sender.email.local_part == "drive-shares-noreply"
  or sender.email.local_part == "drive-shares-dm-noreply"
)
and headers.auth_summary.spf.pass
and strings.ends_with(headers.auth_summary.spf.details.designator,
                      'doclist.bounces.google.com'
)
and headers.auth_summary.dmarc.pass

// not where the reply_to address is within org_domains
and not any(headers.reply_to, .email.domain.domain in $org_domains)

// not where the sender display name is within org_display_names
and not any(regex.iextract(sender.display_name,
                           '^(?P<sender_display_name>.*)\((?:via )?Google'
            ),
            .named_groups["sender_display_name"] in~ $org_display_names
)

// threat actors dont want others to edit the share
and not strings.icontains(body.current_thread.text, 'invited you to edit')
and (
  // check the shared filed name for suspicious indicators
  // alerting keywords
  regex.icontains(strings.replace_confusables(subject.subject),
                  ': \".*(?:Immediate|Urgent|Critical|Alert|Warning|Urgent|Important|Critical Alert|Security Notice)[!:\-]?[^\"]*\"'
  )
  // account issues
  or regex.icontains(strings.replace_confusables(subject.subject),
                     ': \".*(?:Online|Bank(?:ing)?|User|Account|Access|[[:punct:]\s]?(?:ID)|Transactions)\b.*\b(?:Security|Recover|Blocked|Suspen(?:ded|sion)|Restricted|Locked|Disabled|Frozen|Closed)[^\"]*\"'
  )
  // keywords themed as Suspicious
  or regex.icontains(strings.replace_confusables(subject.subject),
                     ': \".*(Suspicious|Unauthorized|Unrecognized|Fraudulent|Scam)\b.*\b(Activity|Transaction|Log[- ]?In|Access|Entry|Sign[- ]?In|Detected)[^\"]*\"'
  )
  // account/identify verification keywords
  or regex.icontains(strings.replace_confusables(subject.subject),
                     ': \".*(?:(?:Verify|Confirm|Update|Review|Complete)\b.*\b(Your (Identity|Account|Online[- ]?ID|Billing Information))|(?:(?:Action|Attention|Verification|Review)[[:punct:]\s](?:Needed|Required)))[^\"]*\"'
  )
  or ( // filenames that in References/ID keywords
    regex.icontains(strings.replace_confusables(subject.subject),
                    ': \".*[[:punct:]\s]+\w+[[:punct:]\s]*[a-zA-Z]*[0-9][a-zA-Z0-9]*\"$'
    )
    // the above regex is a bit "open", so close it by checking it with a more specific "ending" pattern.
    and regex.icontains(strings.replace_confusables(subject.subject),
                        '[[:punct:]]\s*[a-z0-9]{5,}\"$'
    )
  )

  // finally get ready to do link analysis
  // filter out all the links, keeping only the links of interest
  or any(filter(body.links,
                // target the "Open" link
                (
                  .href_url.domain.domain == "drive.google.com"
                  and strings.icontains(.href_url.path, '/view')
                  // this isn't controlled by the actor
                  and .display_text == "Open"
                )
         ),
         // the Google Drive page has been taken down due to TOS violations
         strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
                           "You can't access this item because it is in violation of our Terms of Service"
         )
         // if not taken down
         // inspect the links on the page
         or any(filter(ml.link_analysis(., mode="aggressive").additional_responses,
                       .url.path == "/viewerng/presspage"
                ),
                any(.json,
                    any(.,
                        any(., // this gets us to the array that contains the links embedded in the PDF
                            network.whois(strings.parse_url(.).domain).days_old < 30
                            or strings.parse_url(.).domain.tld in $suspicious_tlds
                            or (
                              strings.parse_url(.).domain.root_domain in $free_subdomain_hosts
                              and strings.parse_url(.).domain.subdomain is not null
                              and strings.parse_url(.).domain.subdomain != "www"
                            )
                            or strings.parse_url(.).domain.domain in $free_file_hosts
                            or strings.parse_url(.).domain.root_domain in $free_file_hosts
                            or strings.parse_url(.).domain.domain in $url_shorteners
                            or strings.parse_url(.).domain.domain in $social_landing_hosts
                            or strings.parse_url(.).domain.root_domain in $url_shorteners
                            or strings.parse_url(.).domain.root_domain in $social_landing_hosts
                        )
                    )
                )
         )
         // if not taken down
         // filter down the links on the google drive page to those that are external to google
         or any(filter(ml.link_analysis(., mode="aggressive").final_dom.links,
                       .href_url.domain.root_domain != 'google.com'
                       // relative links (no domains)
                       and .href_url.domain.domain is not null
                ),
                (
                  // any of those links domains are new
                  network.whois(.href_url.domain).days_old < 30
                  // go to free file hosts
                  or .href_url.domain.root_domain in $free_file_hosts
                  or .href_url.domain.domain in $free_file_hosts

                  // go to free subdomains hosts
                  or (
                    .href_url.domain.root_domain in $free_subdomain_hosts
                    // where there is a subdomain
                    and .href_url.domain.subdomain is not null
                    and .href_url.domain.subdomain != "www"
                  )
                  // go to url shortners
                  or .href_url.domain.root_domain in $url_shorteners
                  or .href_url.domain.root_domain in $social_landing_hosts
                  or .href_url.domain.domain in $url_shorteners
                  or .href_url.domain.domain in $social_landing_hosts
                  or (
                    // find any links that mention common "action" words
                    regex.icontains(.display_text,
                                    '(?:view|click|show|access|download|continue|goto|Validate|Va[il]idar|login|verify|account)'
                    )
                    and (
                      // and when visiting those links, are phishing
                      ml.link_analysis(., mode="aggressive").credphish.disposition == "phishing"

                      // hit a captcha page
                      or ml.link_analysis(., mode="aggressive").credphish.contains_captcha

                      // 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
                      )
                    )
                  )
                )
         )
  )
)

Detection logic

Scope: inbound message.

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.

  1. inbound message
  2. any of:
    • beta.profile.by_reply_to().prevalence is 'new'
    • not:
      • beta.profile.by_reply_to().solicited
  3. sender.email.domain.domain is 'google.com'
  4. any of:
    • sender.email.local_part is 'drive-shares-noreply'
    • sender.email.local_part is 'drive-shares-dm-noreply'
  5. headers.auth_summary.spf.pass
  6. headers.auth_summary.spf.details.designator ends with 'doclist.bounces.google.com'
  7. headers.auth_summary.dmarc.pass
  8. not:
    • any of headers.reply_to where:
      • .email.domain.domain in $org_domains
  9. not:
    • any of regex.iextract(sender.display_name) where:
      • .named_groups['sender_display_name'] in $org_display_names
  10. not:
    • body.current_thread.text contains 'invited you to edit'
  11. any of:
    • strings.replace_confusables(subject.subject) matches ': \\".*(?:Immediate|Urgent|Critical|Alert|Warning|Urgent|Important|Critical Alert|Security Notice)[!:\\-]?[^\\"]*\\"'
    • strings.replace_confusables(subject.subject) matches ': \\".*(?:Online|Bank(?:ing)?|User|Account|Access|[[:punct:]\\s]?(?:ID)|Transactions)\\b.*\\b(?:Security|Recover|Blocked|Suspen(?:ded|sion)|Restricted|Locked|Disabled|Frozen|Closed)[^\\"]*\\"'
    • strings.replace_confusables(subject.subject) matches ': \\".*(Suspicious|Unauthorized|Unrecognized|Fraudulent|Scam)\\b.*\\b(Activity|Transaction|Log[- ]?In|Access|Entry|Sign[- ]?In|Detected)[^\\"]*\\"'
    • strings.replace_confusables(subject.subject) matches ': \\".*(?:(?:Verify|Confirm|Update|Review|Complete)\\b.*\\b(Your (Identity|Account|Online[- ]?ID|Billing Information))|(?:(?:Action|Attention|Verification|Review)[[:punct:]\\s](?:Needed|Required)))[^\\"]*\\"'
    • all of:
      • strings.replace_confusables(subject.subject) matches ': \\".*[[:punct:]\\s]+\\w+[[:punct:]\\s]*[a-zA-Z]*[0-9][a-zA-Z0-9]*\\"$'
      • strings.replace_confusables(subject.subject) matches '[[:punct:]]\\s*[a-z0-9]{5,}\\"$'
    • any of filter(body.links) where any holds:
      • ml.link_analysis(., mode='aggressive').final_dom.display_text contains "You can't access this item because it is in violation of our Terms of Service"
      • any of filter(...) where:
        • any of .json where:
          • any of . where:
            • any of . where any holds:
              • network.whois(strings.parse_url(.).domain).days_old < 30
              • strings.parse_url(.).domain.tld in $suspicious_tlds
              • all of:
                • strings.parse_url(.).domain.root_domain in $free_subdomain_hosts
                • strings.parse_url(.).domain.subdomain is set
                • strings.parse_url(.).domain.subdomain is not 'www'
              • strings.parse_url(.).domain.domain in $free_file_hosts
              • strings.parse_url(.).domain.root_domain in $free_file_hosts
              • strings.parse_url(.).domain.domain in $url_shorteners
              • strings.parse_url(.).domain.domain in $social_landing_hosts
              • strings.parse_url(.).domain.root_domain in $url_shorteners
              • strings.parse_url(.).domain.root_domain in $social_landing_hosts
      • any of filter(...) where any holds:
        • network.whois(.href_url.domain).days_old < 30
        • .href_url.domain.root_domain in $free_file_hosts
        • .href_url.domain.domain in $free_file_hosts
        • all of:
          • .href_url.domain.root_domain in $free_subdomain_hosts
          • .href_url.domain.subdomain is set
          • .href_url.domain.subdomain is not 'www'
        • .href_url.domain.root_domain in $url_shorteners
        • .href_url.domain.root_domain in $social_landing_hosts
        • .href_url.domain.domain in $url_shorteners
        • .href_url.domain.domain in $social_landing_hosts
        • all of:
          • .display_text matches '(?:view|click|show|access|download|continue|goto|Validate|Va[il]idar|login|verify|account)'
          • any of:
            • ml.link_analysis(.).credphish.disposition is 'phishing'
            • ml.link_analysis(.).credphish.contains_captcha
            • all of:
              • length(ml.link_analysis(., mode='aggressive').redirect_history) > 0
              • ml.link_analysis(.).effective_url.domain.root_domain in $tranco_10k

Inspects: body.current_thread.text, body.links, body.links[].display_text, body.links[].href_url.domain.domain, body.links[].href_url.path, headers.auth_summary.dmarc.pass, headers.auth_summary.spf.details.designator, headers.auth_summary.spf.pass, headers.reply_to, headers.reply_to[].email.domain.domain, sender.display_name, sender.email.domain.domain, sender.email.local_part, subject.subject, type.inbound. Sensors: beta.profile.by_reply_to, ml.link_analysis, network.whois, regex.icontains, regex.iextract, strings.ends_with, strings.icontains, strings.parse_url, strings.replace_confusables. Reference lists: $free_file_hosts, $free_subdomain_hosts, $org_display_names, $org_domains, $social_landing_hosts, $suspicious_tlds, $tranco_10k, $url_shorteners.

Indicators matched (18)

FieldMatchValue
sender.email.domain.domainequalsgoogle.com
sender.email.local_partequalsdrive-shares-noreply
sender.email.local_partequalsdrive-shares-dm-noreply
strings.ends_withsuffixdoclist.bounces.google.com
regex.iextractregex^(?P<sender_display_name>.*)\((?:via )?Google
strings.icontainssubstringinvited you to edit
regex.icontainsregex: \".*(?:Immediate|Urgent|Critical|Alert|Warning|Urgent|Important|Critical Alert|Security Notice)[!:\-]?[^\"]*\"
regex.icontainsregex: \".*(?:Online|Bank(?:ing)?|User|Account|Access|[[:punct:]\s]?(?:ID)|Transactions)\b.*\b(?:Security|Recover|Blocked|Suspen(?:ded|sion)|Restricted|Locked|Disabled|Frozen|Closed)[^\"]*\"
regex.icontainsregex: \".*(Suspicious|Unauthorized|Unrecognized|Fraudulent|Scam)\b.*\b(Activity|Transaction|Log[- ]?In|Access|Entry|Sign[- ]?In|Detected)[^\"]*\"
regex.icontainsregex: \".*(?:(?:Verify|Confirm|Update|Review|Complete)\b.*\b(Your (Identity|Account|Online[- ]?ID|Billing Information))|(?:(?:Action|Attention|Verification|Review)[[:punct:]\s](?:Needed|Required)))[^\"]*\"
regex.icontainsregex: \".*[[:punct:]\s]+\w+[[:punct:]\s]*[a-zA-Z]*[0-9][a-zA-Z0-9]*\"$
regex.icontainsregex[[:punct:]]\s*[a-z0-9]{5,}\"$
6 more
body.links[].href_url.domain.domainequalsdrive.google.com
strings.icontainssubstring/view
body.links[].display_textequalsOpen
strings.icontainssubstringYou can't access this item because it is in violation of our Terms of Service
ml.link_analysis(filter(body.links)[], mode='aggressive').additional_responses[].url.pathequals/viewerng/presspage
regex.icontainsregex(?:view|click|show|access|download|continue|goto|Validate|Va[il]idar|login|verify|account)