Detection rules › Sublime MQL

Sublime MQL rules: unicode

RuleSeverity
Unicode QR codemedium

Unicode QR code

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

Identifies messages leveraging Unicode block characters (between U+2580 - U+259F) arranged on consecutive lines to create QR codes. The rule inspects both the overall quantity and specific formatting of these characters, while considering the sender's historical behavior and reputation.

Threat classification

Sublime's own taxonomy (not MITRE ATT&CK).

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion

Telemetry coverage

PlatformRecord / event type
SublimeInbound email message

Message attributes

  • body
  • body.current_thread
  • body.html
  • type

Rule body

type.inbound
// count of the lines ending with and then followed by a unicode block
and regex.count(body.html.inner_text,
                '[\x{2580}-\x{259F}][^\S\r\n]*[\r\n][^\S\r\n]*[\x{2580}-\x{259F}]'
) > 10
// the total number of unicode blocks
and regex.count(body.current_thread.text, '[\x{2580}-\x{259F}]') > 150
and (
  profile.by_sender_email().prevalence != "common"
  or (
    profile.by_sender_email().any_messages_malicious_or_spam
    and not profile.by_sender_email().any_messages_benign
  )
)

Detection logic

Scope: inbound message.

Identifies messages leveraging Unicode block characters (between U+2580 - U+259F) arranged on consecutive lines to create QR codes. The rule inspects both the overall quantity and specific formatting of these characters, while considering the sender's historical behavior and reputation.

  1. inbound message
  2. regex.count(body.html.inner_text, '[\\x{2580}-\\x{259F}][^\\S\\r\\n]*[\\r\\n][^\\S\\r\\n]*[\\x{2580}-\\x{259F}]') > 10
  3. regex.count(body.current_thread.text, '[\\x{2580}-\\x{259F}]') > 150
  4. any of:
    • profile.by_sender_email().prevalence is not 'common'
    • all of:
      • profile.by_sender_email().any_messages_malicious_or_spam
      • not:
        • profile.by_sender_email().any_messages_benign

Inspects: body.current_thread.text, body.html.inner_text, type.inbound. Sensors: profile.by_sender_email, regex.count.

Indicators matched (2)

FieldMatchValue
regex.countregex[\x{2580}-\x{259F}][^\S\r\n]*[\r\n][^\S\r\n]*[\x{2580}-\x{259F}]
regex.countregex[\x{2580}-\x{259F}]

Stages and Predicates

Stage 1: mql_rule

and
  or
    and
      not
        profile.by_sender_email func_call "profile.by_sender_email().any_messages_benign"
      profile.by_sender_email func_call "profile.by_sender_email().any_messages_malicious_or_spam"
    profile.by_sender_email func_call "profile.by_sender_email().prevalence != common"
  regex.count func_call "regex.count(body.current_thread.text, \"[\\x{2580}-\\x{259F}]\") > 150"
  regex.count func_call "regex.count(body.html.inner_text, \"[\\x{2580}-\\x{259F}][^\\S\\r\\n]*[\\r\\n][^\\S\\r\\n]*[\\x{2580}-\\x{259F}]\") > 10"
  type.inbound eq "true"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
type.inboundeq
  • true transforms: boolean
field:"type.inbound" kind:eq value:"true"