教程:使用 ES|QL 进行威胁狩猎

本动手实践教程演示如何使用 Elasticsearch 查询语言(ES|QL)执行高级威胁狩猎技术。

在一个模拟的高级持续性威胁(APT)攻击活动中,我们分析身份验证、进程执行和网络遥测数据中的安全事件,以检测:

  • 通过恶意电子邮件附件进行的初始入侵

  • 通过网络进行的横向移动

  • 权限提升尝试

  • 数据外泄活动

ES|QL 支持强大的转换、过滤、数据丰富和统计分析功能,非常适合复杂的安全调查。本教程提供了使用 ES|QL 进行威胁狩猎的实际示例,从识别可疑用户行为到构建攻击时间线。

要求

你需要一个正在运行的 Elasticsearch 集群 以及 Kibana 才能运行本教程。有关部署选项,请参阅部署类型选择文档。

如何运行 ES|QL 查询

在本教程中,ES|QL 示例以下面的格式显示:

vbnet 复制代码
`

1.  FROM windows-security-logs
2.  | WHERE event.code == "4624"
3.  | LIMIT 1000

`Lobster AI

你可以使用以下方式运行这些查询:

  • 交互式界面:

    • Timeline。在导航菜单中查找 Timeline,或者使用全局搜索字段。

    • Discover。在导航菜单中查找 Discover,或者使用全局搜索字段。

  • 通过 Dev Tools Console 使用 REST API。此方式需要额外的格式:

查看 ES|QL 的 Console 语法

python 复制代码
`

1.  POST /_query?format=txt
2.  {
3.    "query": """
4.      FROM windows-security-logs
5.      | WHERE event.code == "4624"
6.      | LIMIT 1000
7.    """
8.  }

`Lobster AI

步骤 0:添加示例数据

要跟随本教程进行操作,你需要使用 Dev Tools Console 向集群添加示例数据。

总体来说,数据分为两种类型:

  1. 核心索引:这些是包含你要分析的日志和事件的主要安全索引。我们需要三个核心索引:windows-security-logsprocess-logsnetwork-logs

  2. 查找索引:这些是为核心数据提供额外上下文的辅助索引。我们需要三个查找索引:asset-inventoryuser-contextthreat-intel

创建核心索引

首先,为我们的威胁狩猎场景创建核心安全索引:

bash 复制代码
`

1.  PUT /windows-security-logs
2.  {
3.    "mappings": {
4.      "properties": {
5.        "@timestamp": {"type": "date"},
6.        "event": {
7.          "properties": {
8.            "code": {"type": "keyword"}, # Event codes like 4624 (successful logon) and 4625 (failed logon) are stored as keywords for exact matching.
9.            "action": {"type": "keyword"}
10.          }
11.        },
12.        "user": {
13.          "properties": {
14.            "name": {"type": "keyword"},
15.            "domain": {"type": "keyword"}
16.          }
17.        },
18.        "host": {
19.          "properties": {
20.            "name": {"type": "keyword"},
21.            "ip": {"type": "ip"}
22.          }
23.        },
24.        "source": {
25.          "properties": {
26.            "ip": {"type": "ip"}
27.          }
28.        },
29.        "logon": {
30.          "properties": {
31.            "type": {"type": "keyword"}
32.          }
33.        }
34.      }
35.    }
36.  }

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

事件代码(例如 4624(登录成功)和 4625(登录失败))以 keyword 类型存储,以便进行精确匹配。

现在,让我们向 windows-security-logs 索引添加一些身份验证事件示例数据,也就是登录失败和登录成功事件。

bash 复制代码
`

1.  POST /_bulk?refresh=wait_for
2.  {"index":{"_index":"windows-security-logs"}}
3.  {"@timestamp":"2025-05-20T08:15:00Z","event":{"code":"4625","action":"logon_failed"},"user":{"name":"jsmith","domain":"corp"},"host":{"name":"WS-001","ip":"10.1.1.50"},"source":{"ip":"10.1.1.100"}}
4.  {"index":{"_index":"windows-security-logs"}}
5.  {"@timestamp":"2025-05-20T08:17:00Z","event":{"code":"4624","action":"logon_success"},"user":{"name":"jsmith","domain":"corp"},"host":{"name":"WS-001","ip":"10.1.1.50"},"source":{"ip":"10.1.1.100"},"logon":{"type":"3"}}
6.  {"index":{"_index":"windows-security-logs"}}
7.  {"@timestamp":"2025-05-20T09:30:00Z","event":{"code":"4624","action":"logon_success"},"user":{"name":"jsmith","domain":"corp"},"host":{"name":"SRV-001","ip":"10.1.2.10"},"source":{"ip":"10.1.1.50"},"logon":{"type":"3"}}
8.  {"index":{"_index":"windows-security-logs"}}
9.  {"@timestamp":"2025-05-20T10:45:00Z","event":{"code":"4624","action":"logon_success"},"user":{"name":"jsmith","domain":"corp"},"host":{"name":"DB-001","ip":"10.1.3.5"},"source":{"ip":"10.1.2.10"},"logon":{"type":"3"}}
10.  {"index":{"_index":"windows-security-logs"}}
11.  {"@timestamp":"2025-05-20T02:30:00Z","event":{"code":"4624","action":"logon_success"},"user":{"name":"admin","domain":"corp"},"host":{"name":"DC-001","ip":"10.1.4.10"},"source":{"ip":"10.1.3.5"},"logon":{"type":"3"}}

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

接下来,创建一个用于进程执行日志的索引。

bash 复制代码
`

1.  PUT /process-logs
2.  {
3.    "mappings": {
4.      "properties": {
5.        "@timestamp": {"type": "date"},
6.        "process": {
7.          "properties": {
8.            "name": {"type": "keyword"},
9.            "command_line": {"type": "text"}, # Command lines are stored as text fields to enable full-text search for suspicious parameters and encoded commands.
10.            "parent": {
11.              "properties": {
12.                "name": {"type": "keyword"}
13.              }
14.            }
15.          }
16.        },
17.        "user": {
18.          "properties": {
19.            "name": {"type": "keyword"}
20.          }
21.        },
22.        "host": {
23.          "properties": {
24.            "name": {"type": "keyword"}
25.          }
26.        }
27.      }
28.    }
29.  }

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

命令行以 text 字段存储,以支持针对可疑参数和编码命令的全文搜索。

process-logs 索引添加一些示例数据。

swift 复制代码
`

1.  POST /_bulk?refresh=wait_for
2.  {"index":{"_index":"process-logs"}}
3.  {"@timestamp":"2025-05-20T08:20:00Z","process":{"name":"powershell.exe","command_line":"powershell.exe -enc JABzAD0ATgBlAHcALgBPAGIAagBlAGMAdAAgAFMAeQBzAHQAZQBtAC4ATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAA=","parent":{"name":"winword.exe"}},"user":{"name":"jsmith"},"host":{"name":"WS-001"}}
4.  {"index":{"_index":"process-logs"}}
5.  {"@timestamp":"2025-05-20T09:35:00Z","process":{"name":"net.exe","command_line":"net user /domain","parent":{"name":"cmd.exe"}},"user":{"name":"jsmith"},"host":{"name":"SRV-001"}}
6.  {"index":{"_index":"process-logs"}}
7.  {"@timestamp":"2025-05-20T10:50:00Z","process":{"name":"sqlcmd.exe","command_line":"sqlcmd -S localhost -Q \"SELECT * FROM customers\"","parent":{"name":"powershell.exe"}},"user":{"name":"jsmith"},"host":{"name":"DB-001"}}
8.  {"index":{"_index":"process-logs"}}
9.  {"@timestamp":"2025-05-20T02:35:00Z","process":{"name":"ntdsutil.exe","command_line":"ntdsutil \"ac i ntds\" \"ifm\" \"create full c:\\temp\\ntds\"","parent":{"name":"cmd.exe"}},"user":{"name":"admin"},"host":{"name":"DC-001"}}
10.  {"index":{"_index":"process-logs"}}
11.  {"@timestamp":"2025-05-20T12:15:00Z","process":{"name":"schtasks.exe","command_line":"schtasks.exe /create /tn UpdateCheck /tr c:\\windows\\temp\\update.exe /sc daily","parent":{"name":"cmd.exe"}},"user":{"name":"jsmith"},"host":{"name":"WS-001"}}
12.  {"index":{"_index":"process-logs"}}
13.  {"@timestamp":"2025-05-20T12:30:00Z","process":{"name":"schtasks.exe","command_line":"schtasks.exe /create /tn SystemManager /tr powershell.exe -enc ZQBjAGgAbwAgACIASABlAGwAbABvACIA /sc minute /mo 5","parent":{"name":"powershell.exe"}},"user":{"name":"jsmith"},"host":{"name":"SRV-001"}}
14.  {"index":{"_index":"process-logs"}}
15.  {"@timestamp":"2025-05-20T13:15:00Z","process":{"name":"sc.exe","command_line":"sc.exe create RemoteService binPath= c:\\windows\\temp\\remote.exe","parent":{"name":"cmd.exe"}},"user":{"name":"jsmith"},"host":{"name":"DB-001"}}
16.  {"index":{"_index":"process-logs"}}
17.  {"@timestamp":"2025-05-20T13:20:00Z","process":{"name":"sc.exe","command_line":"sc.exe create BackdoorService binPath= c:\\programdata\\svc.exe","parent":{"name":"powershell.exe"}},"user":{"name":"jsmith"},"host":{"name":"SRV-001"}}
18.  {"index":{"_index":"process-logs"}}
19.  {"@timestamp":"2025-05-20T13:25:00Z","process":{"name":"sc.exe","command_line":"sc.exe create PersistenceService binPath= c:\\windows\\system32\\malicious.exe","parent":{"name":"cmd.exe"}},"user":{"name":"admin"},"host":{"name":"DC-001"}}

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

接下来,创建一个用于网络流量日志的索引。

bash 复制代码
`

1.  PUT /network-logs
2.  {
3.    "mappings": {
4.      "properties": {
5.        "@timestamp": {"type": "date"},
6.        "source": {
7.          "properties": {
8.            "ip": {"type": "ip"},
9.            "port": {"type": "integer"}
10.          }
11.        },
12.        "destination": {
13.          "properties": {
14.            "ip": {"type": "ip"},
15.            "port": {"type": "integer"}
16.          }
17.        },
18.        "network": {
19.          "properties": {
20.            "bytes": {"type": "long"},
21.            "protocol": {"type": "keyword"}
22.          }
23.        },
24.        "host": {
25.          "properties": {
26.            "name": {"type": "keyword"}
27.          }
28.        }
29.      }
30.    }
31.  }

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

network-logs 索引添加一些示例数据。

bash 复制代码
`

1.  POST /_bulk?refresh=wait_for
2.  {"index":{"_index":"network-logs"}}
3.  {"@timestamp":"2025-05-20T08:25:00Z","source":{"ip":"10.1.1.50","port":52341},"destination":{"ip":"185.220.101.45","port":443},"network":{"bytes":2048,"protocol":"tcp"},"host":{"name":"WS-001"}}
4.  {"index":{"_index":"network-logs"}}
5.  {"@timestamp":"2025-05-20T11:15:00Z","source":{"ip":"10.1.3.5","port":54892},"destination":{"ip":"185.220.101.45","port":443},"network":{"bytes":50000000,"protocol":"tcp"},"host":{"name":"DB-001"}}
6.  {"index":{"_index":"network-logs"}}
7.  {"@timestamp":"2025-05-20T02:40:00Z","source":{"ip":"10.1.4.10","port":61234},"destination":{"ip":"185.220.101.45","port":443},"network":{"bytes":500000000,"protocol":"tcp"},"host":{"name":"DC-001"}}

`Lobster AI

创建查找索引

查找模式允许这些索引与 LOOKUP JOIN 操作一起使用,从而使用资产上下文丰富安全事件。

使用 lookup 索引模式创建我们需要的索引。

bash 复制代码
`

1.  PUT /asset-inventory
2.  {
3.    "mappings": {
4.      "properties": {
5.        "host.name": {"type": "keyword"},
6.        "asset.criticality": {"type": "keyword"},
7.        "asset.owner": {"type": "keyword"},
8.        "asset.department": {"type": "keyword"}
9.      }
10.    },
11.    "settings": {
12.      "index.mode": "lookup"
13.    }
14.  }

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
bash 复制代码
`

1.  PUT /user-context
2.  {
3.    "mappings": {
4.      "properties": {
5.        "user.name": {"type": "keyword"},
6.        "user.role": {"type": "keyword"},
7.        "user.department": {"type": "keyword"},
8.        "user.privileged": {"type": "boolean"}
9.      }
10.    },
11.    "settings": {
12.      "index.mode": "lookup"
13.    }
14.  }

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
bash 复制代码
`

1.  PUT /threat-intel
2.  {
3.    "mappings": {
4.      "properties": {
5.        "indicator.value": {"type": "keyword"},
6.        "indicator.type": {"type": "keyword"},
7.        "threat.name": {"type": "keyword"},
8.        "threat.severity": {"type": "keyword"}
9.      }
10.    },
11.    "settings": {
12.      "index.mode": "lookup"
13.    }
14.  }

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

现在,我们可以使用上下文数据填充查找索引。这个单独的批量操作可以通过一次请求,将数据分别写入 user-contextthreat-intelasset-inventory 索引。

bash 复制代码
`

1.  POST /_bulk?refresh=wait_for
2.  {"index":{"_index":"asset-inventory"}}
3.  {"host.name":"WS-001","asset.criticality":"medium","asset.owner":"IT","asset.department":"finance"}
4.  {"index":{"_index":"asset-inventory"}}
5.  {"host.name":"SRV-001","asset.criticality":"high","asset.owner":"IT","asset.department":"operations"}
6.  {"index":{"_index":"asset-inventory"}}
7.  {"host.name":"DB-001","asset.criticality":"critical","asset.owner":"DBA","asset.department":"finance"}
8.  {"index":{"_index":"asset-inventory"}}
9.  {"host.name":"DC-001","asset.criticality":"critical","asset.owner":"IT","asset.department":"infrastructure"}
10.  {"index":{"_index":"user-context"}}
11.  {"user.name":"jsmith","user.role":"analyst","user.department":"finance","user.privileged":false}
12.  {"index":{"_index":"user-context"}}
13.  {"user.name":"admin","user.role":"administrator","user.department":"IT","user.privileged":true}
14.  {"index":{"_index":"threat-intel"}}
15.  {"indicator.value":"185.220.101.45","indicator.type":"ip","threat.name":"APT-29","threat.severity":"high"}
16.  {"index":{"_index":"threat-intel"}}
17.  {"indicator.value":"powershell.exe","indicator.type":"process","threat.name":"Living off the Land","threat.severity":"medium"}

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)

步骤 1:狩猎初始入侵指标

我们的威胁狩猎第一阶段关注识别初始入侵。我们希望搜索来自 Office 应用程序的可疑 PowerShell 执行,这是常见的初始攻击向量。

ini 复制代码
`

1.  FROM process-logs
2.  | WHERE process.name == "powershell.exe" AND process.parent.name LIKE "*word*" #1
3.  | LOOKUP JOIN asset-inventory ON host.name  #2
4.  | LOOKUP JOIN user-context ON user.name  #3
5.  | EVAL encoded_command = CASE(process.command_line LIKE "*-enc*", true, false) #4
6.  | WHERE encoded_command == true #5
7.  | STATS count = COUNT(*) BY host.name, user.name, asset.criticality #6
8.  | LIMIT 1000

`Lobster AI
  1. 使用 [WHERE](https://www.elastic.co/docs/reference/query-languages/esql/commands/where "WHERE")[==](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/operators#esql-equals "==")[LIKE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/operators#esql-like "LIKE") 运算符检测 PowerShell 进程。

  2. 使用 [LOOKUP JOIN](https://www.elastic.co/docs/reference/query-languages/esql/commands/lookup-join "LOOKUP JOIN") 与资产清单进行数据丰富。

  3. 使用 LOOKUP JOIN 添加用户上下文。

  4. 使用 [EVAL](https://www.elastic.co/docs/reference/query-languages/esql/commands/eval "EVAL")[CASE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/conditional-functions-and-expressions/case "CASE") 检测编码命令。

  5. 使用 [WHERE](https://www.elastic.co/docs/reference/query-languages/esql/commands/where "WHERE") 进行额外过滤。

  6. 使用 [STATS](https://www.elastic.co/docs/reference/query-languages/esql/commands/stats-by "STATS")[COUNT](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/aggregation-functions/count "COUNT") 按多个字段对结果进行聚合。

响应

响应包含可疑 PowerShell 执行的摘要,包括主机名称、用户名和资产关键性。

count host.name user.name asset.criticality
1 WS-001 jsmith medium

步骤 2:检测横向移动模式

在此步骤中,我们跟踪用户在多个系统上的身份验证情况。这对于识别横向移动和潜在的权限提升非常重要。

此查询演示了 [DATE_TRUNC](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/date-time-functions/date_trunc "DATE_TRUNC") 如何创建时间窗口来进行速度分析,并结合 [COUNT_DISTINCT](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/aggregation-functions/count_distinct "COUNT_DISTINCT") 聚合和 [DATE_DIFF](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/date-time-functions/date_diff "DATE_DIFF") 计算,同时衡量用户在网络资产之间移动的范围和速度。

less 复制代码
`

1.  FROM windows-security-logs
2.  | WHERE event.code == "4624" AND logon.type == "3"
3.  | LOOKUP JOIN asset-inventory ON host.name
4.  | EVAL time_bucket = DATE_TRUNC(30 minute, @timestamp)
5.  | STATS unique_hosts = COUNT_DISTINCT(host.name),
6.          criticality_levels = COUNT_DISTINCT(asset.criticality),
7.          active_periods = COUNT_DISTINCT(time_bucket),
8.          first_login = MIN(@timestamp),
9.          last_login = MAX(@timestamp)
10.  BY user.name
11.  | WHERE unique_hosts > 2
12.  | EVAL time_span_hours = DATE_DIFF("hour", first_login, last_login)
13.  | EVAL movement_velocity = ROUND(unique_hosts / (time_span_hours + 1), 2)
14.  | EVAL lateral_movement_score = unique_hosts * criticality_levels
15.  | SORT lateral_movement_score DESC
16.  | LIMIT 1000

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
  1. 使用 WHERE 进行基本的身份验证过滤。

  2. 使用 DATE_TRUNC 创建时间桶,以进行时间类型分析。

  3. 使用 STATSCOUNT_DISTINCT 计算全面的访问指标。

  4. 使用 DATE_DIFF 计算持续时间。

  5. 使用 EVALCASE 进行风险评分。

响应

响应显示登录到多个主机的用户、这些主机的关键性级别以及其横向移动速度。

unique_hosts criticality_levels active_periods first_login last_login user.name time_span_hours movement_velocity lateral_movement_score
3 3 3 2025-05-20T08:17:00.000Z 2025-05-20T10:45:00.000Z jsmith 2 1 9

步骤 3: 识别数据 访问和潜在的数据外泄

高级攻击者通常会将敏感数据作为目标。我们希望狩猎数据库访问行为,以及向外部系统进行的大规模数据传输。

less 复制代码
`

1.  FROM network-logs
2.  | WHERE NOT CIDR_MATCH(destination.ip, "10.0.0.0/8", "192.168.0.0/16") #1
3.  | EVAL indicator.value = TO_STRING(destination.ip) #2
4.  | LOOKUP JOIN threat-intel ON indicator.value
5.  | LOOKUP JOIN asset-inventory ON host.name
6.  | WHERE threat.name IS NOT NULL
7.  | STATS total_bytes = SUM(network.bytes),
8.          connection_count = COUNT(*),
9.          time_span = DATE_DIFF("hour", MIN(@timestamp), MAX(@timestamp)) #3
10.  BY host.name, destination.ip, threat.name, asset.criticality
11.  | EVAL mb_transferred = ROUND(total_bytes / 1048576, 2) #4
12.  | EVAL risk_score = CASE(
13.      asset.criticality == "critical" AND mb_transferred > 100, 10,
14.      asset.criticality == "high" AND mb_transferred > 100, 7,
15.      mb_transferred > 50, 5,
16.      3
17.    ) #5
18.  | WHERE total_bytes > 1000000
19.  | SORT risk_score DESC, total_bytes DESC
20.  | LIMIT 1000

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
  1. 使用 [CIDR_MATCH](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/ip-functions/cidr_match "CIDR_MATCH") 过滤内部 IP 范围,以检测外部数据传输。

  2. 使用 [TO_STRING](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/type-conversion-functions/to_string "TO_STRING") 统一 IP 格式,以便执行威胁情报查找。

  3. 使用 [DATE_DIFF](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/date-time-functions/date_diff "DATE_DIFF"),结合 SUMCOUNT,衡量一段时间内的数据传输量。

  4. 使用 [ROUND](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/math-functions/round "ROUND") 生成便于人类阅读的数值。

  5. 使用 [CASE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/conditional-functions-and-expressions/case "CASE") 根据资产关键性和传输数据量进行风险评分。

响应

响应显示外部数据传输、其风险评分以及传输的数据量。

total_bytes connection_count time_span host.name destination.ip threat.name asset.criticality mb_transferred risk_score
500000000 1 0 DC-001 185.220.101.45 APT-29 critical 476 10
50000000 1 0 DB-001 185.220.101.45 APT-29 critical 47 3

步骤 4:构建攻击时间线并评估影响

为了了解攻击的推进过程,我们需要跨多个索引构建事件时间线。这有助于我们关联各种行为,并识别攻击者在环境中的驻留时间。

sql 复制代码
`

1.  FROM windows-security-logs, process-logs, network-logs  # 1
2.  | LOOKUP JOIN asset-inventory ON host.name
3.  | LOOKUP JOIN user-context ON user.name
4.  | WHERE user.name == "jsmith" OR user.name == "admin"
5.  | EVAL event_type = CASE(
6.      event.code IS NOT NULL, "Authentication",
7.      process.name IS NOT NULL, "Process Execution",
8.      destination.ip IS NOT NULL, "Network Activity",
9.      "Unknown") # 2
10.  | EVAL dest_ip = TO_STRING(destination.ip)
11.  | EVAL attack_stage = CASE(
12.      process.parent.name LIKE "*word*", "Initial Compromise",
13.      process.name IN ("net.exe", "nltest.exe"), "Reconnaissance",
14.      event.code == "4624" AND logon.type == "3", "Lateral Movement",
15.      process.name IN ("sqlcmd.exe", "ntdsutil.exe"), "Data Access",
16.      dest_ip NOT LIKE "10.*", "Exfiltration",
17.      "Other") # 3
18.  | SORT @timestamp ASC #4
19.  | KEEP @timestamp, event_type, attack_stage, host.name, asset.criticality, user.name, process.name, destination.ip
20.  | LIMIT 1000

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
  1. 使用 FROM 同时读取多个索引,以进行全面的数据关联。

  2. 使用 [IS NOT NULL](https://www.elastic.co/docs/reference/query-languages/esql/commands/processing-commands#null-predicates "IS NOT NULL")[CASE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/conditional-functions-and-expressions/case "CASE"),根据不同数据源对事件类型进行分类。

  3. 使用复杂的 [CASE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/conditional-functions-and-expressions/case "CASE") 逻辑将事件映射到 MITRE ATT&CK 阶段。

  4. 使用 [SORT](https://www.elastic.co/docs/reference/query-languages/esql/commands/sort "SORT") 构建按时间顺序排列的攻击时间线。

响应

响应提供按时间顺序排列的事件时间线,展示攻击者的行为以及对组织造成的影响。

@timestamp event_type attack_stage host.name asset.criticality user.name process.name destination.ip
2025-05-20T02:30:00.000Z 身份验证 横向移动 DC-001 critical admin null null
2025-05-20T02:35:00.000Z 进程执行 数据访问 DC-001 critical admin ntdsutil.exe null
2025-05-20T08:15:00.000Z 身份验证 其他 WS-001 medium jsmith null null
2025-05-20T08:17:00.000Z 身份验证 横向移动 WS-001 medium jsmith null null
2025-05-20T08:20:00.000Z 进程执行 初始入侵 WS-001 medium jsmith powershell.exe null
2025-05-20T09:30:00.000Z 身份验证 横向移动 SRV-001 high jsmith null null
2025-05-20T09:35:00.000Z 进程执行 侦察 SRV-001 high jsmith net.exe null
2025-05-20T10:45:00.000Z 身份验证 横向移动 DB-001 critical jsmith null null
2025-05-20T10:50:00.000Z 进程执行 数据访问 DB-001 critical jsmith sqlcmd.exe null
2025-05-20T12:15:00.000Z 进程执行 其他 WS-001 medium jsmith schtasks.exe null
2025-05-20T12:30:00.000Z 进程执行 其他 SRV-001 high jsmith schtasks.exe null
2025-05-20T13:15:00.000Z 进程执行 其他 DB-001 critical jsmith sc.exe null
2025-05-20T13:20:00.000Z 进程执行 其他 SRV-001 high jsmith sc.exe null
2025-05-20T13:25:00.000Z 进程执行 其他 DC-001 critical admin sc.exe null

步骤 5:狩猎异常的 解释器 使用行为

此查询演示了如何使用 ES|QL 的 [COUNT_DISTINCT](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/aggregation-functions/count_distinct "COUNT_DISTINCT") 函数和条件 [CASE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/conditional-functions-and-expressions/case "CASE") 语句,以用户和部门为维度建立解释器使用行为基线,并利用聚合函数识别异常脚本执行,这类行为可能表明账户已遭入侵或存在内部威胁。

sql 复制代码
`

1.  FROM process-logs
2.  | WHERE process.name IN ("powershell.exe", "cmd.exe", "net.exe", "sqlcmd.exe", "schtasks.exe", "sc.exe")
3.  | LOOKUP JOIN asset-inventory ON host.name
4.  | LOOKUP JOIN user-context ON user.name
5.  | STATS executions = COUNT(*),
6.          unique_hosts = COUNT_DISTINCT(host.name),
7.          unique_commands = COUNT_DISTINCT(process.name)
8.  BY user.name, user.department
9.  | WHERE executions > 1
10.  | EVAL usage_pattern = CASE(
11.      executions > 5, "High Usage",
12.      executions > 3, "Moderate Usage",
13.      "Low Usage"
14.    )
15.  | SORT executions DESC
16.  | LIMIT 1000

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
  1. 使用 WHERE...IN 监控高风险系统工具。

  2. 使用 [LOOKUP JOIN](https://www.elastic.co/docs/reference/query-languages/esql/commands/lookup-join "LOOKUP JOIN")asset-inventoryuser-context 索引结合,为事件添加上下文。

  3. 使用 [COUNT_DISTINCT](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/aggregation-functions/count_distinct "COUNT_DISTINCT") 衡量可疑工具使用的广度。

  4. 使用 [CASE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/conditional-functions-and-expressions/case "CASE") 对使用模式进行分类,以便进行异常检测。

响应

响应显示每个用户和部门的执行次数、唯一主机数量以及使用模式。

executions unique_hosts unique_commands user.name user.department usage_pattern
7 3 5 jsmith finance 高使用量

步骤 6:狩猎持久化机制

此查询展示了 [DATE_TRUNC](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/date-time-functions/date_trunc "DATE_TRUNC") 如何支持对持久化机制进行时间类型分析,通过时间分桶和 [COUNT_DISTINCT](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/aggregation-functions/count_distinct "COUNT_DISTINCT") 识别快速连续创建任务或跨多个时间窗口建立持久化等可疑模式。

less 复制代码
`

1.  FROM process-logs
2.  | WHERE process.name == "schtasks.exe" AND process.command_line:"/create" #1
3.  | LOOKUP JOIN asset-inventory ON host.name
4.  | LOOKUP JOIN user-context ON user.name
5.  | EVAL time_bucket = DATE_TRUNC(1 hour, @timestamp) #2
6.  | STATS task_creations = COUNT(*),
7.          creation_hours = COUNT_DISTINCT(time_bucket) #3
8.  BY user.name, host.name, asset.criticality
9.  | WHERE task_creations > 0
10.  | EVAL persistence_pattern = CASE(
11.      creation_hours > 1, "Multiple Hours",
12.      task_creations > 1, "Burst Creation",
13.      "Single Task"
14.    )
15.  | SORT task_creations DESC
16.  | LIMIT 1000

`Lobster AI![](https://csdnimg.cn/release/blogv2/dist/pc/img/runCode/icon-arrowwhite.png)
  1. 使用带有 : 匹配运算符的 [WHERE](https://www.elastic.co/docs/reference/query-languages/esql/commands/where "WHERE"),检测计划任务创建行为(这是一种常见的持久化机制)。

  2. 使用 [DATE_TRUNC](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/date-time-functions/date_trunc "DATE_TRUNC") 将事件划分到按小时计算的时间桶中,以进行时间类型分析。

  3. 使用 [COUNT_DISTINCT](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/aggregation-functions/count_distinct "COUNT_DISTINCT")time_bucket 衡量任务创建速度。

  4. 使用 [CASE](https://www.elastic.co/docs/reference/query-languages/esql/functions-operators/conditional-functions-and-expressions/case "CASE") 根据时间和频率对可疑模式进行分类。

响应

响应显示每个用户和主机的任务创建数量、创建时间以及持久化模式。

task_creations creation_hours user.name host.name asset.criticality persistence_pattern
1 1 jsmith WS-001 medium 单个任务
1 1 jsmith SRV-001 high 单个任务

其他资源

提示

要了解可以在 Elastic Security 的哪些场景中使用 ES|QL,请参阅 ES|QL for security 概览

原文:Tutorial: Threat hunting with ES|QL | Elastic Docs

相关推荐
智搜广告3 小时前
GEO优化公司怎么选?智搜广告从三个维度帮你判断
大数据·人工智能·python·elasticsearch·microsoft·geo
Elastic 中国社区官方博客3 小时前
Elasticsearch:ES|QL 搜索教程
大数据·数据库·人工智能·sql·elasticsearch·搜索引擎·全文检索
Elasticsearch5 小时前
Elasticsearch 中的查询重写规则:通配符扫描速度提升 2.3 倍
elasticsearch
Elasticsearch5 小时前
隐藏在可观测性数据中的安全攻击
elasticsearch
Elasticsearch19 小时前
Elasticsearch:ES|QL 搜索教程
elasticsearch
玖石书1 天前
Git Submodule 完全指南:从添加到日常维护的常规操作全流程
大数据·git·elasticsearch
晴天161 天前
ES 标准、V8 引擎与 Node.js 版本联动关系全解与实战踩坑
大数据·elasticsearch·node.js
考虑考虑2 天前
ElasticSearch索引命令
运维·后端·elasticsearch
Elastic 中国社区官方博客2 天前
在 Elasticsearch 中回填时间序列数据:通过批量 API 加载数月的历史指标数据
大数据·运维·数据库·人工智能·elasticsearch·搜索引擎·全文检索