Link: Multistage landing - Microsoft Forms abuse

The detection rule matches on message groups which make use of Microsoft Forms as a landing page. The landing page contains links which are newly registered, use free file or subdomain hosts, URL shorteners or when visited are phishing pages, lead to a captcha or redirect to a top website.

Sublime rule (View on GitHub)

  1name: "Link: Multistage landing - Microsoft Forms abuse"
  2description: "The detection rule matches on message groups which make use of Microsoft Forms as a landing page. The landing page contains links which are newly registered, use free file or subdomain hosts, URL shorteners or when visited are phishing pages, lead to a captcha or redirect to a top website."
  3type: "rule"
  4severity: "high"
  5source: |
  6  type.inbound
  7  and any(filter(body.links, .href_url.domain.domain == "forms.office.com"),
  8          // avoid doing Link Analysis if the display-text has strong indications of phishing
  9          (
 10            // replace confusables - observed ITW
 11            regex.icontains(strings.replace_confusables(.display_text),
 12                            'review|proposal|document|efax|restore|[o0]pen|secure|messaging|reset|account|verify|login|notification|alert|urgent|immediate|access|support|\bupdate\b|download|attachment|service|payment|remittance|invoice'
 13            )
 14            and not regex.icontains(strings.replace_confusables(.display_text),
 15                                  'customer service'
 16            )
 17            // add confidence to these strings by using profile.by_sender()
 18            and (
 19              not profile.by_sender().solicited
 20              and profile.by_sender().prevalence in ('new', 'outlier')
 21            )
 22          )
 23          or 
 24          // look at the final_dom.raw
 25          // if the page has been taken down, match
 26          strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 27                            'This form was blocked due to privacy or safety concerns.'
 28          )
 29          // this error has been shown before with the text "Phishing form from content scan. Inner Message: This form has been flagged for potential phishing."
 30          or any(ml.link_analysis(., mode="aggressive").additional_responses,
 31                 strings.icontains(.json["error"]["message"], "phishing")
 32          )
 33          // or MS thinks there are phishing keywords
 34          or any(ml.link_analysis(., mode="aggressive").additional_responses,
 35                 any(.json["form"]["questions"],
 36                     .["subtitleHasPhishingKeywords"] == true
 37                 )
 38                 or any(.json["form"]["questions"],
 39                        .["titleHasPhishingKeywords"] == true
 40                 )
 41                 or any(.json["form"]["descriptiveQuestions"],
 42                        .["titleHasPhishingKeywords"] == true
 43                 )
 44                 or any(.json["form"]["descriptiveQuestions"],
 45                        .["titleHasPhishingKeywords"] == true
 46                 )
 47          )
 48          // this logic checks for three abnormal cases
 49          // 1) no questions
 50          // 2) questions, but no inputs
 51          // 3) a bunch of new lines (used to push down the submit button of the form)
 52          // AND 
 53          // // there is one or two links that isn't "standard" on the form
 54          or (
 55            (
 56              // 1) doesn't contain any sections or questions
 57              any(ml.link_analysis(., mode="aggressive").additional_responses,
 58                  length(.json["form"]["descriptiveQuestions"]) == 0
 59                  and length(.json["form"]["questions"]) == 0
 60              )
 61              or 
 62              // 2) Contains a form section header, but no actual inputs
 63              // possible question types are .Choice, .TextField, .Rating, .DateTime, .Ranking, .MatrixChoiceGroup, .MatrixChoice, and .NPS
 64              any(ml.link_analysis(., mode="aggressive").additional_responses,
 65                  length(.json["form"]["descriptiveQuestions"]) > 0
 66                  and length(.json["form"]["questions"]) == 0
 67              )
 68              or 
 69              // 3) a bunch of new lines (used to push down the submit button of the form)
 70              (
 71                strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 72                               '<br><br>'
 73                ) > 20
 74                or strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 75                                  '\n\n'
 76                ) > 20
 77                or strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 78                                  '<span><span>'
 79                ) > 20
 80                or any(ml.link_analysis(., mode="aggressive").additional_responses,
 81                       any(.json["form"]["questions"],
 82                           strings.icount(.["formsProRTQuestionTitle"],
 83                                          '<br><br>'
 84                           ) > 20
 85                           or strings.icount(.["formsProRTQuestionTitle"], '\n\n') > 20
 86                           or strings.icount(.["formsProRTQuestionTitle"],
 87                                             '<span><span>'
 88                           ) > 20
 89                       )
 90                )
 91              )
 92            )
 93            // AND 
 94            and 
 95            // there is one or two links to another page
 96            0 < length(filter(ml.link_analysis(.).final_dom.links,
 97                              not (
 98                                (
 99                                  (
100                                    .display_text =~ "Privacy and cookies"
101                                    or .display_text =~ "terms of use"
102                                    or .display_text =~ "report abuse"
103                                  )
104                                  and .href_url.domain.root_domain =~ 'microsoft.com'
105                                )
106                                or .href_url.domain.root_domain =~ sender.email.domain.root_domain
107                                or (
108                                  .href_url.domain.tld == "ms"
109                                  // Microsoft does not own the .ms TLD, this checks to ensure it is one of their domains
110                                  and (
111                                    network.whois(.href_url.domain).registrant_company == "Microsoft Corporation"
112                                    or strings.ilike(network.whois(.href_url.domain).registrar_name,
113                                                     "*MarkMonitor*",
114                                                     "*CSC Corporate*",
115                                                     "*com laude*"
116                                    )
117                                  )
118                                )
119                              )
120                       )
121            ) <= 2
122            and (
123              not strings.contains(ml.link_analysis(., mode="aggressive").final_dom.raw,
124                                   'role="progressbar" aria-label="Page 1 of '
125              )
126              or any(ml.link_analysis(., mode="aggressive").additional_responses,
127                     .json["form"]["progressBarEnabled"] == false
128              )
129            )
130          )
131  )  
132attack_types:
133  - "Credential Phishing"
134tactics_and_techniques:
135  - "Impersonation: Brand"
136  - "Social engineering"
137detection_methods:
138  - "HTML analysis"
139  - "URL analysis"
140  - "Content analysis"
141id: "85a2cd12-af74-5451-8bfb-4f36f71eecb7"
to-top