Brand impersonation: SendGrid

Detects inbound messages that impersonate Twilio/SendGrid through display name or domain manipulation, combined with security or authentication-themed content, while failing authentication checks and originating from untrusted sources.

Sublime rule (View on GitHub)

  1name: "Brand impersonation: SendGrid"
  2description: "Detects inbound messages that impersonate Twilio/SendGrid through display name or domain manipulation, combined with security or authentication-themed content, while failing authentication checks and originating from untrusted sources."
  3type: "rule"
  4severity: "medium"
  5source: |
  6  type.inbound
  7  and (
  8    (
  9      // SendGrid impersonation patterns
 10      strings.ilike(strings.replace_confusables(sender.display_name),
 11                    '*sendgrid*'
 12      )
 13      or strings.ilevenshtein(strings.replace_confusables(sender.display_name),
 14                              'sendgrid'
 15      ) <= 1
 16      or regex.icontains(sender.display_name,
 17                         's[\x{2063}\x{200B}]+e[\x{2063}\x{200B}]+n[\x{2063}\x{200B}]+d[\x{2063}\x{200B}]+g[\x{2063}\x{200B}]+r[\x{2063}\x{200B}]+i[\x{2063}\x{200B}]+d'
 18      )
 19      or (
 20        strings.ilike(strings.replace_confusables(sender.email.local_part),
 21                      '*sendgrid*'
 22        )
 23        and (
 24          sender.display_name is null
 25          or strings.ilike(strings.replace_confusables(subject.base),
 26                           '*sendgrid*'
 27          )
 28        )
 29      )
 30      or any(ml.logo_detect(file.message_screenshot()).brands,
 31             .name == "SendGrid" and .confidence == "high"
 32      )
 33    )
 34    or (
 35      // Twilio impersonation patterns
 36      strings.ilike(strings.replace_confusables(sender.display_name), '*twilio*')
 37      or strings.ilevenshtein(strings.replace_confusables(sender.display_name),
 38                              'twilio'
 39      ) <= 1
 40      or (
 41        strings.ilike(strings.replace_confusables(sender.email.local_part),
 42                      '*twilio*'
 43        )
 44        and (
 45          sender.display_name is null
 46          or strings.ilike(strings.replace_confusables(subject.base), '*twilio*')
 47        )
 48      )
 49    )
 50    or strings.icontains(body.current_thread.text, "the sendgrid team")
 51    or 2 of (
 52      regex.icontains(body.current_thread.text, '(?:Twilio|SendGrid)'),
 53      strings.icontains(body.current_thread.text, '1801 California St'),
 54      strings.icontains(body.current_thread.text, 'Denver, CO 80202')
 55    )
 56    // SendGrid content from non-SendGrid marketing platforms
 57    or (
 58      sender.email.domain.root_domain in (
 59        "selfcast.com",
 60        "mailchimp.com",
 61        "constantcontact.com",
 62        "hubspot.com",
 63        "klaviyo.com",
 64        "mailgun.com"
 65      )
 66      and (
 67        (
 68          (
 69            strings.icontains(body.current_thread.text, "sendgrid")
 70            or strings.icontains(subject.base, "sendgrid")
 71          )
 72          and 3 of (
 73            strings.icontains(body.current_thread.text, "webhook"),
 74            strings.icontains(body.current_thread.text, "endpoint"),
 75            strings.icontains(body.current_thread.text, "api"),
 76            strings.icontains(body.current_thread.text, "delivery"),
 77            strings.icontains(body.current_thread.text, "event notification")
 78          )
 79        )
 80        and (
 81          // Look for SendGrid-related content with non-SendGrid tracking links
 82          any(body.links,
 83              strings.icontains(.href_url.url, "selfcast.com")
 84              or (
 85                .display_url.url is not null
 86                and strings.icontains(.display_url.url, "sendgrid.com")
 87              )
 88          )
 89        )
 90      )
 91    )
 92  )
 93  and (
 94    // Content analysis using ML/NLU
 95    any(ml.nlu_classifier(body.current_thread.text).topics,
 96        .name in (
 97          "Security and Authentication",
 98          "Secure Message",
 99          "Reminders and Notifications",
100          "Software and App Updates",
101          "Customer Service and Support"
102        )
103        and .confidence in ("medium", "high")
104    )
105    or any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).topics,
106           .name in (
107             "Security and Authentication",
108             "Secure Message",
109             "Reminders and Notifications",
110             "Software and App Updates",
111             "Customer Service and Support"
112           )
113           and .confidence in ("medium", "high")
114    )
115    or any(ml.nlu_classifier(body.current_thread.text).intents,
116           .name == "cred_theft" and .confidence == "high"
117    )
118    or any(ml.nlu_classifier(beta.ocr(file.message_screenshot()).text).intents,
119           .name == "cred_theft" and .confidence == "high"
120    )
121  
122    // any capacity or limits mentioned
123    or any([subject.base, body.current_thread.text],
124           (strings.icontains(., "capacity") or strings.icontains(., "limit"))
125           and regex.icontains(., '\breach(?:\b|ed)')
126    )
127  )
128  
129  // and the sender is not in org_domains or from sendgrid domains and passes auth
130  and not (
131    sender.email.domain.valid
132    and (
133      sender.email.domain.root_domain in $org_domains
134      or (
135        sender.email.domain.root_domain in (
136          "sendgrid.com",
137          "sendgrid.net",
138          "twilio.com",
139          "swoogo.com", // events planning software used by Twillio
140          "sendsafely.com", // secure delivery used by Twillio
141          "evolve.com", // same address as Twillio
142          "sendgridsolutions.com"
143        )
144      )
145    )
146    and headers.auth_summary.dmarc.pass
147  )
148  // negate highly trusted sender domains unless they fail DMARC authentication
149  and not (
150    sender.email.domain.root_domain in $high_trust_sender_root_domains
151    and coalesce(headers.auth_summary.dmarc.pass, false)
152  )
153  and not profile.by_sender().solicited  
154attack_types:
155  - "BEC/Fraud"
156  - "Credential Phishing"
157  - "Spam"
158tactics_and_techniques:
159  - "Impersonation: Brand"
160  - "Social engineering"
161detection_methods:
162  - "Content analysis"
163  - "Header analysis"
164  - "Natural Language Understanding"
165  - "Optical Character Recognition"
166  - "Sender analysis"
167id: "d800124f-6aa4-58e1-8fa7-beec4958924f"
to-top