Build the same detection in Splunk SPL, Elastic KQL and Microsoft Sentinel KQL at once. 30+ MITRE-tagged presets and a full field-mapping reference.
This SIEM query builder writes the same detection three times — once in Splunk SPL, once in Elastic KQL, and once in Microsoft Sentinel KQL — from a single set of filter conditions. Pick a field, an operator and a value, choose how to group the results, and the tool emits a syntactically correct query for each platform side by side. Everything runs in your browser: no log data is uploaded, no credentials are needed, and nothing is stored.
It exists because detection engineers rarely get to stay on one platform. A rule written for a Splunk deployment has to be re-expressed when the SOC migrates to Sentinel, when a managed service provider onboards a client running Elastic, or when a threat-intel report publishes a detection in a syntax nobody on the team uses daily. The hard part is almost never the logic — it is remembering that a username is user in Splunk, user.name in Elastic Common Schema, and AccountName in the Sentinel SecurityEvent table. This tool holds that mapping so you do not have to.
There are two tabs:
Fifteen normalised fields are supported — user, source IP, destination IP, Windows event ID, process name, command line, host, action, status, port, domain, URL, file path, SHA-256 hash and parent process — each with its platform-specific field name already mapped.
index= and sourcetype= prefix; in Sentinel it becomes the table name the query starts from.The generated query is a starting point, not a finished production rule. Always run it against a bounded time window first, confirm the field names match your own ingestion pipeline, and tune the threshold before you attach an alert to it.
Take the most common detection in any SOC: repeated failed Windows logons from a single source address, which maps to MITRE ATT&CK T1110 (Brute Force). Windows writes event ID 4625 on every failed logon. Here is that detection expressed three ways.
Splunk SPL. SPL starts with a bare search and pipes results through transforming commands:
index=security sourcetype=WinEventLog:Security EventCode=4625
| stats count by src_ip, user
| where count > 5
| sort - count
| head 20
Microsoft Sentinel (KQL). Sentinel KQL always starts from a table name, and every filter is an explicit where operator. Aggregation uses summarize rather than stats:
SecurityEvent
| where EventID == 4625
| summarize FailedAttempts = count() by IpAddress, AccountName
| where FailedAttempts > 5
| order by FailedAttempts desc
| take 20
Elastic KQL. Elastic’s Kibana Query Language is a filter language, not a pipeline language. It expresses the match but not the aggregation — in Kibana you add the group-by through a visualisation or an aggregation clause rather than in the query string:
event.code: "4625" AND event.outcome: "failure" AND source.ip: 10.0.0.*
That last point is the single most important difference between the three, and it catches people out constantly. Splunk SPL and Sentinel KQL are both pipeline languages: you can filter, aggregate, sort and limit in one expression. Elastic KQL only filters. If a detection needs a threshold (“more than five failures in ten minutes”), Elastic expresses that in the rule definition or in an Elasticsearch aggregation, not in the KQL string itself.
The second thing that breaks ported detections is field naming. Elastic standardises on the Elastic Common Schema (ECS), which uses dotted, lower-case, namespaced names. Sentinel uses table-specific PascalCase column names. Splunk uses whatever the Common Information Model or your own props/transforms produced, which in practice is short snake_case. A representative slice of the mapping this tool applies:
| Concept | Splunk SPL | Elastic (ECS) | Sentinel KQL |
|---|---|---|---|
| Username | user | user.name | AccountName |
| Source IP | src_ip | source.ip | IpAddress |
| Destination IP | dest_ip | destination.ip | DestinationIP |
| Windows event ID | EventCode | event.code | EventID |
| Process name | process | process.name | ProcessName |
| Parent process | parent_process | process.parent.name | ParentProcessName |
| Command line | CommandLine | process.command_line | CommandLine |
| Hostname | host | host.name | Computer |
| Destination port | dest_port | destination.port | DestinationPort |
| SHA-256 hash | file_hash | file.hash.sha256 | SHA256 |
| DNS query name | domain | dns.question.name | QueryName |
Operators differ too. Equality is = in SPL, : in Elastic KQL and == in Sentinel KQL. Substring matching is a wildcard on both sides in SPL and Elastic (field="*value*") but a dedicated contains operator in Sentinel. List membership is IN (…) in SPL, in (…) in Sentinel, and an OR-joined group in Elastic.
Base64-encoded PowerShell (T1059.001) is a durable, high-signal detection. The logic is “process is powershell.exe and the command line contains -enc”. Note how differently each language expresses the substring match:
Splunk: index=* process="powershell.exe" AND CommandLine="*-enc*"
Elastic: process.name: "powershell.exe" AND process.command_line: *-enc*
Sentinel: SecurityEvent
| where ProcessName == "powershell.exe"
| where CommandLine contains "-enc"
Tune this one before deploying it. PowerShell accepts abbreviations of -EncodedCommand down to -e, so a determined attacker will use -ec or -EncodedComm; a production version of this rule usually matches a regex over the argument prefix instead of a fixed string. That is exactly the kind of refinement the builder is meant to hand off to you rather than pretend to solve.
Once a detection fires you usually need to enrich it. The DNS lookup tool resolves a suspicious domain and shows its records, the WHOIS lookup gives registration age and registrar, and the hash generator produces the SHA-256 values you will paste into an IOC filter. If you are parsing raw web-server logs before they reach the SIEM, the Nginx log pattern reference covers the field extraction side.
Three: Splunk SPL, Elastic KQL (Kibana Query Language) and Microsoft Sentinel KQL (Kusto Query Language). Every query you build is emitted in all three simultaneously so you can compare them directly.
No, despite the shared acronym. Elastic’s KQL is Kibana Query Language, a filter-only syntax for matching documents. Microsoft’s KQL is Kusto Query Language, a full pipeline analytics language with where, summarize, project, join and dozens of other operators. They share almost nothing except the letters.
It does not. It generates query text that you copy into your own console. No API keys, no connectors, and no log data ever leaves your browser — which also means you can use it from a workstation that has no network path to the SIEM.
Treat them as a well-formed first draft. The syntax is correct and the field mappings reflect the standard schemas, but every environment has its own index names, sourcetypes, custom parsers and normalisation. Run the query over a short time window, verify it returns what you expect, then set thresholds based on your own baseline before alerting on it.
ATT&CK is a public catalogue of adversary techniques observed in real intrusions, each with a stable ID such as T1110 (Brute Force) or T1047 (Windows Management Instrumentation). Tagging detections with technique IDs lets you measure coverage — which techniques you can currently see and which you cannot — rather than just counting rules.
Almost always a field-name or index mismatch. Start by removing every filter and searching the raw index or table for a single event, then confirm the actual field names present on that event and add filters back one at a time. Wrong index, wrong sourcetype, a time range that predates ingestion, and a field that your parser never extracted are the four usual causes.
The KQL output works as the query portion of a custom Elastic detection rule. Threshold logic, however, belongs in the rule configuration rather than the query string, so for a “more than N events” detection you set the rule type to Threshold and configure the field and count there.
Microsoft Sentinel bills primarily on data ingestion and retention rather than per query, but long lookback windows over large tables consume resources and can be slow. Constrain the time range and project only the columns you need — that is good practice for cost and for query performance in every SIEM.
Build the query with the closest normalised field, copy the output, and rename the field in your editor. The value of the tool is the structure and the operator syntax; a single find-and-replace on a field name is a much smaller job than reconstructing a pipeline from scratch.
No. The builder is entirely client-side JavaScript. Filter values you type — including internal hostnames, usernames or IP addresses — stay in the browser tab and are never transmitted.
A SIEM (Security Information and Event Management) query builder helps security analysts construct search queries for SIEM platforms without memorizing each platform's proprietary query language. SIEM systems ingest, normalize, and correlate security events from across an organization's infrastructure — firewalls, endpoints, servers, cloud services, and applications — enabling threat detection, investigation, and compliance reporting.
Each SIEM platform uses a different query syntax: Splunk uses SPL, Microsoft Sentinel uses KQL, Elastic Security uses EQL/Lucene, and CrowdStrike uses specialized query syntax. This tool translates detection logic into the correct syntax for your platform, accelerating threat hunting and reducing query errors.
| Platform | Query Language | Syntax Style | Example: Failed SSH Logins |
|---|---|---|---|
| Splunk | SPL (Search Processing Language) | Pipe-based | index=linux sourcetype=syslog "Failed password" | stats count by src_ip |
| Microsoft Sentinel | KQL (Kusto Query Language) | Tabular pipe | Syslog | where Facility == "auth" and SyslogMessage contains "Failed password" | summarize count() by SrcIP |
| Elastic | EQL / Lucene / ES|QL | Multiple options | event.action:"ssh_login" AND event.outcome:"failure" |
| CrowdStrike | Event Search | Field-value | event_simpleName=UserLogonFailed | stats count by RemoteAddressIP4 |
| IBM QRadar | AQL (Ariel Query Language) | SQL-like | SELECT sourceip, COUNT(*) FROM events WHERE category='Authentication' AND outcome='Failure' GROUP BY sourceip |
The builder supports three major platforms: Splunk SPL (Search Processing Language), Elastic KQL (Kibana Query Language), and Microsoft Sentinel KQL (Kusto Query Language). Each platform has different syntax, and the builder handles field mapping and query generation for all three.
Presets are pre-built filter combinations for common security use cases. Categories include Authentication (failed logins, impossible travel), Network (port scanning, DNS tunneling), Malware (encoded PowerShell, LOLBAS), Data Exfiltration (large transfers, cloud uploads), Cloud (AWS root login, S3 public buckets), and Endpoint (AV disabled, LSASS access).
Each detection preset includes a MITRE ATT&CK technique ID (like T1110 for Brute Force). This maps the detection to the MITRE ATT&CK framework, helping you understand what adversary technique the query is designed to detect. This is useful for coverage mapping and threat modeling.
Different SIEM platforms use different field names for the same data. For example, username is "user" in Splunk, "user.name" in Elastic, and "AccountName" in Sentinel. The builder automatically translates fields when you switch platforms, so you can focus on the logic rather than syntax.
Yes, but with limitations. The builder translates field names and basic operators between platforms. Complex features like subsearches, lookups, or platform-specific functions may need manual adjustment. Use the generated query as a starting point and review for your specific environment.
SPL (Search Processing Language) is Splunk's query language, using pipes and commands like "| stats" and "| where". KQL (Kusto Query Language) is used by Microsoft Sentinel and Elastic, with syntax like "| summarize" and "| where". Elastic also supports Lucene syntax, but we focus on KQL for consistency.
Group By adds aggregation to your query. For example, grouping failed logins by source_ip and user shows you which IPs are targeting which accounts. In Splunk this becomes "| stats count by src_ip, user", in Sentinel it's "| summarize count() by IpAddress, AccountName".
The tool supports 1 hour, 24 hours, 7 days, and 30 days as preset time ranges. The syntax differs by platform: Splunk uses "earliest=-24h", Sentinel uses "| where TimeGenerated > ago(24h)". You can also leave it blank to search all available data.
These queries are starting points for detection development. Before deploying to production, you should: 1) Test in your environment, 2) Tune thresholds to reduce false positives, 3) Add additional filters specific to your data, 4) Consider performance impact of broad queries, 5) Document and review with your team.
Add exclusion filters for known-good activity. For example, exclude your monitoring systems from failed login alerts, or exclude backup servers from large data transfer alerts. Use the NOT operator or add exclusion conditions to your query. Document exceptions for audit purposes.