Detection rules › Sublime MQL

Spam: Attendee list solicitation

Severity
low
Type
rule
Source
github.com/sublime-security/sublime-rules

This rule detects messages claiming to have the attendee list from a specific event, they may list various information such as the number of contacts, the demographic and sample contacts. The messages typically offer to send pricing information upon request.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesSpam

Event coverage

Rule body MQL

type.inbound
and length(body.current_thread.text) < 2000
and length(body.links) < 5
and any(ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics,
        .name in ("Contact List Solicitation", "B2B Cold Outreach")
        and .confidence in ("medium", "high")
)
and (
  (
    (
      any([subject.subject, body.current_thread.text],
          (
            regex.icontains(.,
                            '(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer|Lead)(?:[[:punct:]]*s)?(?:\s\w*){0,9}(?:\blist(?:\b|[^ei])|database)'
            )
            and not (
              regex.icount(.,
                           '(email|contact)(?:[[:punct:]]*s)?(?:\s\w*){0,9}list'
              ) == 1
              and regex.icontains(.,
                                  '(?:unsub|remove|safe|delete|leave|update|part of|be added|safe)[[:punct:]]*s?(?:\s\w*){0,9}(mailing|email|my|sender)(?:\s\w*){0,9}list(?:\b|[^ei])',
                                  'email list(?:\b|[^ei])[[:punct:]]*s?(\s\w*){0,5}(?:unsub|remove|safe|delete|leave|up to date|part of|be added)'
              )
            )
          )
          or regex.icontains(.,
                             '\b(?:list|database)(?:[[:punct:]]*s)?\b(\s\w*){0,9}(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer)s?'
          )
      )
    )
    and (
      regex.icontains(body.current_thread.text,
                      "(?:interest(s|ed)|accessing|purchas|obtain|acuir|sample|provide.{0,10}samples|counts|pricing)"
      )
      or any(body.previous_threads,
             regex.icontains(.text,
                             "(?:interest(s|ed)|accessing|purchas|obtain|acuir|sample|provide.{0,10}samples|counts|pricing)"
             )
      )
    )
    and not regex.icontains(body.current_thread.text,
                            "(?:debit card|transaction.{0,20}processed)"
    )
  )
  // if there are indicators of a previous thread, also inspect the previous thread
  or (
    // contains references to the previous thread
    2 of (
      regex.icontains(body.current_thread.text, '(?:get|got|had) a chance'),
      regex.icontains(body.current_thread.text, '(take|move)(\Wthis)?\Wforward'),
      regex.icontains(body.current_thread.text,
                      '(review|drop me a line about) (my|this|it)'
      ),
      regex.icontains(body.current_thread.text, 'missed it( the)? first time'),
      regex.icontains(body.current_thread.text,
                      '(?:below|previous(ly)?|last|prior|earlier) (message|email|sent)'
      ),
      regex.icontains(body.current_thread.text,
                      // "the email I sent you earlier"
                      '(e?mail|message).{0,20}(sent).{0,20}(?:below|previous(ly)?|last|prior|earlier)'
      ),
      regex.icontains(body.current_thread.text,
                      '(sent).{0,50}(e?mail|message) (?:below|previous(ly)?|last|prior|earlier)'
      ),
      regex.icontains(body.current_thread.text, 'follow(?:ing)?(-| )up'),
      regex.icontains(body.current_thread.text, '(?:contact|attendee)s? list'),
      regex.icontains(body.current_thread.text, '(any|get an) update.{0,50}\?'),
      regex.icontains(body.current_thread.text, '(heard?|circling) back'),
      strings.icontains(body.current_thread.text, 'recently sent'),
      strings.icontains(body.current_thread.text, 'still interested'),
      regex.icontains(body.current_thread.text,
                      'did you (get|receive) (it|my (message|e?mail))'
      ),
      regex.icontains(body.current_thread.text, '(swift|quick|short) response'),
      regex.icontains(body.current_thread.text, 'kindly.{0,30}.interested'),
    )
    and any([body.html.display_text, body.plain.raw],
            (
              3 of (
                strings.icontains(., "from:"),
                strings.icontains(., "to:"),
                strings.icontains(., "sent:"),
                strings.icontains(., "date:"),
                strings.icontains(., "cc:"),
                strings.icontains(., "subject:"),
                strings.icontains(., "--Original Message--")
              )
              or strings.icontains(.,
                                   strings.concat(sender.display_name,
                                                  " <",
                                                  sender.email.email,
                                                  "> wrote:"
                                   )
              )
            )
            // match _after_ the previous thread indciators
            and (
              regex.icontains(.,
                              '(?:from|to|sent|date|cc|subject|wrote):(.|\W)*(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Mailing)(?:[[:punct:]]*s)?(?:\s\w*){0,9}(?:list(?:\b|[^ei])|database)'
              )
              or regex.icontains(.,
                                 '(?:from|to|sent|date|cc|subject|wrote):(.|\W)*(?:list(?:\b|[^ei])|database)(?:[[:punct:]]*s)?(\s\w*){0,9}(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Mailing)s?'
              )
              or (
                2 of (
                  strings.icontains(., "provide counts"),
                  regex.icontains(., "(?:verified|fresh) data"),
                  strings.icontains(., "precise targeting"),
                  strings.icontains(., "deliverability"),
                  regex.icontains(., "target (verticals|regions|criteria)")
                )
                and regex.icontains(., '(?:list(?:\b|[^ei])|database)')
              )
            )
    )
  )
)
// negate Zendesk support tickets
and not any(body.links,
            .href_url.domain.root_domain in ('zendesk.com')
            and .display_text == 'Zendesk'
)
and not profile.by_sender().solicited
and not profile.by_sender().any_messages_benign

Detection logic

Scope: inbound message.

This rule detects messages claiming to have the attendee list from a specific event, they may list various information such as the number of contacts, the demographic and sample contacts. The messages typically offer to send pricing information upon request.

  1. inbound message
  2. length(body.current_thread.text) < 2000
  3. length(body.links) < 5
  4. any of ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics where all hold:
    • .name in ('Contact List Solicitation', 'B2B Cold Outreach')
    • .confidence in ('medium', 'high')
  5. any of:
    • all of:
      • any of [subject.subject, body.current_thread.text] where any holds:
        • all of:
          • . matches '(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer|Lead)(?:[[:punct:]]*s)?(?:\\s\\w*){0,9}(?:\\blist(?:\\b|[^ei])|database)'
          • not:
            • all of:
              • regex.icount(., '(email|contact)(?:[[:punct:]]*s)?(?:\\s\\w*){0,9}list') is 1
              • . matches any of 2 patterns
                • (?:unsub|remove|safe|delete|leave|update|part of|be added|safe)[[:punct:]]*s?(?:\s\w*){0,9}(mailing|email|my|sender)(?:\s\w*){0,9}list(?:\b|[^ei])
                • email list(?:\b|[^ei])[[:punct:]]*s?(\s\w*){0,5}(?:unsub|remove|safe|delete|leave|up to date|part of|be added)
        • . matches '\\b(?:list|database)(?:[[:punct:]]*s)?\\b(\\s\\w*){0,9}(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer)s?'
      • any of:
        • body.current_thread.text matches '(?:interest(s|ed)|accessing|purchas|obtain|acuir|sample|provide.{0,10}samples|counts|pricing)'
        • any of body.previous_threads where:
          • .text matches '(?:interest(s|ed)|accessing|purchas|obtain|acuir|sample|provide.{0,10}samples|counts|pricing)'
      • not:
        • body.current_thread.text matches '(?:debit card|transaction.{0,20}processed)'
    • all of:
      • at least 2 of:
        • body.current_thread.text matches '(?:get|got|had) a chance'
        • body.current_thread.text matches '(take|move)(\\Wthis)?\\Wforward'
        • body.current_thread.text matches '(review|drop me a line about) (my|this|it)'
        • body.current_thread.text matches 'missed it( the)? first time'
        • body.current_thread.text matches '(?:below|previous(ly)?|last|prior|earlier) (message|email|sent)'
        • body.current_thread.text matches '(e?mail|message).{0,20}(sent).{0,20}(?:below|previous(ly)?|last|prior|earlier)'
        • body.current_thread.text matches '(sent).{0,50}(e?mail|message) (?:below|previous(ly)?|last|prior|earlier)'
        • body.current_thread.text matches 'follow(?:ing)?(-| )up'
        • body.current_thread.text matches '(?:contact|attendee)s? list'
        • body.current_thread.text matches '(any|get an) update.{0,50}\\?'
        • body.current_thread.text matches '(heard?|circling) back'
        • body.current_thread.text contains 'recently sent'
        • body.current_thread.text contains 'still interested'
        • body.current_thread.text matches 'did you (get|receive) (it|my (message|e?mail))'
        • body.current_thread.text matches '(swift|quick|short) response'
        • body.current_thread.text matches 'kindly.{0,30}.interested'
      • any of [body.html.display_text, body.plain.raw] where all hold:
        • any of:
          • at least 3 of 7: . contains any of 7 patterns
            • from:
            • to:
            • sent:
            • date:
            • cc:
            • subject:
            • --Original Message--
          • strings.icontains(.)
        • any of:
          • . matches '(?:from|to|sent|date|cc|subject|wrote):(.|\\W)*(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Mailing)(?:[[:punct:]]*s)?(?:\\s\\w*){0,9}(?:list(?:\\b|[^ei])|database)'
          • . matches '(?:from|to|sent|date|cc|subject|wrote):(.|\\W)*(?:list(?:\\b|[^ei])|database)(?:[[:punct:]]*s)?(\\s\\w*){0,9}(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Mailing)s?'
          • all of:
            • at least 2 of:
              • . contains 'provide counts'
              • . matches '(?:verified|fresh) data'
              • . contains 'precise targeting'
              • . contains 'deliverability'
              • . matches 'target (verticals|regions|criteria)'
            • . matches '(?:list(?:\\b|[^ei])|database)'
  6. not:
    • any of body.links where all hold:
      • .href_url.domain.root_domain in ('zendesk.com')
      • .display_text is 'Zendesk'
  7. not:
    • profile.by_sender().solicited
  8. not:
    • profile.by_sender().any_messages_benign

Inspects: body.current_thread.text, body.html.display_text, body.links, body.links[].display_text, body.links[].href_url.domain.root_domain, body.plain.raw, body.previous_threads, body.previous_threads[].text, sender.display_name, sender.email.email, subject.subject, type.inbound. Sensors: ml.nlu_classifier, profile.by_sender, regex.icontains, regex.icount, strings.concat, strings.icontains.

Indicators matched (44)

FieldMatchValue
ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics[].namememberContact List Solicitation
ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics[].namememberB2B Cold Outreach
ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics[].confidencemembermedium
ml.nlu_classifier(coalesce(body.html.display_text, body.plain.raw)).topics[].confidencememberhigh
regex.icontainsregex(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer|Lead)(?:[[:punct:]]*s)?(?:\s\w*){0,9}(?:\blist(?:\b|[^ei])|database)
regex.icountregex(email|contact)(?:[[:punct:]]*s)?(?:\s\w*){0,9}list
regex.icontainsregex(?:unsub|remove|safe|delete|leave|update|part of|be added|safe)[[:punct:]]*s?(?:\s\w*){0,9}(mailing|email|my|sender)(?:\s\w*){0,9}list(?:\b|[^ei])
regex.icontainsregexemail list(?:\b|[^ei])[[:punct:]]*s?(\s\w*){0,5}(?:unsub|remove|safe|delete|leave|up to date|part of|be added)
regex.icontainsregex\b(?:list|database)(?:[[:punct:]]*s)?\b(\s\w*){0,9}(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer)s?
regex.icontainsregex(?:interest(s|ed)|accessing|purchas|obtain|acuir|sample|provide.{0,10}samples|counts|pricing)
regex.icontainsregex(?:debit card|transaction.{0,20}processed)
regex.icontainsregex(?:get|got|had) a chance
32 more
regex.icontainsregex(take|move)(\Wthis)?\Wforward
regex.icontainsregex(review|drop me a line about) (my|this|it)
regex.icontainsregexmissed it( the)? first time
regex.icontainsregex(?:below|previous(ly)?|last|prior|earlier) (message|email|sent)
regex.icontainsregex(e?mail|message).{0,20}(sent).{0,20}(?:below|previous(ly)?|last|prior|earlier)
regex.icontainsregex(sent).{0,50}(e?mail|message) (?:below|previous(ly)?|last|prior|earlier)
regex.icontainsregexfollow(?:ing)?(-| )up
regex.icontainsregex(?:contact|attendee)s? list
regex.icontainsregex(any|get an) update.{0,50}\?
regex.icontainsregex(heard?|circling) back
strings.icontainssubstringrecently sent
strings.icontainssubstringstill interested
regex.icontainsregexdid you (get|receive) (it|my (message|e?mail))
regex.icontainsregex(swift|quick|short) response
regex.icontainsregexkindly.{0,30}.interested
strings.icontainssubstringfrom:
strings.icontainssubstringto:
strings.icontainssubstringsent:
strings.icontainssubstringdate:
strings.icontainssubstringcc:
strings.icontainssubstringsubject:
strings.icontainssubstring--Original Message--
regex.icontainsregex(?:from|to|sent|date|cc|subject|wrote):(.|\W)*(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Mailing)(?:[[:punct:]]*s)?(?:\s\w*){0,9}(?:list(?:\b|[^ei])|database)
regex.icontainsregex(?:from|to|sent|date|cc|subject|wrote):(.|\W)*(?:list(?:\b|[^ei])|database)(?:[[:punct:]]*s)?(\s\w*){0,9}(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Mailing)s?
strings.icontainssubstringprovide counts
regex.icontainsregex(?:verified|fresh) data
strings.icontainssubstringprecise targeting
strings.icontainssubstringdeliverability
regex.icontainsregextarget (verticals|regions|criteria)
regex.icontainsregex(?:list(?:\b|[^ei])|database)
body.links[].href_url.domain.root_domainmemberzendesk.com
body.links[].display_textequalsZendesk