QR Code with suspicious indicators

This rule flags messages with QR codes in attachments when there are three or fewer attachments. If no attachments are present, the rule captures a screenshot of the message for analysis. Additional triggers include: sender's name containing the recipient's SLD, recipient's email mentioned in the body, an empty message body, a suspicious subject, or undisclosed recipients.

Sublime rule (View on GitHub)

  1name: "QR Code with suspicious indicators"
  2description: |
  3    This rule flags messages with QR codes in attachments when there are three or fewer attachments. If no attachments are present, the rule captures a screenshot of the message for analysis. Additional triggers include: sender's name containing the recipient's SLD, recipient's email mentioned in the body, an empty message body, a suspicious subject, or undisclosed recipients.
  4type: "rule"
  5severity: "high"
  6source: |
  7  type.inbound
  8  and (
  9    length(attachments) <= 3
 10    and (
 11      any(attachments,
 12          .file_type in $file_types_images
 13          and any(file.explode(.),
 14                  .scan.qr.type is not null
 15                  and regex.contains(.scan.qr.data, '\.')
 16                  // exclude images taken with mobile cameras and screenshots from android
 17                  and not any(.scan.exiftool.fields,
 18                              .key == "Model"
 19                              or (
 20                                .key == "Software"
 21                                and strings.starts_with(.value, "Android")
 22                              )
 23                  )
 24                  // exclude images taken with mobile cameras and screenshots from Apple
 25                  and not any(.scan.exiftool.fields,
 26                              .key == "DeviceManufacturer"
 27                              and .value == "Apple Computer Inc."
 28                  )
 29          )
 30      )
 31      or (
 32        length(attachments) == 0
 33        and any(file.explode(beta.message_screenshot()),
 34                .scan.exiftool.image_height < 2000
 35                and .scan.exiftool.image_width < 2000
 36                and .scan.qr.type is not null
 37                and regex.contains(.scan.qr.data, '\.')
 38        )
 39      )
 40    )
 41    and (
 42      any(recipients.to,
 43          strings.icontains(sender.display_name, .email.domain.sld)
 44      )
 45      or length(body.current_thread.text) is null
 46      or body.current_thread.text == ""
 47      or regex.contains(subject.subject,
 48                        "(Authenticat(e|or|ion)|2fa|Multi.Factor|(qr|bar).code|action.require|alert|Att(n|ention):)"
 49      )
 50      or (any(recipients.to, strings.icontains(subject.subject, .display_name)))
 51      or (
 52        (
 53          length(recipients.to) == 0
 54          or all(recipients.to, .display_name == "Undisclosed recipients")
 55        )
 56        and length(recipients.cc) == 0
 57        and length(recipients.bcc) == 0
 58      )
 59      or any(file.explode(beta.message_screenshot()),
 60             (
 61               .scan.qr.url.domain.tld in $suspicious_tlds
 62               and .scan.qr.url.domain.root_domain != "app.link"
 63             )
 64             or 
 65             // linkanalysis phishing disposition
 66             any([beta.linkanalysis(.scan.qr.url)],
 67                 .credphish.disposition == "phishing"
 68             )
 69      )
 70      or any(attachments,
 71             .file_type in $file_types_images
 72             and any(file.explode(.),
 73                     (
 74                       .scan.qr.url.domain.tld in $suspicious_tlds
 75                       and .scan.qr.url.domain.root_domain != "app.link"
 76                     )
 77                     and .scan.qr.url.domain.root_domain not in $org_domains
 78             )
 79      )
 80      or sender.email.domain.tld in $suspicious_tlds
 81    )
 82  
 83    // sender profile is new or outlier
 84    and (
 85      (
 86        profile.by_sender().prevalence in ("new", "outlier")
 87        and not profile.by_sender().solicited
 88      )
 89      or (
 90        profile.by_sender().any_messages_malicious_or_spam
 91        and not profile.by_sender().any_false_positives
 92      )
 93    )
 94  
 95    // negate highly trusted sender domains unless they fail DMARC authentication
 96    and (
 97      (
 98        sender.email.domain.root_domain in $high_trust_sender_root_domains
 99        and (
100          any(distinct(headers.hops, .authentication_results.dmarc is not null),
101              strings.ilike(.authentication_results.dmarc, "*fail")
102          )
103        )
104      )
105      or sender.email.domain.root_domain not in $high_trust_sender_root_domains
106    )
107  )  
108attack_types:
109  - "Credential Phishing"
110tactics_and_techniques:
111  - "QR code"
112  - "Social engineering"
113detection_methods:
114  - "Content analysis"
115  - "Header analysis"
116  - "Computer Vision"
117  - "Natural Language Understanding"
118  - "QR code analysis"
119  - "Sender analysis"
120  - "URL analysis"
121id: "04f5c34f-6518-512d-916c-4c2c2827c6a9"
to-top