EXPLORE
← Back to Explore
sublimemediumRule

Attachment: PDF bid/proposal lure with credential theft indicators

Detects single-page PDF attachments containing bid, proposal, RFP, RFQ, or quotation-related lures combined with high-confidence credential theft language or suspicious domains. The rule examines various locations including PDF URLs, OCR content, file names, subject lines, and message body for these indicators.

MITRE ATT&CK

initial-access

Detection Query

type.inbound
// only one attachment
and length(attachments) == 1
// only pdfs with one page
//
// This rule makes use of a beta feature and is subject to change without notice
// using the beta feature in custom rules is not suggested until it has been formally released
//
and any(attachments, .file_type == 'pdf' and beta.parse_exif(.).page_count == 1)
// two of these...
and 2 of (
  // bid/rfp/proposal phrases commonly observed in lures which are in the display text of a url from the pdf
  any(attachments,
      any(file.explode(.),
          any(.scan.url.urls,
              regex.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
                              '(?:\b(?:request|review)\b.{1,5}\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)'
              )
          )
      )
  ),
  (
    // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message
    any([subject.base, sender.display_name, body.current_thread.text],
        regex.icontains(., '\b(?:bid|proposal|rfp|rfq|quotation)\b')
    )
  ),
  // bid/rfp/proposal phrases commonly observed in lures which are in the file name
  any(attachments,
      regex.icontains(.file_name, '\b(?:bid|proposal|rfp|rfq|quotation)\b')
  ),
  any(attachments,
      any(file.explode(.),
          // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf
          regex.icontains(.scan.ocr.raw,
                          '(?:\b(?:request|review)\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)'
          )
      )
  ),
  (
    any(attachments,
        any(file.explode(.),
            any(.scan.url.urls,
                // bid/rfp/proposal phrases commonly observed in lures which are in the url
                regex.icontains(.url,
                                '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'
                )
            )
        )
    )
  )
)

// ocr indicates high confidence cred theft
and (
  any(attachments,
      any(file.explode(.),
          any(ml.nlu_classifier(.scan.ocr.raw).intents,
              .name == 'cred_theft' and .confidence == 'high'
          )
          or any(ml.nlu_classifier(.scan.ocr.raw).topics,
                 .name == 'Purchase Orders' and .confidence == 'high'
          )
      )
  )
  // message body current thread indicates high confidence cred theft
  or any(ml.nlu_classifier(body.current_thread.text).intents,
         .name == 'cred_theft' and .confidence == 'high'
  )
  // message body current thread indicates high confidence cred theft
  or any(ml.nlu_classifier(body.current_thread.text).topics,
         .name == 'Purchase Orders' and .confidence == 'high'
  )
)

// pdf contains some suspicious url domain
and (
  any(attachments,
      any(file.explode(.),
          any(.scan.url.urls,
              .domain.root_domain in $self_service_creation_platform_domains
              or .domain.domain in $self_service_creation_platform_domains
              or .domain.root_domain in $free_file_hosts
              or .domain.domain in $free_file_hosts
              or .domain.root_domain in $free_subdomain_hosts
              or .domain.domain in $free_subdomain_hosts
              or .domain.tld in $suspicious_tlds
              or .domain.domain in $url_shorteners
              or .domain.root_domain in $url_shorteners
          )
      )
  )
)
// we dont want emails where all the links are docusign or dotloop
and not all(body.links,
            .href_url.domain.root_domain in (
              'docusign.net',
              'docusign.com',
              'dotloop.com'
            )
)
// negating solicited senders is necessary due to the nature of the rule
and not profile.by_sender().solicited

// negate workflow robot
and not (
  sender.email.local_part == 'workflow.robot'
  and sender.email.domain.root_domain == 'effem.com'
)

Data Sources

Email MessagesEmail HeadersEmail Attachments

Platforms

email
Raw Content
name: "Attachment: PDF bid/proposal lure with credential theft indicators"
description: "Detects single-page PDF attachments containing bid, proposal, RFP, RFQ, or quotation-related lures combined with high-confidence credential theft language or suspicious domains. The rule examines various locations including PDF URLs, OCR content, file names, subject lines, and message body for these indicators."
type: "rule"
severity: "medium"
source: |
  type.inbound
  // only one attachment
  and length(attachments) == 1
  // only pdfs with one page
  //
  // This rule makes use of a beta feature and is subject to change without notice
  // using the beta feature in custom rules is not suggested until it has been formally released
  //
  and any(attachments, .file_type == 'pdf' and beta.parse_exif(.).page_count == 1)
  // two of these...
  and 2 of (
    // bid/rfp/proposal phrases commonly observed in lures which are in the display text of a url from the pdf
    any(attachments,
        any(file.explode(.),
            any(.scan.url.urls,
                regex.icontains(ml.link_analysis(., mode="aggressive").final_dom.display_text,
                                '(?:\b(?:request|review)\b.{1,5}\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)'
                )
            )
        )
    ),
    (
      // bid/rfp/proposal phrases commonly observed in lures which are in various spots in the message
      any([subject.base, sender.display_name, body.current_thread.text],
          regex.icontains(., '\b(?:bid|proposal|rfp|rfq|quotation)\b')
      )
    ),
    // bid/rfp/proposal phrases commonly observed in lures which are in the file name
    any(attachments,
        regex.icontains(.file_name, '\b(?:bid|proposal|rfp|rfq|quotation)\b')
    ),
    any(attachments,
        any(file.explode(.),
            // bid/rfp/proposal phrases commonly observed in lures which are in the ocr of the pdf
            regex.icontains(.scan.ocr.raw,
                            '(?:\b(?:request|review)\b.{1,5}\\b(?:bid|proposal|rfp|rfq|quotation)\b|\b(?:bid|proposal|rfp|rfq|quotation)\b.{1,5}\b(?:request|review)\b)'
            )
        )
    ),
    (
      any(attachments,
          any(file.explode(.),
              any(.scan.url.urls,
                  // bid/rfp/proposal phrases commonly observed in lures which are in the url
                  regex.icontains(.url,
                                  '(?:bid|proposal|agreement|contract|settlement|RFQ|RFP|quotation)'
                  )
              )
          )
      )
    )
  )
  
  // ocr indicates high confidence cred theft
  and (
    any(attachments,
        any(file.explode(.),
            any(ml.nlu_classifier(.scan.ocr.raw).intents,
                .name == 'cred_theft' and .confidence == 'high'
            )
            or any(ml.nlu_classifier(.scan.ocr.raw).topics,
                   .name == 'Purchase Orders' and .confidence == 'high'
            )
        )
    )
    // message body current thread indicates high confidence cred theft
    or any(ml.nlu_classifier(body.current_thread.text).intents,
           .name == 'cred_theft' and .confidence == 'high'
    )
    // message body current thread indicates high confidence cred theft
    or any(ml.nlu_classifier(body.current_thread.text).topics,
           .name == 'Purchase Orders' and .confidence == 'high'
    )
  )
  
  // pdf contains some suspicious url domain
  and (
    any(attachments,
        any(file.explode(.),
            any(.scan.url.urls,
                .domain.root_domain in $self_service_creation_platform_domains
                or .domain.domain in $self_service_creation_platform_domains
                or .domain.root_domain in $free_file_hosts
                or .domain.domain in $free_file_hosts
                or .domain.root_domain in $free_subdomain_hosts
                or .domain.domain in $free_subdomain_hosts
                or .domain.tld in $suspicious_tlds
                or .domain.domain in $url_shorteners
                or .domain.root_domain in $url_shorteners
            )
        )
    )
  )
  // we dont want emails where all the links are docusign or dotloop
  and not all(body.links,
              .href_url.domain.root_domain in (
                'docusign.net',
                'docusign.com',
                'dotloop.com'
              )
  )
  // negating solicited senders is necessary due to the nature of the rule
  and not profile.by_sender().solicited
  
  // negate workflow robot
  and not (
    sender.email.local_part == 'workflow.robot'
    and sender.email.domain.root_domain == 'effem.com'
  )
attack_types:
  - "BEC/Fraud"
  - "Credential Phishing"
tactics_and_techniques:
  - "PDF"
  - "Social engineering"
  - "Free file host"
  - "Free subdomain host"
detection_methods:
  - "File analysis"
  - "Content analysis"
  - "Optical Character Recognition"
  - "Natural Language Understanding"
  - "URL analysis"
  - "Exif analysis"
id: "7944c428-b0de-5641-9e71-c1590f1c71e5"