Detection rules › Sublime MQL

Credential Phishing: W-2 lure with inline SVG Windows logo

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

Detects inbound messages containing a link with W-2 display text and an inline SVG constructed from four colored rectangles approximating the Microsoft Windows logo. Threat actors use hand-crafted SVG elements rather than image attachments to bypass image-based detection and render a convincing Windows or Microsoft brand impersonation directly in the email body. The color matching uses fuzzy hex ranges to account for minor variations across campaigns.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesEvasion, HTML smuggling, Social engineering

Event coverage

Rule body MQL

type.inbound
// display text contains a reference to W2
and any(body.current_thread.links,
        regex.icontains(strings.replace_confusables(.display_text),
                        '(?:W|VV)\s*-?\s*2'
        )
)
// inline SVG that mimics the Windows logo
and regex.icontains(body.html.raw,
                    '<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[c-f][0-9a-f][0-3][0-9a-f][0-3][0-9a-f]">\s*<\/rect>\s*<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[0-3][0-9a-f][8-f][0-9a-f][2-6][0-9a-f]">\s*<\/rect>\s*<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[0-3][0-9a-f][5-9][0-9a-f][a-f][0-9a-f]">\s*<\/rect>\s*<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[c-f][0-9a-f][a-f][0-9a-f][0-3][0-9a-f]">\s*<\/rect>\s*<\/svg>\s*<\/td>'
)

Detection logic

Scope: inbound message.

Detects inbound messages containing a link with W-2 display text and an inline SVG constructed from four colored rectangles approximating the Microsoft Windows logo. Threat actors use hand-crafted SVG elements rather than image attachments to bypass image-based detection and render a convincing Windows or Microsoft brand impersonation directly in the email body. The color matching uses fuzzy hex ranges to account for minor variations across campaigns.

  1. inbound message
  2. any of body.current_thread.links where:
    • strings.replace_confusables(.display_text) matches '(?:W|VV)\\s*-?\\s*2'
  3. body.html.raw matches '<rect x="\\d+" y="\\d+" width="\\d+" height="\\d+" fill="#[c-f][0-9a-f][0-3][0-9a-f][0-3][0-9a-f]">\\s*<\\/rect>\\s*<rect x="\\d+" y="\\d+" width="\\d+" height="\\d+" fill="#[0-3][0-9a-f][8-f][0-9a-f][2-6][0-9a-f]">\\s*<\\/rect>\\s*<rect x="\\d+" y="\\d+" width="\\d+" height="\\d+" fill="#[0-3][0-9a-f][5-9][0-9a-f][a-f][0-9a-f]">\\s*<\\/rect>\\s*<rect x="\\d+" y="\\d+" width="\\d+" height="\\d+" fill="#[c-f][0-9a-f][a-f][0-9a-f][0-3][0-9a-f]">\\s*<\\/rect>\\s*<\\/svg>\\s*<\\/td>'

Inspects: body.current_thread.links, body.current_thread.links[].display_text, body.html.raw, type.inbound. Sensors: regex.icontains, strings.replace_confusables.

Indicators matched (2)

FieldMatchValue
regex.icontainsregex(?:W|VV)\s*-?\s*2
regex.icontainsregex<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[c-f][0-9a-f][0-3][0-9a-f][0-3][0-9a-f]">\s*<\/rect>\s*<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[0-3][0-9a-f][8-f][0-9a-f][2-6][0-9a-f]">\s*<\/rect>\s*<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[0-3][0-9a-f][5-9][0-9a-f][a-f][0-9a-f]">\s*<\/rect>\s*<rect x="\d+" y="\d+" width="\d+" height="\d+" fill="#[c-f][0-9a-f][a-f][0-9a-f][0-3][0-9a-f]">\s*<\/rect>\s*<\/svg>\s*<\/td>