Detection rules › Panther

Panther rules: standard

RuleSeverity
DNS Base64 Encoded Querymedium

DNS Base64 Encoded Query

#
Severity
medium
Entities
domain_names, ip_addresses, md5_hashes, trace_ids
Log types
Crowdstrike.FDREvent, AWS.VPCDns, CiscoUmbrella.DNS
Reference
zofixer.com
Source
github.com/panther-labs/panther-analysis

Detects DNS queries with Base64 encoded subdomains, which could indicate an attempt to obfuscate data exfil.

Detection logic

from panther_base_helpers import defang_ioc, is_base64

DECODED = ""


def rule(event):
    query = event.udm("dns_query", default="")
    if not query:
        return False
    args = query.split(".")

    # Check if Base64 encoded arguments are present in the command line
    for arg in args:
        # pylint: disable=global-statement
        global DECODED
        DECODED = is_base64(arg)
        if DECODED:
            return True

    return False


def title(event):
    defang_query = defang_ioc(event.udm("dns_query")) if event.udm("dns_query") else "no query"
    return f'Base64 encoded query detected from [{event.udm("source_ip")}], [{defang_query}]'


def alert_context(event):
    context = {}
    context["source ip"] = event.udm("source_ip")
    context["defanged query"] = (
        defang_ioc(event.udm("dns_query")) if event.udm("dns_query") else "no query"
    )
    context["decoded url part"] = DECODED
    return context

Rule specification

AnalysisType: rule
DisplayName: "DNS Base64 Encoded Query"
Description: Detects DNS queries with Base64 encoded subdomains, which could indicate an attempt to obfuscate data exfil.
RuleID: "Standard.DNSBase64"
Enabled: false
Filename: standard_dns_base64.py
Reference: https://zofixer.com/what-is-base64-disclosure-vulnerability/
Severity: Medium
DedupPeriodMinutes: 60
Threshold: 1
LogTypes:
  - Crowdstrike.FDREvent
  - AWS.VPCDns
  - CiscoUmbrella.DNS

Stages and Predicates

Fires on Crowdstrike.FDREvent, AWS.VPCDns, CiscoUmbrella.DNS events when the condition below holds.

Condition

  • dns_query is present

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

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
dns_queryis_not_null
  • (no value, null check)
field:"dns_query" kind:is_not_null

Output fields

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

Field
source_ip

Worked example

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

Sample Test Event
{
  "account_id": "123456789012",
  "answers": [
    {
      "Class": "IN",
      "Rdata": "172.31.46.187",
      "Type": "A"
    }
  ],
  "p_log_type": "AWS.VPCDns",
  "query_class": "IN",
  "query_name": "c29tZSBsb25nIGJhc2U2NCBzdHJpbmc=.file1.16s.us",
  "query_timestamp": "2023-04-11 01:29:20",
  "query_type": "A",
  "rcode": "NOERROR",
  "region": "us-west-2",
  "srcaddr": "172.31.46.187",
  "srcids": {
    "instance": "i-09d9aa4e31675db61"
  },
  "srcport": "36899",
  "transport": "UDP",
  "version": "1.100000",
  "vpc_id": "vpc-c26c48ba"
}