Suspected cross-site scripting (XSS) found in subject
This rule detects Cross-Site Scripting (XSS) attempts within email subjects. It bypasses messages from highly trusted domains unless they fail authentication. However, the rule remains flexible, triggering even for trusted domains when emails are sent from Google Groups, ensuring thorough protection against potential threats while minimizing false positives.
Sublime rule (View on GitHub)
1name: "Suspected cross-site scripting (XSS) found in subject"
2description: "This rule detects Cross-Site Scripting (XSS) attempts within email subjects. It bypasses messages from highly trusted domains unless they fail authentication. However, the rule remains flexible, triggering even for trusted domains when emails are sent from Google Groups, ensuring thorough protection against potential threats while minimizing false positives."
3type: "rule"
4severity: "medium"
5source: |
6 type.inbound
7 // subject contains suspected cross site scripting
8 and regex.icontains(subject.subject,
9 '(?:[<]|%(25)?3c|\\u003c|\\x3c|&[lg]t;|&n[vw][lg]t;)\/?(?:script(?:\s*/?\s*src\s*=)?|div|iframe|embed|object|style|form|meta|link|svg|img|audio|video|source|body|input|textarea|select|noscript|(?:/|%(25)?2f)?title|(?:/|%(25)?2f)?textarea|(?:/|%(25)?2f)?style|(?:/|%(25)?2f)?template|(?:/|%(25)?2f)?noembed)',
10 // constructor chain pattern
11 'constructor\.constructor|\[\s*constructor\s*\]|\.__proto__|\[constructor\]'
12 )
13
14 // and contains html or url encoded strings, hex escaped strings, opening or closing html tags, or escaped non word characters
15 and // subject contains common event handlers
16 regex.icontains(subject.subject,
17 '(?:\b|%[a-f0-9]{2})(?:on(?:abort|blur|change|click|dblclick|error|focus|load|mouse(?:over|out|move|down|up)|key(?:down|up|press)|reset|select|submit|unload)|srcdoc|src\s*(?:=|%(?:25)?3d))',
18 // subject contains javascript funcitons
19 '(?:\b|%(?:25)?[a-f0-9]{2})(?:javascript|eval|settimeout|setinterval|document\.(?:cookie|write|location|createElement|body|appendChild)|fetch|constructor|__proto__|prototype|atob|getScript|script(?:\s|%(?:25)?20)src)(?:\b|%(?:25)?[a-f0-9]{2})',
20 // url encoded forms of script src
21 '(?:\b|%(?:25)?[a-f0-9]{2})script(?:\s|%(?:25)?20)src(?:\b|%(?:25)?[a-f0-9]{2})'
22 )
23 and regex.icontains(subject.subject,
24 // Pattern 1: Quote followed by various special characters in encoded/literal forms:
25 // - < > angle brackets (%3C, %3E, literal, <, >)
26 // - quotes (", ')
27 // - parentheses ((, ))
28 // - curly braces ({, })
29 // - square brackets ([, ])
30 // - equals sign (=)
31 // - forward/backward slashes (/, \)
32 // - colon (:)
33 // - semicolon (;)
34 '[\x27\x22](?:%3[CE]|[<>]|&(?:lt|gt|quot|apos|[lr](?:par|cub|sqb)|equals|[bs]ol|colon|semi)\x3b)',
35 // Pattern 2: Encoded/special characters followed by quote
36 // Same as above but in reverse order - special chars followed by quote
37 '(?:%3[CE]|[<>]|&(?:lt|gt|quot|apos|[lr](?:par|cub|sqb)|equals|[bs]ol|colon|semi)\x3b)[\x27\x22]',
38
39 // Pattern 3: Hexadecimal or decimal HTML entities with semicolon
40 // e.g., ' (hex) or ' (decimal)
41 '&#[xX]?[a-f0-9]+;',
42
43 // Pattern 4: Raw decimal HTML entities
44 // e.g., < (without semicolon)
45 '&#\d+',
46
47 // Pattern 5: URL encoded characters
48 // e.g., %3C for <, %3E for >, %22 for ", %27 for '
49 '%[a-f0-9]{2}',
50
51 // Pattern 6: Unicode/hex escapes
52 // e.g., \u003C for <, \x3C for
53 '\\[xXuU][a-f0-9]{4}',
54 // New patterns for this type of payload
55 '</[^>]+/[^>]+>', // Matches closing tags with slash delimiters
56 '//[^"\x27>\s]+', // Matches protocol-relative URLs
57 'xss\.report', // Specific known XSS domains
58 '/\*|\*/|\-\->', // comment chars (/*, */, -->)
59 )
60
61 // negate highly trusted sender domains unless they fail DMARC authentication
62 and (
63 (
64 sender.email.domain.root_domain in $high_trust_sender_root_domains
65 and (
66 any(distinct(headers.hops, .authentication_results.dmarc is not null),
67 strings.ilike(.authentication_results.dmarc, "*fail")
68 )
69 or (
70 strings.icontains(sender.display_name, "via")
71 and any(headers.hops,
72 any(.fields,
73 .name == "List-ID"
74 and strings.ends_with(.value,
75 strings.concat(sender.email.domain.domain,
76 ">"
77 )
78 )
79 )
80 )
81 )
82 )
83 )
84 or sender.email.domain.root_domain not in $high_trust_sender_root_domains
85 )
86attack_types:
87 - "Credential Phishing"
88tactics_and_techniques:
89 - "Evasion"
90 - "Scripting"
91detection_methods:
92 - "Content analysis"
93 - "Sender analysis"
94id: "8a946cfa-58ea-59c5-9726-94a1892b5556"