Attachment: PDF with recipient email in link

Detects PDF attachments that contain the recipient's domain in the filename and include a link personalized with the recipient's email address, either in the URL directly, encoded in base64, or within a QR code.

Sublime rule (View on GitHub)

  1name: "Attachment: PDF with recipient email in link"
  2description: "Detects PDF attachments that contain the recipient's domain in the filename and include a link personalized with the recipient's email address, either in the URL directly, encoded in base64, or within a QR code."
  3type: "rule"
  4severity: "high"
  5source: |
  6  type.inbound
  7  // one or more PDF documents
  8  and length(filter(attachments, .file_type == "pdf")) >= 1
  9  and length(attachments) <= 4
 10  // a single recipient (this is in the link so there can be only one)
 11  and length(recipients.to) == 1
 12  and all(recipients.to, .email.domain.valid)
 13  and any(filter(attachments, .file_type == "pdf"),
 14          (
 15            // the urls in the PDF
 16            any(filter(file.explode(.), .depth == 0),
 17                // remove links we are not interested in
 18                any(filter(.scan.pdf.urls,
 19                           // remove mailto: links
 20                           not strings.istarts_with(.url, 'mailto:')
 21                           and not strings.istarts_with(.url, 'email:')
 22                           // remove links found in exiftool output
 23                           and not (
 24                             ..scan.exiftool.producer is not null
 25                             and strings.icontains(..scan.exiftool.producer,
 26                                                   .domain.domain
 27                             )
 28                           )
 29  
 30                           // remove links found in exiftool output
 31                           and not (
 32                             ..scan.exiftool.creator is not null
 33                             and strings.icontains(..scan.exiftool.creator,
 34                                                   .domain.domain
 35                             )
 36                           )
 37                           // legitimate domains that exhibits this behavior
 38                           and .domain.root_domain not in (
 39                             "univarsolutions.com",
 40                             "westpac.com.au",
 41                             "safeshiphub.com",
 42                             "sharepoint.com"
 43                           )
 44                    ),
 45                    // it contains the email address of the recipient
 46                    any(recipients.to,
 47                        .email.domain.valid
 48                        and (
 49                          strings.icontains(..url, .email.email)
 50                          // or the base64 encoded email
 51                          or any(strings.scan_base64(..url,
 52                                                     format="url",
 53                                                     ignore_padding=true
 54                                 ),
 55                                 strings.icontains(., ..email.email)
 56                          )
 57                          or strings.decode_hex(..fragment) == .email.email
 58                        )
 59                    )
 60                )
 61            )
 62            // or there is a QR code
 63            or (
 64              //
 65              // This rule makes use of a beta feature and is subject to change without notice
 66              // using the beta feature in custom rules is not suggested until it has been formally released
 67              //
 68              any(beta.scan_qr(.).items,
 69                  .url.domain.valid
 70                  and any(recipients.to,
 71                          // QR code contains the email
 72                          (
 73                            strings.icontains(..url.url, .email.email)
 74                            // QR code contains the base64 endcoded email
 75                            or any(strings.scan_base64(..url.url,
 76                                                       format="url",
 77                                                       ignore_padding=true
 78                                   ),
 79                                   strings.icontains(., ..email.email)
 80                            )
 81                            or strings.decode_hex(..url.fragment) == .email.email
 82                          )
 83                  )
 84              )
 85            )
 86          )
 87  )  
 88tags:
 89 - "Attack surface reduction"
 90attack_types:
 91  - "Credential Phishing"
 92tactics_and_techniques:
 93  - "PDF"
 94  - "QR code"
 95  - "Encryption"
 96  - "Social engineering"
 97detection_methods:
 98  - "File analysis"
 99  - "QR code analysis"
100  - "URL analysis"
101id: "0399d08f-57c6-58cb-87dc-8e58ccd0bc1b"

Related rules

to-top