diff --git a/detection-rules/spam_attendee_list_solicitation.yml b/detection-rules/spam_attendee_list_solicitation.yml index c08e8d4d2e3..c3f42b9fe9c 100644 --- a/detection-rules/spam_attendee_list_solicitation.yml +++ b/detection-rules/spam_attendee_list_solicitation.yml @@ -4,114 +4,120 @@ type: "rule" severity: "low" source: | type.inbound - and length(body.current_thread.text) < 2000 - and length(body.links) < 5 - and any(beta.ml_topic(coalesce(body.html.display_text, body.plain.raw)).topics, - .name in ("Contact List Solicitation", "B2B Cold Outreach") - and .confidence in ("medium", "high") - ) - and ( + and 4 of ( + length(body.current_thread.text) < 2000, + length(body.links) < 5, + any(beta.ml_topic(coalesce(body.html.display_text, body.plain.raw)).topics, + .name in ("Contact List Solicitation", "B2B Cold Outreach") + and .confidence in ("medium", "high") + ), ( ( - any([subject.subject, body.current_thread.text], - ( - regex.icontains(., - '(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer)(?:[[:punct:]]*s)?(?:\s\w*){0,9}(?:list(?:\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)" - ) - and not regex.icontains(body.current_thread.text, - "(?:debit card|transaction.{0,20}processed|receipt)" - ) - ) - // 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], + ( + any([subject.subject, body.current_thread.text], ( - 3 of ( - strings.icontains(., "from:"), - strings.icontains(., "to:"), - strings.icontains(., "sent:"), - strings.icontains(., "date:"), - strings.icontains(., "cc:"), - strings.icontains(., "subject:"), - strings.icontains(., "--Original Message--") + regex.icontains(., + '(?:Attendee|Buyer|Contact|Decision Maker|Email|Member|Participant|Professional|Registrant|User|Visitor|Store|Grocer)(?:[[:punct:]]*s)?(?:\s\w*){0,9}(?:list(?:\b|[^ei])|database)' ) - or strings.icontains(., - strings.concat(sender.display_name, - " <", - sender.email.email, - "> wrote:" - ) + 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)' + ) ) ) - // 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 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)" + ) + and not regex.icontains(body.current_thread.text, + "(?:debit card|transaction.{0,20}processed|receipt)" + ) + ) + // 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:" + ) + ) ) - 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)") + // 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)') ) - and regex.icontains(., '(?:list(?:\b|[^ei])|database)') ) - ) + ) ) + ), + sender.email.domain.domain in $free_email_providers, + regex.icontains(sender.email.local_part, + '(connect|attend|lead|data|b2b|expo|search|provider|list|prospect|solution|event|trade|show|plan|info|estimat)' ) ) // negate Zendesk support tickets