Detection rules › Sublime MQL

DLP - PCI: Visa Credit Card Number

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

Detects outbound emails containing Visa credit card numbers in the message body or text-parseable attachments. Visa card numbers begin with 4 and are 13 or 16 digits long, optionally separated by spaces or dashes (e.g. 4111 1111 1111 1111 or 4111-1111-1111-1111). Deploy this rule with the "Block Delivery" action to prevent PCI data exfiltration, or in passive mode to monitor and audit outbound mail containing card numbers. Regex engine: RE2 (Golang). No PCRE lookbehind — word boundaries (\b) are used instead. Attachment content is extracted via file.explode() / .scan.strings.strings.

Event coverage

Rule body MQL

type.outbound
and (
  // Body: Visa 16-digit (4XXX XXXX XXXX XXXX or 4XXX-XXXX-XXXX-XXXX)
  regex.contains(body.current_thread.text,
    '\b4\d{3}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b'
  )

  // Body: Visa 13-digit legacy (4XXX XXXX XXXXX)
  or regex.contains(body.current_thread.text,
    '\b4\d{3}[\s-]?\d{4}[\s-]?\d{5}\b'
  )

  // Attachments: scan extracted strings from PDFs, Office docs, CSVs, etc.
  or any(attachments,
    .file_extension in~ ('pdf', 'doc', 'docx', 'xls', 'xlsx', 'txt', 'csv', 'eml', 'msg')
    and any(file.explode(.),
      any(.scan.strings.strings,
        regex.contains(., '\b4\d{3}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b')
        or regex.contains(., '\b4\d{3}[\s-]?\d{4}[\s-]?\d{5}\b')
      )
    )
  )
)

Detection logic

Scope: outbound message.

Detects outbound emails containing Visa credit card numbers in the message body or text-parseable attachments. Visa card numbers begin with 4 and are 13 or 16 digits long, optionally separated by spaces or dashes (e.g. 4111 1111 1111 1111 or 4111-1111-1111-1111). Deploy this rule with the "Block Delivery" action to prevent PCI data exfiltration, or in passive mode to monitor and audit outbound mail containing card numbers. Regex engine: RE2 (Golang). No PCRE lookbehind — word boundaries (\b) are used instead. Attachment content is extracted via file.explode() / .scan.strings.strings.

  1. outbound message
  2. any of:
    • body.current_thread.text matches '\\b4\\d{3}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b'
    • body.current_thread.text matches '\\b4\\d{3}[\\s-]?\\d{4}[\\s-]?\\d{5}\\b'
    • any of attachments where all hold:
      • .file_extension in ('pdf', 'doc', 'docx', 'xls', 'xlsx', 'txt', 'csv', 'eml', 'msg')
      • any of file.explode(.) where:
        • any of .scan.strings.strings where any holds:
          • . matches '\\b4\\d{3}[\\s-]?\\d{4}[\\s-]?\\d{4}[\\s-]?\\d{4}\\b'
          • . matches '\\b4\\d{3}[\\s-]?\\d{4}[\\s-]?\\d{5}\\b'

Inspects: attachments[].file_extension, body.current_thread.text, type.outbound. Sensors: file.explode, regex.contains.

Indicators matched (11)

FieldMatchValue
regex.containsregex\b4\d{3}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b
regex.containsregex\b4\d{3}[\s-]?\d{4}[\s-]?\d{5}\b
attachments[].file_extensionmemberpdf
attachments[].file_extensionmemberdoc
attachments[].file_extensionmemberdocx
attachments[].file_extensionmemberxls
attachments[].file_extensionmemberxlsx
attachments[].file_extensionmembertxt
attachments[].file_extensionmembercsv
attachments[].file_extensionmembereml
attachments[].file_extensionmembermsg