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            // add confidence to these strings by using profile.by_sender()
 15            and (
 16              not profile.by_sender().solicited
 17              and profile.by_sender().prevalence in ('new', 'outlier')
 18            )
 19          )
 20          or 
 21          // look at the final_dom.raw
 22          // if the page has been taken down, match
 23          strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 24                            'This form was blocked due to privacy or safety concerns.'
 25          )
 26          // this error has been shown before with the text "Phishing form from content scan. Inner Message: This form has been flagged for potential phishing."
 27          or any(ml.link_analysis(., mode="aggressive").additional_responses,
 28                 strings.icontains(.json["error"]["message"], "phishing")
 29          )
 30          // or MS thinks there are phishing keywords
 31          or any(ml.link_analysis(., mode="aggressive").additional_responses,
 32                 any(.json["form"]["questions"],
 33                     .["subtitleHasPhishingKeywords"] == true
 34                 )
 35                 or any(.json["form"]["questions"],
 36                        .["titleHasPhishingKeywords"] == true
 37                 )
 38                 or any(.json["form"]["descriptiveQuestions"],
 39                        .["titleHasPhishingKeywords"] == true
 40                 )
 41                 or any(.json["form"]["descriptiveQuestions"],
 42                        .["titleHasPhishingKeywords"] == true
 43                 )
 44          )
 45          // this logic checks for three abnormal cases
 46          // 1) no questions
 47          // 2) questions, but no inputs
 48          // 3) a bunch of new lines (used to push down the submit button of the form)
 49          // AND 
 50          // // there is one or two links that isn't "standard" on the form
 51          or (
 52            (
 53              // 1) doesn't contain any sections or questions
 54              any(ml.link_analysis(., mode="aggressive").additional_responses,
 55                  length(.json["form"]["descriptiveQuestions"]) == 0
 56                  and length(.json["form"]["questions"]) == 0
 57              )
 58              or 
 59              // 2) Contains a form section header, but no actual inputs
 60              // possible question types are .Choice, .TextField, .Rating, .DateTime, .Ranking, .MatrixChoiceGroup, .MatrixChoice, and .NPS
 61              any(ml.link_analysis(., mode="aggressive").additional_responses,
 62                  length(.json["form"]["descriptiveQuestions"]) > 0
 63                  and length(.json["form"]["questions"]) == 0
 64              )
 65              or 
 66              // 3) a bunch of new lines (used to push down the submit button of the form)
 67              (
 68                strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 69                               '<br><br>'
 70                ) > 20
 71                or strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 72                                  '\n\n'
 73                ) > 20
 74                or strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 75                                  '<span><span>'
 76                ) > 20
 77                or any(ml.link_analysis(., mode="aggressive").additional_responses,
 78                       any(.json["form"]["questions"],
 79                           strings.icount(.["formsProRTQuestionTitle"],
 80                                          '<br><br>'
 81                           ) > 20
 82                           or strings.icount(.["formsProRTQuestionTitle"], '\n\n') > 20
 83                           or strings.icount(.["formsProRTQuestionTitle"],
 84                                             '<span><span>'
 85                           ) > 20
 86                       )
 87                )
 88              )
 89            )
 90            // AND 
 91            and 
 92            // there is one or two links to another page
 93            0 < length(filter(ml.link_analysis(.).final_dom.links,
 94                              not (
 95                                (
 96                                  (
 97                                    .display_text =~ "Privacy and cookies"
 98                                    or .display_text =~ "terms of use"
 99                                    or .display_text =~ "report abuse"
100                                  )
101                                  and .href_url.domain.root_domain =~ 'microsoft.com'
102                                )
103                                or .href_url.domain.root_domain =~ sender.email.domain.root_domain
104                                or .href_url.domain.tld == "ms"
105                              )
106                       )
107            ) <= 2
108            and (
109              not strings.contains(ml.link_analysis(., mode="aggressive").final_dom.raw,
110                                   'role="progressbar" aria-label="Page 1 of '
111              )
112              or any(ml.link_analysis(., mode="aggressive").additional_responses,
113                     .json["form"]["progressBarEnabled"] == false
114              )
115            )
116          )
117  )  
118attack_types:
119  - "Credential Phishing"
120tactics_and_techniques:
121  - "Impersonation: Brand"
122  - "Social engineering"
123detection_methods:
124  - "HTML analysis"
125  - "URL analysis"
126  - "Content analysis"
127id: "85a2cd12-af74-5451-8bfb-4f36f71eecb7"
to-top