Link: Tycoon2FA phishing kit (non-exhaustive)

Detects links utilizing the Tycoon2FA phishing kit, identified by specific DOM structure patterns and CDN characteristics, combined with suspicious domain indicators such as free subdomain hosts or suspicious TLDs. As the Tycoon2FA kit is evolving, this rule will not detect all variants of Tycoon2FA phishing, and is designed to compliment existing and future detections.

Sublime rule (View on GitHub)

  1name: "Link: Tycoon2FA phishing kit (non-exhaustive)"
  2description: "Detects links utilizing the Tycoon2FA phishing kit, identified by specific DOM structure patterns and CDN characteristics, combined with suspicious domain indicators such as free subdomain hosts or suspicious TLDs. As the Tycoon2FA kit is evolving, this rule will not detect all variants of Tycoon2FA phishing, and is designed to compliment existing and future detections."
  3type: "rule"
  4severity: "high"
  5source: |
  6  type.inbound
  7  and length(body.current_thread.links) < 10
  8  and any(body.current_thread.links,
  9          // initial suspicious link check
 10          (
 11            .href_url.domain.root_domain in $free_subdomain_hosts
 12            or .href_url.domain.tld in $suspicious_tlds
 13            or any(recipients.to,
 14                   strings.icontains(..href_url.url, .email.email)
 15                   and .email.domain.valid
 16            )
 17          )
 18  
 19          // known Tycoon pattern (benign on its own, but a good confirming indicator when coupled with additional logic)
 20          and any(ml.link_analysis(.).unique_urls_accessed,
 21                  .path in ("/cdn-cgi/rum")
 22          )
 23  
 24          // begin CAPTCHA options
 25          and (
 26            // Grid "CAPTCHA"
 27            (
 28              length(distinct(map(html.xpath(ml.link_analysis(.).final_dom,
 29                                             '//*/@class'
 30                                  ).nodes,
 31                                  .raw
 32                              ),
 33                              .
 34                     )
 35              ) == 5
 36              and all(distinct(map(html.xpath(ml.link_analysis(.).final_dom,
 37                                              '//*/@class'
 38                                   ).nodes,
 39                                   .raw
 40                               ),
 41                               .
 42                      ),
 43                      . in ("card", "title", "hint", "grid", "dot")
 44              )
 45            )
 46            // Unsplash image selection "CAPTCHA"
 47            or (
 48              any(distinct(map(html.xpath(ml.link_analysis(.).final_dom,
 49                                          '//*/@class'
 50                               ).nodes,
 51                               .raw
 52                           ),
 53                           .
 54                  ),
 55                  . in (
 56                    "captcha-container",
 57                    "puzzle-piece drag-hint",
 58                    "puzzle-image"
 59                  )
 60              )
 61              or length(filter(ml.link_analysis(.).unique_urls_accessed,
 62                               .domain.domain == "images.unsplash.com"
 63                        )
 64              ) > 4
 65              or any(file.explode(ml.link_analysis(.).final_dom),
 66                     length(filter(.scan.javascript.identifiers,
 67                                   strings.icontains(., "puzzle")
 68                            )
 69                     ) > 3
 70              )
 71              or strings.ilike(ml.link_analysis(.).final_dom.raw,
 72                               "*Please align the puzzle correctly*",
 73                               "*Verified! You may proceed*",
 74                               "*Human Check*",
 75                               "*needs to review the security of your connection before proceeding.*"
 76              )
 77            )
 78            
 79            // Randomized image domain CAPTCHA
 80            // all image URL domains accessed are unique from each other
 81            or (
 82              length(filter(ml.link_analysis(.).unique_urls_accessed,
 83                            any([".jpg", ".png", ".jpeg"],
 84                                strings.ends_with(..path, .)
 85                            )
 86                     )
 87              ) == length(distinct(filter(ml.link_analysis(.).unique_urls_accessed,
 88                                          any([".jpg", ".png", ".jpeg"],
 89                                              strings.ends_with(..path, .)
 90                                          )
 91                                   ),
 92                                   .domain.root_domain
 93                          )
 94              )
 95              and length(filter(ml.link_analysis(.).unique_urls_accessed,
 96                                any([".jpg", ".png", ".jpeg"],
 97                                    strings.ends_with(..path, .)
 98                                )
 99                         )
100              ) > 4
101            )
102  
103            // Reoccuring form pattern
104            or length(html.xpath(ml.link_analysis(.).final_dom,
105                                 "//form[@method='POST']//input[@name='zone' and @type='hidden']"
106                      ).nodes
107            ) == 1
108          )
109  )  
110
111attack_types:
112  - "Credential Phishing"
113tactics_and_techniques:
114  - "Free subdomain host"
115  - "Evasion"
116  - "Credential Phishing"
117detection_methods:
118  - "URL analysis"
119  - "HTML analysis"
120  - "Content analysis"
121id: "a070d4e2-9d0c-5b85-b7a5-18ee6fb66720"
to-top