Detection rules › Panther

Panther rules: malicious

RuleSeverity
Malicious SSO DNS Lookupmedium

Malicious SSO DNS Lookup

#
Severity
medium
Entities
domain_names, ip_addresses, trace_ids
Log types
CiscoUmbrella.DNS, Crowdstrike.DNSRequest, Crowdstrike.FDREvent, Suricata.DNS, Zeek.DNS
Tags
Configuration Required
Reference
www.cloudns.net
Source
github.com/panther-labs/panther-analysis

The rule looks for DNS requests to sites potentially posing as SSO domains.

MITRE ATT&CK coverage

TacticTechniques
Initial Access

Detection logic

"""
We highly recommend running this logic over 30 days of historical data using data replay
before enabling this in your Panther instance. If ALLOWED_DOMAINS is not fully populated with
domains you own, that contain your company name, false positive alerts will be generated.

Recommended steps to enable:
    1. Change COMPANY_NAME to match your organization
    2. Update the occurrences of "company_name_here" in malicious_sso_dns_lookup.yml
    3. Add known domains containing COMPANY_NAME to ALLOWED_DOMAINS
    4. Run local tests
    5. Run a Data Replay test to identify unknown domains that should be in ALLOWED_DOMAINS
"""

from panther_crowdstrike_fdr_helpers import filter_crowdstrike_fdr_event_type

# *** Change this to match your company name ***
COMPANY_NAME = "company_name_here"

# Ref: https://blog.group-ib.com/0ktapus
FAKE_KEYWORDS = [
    "sso",
    "okta",
    "corp",
    "vpn",
    "citrix",
    "help",
    "edge",
]

# Add known good domains that contain your company name
ALLOWED_DOMAINS = [
    ".amazonaws.com",
    ".okta.com",
    ".oktapreview.com",
    #   "COMPANY.com",
]


def rule(event):
    # We need to run either for Crowdstrike.DnsRequest or for DnsRequest.FDREvent of 'DnsRequest'
    # type. Crowdstrike.DnsRequest is covered because of the association with the type
    if filter_crowdstrike_fdr_event_type(event, "DnsRequest"):
        return False

    # check domain for company name AND a fake keyword
    for domain in event.get("p_any_domain_names", []):
        domain_was_allowed = [x for x in ALLOWED_DOMAINS if domain.lower().endswith(x)]
        if domain_was_allowed:
            continue
        if COMPANY_NAME in domain.lower():
            fake_matches = [x for x in FAKE_KEYWORDS if x in domain.lower()]
            if fake_matches:
                return True

    # The domain did not have a fake keyword and the company name
    return False


def title(event):
    return (
        f"Potential Malicious SSO Domain - {event.get('p_any_domain_names',['NO_DOMAINs_FOUND'])}"
    )

Rule specification

AnalysisType: rule
Filename: malicious_sso_dns_lookup.py
RuleID: "Standard.MaliciousSSODNSLookup"
DedupPeriodMinutes: 1440 # dedup & threshold is high to prevent alert storms from FPs
DisplayName: "Malicious SSO DNS Lookup"
Enabled: false
LogTypes:
  - CiscoUmbrella.DNS
  - Crowdstrike.DNSRequest
  - Crowdstrike.FDREvent
  - Suricata.DNS
  - Zeek.DNS
Severity: Medium
Threshold: 1000 # dedup & threshold is high to prevent alert storms from FPs
Tags:
  - Configuration Required
Reports:
  MITRE ATT&CK:
    - TA0001:T1566
Description: The rule looks for DNS requests to sites potentially posing as SSO domains.
Runbook: Verify if the destination domain is owned by your organization.
Reference: https://www.cloudns.net/wiki/article/254/#:~:text=A%20DNS%20query%20(also%20known,associated%20with%20a%20domain%20name
SummaryAttributes:
  - p_any_ip_addresses

Stages and Predicates

Fires on CiscoUmbrella.DNS, Crowdstrike.DNSRequest, Crowdstrike.FDREvent (and 2 more) events when any of the conditions below holds.

Condition

  • any of:
    • p_log_type is not Crowdstrike.FDREvent
    • fdr_event_type is DnsRequest

This rule also runs imperative logic the parser cannot express as a filter. The conditions above are the structured part it could extract.

Alert cadence
alerts after 1000 matches within 1d

Exclusions

The rule actively suppresses these predicates.

FieldKindExcluded valuesSearch
fdr_event_typeneDnsRequestexcludes:fdr_event_type field:"fdr_event_type" value:"DnsRequest"
p_log_typeeqCrowdstrike.FDREventexcludes:p_log_type field:"p_log_type" value:"Crowdstrike.FDREvent"

Indicators

These rows show field, operator, and value matches.

Output fields

Fields the rule emits when it matches, drawn from the rule's alert_context.

Field
p_any_domain_names

Response runbook

Verify if the destination domain is owned by your organization.

Worked example

A sample event from the rule's unit tests that triggers a match.

Sample Test Event
{
  "ContextProcessId": "440890253753908704",
  "ContextThreadId": "0",
  "ContextTimeStamp": "2022-08-31 07:03:48.879",
  "DomainName": "company_name_here-okta.com",
  "EffectiveTransmissionClass": 2,
  "Entitlements": "15",
  "RequestType": "1",
  "event_platform": "Mac",
  "event_simpleName": "DnsRequest",
  "name": "DnsRequestMacV2",
  "p_any_domain_names": [
    "company_name_here-okta.com"
  ],
  "timestamp": "2022-08-31 07:03:49.195"
}