Service abuse: Substack credential theft with confusable characters and branded button redirects

Detects messages from Substack that use confusable characters in the sender display name, contain purple buttons or typical button classes that redirect to non-Substack domains, and include credential theft content with urgency indicators.

Sublime rule (View on GitHub)

 1name: "Service abuse: Substack credential theft with confusable characters and branded button redirects"
 2description: "Detects messages from Substack that use confusable characters in the sender display name, contain purple buttons or typical button classes that redirect to non-Substack domains, and include credential theft content with urgency indicators."
 3type: "rule"
 4severity: "medium"
 5source: |
 6  type.inbound
 7  and sender.email.domain.root_domain == 'substack.com'
 8  and 2 of (
 9    // substack-branded elements pointing to non-substack domains
10    any(filter(html.xpath(body.html, '//a[@href]').nodes,
11               // purple button or typical button classes
12               (
13                 strings.icontains(.raw, 'background-color: #7c3aed')
14                 or strings.icontains(.raw, 'background-color:#7c3aed')
15                 or strings.icontains(.raw, 'class="button')
16                 or strings.icontains(.raw, 'bgcolor="#7c3aed"')
17               )
18        ),
19        // rewrites to non-Substack domain
20        any(.links, .href_url.domain.root_domain not in~ ('substack.com'))
21    ),
22    // sender name contains confusables
23    sender.display_name != strings.replace_confusables(sender.display_name),
24    // lots of urgency entities
25    length(filter(ml.nlu_classifier(body.current_thread.text).entities,
26                  .name == "urgency"
27           )
28    ) >= 5,
29    // excessive hidden character spam in HTML source
30    any(html.xpath(body.html, '//*').nodes,
31        (
32          strings.count(.raw, '­') + strings.count(.raw, '͏')
33   + strings.count(.raw, ' ')
34        ) > 100
35    )
36  )
37  // cred theft
38  and (
39    any(ml.nlu_classifier(body.current_thread.text).intents,
40        .name == "cred_theft" and .confidence != "low"
41    )
42  )  
43attack_types:
44  - "Credential Phishing"
45tactics_and_techniques:
46  - "Social engineering"
47  - "Evasion"
48detection_methods:
49  - "Sender analysis"
50  - "HTML analysis"
51  - "Natural Language Understanding"
52  - "URL analysis"
53id: "45bf0daf-e576-57ed-92d6-b351d4ab74b6"
to-top