Attachment: Microsoft 365 credential phishing

Looks for messages with an image attachment that contains words related to Microsoft, Office365, and passwords.

Sublime rule (View on GitHub)

  1name: "Attachment: Microsoft 365 credential phishing"
  2description: |
  3    Looks for messages with an image attachment that contains words related to Microsoft, Office365, and passwords.
  4type: "rule"
  5severity: "high"
  6source: |
  7  type.inbound
  8  and length(filter(attachments, .file_type not in $file_types_images)) == 0
  9  and (
 10    any(attachments,
 11        .file_type in $file_types_images
 12        and any(ml.logo_detect(.).brands, strings.starts_with(.name, "Microsoft"))
 13    )
 14    or any(attachments,
 15           .file_type in $file_types_images
 16           and any(file.explode(.),
 17                   strings.ilike(.scan.ocr.raw, "*microsoft*", "*office")
 18                   and length(.scan.ocr.raw) < 1500
 19           )
 20    )
 21  )
 22  and any(attachments,
 23          .file_type in $file_types_images
 24          and any(file.explode(.),
 25                  length(filter([
 26                                  "password",
 27                                  "unread messages",
 28                                  "Shared Documents",
 29                                  "expiration",
 30                                  "expire",
 31                                  "expiring",
 32                                  "kindly",
 33                                  "renew",
 34                                  "review",
 35                                  "emails failed",
 36                                  "kicked out",
 37                                  "prevented",
 38                                  "storage",
 39                                  "required now",
 40                                  "cache",
 41                                  "qr code",
 42                                  "security update",
 43                                  "invoice",
 44                                  "retrieve",
 45                                  "blocked"
 46                                ],
 47                                strings.icontains(..scan.ocr.raw, .)
 48                         )
 49                  ) >= 2
 50                  or (
 51                    any(ml.nlu_classifier(.scan.ocr.raw).intents,
 52                        .name == "cred_theft" and .confidence == "high"
 53                    )
 54                    and length(ml.nlu_classifier(.scan.ocr.raw).entities) > 1
 55                  )
 56          )
 57  )
 58  and (
 59    not any(headers.hops,
 60            .authentication_results.compauth.verdict is not null
 61            and .authentication_results.compauth.verdict == "pass"
 62            and sender.email.domain.domain in (
 63              "microsoft.com",
 64              "sharepointonline.com"
 65            )
 66    )
 67  )
 68  
 69  // negate angelbeat urls and microsoft disclaimer links
 70  and (
 71    length(body.links) > 0
 72    and not all(body.links,
 73                .href_url.domain.root_domain in (
 74                  "abeatinfo.com",
 75                  "abeatinvite.com",
 76                  "aka.ms",
 77                  "angelbeat.com"
 78                )
 79    )
 80  )
 81  
 82  // negate replies
 83  and (
 84    (
 85      (length(headers.references) > 0 or headers.in_reply_to is null)
 86      and not (
 87        (
 88          strings.istarts_with(subject.subject, "RE:")
 89          or strings.istarts_with(subject.subject, "R:")
 90          or strings.istarts_with(subject.subject, "ODG:")
 91          or strings.istarts_with(subject.subject, "答复:")
 92          or strings.istarts_with(subject.subject, "AW:")
 93          or strings.istarts_with(subject.subject, "TR:")
 94          or strings.istarts_with(subject.subject, "FWD:")
 95          or regex.icontains(subject.subject,
 96                             '^(\[[^\]]+\]\s?){0,3}(re|fwd?)\s?:'
 97          )
 98        )
 99      )
100    )
101    or length(headers.references) == 0
102  )
103  and (
104    not profile.by_sender().solicited
105    or (
106      profile.by_sender().any_messages_malicious_or_spam
107      and not profile.by_sender().any_messages_benign
108    )
109  )
110  
111  // negate highly trusted sender domains unless they fail DMARC authentication
112  and (
113    (
114      sender.email.domain.root_domain in $high_trust_sender_root_domains
115      and not headers.auth_summary.dmarc.pass
116    )
117    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
118  )
119  and not profile.by_sender().any_messages_benign  
120attack_types:
121  - "Credential Phishing"
122tactics_and_techniques:
123  - "Impersonation: Brand"
124  - "Social engineering"
125detection_methods:
126  - "Content analysis"
127  - "File analysis"
128  - "Header analysis"
129  - "Optical Character Recognition"
130  - "Sender analysis"
131id: "edce0229-5e8f-5359-a5c8-36570840049f"
to-top