Request for Quote or Purchase (RFQ|RFP) with suspicious sender or recipient pattern

RFQ/RFP scams involve fraudulent emails posing as legitimate requests for quotations or purchases, often sent by scammers impersonating reputable organizations. These scams aim to deceive recipients into providing sensitive information or conducting unauthorized transactions, often leading to financial loss, or data leakage.

Sublime rule (View on GitHub)

  1name: "Request for Quote or Purchase (RFQ|RFP) with suspicious sender or recipient pattern"
  2description: |
  3  RFQ/RFP scams involve fraudulent emails posing as legitimate requests for quotations or purchases, often sent by scammers impersonating reputable organizations.
  4  These scams aim to deceive recipients into providing sensitive information or conducting unauthorized transactions, often leading to financial loss, or data leakage.  
  5type: "rule"
  6severity: "medium"
  7source: |
  8  type.inbound
  9  and 1 of (
 10    (
 11      (
 12        length(recipients.to) == 0
 13        or all(recipients.to,
 14               .display_name in (
 15                 "Undisclosed recipients",
 16                 "undisclosed-recipients"
 17               )
 18        )
 19      )
 20      and length(recipients.cc) == 0
 21      and length(recipients.bcc) == 0
 22    ),
 23    (
 24      sender.email.domain.root_domain in $free_email_providers
 25      and any(headers.reply_to, .email.email != sender.email.email)
 26      and any(headers.reply_to, .email.email not in $recipient_emails)
 27    ),
 28    (
 29      length(headers.reply_to) > 0
 30      and all(headers.reply_to,
 31              .email.domain.root_domain != sender.email.domain.root_domain
 32      )
 33    )
 34  )
 35  and (
 36    2 of (
 37      (
 38        regex.icontains(body.current_thread.text,
 39                        '(discuss.{0,15}purchas(e|ing))'
 40        )
 41      ),
 42      (
 43        regex.icontains(body.current_thread.text,
 44                        '(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)'
 45        )
 46      ),
 47      (
 48        regex.icontains(body.current_thread.text,
 49                        '(please|kindly).{0,30}quot(e|ation)'
 50        )
 51      ),
 52      (
 53        regex.icontains(subject.subject,
 54                        '(request for (purchase|quot(e|ation))|\bRFQ\b|\bRFP\b|bid invit(e|ation))'
 55        )
 56      ),
 57      (
 58        any(attachments,
 59            regex.icontains(.file_name, "(purchase.?order|Quot(e|ation))")
 60        )
 61      ),
 62      (
 63        any(ml.nlu_classifier(body.current_thread.text).entities,
 64            .name == "request"
 65        )
 66        and any(ml.nlu_classifier(body.current_thread.text).entities,
 67                .name == "urgency"
 68        )
 69      ),
 70      (
 71        any(ml.nlu_classifier(body.current_thread.text).tags,
 72            .name == "purchase_order" and .confidence == "high"
 73        )
 74      ),
 75      (
 76        0 < length(filter(body.links,
 77                          (
 78                            .href_url.domain.domain in $free_subdomain_hosts
 79                            or .href_url.domain.domain in $free_file_hosts
 80                            or network.whois(.href_url.domain).days_old < 30
 81                          )
 82                          and (
 83                            regex.match(.display_text, '[A-Z ]+')
 84                            or any(ml.nlu_classifier(.display_text).entities,
 85                                   .name in ("request", "urgency")
 86                            )
 87                          )
 88                   )
 89        ) < 3
 90      )
 91    )
 92    or (
 93      length(attachments) == 1
 94      and length(body.current_thread.text) < 100
 95      and all(attachments,
 96              .file_type in $file_types_images
 97              and any(file.explode(.),
 98                      2 of (
 99                        regex.icontains(.scan.ocr.raw,
100                                        '(discuss.{0,15}purchas(e|ing))'
101                        ),
102                        regex.icontains(.scan.ocr.raw,
103                                        '(sign(ed?)|view).{0,10}(purchase order)|Request for a Quot(e|ation)'
104                        ),
105                        regex.icontains(.scan.ocr.raw,
106                                        '(please|kindly).{0,30}quote'
107                        ),
108                        (
109                          any(ml.nlu_classifier(.scan.ocr.raw).entities,
110                              .name == "request"
111                          )
112                          and any(ml.nlu_classifier(.scan.ocr.raw).entities,
113                                  .name == "urgency"
114                          )
115                        ),
116                        any(ml.nlu_classifier(.scan.ocr.raw).tags,
117                            .name == "purchase_order" and .confidence == "high"
118                        )
119                      )
120              )
121      )
122    )
123  )
124  
125  // negate highly trusted sender domains unless they fail DMARC authentication
126  and (
127    (
128      sender.email.domain.root_domain in $high_trust_sender_root_domains
129      and not headers.auth_summary.dmarc.pass
130    )
131    or sender.email.domain.root_domain not in $high_trust_sender_root_domains
132  )
133  and not profile.by_sender().solicited
134  and not profile.by_sender().any_false_positives  
135
136attack_types:
137  - "BEC/Fraud"
138tactics_and_techniques:
139  - "Evasion"
140  - "Free email provider"
141detection_methods:
142  - "Content analysis"
143  - "Natural Language Understanding"
144  - "URL analysis"
145id: "2ac0d329-c1fb-5c87-98dd-ea3e5b85377a"
to-top