Unexpected Dns Traffic

osquery
Catch DNS traffic going to machines other than the host-configured DNS server (state-based)
Author

Chainguard

Published

January 29, 2025

Description

ODK (osquery-defense-kit) is unique in that the queries are designed to be used as part of a production detection & response pipeline. The detection queries are formulated to return zero rows during normal expected behavior, so that they may be configured to generate alerts when rows are returned.

Query

-- Catch DNS traffic going to machines other than the host-configured DNS server (state-based)
--
-- references:
--   * https://attack.mitre.org/techniques/T1071/004/ (C2: Application Layer Protocol: DNS)
--
-- tags: transient state net often dns
--
-- NOTE: This only supports IPv4 traffic due to an osquery bug with 'dns_resolvers'
SELECT
  s.family,
  protocol,
  s.local_port,
  s.remote_port,
  s.local_address,
  s.remote_address,
  p.name,
  p.path,
  p.cmdline AS child_cmd,
  p.cwd,
  s.pid,
  p.parent AS parent_pid,
  pp.cmdline AS parent_cmd,
  hash.sha256,
  GROUP_CONCAT(
    (
      SELECT DISTINCT
        address
      FROM
        dns_resolvers
      WHERE
        type = 'nameserver'
        AND address != ''
    ),
    ','
  ) AS sys_resolvers,
  CONCAT (p.name, ',', remote_address, ',', remote_port) AS exception_key
FROM
  process_open_sockets s
  LEFT JOIN processes p ON s.pid = p.pid
  LEFT JOIN processes pp ON p.parent = pp.pid
  LEFT JOIN hash ON p.path = hash.path
WHERE
  remote_port IN (53, 5353)
  AND remote_address NOT LIKE '%:%'
  AND s.remote_address NOT LIKE '172.1%'
  AND s.remote_address NOT LIKE '172.2%'
  AND s.remote_address NOT LIKE '172.30.%'
  AND s.remote_address NOT LIKE '172.31.%'
  AND s.remote_address NOT LIKE '10.%'
  AND s.remote_address NOT LIKE '192.168.%'
  AND s.remote_address NOT LIKE '127.%'
  AND remote_address NOT IN (
    SELECT DISTINCT
      address
    FROM
      dns_resolvers
    WHERE
      type = 'nameserver'
      and address != ''
  )
  -- systemd-resolve sometimes shows up this way
  -- If we could narrow this down using 'sys_resolvers' I would, but it is misuse of GROUP_CONCAT
  AND NOT (
    s.pid = -1
    AND s.remote_port = 53
    and s.protocol = 17
    and p.parent = ''
  )
  -- Some applications hard-code a safe DNS resolver, or allow the user to configure one
  AND s.remote_address NOT IN (
    '1.0.0.1', -- Cloudflare
    '1.1.1.1', -- Cloudflare
    '1.1.1.2', -- Cloudflare
    '8.8.8.8', -- Google
    '8.8.4.4', -- Google (backup)
    '208.67.222.222', -- OpenDNS
    '75.75.75.75', -- Comcast
    '68.105.28.13', -- Cox
    '84.116.46.21' -- Liberty Gloval B.V. (major NL telco)
  )
  -- Other exceptions
  AND exception_key NOT IN (
    'Arc Helper,1.0.0.1,53',
    'coredns,0.0.0.0,53',
    'goland,149.112.112.10,53',
    'nessusd,50.16.123.71,53',
    'syncthing,46.162.192.181,53'
  )
  -- Local DNS servers and custom clients go here
  AND p.path NOT IN (
    '/Applications/Evernote.app/Contents/Frameworks/Evernote Helper.app/Contents/MacOS/Evernote Helper',
    '/Applications/Evernote.app/Contents/MacOS/Evernote',
    '/Applications/Slack.app/Contents/Frameworks/Slack Helper.app/Contents/MacOS/Slack Helper',
    '/Applications/Spotify.app/Contents/Frameworks/Spotify Helper.app/Contents/MacOS/Spotify Helper',
    '/Applications/Tailscale.app/Contents/PlugIns/IPNExtension.appex/Contents/MacOS/IPNExtension',
    '/opt/podman/bin/gvproxy',
    '/sbin/apk',
    '/System/Volumes/Preboot/Cryptexes/Incoming/OS/System/Library/Frameworks/WebKit.framework/Versions/A/XPCServices/com.apple.WebKit.Networking.xpc/Contents/MacOS/com.apple.WebKit.Networking',
    '/usr/bin/tailscaled',
    '/usr/lib/systemd/systemd-resolved',
    '/usr/sbin/mDNSResponder'
  )
  AND p.path NOT LIKE '%/podman/gvproxy'
  AND p.path NOT LIKE '%/Steam/Steam.AppBundle/Steam/Contents/MacOS/Frameworks/Steam Helper.app/Contents/MacOS/Steam Helper'
  AND p.path NOT LIKE '/Applications/Google Chrome.app/Contents/Frameworks/Google Chrome Framework.framework/Versions/%/Helpers/Google Chrome Helper.app/Contents/MacOS/Google Chrome Helper'
  -- Workaround for the GROUP_CONCAT subselect adding a blank ent
  -- Workaround for the GROUP_CONCAT subselect adding a blank ent
GROUP BY
  s.remote_address,
  s.remote_port
HAVING
  remote_address != ''

tags: SStagSS

Reference

https://github.com/chainguard-dev/osquery-defense-kit