Skip to content

Update paypal_invoice_abuse.yml #2684

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 117 additions & 143 deletions detection-rules/paypal_invoice_abuse.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,153 +17,127 @@ source: |
"paypal.com.ar",
"paypal.co.uk"
)
and (
strings.ilike(body.html.display_text, "*seller note*")
or strings.ilike(body.html.display_text, "*Note from *")
or strings.ilike(body.html.display_text, "*Address Updated:*")
// payment notificiations that are sent to a recipient which is not the mailbox id
// attempts to include ones amplified via a DL
or (
strings.ilike(body.html.display_text, "*You Sent *")
and all(recipients.to,
.email.domain.domain not in $org_domains
and .email.email != mailbox.email.email
)
)
// phone number in subject
// the subject contains the seller's "name", attacks have been seen with the entire callback text in the seller's name
or (
regex.icontains(strings.replace_confusables(subject.subject),
'.*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*'
)
or regex.icontains(strings.replace_confusables(subject.subject),
'.*\+[ilo0-9]{1,3}[ilo0-9]{10}.*'
)
or // +12028001238
regex.icontains(strings.replace_confusables(subject.subject),
'.*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*'
)
or // 202-800-1238
regex.icontains(strings.replace_confusables(subject.subject),
'.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*'
)
or // (202) 800-1238
regex.icontains(strings.replace_confusables(subject.subject),
'.*\([ilo0-9]{3}\)\s[ilo0-9]{3}-[ilo0-9]{4}.*'
)
or // (202)-800-1238
regex.icontains(strings.replace_confusables(subject.subject),
'.*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*'
)
or ( // 8123456789
regex.icontains(strings.replace_confusables(subject.subject),
'.*8[ilo0-9]{9}.*'
)
and regex.icontains(strings.replace_confusables(subject.subject),
'\+[1l]'
)
)
)
)
// keep in sync with https://github.com/sublime-security/sublime-rules/blob/main/detection-rules/callback_phishing_sumup.yml
and (
(
// icontains a phone number
(
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}.*\n'
)
or regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\+[ilo0-9]{1,3}[ilo0-9]{10}.*\n'
)
or // +12028001238
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}.*\n'
)
or // 202-800-1238
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}.*\n'
)
or // (202) 800-1238
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\([ilo0-9]{3}\)\s[ilo0-9]{3}-[ilo0-9]{4}.*\n'
)
or // (202)-800-1238
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}.*\n'
)
or ( // 8123456789
regex.icontains(strings.replace_confusables(body.current_thread.text),
'.*8[ilo0-9]{9}.*\n'
)
and regex.icontains(strings.replace_confusables(body.current_thread.text
),
'\+[1l]'
)
)
)
and (
(
4 of (
strings.ilike(body.html.inner_text, '*you did not*'),
strings.ilike(body.html.inner_text, '*is not for*'),
strings.ilike(body.html.inner_text, '*done by you*'),
regex.icontains(body.html.inner_text, "didn\'t ma[kd]e this"),
strings.ilike(body.html.inner_text, '*Fruad Alert*'),
strings.ilike(body.html.inner_text, '*Fraud Alert*'),
strings.ilike(body.html.inner_text, '*fraudulent*'),
strings.ilike(body.html.inner_text, '*using your PayPal*'),
strings.ilike(body.html.inner_text, '*subscription*'),
strings.ilike(body.html.inner_text, '*antivirus*'),
strings.ilike(body.html.inner_text, '*order*'),
strings.ilike(body.html.inner_text, '*support*'),
strings.ilike(body.html.inner_text, '*sincerely apologize*'),
strings.ilike(body.html.inner_text, '*receipt*'),
strings.ilike(body.html.inner_text, '*invoice*'),
strings.ilike(body.html.inner_text, '*Purchase*'),
strings.ilike(body.html.inner_text, '*transaction*'),
strings.ilike(body.html.inner_text, '*Market*Value*'),
strings.ilike(body.html.inner_text, '*BTC*'),
strings.ilike(body.html.inner_text, '*call*'),
strings.ilike(body.html.inner_text, '*get in touch with our*'),
strings.ilike(body.html.inner_text, '*quickly inform*'),
strings.ilike(body.html.inner_text, '*quickly reach *'),
strings.ilike(body.html.inner_text, '*detected unusual transactions*'),
strings.ilike(body.html.inner_text, '*without your authorization*'),
strings.ilike(body.html.inner_text, '*cancel*'),
strings.ilike(body.html.inner_text, '*renew*'),
strings.ilike(body.html.inner_text, '*refund*'),
strings.ilike(body.html.inner_text, '*+1*'),
regex.icontains(body.html.inner_text, 'help.{0,3}desk'),
strings.ilike(body.html.inner_text, '* your funds*'),
strings.ilike(body.html.inner_text, '* your checking*'),
strings.ilike(body.html.inner_text, '* your saving*'),
strings.ilike(body.html.inner_text, '*transfer*'),
strings.ilike(body.html.inner_text, '*secure your account*'),
strings.ilike(body.html.inner_text, '*recover your*'),
strings.ilike(body.html.inner_text, '*unusual activity*'),
strings.ilike(body.html.inner_text, '*suspicious transaction*'),
strings.ilike(body.html.inner_text, '*transaction history*'),
strings.ilike(body.html.inner_text, '*please ignore this*'),
strings.ilike(body.html.inner_text, '*report activity*'),
and any(filter(beta.html_xpath(body.html,
// all the tables, which don't have descendant tables, after the first image and before a hr with a footerDivider class that appears after the current table.
// using //text()[normalize-space()] allows us to split each table up by line breaks, so each line can be inspected uniquely
'//img[@alt="PayPal"]/following::table[not(descendant::table) and count(following::hr[@class="footerDivider"]) > 0]//text()[normalize-space()]'
).nodes,
(
// icontains a phone number
(
regex.icontains(strings.replace_confusables(.display_text),
'\b\+?([ilo0-9]{1}.)?\(?[ilo0-9]{3}?\)?.[ilo0-9]{3}.?[ilo0-9]{4}\b'
)
or regex.icontains(strings.replace_confusables(.display_text),
'\+[ilo0-9]{1,3}[ilo0-9]{10}'
)
or // +12028001238
regex.icontains(strings.replace_confusables(.display_text),
'[ilo0-9]{3}\.[ilo0-9]{3}\.[ilo0-9]{4}'
)
or // 202-800-1238
regex.icontains(strings.replace_confusables(.display_text),
'[ilo0-9]{3}-[ilo0-9]{3}-[ilo0-9]{4}'
)
or // (202) 800-1238
regex.icontains(strings.replace_confusables(.display_text),
'\([ilo0-9]{3}\)\s[ilo0-9]{3}-[ilo0-9]{4}'
)
or // (202)-800-1238
regex.icontains(strings.replace_confusables(.display_text),
'\([ilo0-9]{3}\)-[ilo0-9]{3}-[ilo0-9]{4}'
)
or ( // 8123456789
regex.icontains(strings.replace_confusables(.display_text),
'8[ilo0-9]{9}'
)
and regex.icontains(strings.replace_confusables(.display_text
),
'\+[1l]'
)
)
)
)
// filter out elements which contain non actor controlled details
// this often wording from paypal templates that might contain phone numbers
// but are not elements that are actor controlled.

// main customer service number
and not strings.icontains(.display_text, '888-221-1161')
// credit services number
and not strings.icontains(.display_text, '844-896-4937')
// pay in 4 number
and not strings.icontains(.display_text, '(800) 504-7534')
// often the transcation id looks like a phone number and matches the regex
and not regex.icontains(.display_text, "Transaction (date|ID)\n")
// this segment can include phone numbers, but the wording is not actor controlled and shows up "under the fold" in the templates
and not strings.istarts_with(.display_text, "If you have any questions about this payment, you can")
),
strings.icontains(.display_text, "you did not")
or strings.icontains(.display_text, "Critical Alert")
or strings.icontains(.display_text, "is not for")
or strings.icontains(.display_text, "done by you")
or regex.icontains(.display_text, "don['’]t recognize")
or regex.icontains(.display_text, "didn['’]t (?:ma[kd]e|place) this")
or regex.icontains(.display_text, "[wh]as.*placed by you")
or strings.icontains(.display_text, "issue with")
or regex.icontains(.display_text, "was.*made by you")
or (
strings.icontains(.display_text, "Fraud")
and strings.icontains(.display_text, "Alert")
)
)
or regex.icontains(body.current_thread.text,
'note from.{0,50}(?:call|reach|contact|paypal)'
)
or any(ml.nlu_classifier(body.current_thread.text).intents,
.name == "callback_scam"
)
or (
or strings.icontains(.display_text, "fraudulent")
or strings.icontains(.display_text, "using your PayPal")
or strings.icontains(.display_text, "subscription")
or strings.icontains(.display_text, "antivirus")
or strings.icontains(.display_text, "support")
or strings.icontains(.display_text, "sincerely apologize")
or strings.icontains(.display_text, "receipt")
// pull in common wording from transaction types from paypal
// this wording should be part of the template and not actor controlled
// but is generally prepended or appended with actor controlled elements
// such as using the business name to deliver callback details
// when a phone number is present
or strings.icontains(.display_text, "sent you an invoice")
or strings.icontains(.display_text, "a money request")
or strings.icontains(.display_text, "invited you as a developer")

//
or strings.icontains(.display_text, "Purchase")
or strings.icontains(.display_text, "Market*Value")
or strings.icontains(.display_text, "BTC")
or strings.icontains(.display_text, "Etherium (ETH)")
or strings.icontains(.display_text, "get in touch with our")
or strings.icontains(.display_text, "quickly inform")
or strings.icontains(.display_text, "quickly reach ")
or strings.icontains(.display_text, "detected unusual transactions")
or strings.icontains(.display_text, "without your authorization")
or strings.icontains(.display_text, "unauthorized activitiy")
or strings.icontains(.display_text, "unauthorized transaction")
or strings.icontains(.display_text, "cancel")
or strings.icontains(.display_text, "renew")
or strings.icontains(.display_text, "refund")
or regex.icontains(.display_text, 'help.{0,3}desk')
or strings.icontains(.display_text, " your funds")
or strings.icontains(.display_text, " your checking")
or strings.icontains(.display_text, " your saving")
or strings.icontains(.display_text, "secure your account")
or strings.icontains(.display_text, "recover your")
or strings.icontains(.display_text, "unusual activity")
or strings.icontains(.display_text, "suspicious transaction")
or strings.icontains(.display_text, "transaction history")
or strings.icontains(.display_text, "please ignore this")
or strings.icontains(.display_text, "will be approved")
or strings.icontains(.display_text, "report activity")

// Unicode confusables words obfuscated in note
regex.icontains(body.html.inner_text,
'\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹'
or regex.icontains(.display_text,
'\+𝟭|𝗽𝗮𝘆𝗺𝗲𝗻𝘁|𝗛𝗲𝗹𝗽 𝗗𝗲𝘀𝗸|𝗿𝗲𝗳𝘂𝗻𝗱|𝗮𝗻𝘁𝗶𝘃𝗶𝗿𝘂𝘀|𝗰𝗮𝗹𝗹|𝗰𝗮𝗻𝗰𝗲𝗹|𝗰𝗼𝗻𝘁𝗮𝗰𝘁|cᴀʟʟ'
)
or strings.icontains(.display_text, "kindly")
or regex.icontains(strings.replace_confusables(.display_text),
'(?:call|cᴀʟʟ|reach|contact|get in touch|inform|let us know)'
)
)
or strings.ilike(body.html.inner_text, '*kindly*')
)
)
)
attack_types:
- "BEC/Fraud"
Expand Down
Loading