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 shortners or when visited are phishing pages, lead to a captcha or rediret 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 shortners or when visited are phishing pages, lead to a captcha or rediret 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            any([
 11                  "REVIEW",
 12                  "PROPOSAL",
 13                  "DOCUMENT",
 14                  "PASSWORD",
 15                  "eFax",
 16                  "Restore",
 17                  "OPEN",
 18                  "Secure",
 19                  "Messaging",
 20                  "Reset",
 21                  "Account",
 22                  "Verify",
 23                  "Login",
 24                  "Notification",
 25                  "Alert",
 26                  "Urgent",
 27                  "Immediate",
 28                  "Access",
 29                  "Support",
 30                  "Update",
 31                  "Download",
 32                  "Attachment",
 33                  "Service",
 34                  "Payment",
 35                  "Remittance",
 36                  "Invoice"
 37                ],
 38                // replace confusables - observed ITW
 39                strings.icontains(strings.replace_confusables(..display_text), .)
 40            // add confidence to these strings by using profile.by_sender()
 41            )
 42            and (
 43              not profile.by_sender().solicited
 44              and profile.by_sender().prevalence in ('new', 'outlier')
 45            )
 46          )
 47          or 
 48          // look at the final_dom.raw
 49          // if the page has been taken down, match
 50          strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 51                            'This form was blocked due to privacy or safety concerns.'
 52          )
 53          // this logic checks for three abnormal cases
 54          // 1) no questions
 55          // 2) questions, but no inputs
 56          // 3) a bunch of new lines (used to push down the submit button of the form)
 57          // AND 
 58          // // there is one or two links that isn't "standard" on the form
 59          or (
 60            (
 61              // 1) doesn't contain any descriptive questions or questions
 62              strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 63                                // closes the question-list div
 64                                '<div id="question-list"></div>'
 65              )
 66              or 
 67              // 2) Contains questions, but no inputs
 68              (
 69                // has a question
 70                strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 71                                  // starts a new div
 72                                  'id="question-list"><div>'
 73                )
 74                // no inputs
 75                and not strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 76                                          '<input '
 77                )
 78                // no required fields
 79                and not strings.icontains(ml.link_analysis(., mode="aggressive").final_dom.raw,
 80                                          '<span>Required</span>'
 81                )
 82              )
 83              or 
 84              // 3) a bunch of new lines (used to push down the submit button of the form)
 85              (
 86                strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 87                               '<br><br>'
 88                ) > 20
 89                or strings.icount(ml.link_analysis(., mode="aggressive").final_dom.raw,
 90                                  '\n\n'
 91                ) > 20
 92              )
 93            )
 94            // AND 
 95            and 
 96            // there is one or two links to another page
 97            0 < length(filter(ml.link_analysis(.).final_dom.links,
 98                              .display_text is null
 99                              or (
100                                .display_text !~ "Privacy and cookies"
101                                and .display_text !~ "terms of use"
102                                and .display_text !~ "report abuse"
103                                and .href_url.domain.root_domain != 'microsoft.com'
104                              )
105                       )
106            ) <= 2
107            and not strings.contains(ml.link_analysis(., mode="aggressive").final_dom.raw,
108                                     'role="progressbar" aria-label="Page 1 of '
109            )
110          )
111  )  
112attack_types:
113  - "Credential Phishing"
114tactics_and_techniques:
115  - "Impersonation: Brand"
116  - "Social engineering"
117detection_methods:
118  - "HTML analysis"
119  - "URL analysis"
120  - "Content analysis"
121id: "85a2cd12-af74-5451-8bfb-4f36f71eecb7"
to-top