[QueryCorner][June2022] Data Lake Device Card - Windows

Purpose

This query is designed to give you a "Total Report" of what is happening on a specific device. Such details include:

  • Computer Name
  • Bitlocker Info
  • Hardware_vendor
  • OS Info
  • CPU model
  • Memory info
  • Disk Info
  • MAC address
  • Open port
  • Login user
  • Application
  • Certificate
  • Windows Update
  • Networks Info

Prerequisites

You must have XDR enabled in your environment. This is entirely a Data Lake query. See this guide on ensuring Data Lake hydration is enabled for the platform.

This is intended for Windows.

Query Focus

This beautifully made script is a brain-dump of  and  

DISCLAIMERS FOR USING THIS QUERY:

  • The query works the best when run to collect a single device's information at a time - specify full device name in $$device_name$$ variable,
    • Using % in a variable will limit the output as it runs as one query against the whole datalake database unlike a live discover query.
  • It collects a lot more data than what is displayed in results,
    • We have intently not removed those fields since it adds flexibility and potential to restructure the displayed data fields when needed as per the need/requirements
    • This may be particularly useful for someone using API integration to the XDR Platform for displaying dashboard information

-- Device Card Query for Datalake
-- VARIABLE   device_name   STRING    NOTE: Specify full Device Name in variable.
-- NOTE: This is a Single Device Card Query, Running this query for all or multiple devices will return incomplete/appropriate result. DO NOT USE WILDCARD in VARIABLE

WITH latest_result AS (
    SELECT
        meta_hostname AS ep_name,
        MAX(ingestion_timestamp) AS max_time
    FROM xdr_data
    WHERE query_name = 'disk_encryption_windows'
    GROUP BY meta_hostname
),

encryption_details AS (

SELECT
    xdr_data.meta_hostname AS ep_name,
    xdr_data.drive_letter,
    xdr_data.protection_status,
    xdr_data.unix_time AS latest_result,
    xdr_data.encryption_method,
    xdr_data.drive_device_id,
    xdr_data.persistent_volume_id,
    xdr_data.conversion_status,
    xdr_data.version,
    xdr_data.percentage_encrypted,
    xdr_data.lock_status
FROM xdr_data
INNER JOIN latest_result ON
    xdr_data.meta_hostname = latest_result.ep_name
    AND xdr_data.ingestion_timestamp = latest_result.max_time
WHERE
    xdr_data.query_name = 'disk_encryption_windows'
    AND xdr_data.meta_hostname LIKE '$$device_name$$'
),

PENDING_UPDATES AS (

  SELECT
      meta_hostname AS ep_name,
      title,
      support_url,
      msrc_severity,
      installed,
      mandatory,
      size,
      hotfix_id
  FROM xdr_data
  WHERE query_name = 'pending_windows_updates_patch'
  AND meta_hostname LIKE '$$device_name$$'
  LIMIT 5
),

LISTENING_PORTS AS (

  SELECT
    meta_hostname AS ep_name,
    name,
    address,
    port,
    pid,
    path
FROM xdr_data
WHERE query_name = 'listening_ports'
AND port < 1000 OR port = 3389
AND meta_hostname LIKE '$$device_name$$'
LIMIT 5

),

INTERFACE_DETAILS AS (

  SELECT DISTINCT
    meta_hostname AS ep_name,
   -- meta_ip_address,
   -- query_name,
    address,
   -- broadcast,
   -- ibytes,
    interface,
    mac
    /*mask,
    mtu,
    obytes,
    meta_boot_time,
    meta_eid,
    meta_endpoint_type,
    meta_ip_mask,
    meta_mac_address,
    meta_os_name,
    meta_os_platform,
    meta_os_version,
    meta_public_ip,
    meta_query_pack_version,
    meta_username,
    calendar_time,
    counter,
    epoch,
    host_identifier,
    numerics,
    osquery_action,
    unix_time,
    customer_id,
    endpoint_id,
    upload_size*/
FROM xdr_data
WHERE query_name = 'network_interfaces'
AND meta_hostname LIKE '$$device_name$$'
AND mask LIKE '255.%.%.%' AND address <> '127.0.0.1'
LIMIT 5

),

LIST_OF_PUA AS (

  WITH full_list AS (
    SELECT
        linux_processes.meta_hostname AS ep_name,
        linux_processes.time AS date_time,
        NULL AS parent_process_name,
        linux_processes.name AS process_name,
        (
            SELECT DISTINCT linux_users.username
            FROM
                xdr_data AS linux_users
            WHERE
                query_name = 'user_accounts'
                AND linux_users.meta_hostname = linux_processes.meta_hostname
                AND linux_users.uid = linux_processes.uid
        ) AS user_name,
        linux_processes.cmdline AS cmd_line,
        linux_processes.pids || ':' || CAST(linux_processes.time AS VARCHAR) AS sophos_pid,
        NULL AS parent_sophos_pid,
        linux_processes.sha256 AS sha256,
        linux_processes.sha1 AS sha1,
        linux_processes.path AS path,
        NULL AS ml_score,
        NULL AS pua_score,
        NULL AS global_rep,
        NULL AS local_rep,
        linux_processes.gid AS gid,
        linux_processes.uid AS uid,
        linux_processes.euid AS euid,
        linux_processes.egid AS egid,
        NULL AS parent_path
    FROM
        xdr_data AS linux_processes
    WHERE
        linux_processes.query_name = 'running_processes_linux_events'
        AND LOWER(linux_processes.meta_hostname) LIKE LOWER('$$device_name$$')

    UNION ALL

    SELECT
        windows_processes.meta_hostname AS ep_name,
        windows_processes.time AS date_time,
        windows_processes.parent_name AS parent_process_name,
        windows_processes.name AS process_name,
        windows_processes.username AS user_name,
        windows_processes.cmdline AS cmd_line,
        windows_processes.sophos_pid AS sophos_pid,
        windows_processes.parent_sophos_pid AS parent_sophos_pid,
        windows_processes.sha256 AS sha256,
        NULL AS sha1,
        windows_processes.path AS path,
        windows_processes.ml_score AS ml_score,
        windows_processes.pua_score AS pua_score,
        windows_processes.global_rep AS global_rep,
        windows_processes.local_rep AS local_rep,
        NULL AS gid,
        NULL AS uid,
        NULL AS euid,
        NULL AS egid,
        windows_processes.parent_path AS parent_path
    FROM
        xdr_data AS windows_processes
    WHERE
        windows_processes.query_name = 'running_processes_windows_sophos'
        AND LOWER(windows_processes.meta_hostname) LIKE LOWER('$$device_name$$')
)

SELECT
    ep_name,
    COUNT(DISTINCT sophos_pid) AS instances,
    process_name,
    path,
    cmd_line,
    DATE_FORMAT(FROM_UNIXTIME(MIN(date_time)), '%Y-%m-%dT%H:%i:%SZ') AS first_seen,
    DATE_FORMAT(FROM_UNIXTIME(MAX(date_time)), '%Y-%m-%dT%H:%i:%SZ') AS last_seen,
    user_name,
    parent_process_name,
    parent_path,
    ARRAY_JOIN(ARRAY_AGG(DISTINCT sophos_pid), CHR(10)) AS sophos_pid_list,
    ARRAY_JOIN(ARRAY_AGG(DISTINCT parent_sophos_pid), CHR(10)) AS parent_sophos_pid_list,
    sha256,
    sha1,
    ml_score,
    pua_score,
    global_rep,
    local_rep,
    gid,
    uid,
    euid,
    egid
FROM
    full_list
WHERE ep_name LIKE '$$device_name$$'
GROUP BY
    ep_name,
    user_name,
    parent_process_name,
    process_name,
    cmd_line,
    sha256,
    sha1,
    path,
    ml_score,
    pua_score,
    global_rep,
    local_rep,
    gid,
    uid,
    euid,
    egid,
    parent_path
ORDER BY pua_score DESC
LIMIT 5

),

LIST_OF_MAL AS (

  WITH full_list AS (
    SELECT
        linux_processes.meta_hostname AS ep_name,
        linux_processes.time AS date_time,
        NULL AS parent_process_name,
        linux_processes.name AS process_name,
        (
            SELECT DISTINCT linux_users.username
            FROM
                xdr_data AS linux_users
            WHERE
                query_name = 'user_accounts'
                AND linux_users.meta_hostname = linux_processes.meta_hostname
                AND linux_users.uid = linux_processes.uid
        ) AS user_name,
        linux_processes.cmdline AS cmd_line,
        linux_processes.pids || ':' || CAST(linux_processes.time AS VARCHAR) AS sophos_pid,
        NULL AS parent_sophos_pid,
        linux_processes.sha256 AS sha256,
        linux_processes.sha1 AS sha1,
        linux_processes.path AS path,
        NULL AS ml_score,
        NULL AS pua_score,
        NULL AS global_rep,
        NULL AS local_rep,
        linux_processes.gid AS gid,
        linux_processes.uid AS uid,
        linux_processes.euid AS euid,
        linux_processes.egid AS egid,
        NULL AS parent_path
    FROM
        xdr_data AS linux_processes
    WHERE
        linux_processes.query_name = 'running_processes_linux_events'
        AND LOWER(linux_processes.meta_hostname) LIKE LOWER('$$device_name$$')

    UNION ALL

    SELECT
        windows_processes.meta_hostname AS ep_name,
        windows_processes.time AS date_time,
        windows_processes.parent_name AS parent_process_name,
        windows_processes.name AS process_name,
        windows_processes.username AS user_name,
        windows_processes.cmdline AS cmd_line,
        windows_processes.sophos_pid AS sophos_pid,
        windows_processes.parent_sophos_pid AS parent_sophos_pid,
        windows_processes.sha256 AS sha256,
        NULL AS sha1,
        windows_processes.path AS path,
        windows_processes.ml_score AS ml_score,
        windows_processes.pua_score AS pua_score,
        windows_processes.global_rep AS global_rep,
        windows_processes.local_rep AS local_rep,
        NULL AS gid,
        NULL AS uid,
        NULL AS euid,
        NULL AS egid,
        windows_processes.parent_path AS parent_path
    FROM
        xdr_data AS windows_processes
    WHERE
        windows_processes.query_name = 'running_processes_windows_sophos'
        AND LOWER(windows_processes.meta_hostname) LIKE LOWER('$$device_name$$')
)

SELECT
    ep_name,
    COUNT(DISTINCT sophos_pid) AS instances,
    process_name,
    path,
    cmd_line,
    DATE_FORMAT(FROM_UNIXTIME(MIN(date_time)), '%Y-%m-%dT%H:%i:%SZ') AS first_seen,
    DATE_FORMAT(FROM_UNIXTIME(MAX(date_time)), '%Y-%m-%dT%H:%i:%SZ') AS last_seen,
    user_name,
    parent_process_name,
    parent_path,
    ARRAY_JOIN(ARRAY_AGG(DISTINCT sophos_pid), CHR(10)) AS sophos_pid_list,
    ARRAY_JOIN(ARRAY_AGG(DISTINCT parent_sophos_pid), CHR(10)) AS parent_sophos_pid_list,
    sha256,
    sha1,
    ml_score,
    pua_score,
    global_rep,
    local_rep,
    gid,
    uid,
    euid,
    egid
FROM
    full_list
WHERE ep_name LIKE '$$device_name$$'
GROUP BY
    ep_name,
    user_name,
    parent_process_name,
    process_name,
    cmd_line,
    sha256,
    sha1,
    path,
    ml_score,
    pua_score,
    global_rep,
    local_rep,
    gid,
    uid,
    euid,
    egid,
    parent_path
ORDER BY ml_score DESC
LIMIT 5

),

LIST_OF_ADMINS AS (

  SELECT DISTINCT
      meta_hostname AS ep_name,
      uid,
      --gid,
      username,
      description,
      directory,
      shell,
      type,
      uuid
  FROM xdr_data
  WHERE query_name = 'user_accounts'
  AND uid = 500
  AND meta_hostname LIKE '$$device_name$$'

),

DATALAKE_UPLOAD AS (

   SELECT
      meta_hostname ep_name,
      FORMAT('%,.2f',ROUND( ((to_unixtime(now())-to_unixtime(MAX(ingestion_timestamp)))/60/60),2)) Data_Latency_Hours,
      FORMAT('%,.2f',ROUND( ((to_unixtime(MAX(ingestion_timestamp)) - to_unixtime(MIN(ingestion_timestamp)))/60/60/24), 2)) Days_of_data,
      FORMAT('%,.2f',ROUND( (CAST( SUM(upload_size) AS DOUBLE)/1024/1024),3)) Total_Size_MB,
      COUNT(meta_hostname) DataLake_Records
   FROM
      xdr_data
   WHERE
      meta_hostname LIKE '$$device_name$$'
   GROUP BY meta_hostname
)

-- BLANK LINE BETWEEN EACH DEVICE
SELECT CAST(' ' AS VARCHAR) ATTRIBUTE, CAST(' ' AS VARCHAR) VALUE, CAST(' ' AS VARCHAR) CONTEXT, CAST(' ' AS VARCHAR) CONTEXT_DATA, CAST(' ' AS VARCHAR) NOTES

UNION ALL

SELECT CAST('=========================' AS VARCHAR) ATTRIBUTE, CAST('=========================' AS VARCHAR) VALUE, CAST('=========================' AS VARCHAR) CONTEXT, CAST('=========================' AS VARCHAR) CONTEXT_DATA, CAST('=========================' AS VARCHAR) NOTES

UNION ALL

SELECT CAST('DEVICE INFO' AS VARCHAR) ATTRIBUTE, CAST(' ' AS VARCHAR) VALUE, CAST(' ' AS VARCHAR) CONTEXT, CAST(' ' AS VARCHAR) CONTEXT_DATA, CAST(' ' AS VARCHAR) NOTES

UNION ALL

--LIST_OF_ADMINS
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'LIST_OF_ADMINS' VALUE, CAST('User Name: ' || username AS VARCHAR) CONTEXT, CAST('Type: '|| type AS VARCHAR) CONTEXT_DATA, CAST(' ' AS VARCHAR) NOTES FROM LIST_OF_ADMINS WHERE ep_name LIKE '$$device_name$$'

UNION ALL

--ENCRYPTION DETAILS
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'ENCRYPTION_DETAILS' VALUE, CAST('Drive Letter: ' || drive_letter AS VARCHAR) CONTEXT, CAST('Protection_Status: '|| protection_status AS VARCHAR) CONTEXT_DATA, CAST(' ' AS VARCHAR) NOTES FROM encryption_details WHERE ep_name LIKE '$$device_name$$'

UNION ALL

--PENDING WINDOWS UPDATES (LIMIT 5)
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'PENDING_WINDOWS_UPDATES' VALUE, CAST('Title: ' || title AS VARCHAR) CONTEXT, CAST('HOTFIX_ID: '|| hotfix_id AS VARCHAR) CONTEXT_DATA, CAST(' ' AS VARCHAR) NOTES FROM PENDING_UPDATES WHERE ep_name LIKE '$$device_name$$'

UNION ALL

--LISTENING_PORTS (LIMIT 5) (1-1000,3389)
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'LISTENING_PORTS' VALUE, CAST('Process Name: '|| name AS VARCHAR) CONTEXT, 'LISTENING_PORTS: '||CAST(port AS VARCHAR) CONTEXT_DATA, CAST(' ' AS VARCHAR) NOTES FROM LISTENING_PORTS WHERE ep_name LIKE '$$device_name$$'

UNION ALL

--INTERFACE_DETAILS (LIMIT 5) (IPv4 ONLY)
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'INTERFACE_DETAILS' VALUE, 'IP_ADDR: '|| address CONTEXT, 'INTERFACE_NAME: '||interface||chr(10)||'MAC_ADDR: '|| mac CONTEXT_DATA, CAST(' ' AS VARCHAR) NOTES FROM INTERFACE_DETAILS WHERE ep_name LIKE '$$device_name$$'

UNION ALL

--SUSPECT PUA (LIMIT 5)
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'SUSPECT_PUA' VALUE, 'PROCESS_NAME: '|| process_name ||chr(10)||'INSTANCES: '||CAST(instances AS VARCHAR) CONTEXT, 'PUA_SCORE: '||CAST(pua_score AS VARCHAR)||chr(10)||'LAST_SEEN: '|| last_seen CONTEXT_DATA, 'USER_NAME: '||user_name NOTES FROM LIST_OF_PUA WHERE ep_name LIKE '$$device_name$$' AND pua_score > 30

UNION ALL

--SUSPECT MAL (LIMIT 5)
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'SUSPECT_MAL' VALUE, 'PROCESS_NAME: '|| process_name ||chr(10)||'INSTANCES: '||CAST(instances AS VARCHAR) CONTEXT, 'ML_SCORE: '||CAST(ml_score AS VARCHAR)||chr(10)||'LAST_SEEN: '|| last_seen CONTEXT_DATA, 'USER_NAME: '||user_name NOTES FROM LIST_OF_MAL WHERE ep_name LIKE '$$device_name$$' AND ml_score > 30

UNION ALL

--DEVICE DATALAKE UPLOAD INFO
SELECT CAST('Device Name: '||ep_name AS VARCHAR) ATTRIBUTE, 'DATALAKE_UPLOAD' || '' VALUE, 'Data_Latency_Hours: ' || Data_Latency_Hours||chr(10)||'Days_of_data: '|| Days_of_data CONTEXT, 'Total_Size_MB: '|| Total_Size_MB||chr(10)||'DataLake_Records: '|| CAST(DataLake_Records AS VARCHAR) CONTEXT_DATA, '' NOTES FROM DATALAKE_UPLOAD WHERE ep_name LIKE '$$device_name$$' GROUP BY ep_name, Data_Latency_Hours, Days_of_data, Total_Size_MB, DataLake_Records

Understanding the Code

This query is 400+ lines of syntax - by far one of the largest ones many use in their hunting. 

The two core principles to take away from this query are virtual tables and cast functions. The query works by allowing the platform to bundle information in small virtual tables over and over. It will then cache and separate each bundle or result line by line.


Happy querying!

-jk



Minor edits
[edited by: Qoosh at 9:44 PM (GMT -7) on 28 Jun 2022]