Detection rules › Sublime MQL

Brand impersonation: Fake DocuSign HTML table not linking to DocuSign domains

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

Detects HTML table elements that mimick DocuSign templates linking to non-DocuSign destinations. The rule negates high trusted sender domains and legitimate replies.

Threat classification

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

CategoryValues
Attack typesCredential Phishing
Tactics and techniquesImpersonation: Brand, Social engineering

Event coverage

Rule body MQL

type.inbound
and length(attachments) == 0
and (
  0 < length(body.links) < 10
  // ignore link count when the HTML is padded with whitespace
  // indicative of thread hijacking/copy-pasting
  or regex.icount(body.html.raw, '(<br\s*/?>[\s\n]*)') > 50
)
and (
  regex.icontains(body.html.raw, '<font size="[0-9]">DocuSign</font>')
  or regex.icontains(body.html.raw, '<span[^>]*style="[^"]*">DocuSign<\/span>')
  or regex.icontains(body.html.raw, '<strong>DocuSign</strong>')
  or regex.icontains(body.html.raw,
                     'D&#917540;&#917540;o&#917540;&#917540;c\x{FE00}uS&#917540;&#917540;i\x{FE00}gn'
  )
  or any(body.links, regex.icontains(.display_text, 'view.{0,3}doc'))
  or any(body.links, regex.contains(.display_text, '\bDOCUMENT'))
)
and (
  regex.icontains(body.html.raw, 'background:\s*rgb\(30,\s*76,\s*161\)')
  or regex.icontains(body.html.raw,
                     'background-color:\s*rgb\(30,\s*76,\s*161\)'
  )
  or regex.icontains(body.html.raw,
                     'background-color:\s*rgb\(61,\s*170,\s*73\)'
  )
  or regex.icontains(body.html.raw,
                     '<div[^>]*BACKGROUND-COLOR: #1e4ca1[^>]*>|<td[^>]*BACKGROUND-COLOR: #1e4ca1[^>]*>'
  )
  or regex.icontains(body.html.raw, 'background-color:#214e9f;')
  or regex.icontains(body.html.raw, 'background-color:#3260a7')
  or regex.icontains(body.html.raw,
                     '<table[^>]*cellspacing="0"[^>]*cellpadding="0"[^>]*>\s*<tbody[^>]*>\s*<tr[^>]*>\s*<td[^>]*style="BACKGROUND:\s*rgb\(247,247,247\);\s*width:\s*[0-9]{2,3}px;\s*padding:20px;\s*margin:\s*[0-9]{2,3}px"[^>]*>.*<div[^>]*style="BACKGROUND:\s*rgb\(30,76,161\);\s*padding:[0-9]{2,3}px;\s*color:#EFEFEF"[^>]*align="center"[^>]*>.*DOCUMENT.*</a>'
  )
  // Docusign Blue Box template with button
  or (
    regex.icontains(body.html.raw,
                    '<(td|div)[^>]*style="[^"]*background(-color)?:\s*(#1e4ca1|rgb\(30,\s*76,\s*161\))[^"]*"[^>]*>'
    )
    and (
      regex.icontains(body.html.raw,
                      '<a[^>]*style="[^"]*background-color:\s*(#[A-Fa-f0-9]{6}|rgb\([^)]*\))[^"]*"[^>]*>.*?<span[^>]*>.*?<\/span>.*?<\/a>'
      )
      // white link with a border
      or (
        regex.icontains(body.html.raw,
                        '<a[^>]*style="[^"]*color:\s*(white|#fff|#ffffff|#FFF|#FFFFFF|rgb\(\s*255\s*,\s*255\s*,\s*255\s*\)|rgba\(\s*255\s*,\s*255\s*,\s*255\s*,\s*[0-9.]+\s*\)|rgb\(\s*100%\s*,\s*100%\s*,\s*100%\s*\))[^"]*"[^>]*>.*?<\/a>'
        )
        and regex.icontains(body.html.raw,
                            '<a[^>]*style="[^"]*border:[^"]*"[^>]*>.*?<\/a>'
        )
      )
    )
  )
)
and any(body.links,
        not strings.ilike(.href_url.domain.root_domain, "docusign.*")
        and (
          .display_text is null or regex.contains(.display_text, '\bDOCUMENT')
        )
)
// negate highly trusted sender domains unless they fail DMARC authentication
and (
  (
    sender.email.domain.root_domain in $high_trust_sender_root_domains
    and (
      any(distinct(headers.hops, .authentication_results.dmarc is not null),
          strings.ilike(.authentication_results.dmarc, "*fail")
      )
    )
  )
  or sender.email.domain.root_domain not in $high_trust_sender_root_domains
)

// negate legit replies
and not (length(headers.references) > 0 or headers.in_reply_to is not null)
and not profile.by_sender().any_messages_benign

// negate docusign X-Return-Path
and not any(headers.hops,
            .index == 0
            and any(.fields,
                    .name == "X-Return-Path"
                    and strings.ends_with(.value, "docusign.net")
            )
)

Detection logic

Scope: inbound message.

Detects HTML table elements that mimick DocuSign templates linking to non-DocuSign destinations. The rule negates high trusted sender domains and legitimate replies.

  1. inbound message
  2. length(attachments) is 0
  3. any of:
    • all of:
      • length(body.links) > 0
      • length(body.links) < 10
    • regex.icount(body.html.raw, '(<br\\s*/?>[\\s\\n]*)') > 50
  4. any of:
    • body.html.raw matches '<font size="[0-9]">DocuSign</font>'
    • body.html.raw matches '<span[^>]*style="[^"]*">DocuSign<\\/span>'
    • body.html.raw matches '<strong>DocuSign</strong>'
    • body.html.raw matches 'D&#917540;&#917540;o&#917540;&#917540;c\\x{FE00}uS&#917540;&#917540;i\\x{FE00}gn'
    • any of body.links where:
      • .display_text matches 'view.{0,3}doc'
    • any of body.links where:
      • .display_text matches '\\bDOCUMENT'
  5. any of:
    • body.html.raw matches 'background:\\s*rgb\\(30,\\s*76,\\s*161\\)'
    • body.html.raw matches 'background-color:\\s*rgb\\(30,\\s*76,\\s*161\\)'
    • body.html.raw matches 'background-color:\\s*rgb\\(61,\\s*170,\\s*73\\)'
    • body.html.raw matches '<div[^>]*BACKGROUND-COLOR: #1e4ca1[^>]*>|<td[^>]*BACKGROUND-COLOR: #1e4ca1[^>]*>'
    • body.html.raw matches 'background-color:#214e9f;'
    • body.html.raw matches 'background-color:#3260a7'
    • body.html.raw matches '<table[^>]*cellspacing="0"[^>]*cellpadding="0"[^>]*>\\s*<tbody[^>]*>\\s*<tr[^>]*>\\s*<td[^>]*style="BACKGROUND:\\s*rgb\\(247,247,247\\);\\s*width:\\s*[0-9]{2,3}px;\\s*padding:20px;\\s*margin:\\s*[0-9]{2,3}px"[^>]*>.*<div[^>]*style="BACKGROUND:\\s*rgb\\(30,76,161\\);\\s*padding:[0-9]{2,3}px;\\s*color:#EFEFEF"[^>]*align="center"[^>]*>.*DOCUMENT.*</a>'
    • all of:
      • body.html.raw matches '<(td|div)[^>]*style="[^"]*background(-color)?:\\s*(#1e4ca1|rgb\\(30,\\s*76,\\s*161\\))[^"]*"[^>]*>'
      • any of:
        • body.html.raw matches '<a[^>]*style="[^"]*background-color:\\s*(#[A-Fa-f0-9]{6}|rgb\\([^)]*\\))[^"]*"[^>]*>.*?<span[^>]*>.*?<\\/span>.*?<\\/a>'
        • all of:
          • body.html.raw matches '<a[^>]*style="[^"]*color:\\s*(white|#fff|#ffffff|#FFF|#FFFFFF|rgb\\(\\s*255\\s*,\\s*255\\s*,\\s*255\\s*\\)|rgba\\(\\s*255\\s*,\\s*255\\s*,\\s*255\\s*,\\s*[0-9.]+\\s*\\)|rgb\\(\\s*100%\\s*,\\s*100%\\s*,\\s*100%\\s*\\))[^"]*"[^>]*>.*?<\\/a>'
          • body.html.raw matches '<a[^>]*style="[^"]*border:[^"]*"[^>]*>.*?<\\/a>'
  6. any of body.links where all hold:
    • not:
      • .href_url.domain.root_domain matches 'docusign.*'
    • any of:
      • .display_text is missing
      • .display_text matches '\\bDOCUMENT'
  7. any of:
    • all of:
      • sender.email.domain.root_domain in $high_trust_sender_root_domains
      • any of distinct(headers.hops) where:
        • .authentication_results.dmarc matches '*fail'
    • sender.email.domain.root_domain not in $high_trust_sender_root_domains
  8. none of:
    • length(headers.references) > 0
    • headers.in_reply_to is set
  9. not:
    • profile.by_sender().any_messages_benign
  10. not:
    • any of headers.hops where all hold:
      • .index is 0
      • any of .fields where all hold:
        • .name is 'X-Return-Path'
        • .value ends with 'docusign.net'

Inspects: body.html.raw, body.links, body.links[].display_text, body.links[].href_url.domain.root_domain, headers.hops, headers.hops[].authentication_results.dmarc, headers.hops[].fields, headers.hops[].fields[].name, headers.hops[].fields[].value, headers.hops[].index, headers.in_reply_to, headers.references, sender.email.domain.root_domain, type.inbound. Sensors: profile.by_sender, regex.contains, regex.icontains, regex.icount, strings.ends_with, strings.ilike. Reference lists: $high_trust_sender_root_domains.

Indicators matched (22)

FieldMatchValue
regex.icountregex(<br\s*/?>[\s\n]*)
regex.icontainsregex<font size="[0-9]">DocuSign</font>
regex.icontainsregex<span[^>]*style="[^"]*">DocuSign<\/span>
regex.icontainsregex<strong>DocuSign</strong>
regex.icontainsregexD&#917540;&#917540;o&#917540;&#917540;c\x{FE00}uS&#917540;&#917540;i\x{FE00}gn
regex.icontainsregexview.{0,3}doc
regex.containsregex\bDOCUMENT
regex.icontainsregexbackground:\s*rgb\(30,\s*76,\s*161\)
regex.icontainsregexbackground-color:\s*rgb\(30,\s*76,\s*161\)
regex.icontainsregexbackground-color:\s*rgb\(61,\s*170,\s*73\)
regex.icontainsregex<div[^>]*BACKGROUND-COLOR: #1e4ca1[^>]*>|<td[^>]*BACKGROUND-COLOR: #1e4ca1[^>]*>
regex.icontainsregexbackground-color:#214e9f;
10 more
regex.icontainsregexbackground-color:#3260a7
regex.icontainsregex<table[^>]*cellspacing="0"[^>]*cellpadding="0"[^>]*>\s*<tbody[^>]*>\s*<tr[^>]*>\s*<td[^>]*style="BACKGROUND:\s*rgb\(247,247,247\);\s*width:\s*[0-9]{2,3}px;\s*padding:20px;\s*margin:\s*[0-9]{2,3}px"[^>]*>.*<div[^>]*style="BACKGROUND:\s*rgb\(30,76,161\);\s*padding:[0-9]{2,3}px;\s*color:#EFEFEF"[^>]*align="center"[^>]*>.*DOCUMENT.*</a>
regex.icontainsregex<(td|div)[^>]*style="[^"]*background(-color)?:\s*(#1e4ca1|rgb\(30,\s*76,\s*161\))[^"]*"[^>]*>
regex.icontainsregex<a[^>]*style="[^"]*background-color:\s*(#[A-Fa-f0-9]{6}|rgb\([^)]*\))[^"]*"[^>]*>.*?<span[^>]*>.*?<\/span>.*?<\/a>
regex.icontainsregex<a[^>]*style="[^"]*color:\s*(white|#fff|#ffffff|#FFF|#FFFFFF|rgb\(\s*255\s*,\s*255\s*,\s*255\s*\)|rgba\(\s*255\s*,\s*255\s*,\s*255\s*,\s*[0-9.]+\s*\)|rgb\(\s*100%\s*,\s*100%\s*,\s*100%\s*\))[^"]*"[^>]*>.*?<\/a>
regex.icontainsregex<a[^>]*style="[^"]*border:[^"]*"[^>]*>.*?<\/a>
strings.ilikesubstringdocusign.*
strings.ilikesubstring*fail
headers.hops[].fields[].nameequalsX-Return-Path
strings.ends_withsuffixdocusign.net