Mastering Kibana Query Language (KQL) for Threat Hunting
When you deploy a SIEM like Elastic Security, the volume of data can be overwhelming. A medium-sized enterprise can easily generate billions of log events per week. For a security analyst, finding a single malicious PowerShell command in that ocean of data is impossible without a fast, intuitive way to search.
Enter the Kibana Query Language (KQL). KQL is the default search language in Kibana, designed specifically for rapid filtering and data exploration. It is the primary weapon a Blue Teamer uses to conduct active threat hunts.
In this post, we will cover the fundamentals of KQL and provide practical examples of how to use it to hunt for malicious activity.
KQL vs. Lucene
Historically, Kibana relied on the Lucene query syntax. While Lucene is incredibly powerful, its syntax can be clunky, and it requires a deep understanding of how Elasticsearch indexes text.
KQL was built to simplify the analyst experience. It supports auto-complete, seamlessly handles complex logical operators, and automatically queries nested fields without requiring convoluted syntax.
Note: If you are an experienced Elastic user, you can still toggle back to Lucene in the Kibana search bar, but KQL is strongly recommended for daily SOC operations.
The Basics: Free Text and Field-Level Searches
Free Text Search:
If you simply want to search across all indexed fields for a specific IP address or a keyword, you just type it into the search bar:
"192.168.1.50"
While this is easy, it is highly inefficient and slow on massive datasets, as Elasticsearch has to scan every single field.
Field-Level Search (The Right Way):
To make your searches lightning-fast, you should specify the exact field you are targeting using a colon (:).
source.ip : "192.168.1.50"
user.name : "admin"
Logical Operators
KQL uses standard boolean operators (and, or, not) to chain multiple conditions together. These operators are case-insensitive, but capitalizing them is a best practice for readability.
Example: Hunting for failed RDP logins from a specific subnet.
event.code : 4625 AND process.name : "svchost.exe" AND source.ip : 10.10.0.0/16
Example: Excluding noise (The NOT Operator).
When threat hunting, you often need to filter out legitimate business processes to find the anomalies.
process.name : "powershell.exe" AND NOT user.name : "service_sccm"
Wildcards and Range Queries
KQL supports the use of wildcards (*) to match partial strings, which is incredibly useful for catching variations of malware names or dynamic directories.
Example: Hunting for executables running from the Temp directory.
process.executable : *\\Windows\\Temp\\*.exe
KQL also supports mathematical range operators (>, >=, <, <=) for numerical fields and timestamps.
Example: Hunting for large outbound network transfers (Data Exfiltration).
network.direction : "outbound" AND destination.bytes >= 500000000
Practical Threat Hunting: The Encoded Command
Let's put it all together to hunt for a classic Red Team technique: executing a Base64 encoded PowerShell script to bypass endpoint logging.
Because Elastic uses the Elastic Common Schema (ECS), field names are standardized. We can write a single KQL query that looks for the powershell.exe process combined with common command-line flags used for encoding (-e, -enc, -encodedcommand):
process.name : ("powershell.exe" OR "pwsh.exe") AND process.command_line : (*-e * OR *-enc * OR *-encodedCommand *) AND NOT user.name : "SYSTEM"
If you drop this query into the Kibana Discover tab, you will instantly filter out millions of benign logs and be presented only with the highly suspicious PowerShell executions.
Conclusion
Mastering KQL is the fastest way to elevate your value as a SOC analyst. By moving away from slow, free-text searches and leveraging structured field queries, wildcards, and exclusions, you can slice through terabytes of logs in seconds to uncover hidden adversaries.