Link: Display text matches subject line

Message with short body text contains a single link where the display text matches the subject line. The link is deceptive and the recipient patterns are unusual, such as the recipient's address appearing in the body or undisclosed recipients being used.

Sublime rule (View on GitHub)

  1name: "Link: Display text matches subject line"
  2description: "Message with short body text contains a single link where the display text matches the subject line. The link is deceptive and the recipient patterns are unusual, such as the recipient's address appearing in the body or undisclosed recipients being used."
  3type: "rule"
  4severity: "medium"
  5source: |
  6  type.inbound
  7  
  8  // short body
  9  and length(body.current_thread.text) < 1500
 10  
 11  // suspicious recipient patterns
 12  and (
 13    // recipient email is contained within the body
 14    (
 15      length(recipients.to) == 1
 16      and all(recipients.to,
 17              strings.icontains(body.current_thread.text, .email.email)
 18      )
 19    )
 20    // the sender is the recipient
 21    or sender.email.email in map(recipients.to, .email.email)
 22    // none of the recipients are valid (generally undisclosed recipients)
 23    or not all(recipients.to, .email.domain.valid)
 24  )
 25  // few overall links
 26  and length(body.links) < 10
 27  // none of the links are unsubscribe links
 28  and not any(body.links,
 29              strings.icontains(.display_text, 'unsub')
 30              or strings.icontains(.href_url.url, 'unsub')
 31              or strings.icontains(.display_text, 'optout')
 32              or strings.icontains(.href_url.url, 'optout')
 33              or strings.icontains(.display_text, 'subscription')
 34              // google confidential email use the subject as a link
 35              or .href_url.domain.domain == "confidential-mail.google.com"
 36  )
 37  
 38  // even fewer links which are
 39  and 0 < length(filter(body.links,
 40                        // not related to the sender domain
 41                        .href_url.domain.root_domain != sender.email.domain.root_domain
 42                        // not related to the recipient domain
 43                        and not any(recipients.to,
 44                                    .email.domain.root_domain == ..href_url.domain.root_domain
 45                        )
 46                        // filter out links common in signatures
 47                        and not .href_url.domain.root_domain in (
 48                          "facebook.com",
 49                          "instagram.com",
 50                          'twitter.com',
 51                          'x.com'
 52                        )
 53                        // do not contain a display_text (TP samples have the display_text of the subject)
 54                        // // this removes domains found in signatures
 55                        and .display_text is not null
 56                        // not the aka.ms in warning banners
 57                        and not .href_url.domain.domain == "aka.ms"
 58                 )
 59  ) <= 3
 60  
 61  // exactly one link with display text that matches the subject
 62  and length(filter(body.links, subject.subject =~ .display_text)) == 1
 63  and (
 64    // the link with the display_text of the subject
 65    any(filter(body.links, subject.subject =~ .display_text),
 66        // when visited is phishing
 67        ml.link_analysis(.).credphish.disposition == "phishing"
 68        or ml.link_analysis(.).final_dom.display_text == "Verify you are human"
 69        or .href_url.domain.domain in $self_service_creation_platform_domains
 70        or .href_url.domain.domain in $url_shorteners
 71    )
 72    // or the body is cred_theft
 73    or any(ml.nlu_classifier(body.current_thread.text).intents,
 74           .name == "cred_theft"
 75    )
 76  )
 77  
 78  // the display text of a link is the subject
 79  and subject.subject in map(body.links, .display_text)
 80  
 81  // exclude common in signup links/password resets which are observed in links all the time
 82  and not (
 83    strings.icontains(subject.subject, 'confirm')
 84    or strings.icontains(subject.subject, 'activate')
 85    or strings.icontains(subject.subject, 'reset')
 86    or strings.icontains(subject.subject, 'unlock')
 87    or strings.icontains(subject.subject, 'login')
 88    or strings.icontains(subject.subject, 'log in')
 89  )  
 90attack_types:
 91  - "BEC/Fraud"
 92  - "Credential Phishing"
 93tactics_and_techniques:
 94  - "Social engineering"
 95  - "Evasion"
 96detection_methods:
 97  - "Header analysis"
 98  - "Content analysis"
 99  - "Natural Language Understanding"
100  - "URL analysis"
101id: "ba722cf0-b94e-55d2-b29a-df6fab80a164"
to-top