diff --git a/detections/experimental/endpoint/detect_suspicious_processnames_using_pretrained_model_in_dsdl.yml b/detections/experimental/endpoint/detect_suspicious_processnames_using_pretrained_model_in_dsdl.yml new file mode 100644 index 0000000000..fbc9291da5 --- /dev/null +++ b/detections/experimental/endpoint/detect_suspicious_processnames_using_pretrained_model_in_dsdl.yml @@ -0,0 +1,117 @@ +name: Detect suspicious processnames using a pretrained model in DSDL +id: a15f8977-ad7d-4669-92ef-b59b97219bf5 +version: 1 +date: "2023-01-23" +author: Abhinav Mishra, Kumar Sharad and Namratha Sreekanta, Splunk +type: Anomaly +datamodel: +- Endpoint +description: The following analytic uses a pre-trained Deep Learning model to + predict whether a processname is suspicious or not. Malwares and malicious + programs such as ransomware often use tactics, techniques, and procedures + (TTPs) such as copying malicious files to the local machine to propagate + themselves across the network. A key indicator of compromise is that after + a successful execution of the malware, it copies itself as an executable file + with a randomly generated filename and places this file in one of the + directories. Such techniques are seen in several malwares such as TrickBot. + We develop machine learning model that uses a Recurrent Neural Network (RNN) + to distinguish between malicious and benign processnames. The model is trained + independently and is then made available for download. We use a character level + RNN to classify malicious vs. benign processnames. The higher is_malicious_prob, + the more likely is the processname to be suspicious (between [0,1]). The threshold + for flagging a processname as suspicious is set as 0.5. +search: '| tstats `security_content_summariesonly` count min(_time) as firstTime + max(_time) as lastTime from datamodel=Endpoint.Processes + by Processes.process_name Processes.parent_process_name Processes.process + Processes.user Processes.dest + | `drop_dm_object_name(Processes)` + | rename process_name as text + | fields text, parent_process_name, process, user, dest + | apply detect_suspicious_processnames_using_pretrained_model_in_dsdl + | rename predicted_label as is_suspicious_score + | rename text as process_name + | where is_suspicious_score > 0.5 + | `detect_suspicious_processnames_using_pretrained_model_in_dsdl_filter`' + +how_to_implement: 'Steps to deploy detect suspicious processnames model into Splunk App + DSDL. This detection depends on the Splunk app for Data Science and Deep + Learning which can be found here - `https://splunkbase.splunk.com/app/4607/` + and the Endpoint datamodel. The detection uses a pre-trained + deep learning model that needs to be deployed in the DSDL app. Follow the steps + for deployment here - `https://github.com/splunk/security_content/wiki/How-to-deploy-pre-trained-Deep-Learning-models-for-ESCU`.\ + + * Download the `artifacts .tar.gz` file from the link - `https://seal.splunkresearch.com/detect_suspicious_processnames_using_pretrained_model_in_dsdl.tar.gz`.\ + + * Download the `detect_suspicious_processnames_using_pretrained_model_in_dsdl.ipynb` + Jupyter notebook from the link - `https://github.com/splunk/security_content/notebooks`.\ + + * Login to the Jupyter Lab assigned for `detect_suspicious_processnames_using_pretrained_model_in_dsdl` + container. This container should be listed on Containers page for DSDL app.\ + + * Follow the steps below inside Jupyter Notebook:\ + + * Upload the `detect_suspicious_processnames_using_pretrained_model_in_dsdl.tar.gz` file + into `app/model/data/detect_suspicious_processnames_using_pretrained_model_in_dsdl/` path using the upload option in the Jupyter Notebook.\ + + * Untar the artifact `detect_suspicious_processnames_using_pretrained_model_in_dsdl.tar.gz` using + `tar -xf app/model/data/detect_suspicious_processnames_using_pretrained_model_in_dsdl.tar.gz -C app/model/data/detect_suspicious_processnames_using_pretrained_model_in_dsdl/`.\ + + * Upload `detect_suspicious_processnames_using_pretrained_model_in_dsdl.ipynb` into the Jupyter Notebooks + folder using the upload option in Jupyter Notebook.\ + + * Save the notebook using the save option in Jupyter Notebook.\ + + * Upload `detect_suspicious_processnames_using_pretrained_model_in_dsdl.json` into `notebooks/data` + folder.' +known_false_positives: False positives may be present if a suspicious processname + is similar to a benign processname. +references: +- https://www.cisa.gov/uscert/ncas/alerts/aa20-302a +- https://www.splunk.com/en_us/blog/security/random-words-on-entropy-and-dns.html +tags: + analytic_story: + - Suspicious Command-Line Executions + asset_type: Endpoint + cis20: + - CIS 8 + - CIS 12 + - CIS 13 + confidence: 90 + context: + - Source:Endpoint + - Stage:Execution + impact: 50 + kill_chain_phases: + - Exploitation + message: The process $process$ is running from an unusual place by $user$ on $dest$ with a processname + that appears to be randomly generated. + mitre_attack_id: + - T1059 + nist: + - PR.DS + - PR.PT + - DE.AE + - DE.CM + observable: + - name: dest + type: Hostname + role: + - Victim + - name: user + type: User + role: + - Victim + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Processes.process + - Processes.parent_process_name + - Processes.process_name + - Processes.parent_process + - Processes.user + - Processes.dest + risk_score: 45 + security_domain: Endpoint \ No newline at end of file diff --git a/detections/experimental/network/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.yml b/detections/experimental/network/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.yml index c244925543..2ecfe5c278 100644 --- a/detections/experimental/network/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.yml +++ b/detections/experimental/network/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.yml @@ -35,30 +35,31 @@ search: '| tstats `security_content_summariesonly` count min(_time) as firstTime how_to_implement: 'Steps to deploy detect suspicious DNS TXT records model into Splunk App DSDL. This detection depends on the Splunk app for Data Science and Deep - Learning which can be found here - https://splunkbase.splunk.com/app/4607/ + Learning which can be found here - `https://splunkbase.splunk.com/app/4607/` and the Network Resolution datamodel which can be found here - - https://splunkbase.splunk.com/app/1621/. The detection uses a pre-trained + `https://splunkbase.splunk.com/app/1621/`. The detection uses a pre-trained deep learning model that needs to be deployed in DSDL app. Follow the steps for deployment here - `https://github.com/splunk/security_content/wiki/How-to-deploy-pre-trained-Deep-Learning-models-for-ESCU`.\ - * Download the `artifacts .tar.gz` file from the link - https://seal.splunkresearch.com/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz - Download the `detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.ipynb` - Jupyter notebook from https://github.com/splunk/security_content/notebooks\ + * Download the `artifacts .tar.gz` file from the link - `https://seal.splunkresearch.com/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz`. + + * Download the `detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.ipynb` + Jupyter notebook from `https://github.com/splunk/security_content/notebooks`.\ * Login to the Jupyter Lab assigned for - detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl container. + `detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl` container. This container should be listed on Containers page for DSDL app.\ - * Below steps need to be followed inside Jupyter lab \ + * Below steps need to be followed inside Jupyter lab.\ - * Upload the detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz file + * Upload the `detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz` file into `app/model/data` path using the upload option in the jupyter notebook.\ - * Untar the artifact detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz using `tar -xf app/model/data/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz -C app/model/data`\ + * Untar the artifact `detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz` using `tar -xf app/model/data/detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.tar.gz -C app/model/data`.\ - * Upload detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.pynb into Jupyter lab notebooks folder using the upload option in Jupyter lab \ + * Upload detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.ipynb` into Jupyter lab notebooks folder using the upload option in Jupyter lab.\ - * Save the notebook using the save option in jupyter notebook. \ + * Save the notebook using the save option in Jupyter notebook.\ * Upload `detect_suspicious_dns_txt_records_using_pretrained_model_in_dsdl.json` into `notebooks/data` folder.' known_false_positives: False positives may be present if DNS TXT record contents @@ -113,4 +114,4 @@ tags: - DNS.dest - DNS.answer risk_score: 45 - security_domain: network + security_domain: network \ No newline at end of file diff --git a/lookups/__mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl.mlmodel b/lookups/__mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl.mlmodel new file mode 100644 index 0000000000..7adfaa2dee --- /dev/null +++ b/lookups/__mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl.mlmodel @@ -0,0 +1,2 @@ +algo,model,options +MLTKContainer,"{""__mlspl_type"": [""mltkc.MLTKContainer"", ""MLTKContainer""], ""dict"": {""endpoint_url"": ""https://localhost:58216"", ""out_params"": {""params"": {""mode"": ""stage"", ""algo"": ""detect_suspicious_processnames_using_pretrained_model_in_dsdl""}, ""args"": [""label"", ""text""], ""target_variable"": [""label""], ""feature_variables"": [""text""], ""model_name"": ""detect_suspicious_processnames_using_pretrained_model_in_dsdl"", ""algo_name"": ""MLTKContainer"", ""mlspl_limits"": {""handle_new_cat"": ""default"", ""max_distinct_cat_values"": ""100"", ""max_distinct_cat_values_for_classifiers"": ""100"", ""max_distinct_cat_values_for_scoring"": ""100"", ""max_fit_time"": ""600"", ""max_inputs"": ""100000"", ""max_memory_usage_mb"": ""4000"", ""max_model_size_mb"": ""30"", ""max_score_time"": ""600"", ""use_sampling"": ""true""}, ""kfold_cv"": null}, ""feature_variables"": [""text""], ""target_variable"": ""label""}}","{""params"": {""mode"": ""stage"", ""algo"": ""detect_suspicious_processnames_using_pretrained_model_in_dsdl""}, ""args"": [""label"", ""text""], ""target_variable"": [""label""], ""feature_variables"": [""text""], ""model_name"": ""detect_suspicious_processnames_using_pretrained_model_in_dsdl"", ""algo_name"": ""MLTKContainer"", ""mlspl_limits"": {""handle_new_cat"": ""default"", ""max_distinct_cat_values"": ""100"", ""max_distinct_cat_values_for_classifiers"": ""100"", ""max_distinct_cat_values_for_scoring"": ""100"", ""max_fit_time"": ""600"", ""max_inputs"": ""100000"", ""max_memory_usage_mb"": ""4000"", ""max_model_size_mb"": ""30"", ""max_score_time"": ""600"", ""use_sampling"": ""true""}, ""kfold_cv"": null}" diff --git a/lookups/__mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl.yml b/lookups/__mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl.yml new file mode 100644 index 0000000000..dfe23d09ca --- /dev/null +++ b/lookups/__mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl.yml @@ -0,0 +1,4 @@ +description: Detect a suspicious processname using Pretrained Model in DSDL +filename: __mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl.mlmodel +name: __mlspl_detect_suspicious_processnames_using_pretrained_model_in_dsdl +case_sensitive_match: 'false' \ No newline at end of file diff --git a/notebooks/detect_suspicious_processnames_using_pretrained_model_in_dsdl.ipynb b/notebooks/detect_suspicious_processnames_using_pretrained_model_in_dsdl.ipynb new file mode 100644 index 0000000000..4d12d17579 --- /dev/null +++ b/notebooks/detect_suspicious_processnames_using_pretrained_model_in_dsdl.ipynb @@ -0,0 +1,973 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "# Deep Learning model to detect suspiciously named files" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "tags": [] + }, + "source": [ + "This notebook uses a pre-trained Deep Learning model to predict whether a processname is suspicious or not.\n", + "\n", + "Malwares and malicious programs such as ransomware often use tactics, techniques, and procedures (TTPs) such as copying malicious files to the local machine to propagate themselves across the network. A key indicator of compromise is that after a successful execution of the malware, it copies itself as an executable file with a randomly generated filename and places this file in one of the directories. Such techniques are seen in several malwares such as TrickBot. \n", + "\n", + "We develop machine learning model that uses a Recurrent Neural Network (RNN) to distinguish between malicious and benign processnames. The model is trained independently and is then made available for download. We use a character level RNN to classify malicious vs. benign processnames. Higher the `is_malicious_prob`, the more likely is the processname to be suspicious (between `[0,1]`). The threshold for flagging a processname as suspicious is set at `0.5`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stage 0 - import libraries\n", + "At stage 0 we define all imports necessary to run our subsequent code depending on various libraries." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "deletable": false, + "name": "mltkc_import" + }, + "outputs": [], + "source": [ + "# This definition exposes all python module imports that should be available in all subsequent commands\n", + "\n", + "import pandas as pd\n", + "import numpy as np\n", + "import random\n", + "import string\n", + "import torch\n", + "import torch.nn as nn\n", + "\n", + "# global constants\n", + "MODEL_DIRECTORY = \"/srv/app/model/data/detect_suspicious_processnames_using_pretrained_model_in_dsdl/detect_suspicious_processnames_using_pretrained_model_in_dsdl.pt\"\n", + "\n", + "# model parameters\n", + "all_letters = string.ascii_lowercase\n", + "n_letters = len(all_letters)\n", + "n_hidden = 32\n", + "n_categories = 2\n", + "learning_rate = 5e-4" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "numpy version: 1.23.3\n", + "pandas version: 1.5.0\n" + ] + } + ], + "source": [ + "# THIS CELL IS NOT EXPORTED - free notebook cell for testing or development purposes\n", + "print(\"numpy version: \" + np.__version__)\n", + "print(\"pandas version: \" + pd.__version__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Stage 1 - get a data sample from Splunk\n", + "There are currently 2 ways to retrieve data from Splunk: Option 1 is to interactively pull data from Splunk into the DSDL Jupyter Lab environment. This is useful when the Splunk REST API is accessible from the Jupyter environment and a valid Splunk auth token is defined in the DSDL app. This option has advantages to quickly experiment with different Splunk SPL queries and further interactively work with the search results in Jupyter.\n", + "\n", + "### Option 1 - pull data from Splunk" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "from dsdlsupport import SplunkSearch as SplunkSearch" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "07142129edfe4bb6b4159c9fbc7ec0d8", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "VBox(children=(HBox(children=(Textarea(value='| makeresults count=10 \\n| streamstats c as i \\n| eval s = i%3 \\…" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "search = SplunkSearch.SplunkSearch()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
| \n", + " | _time | \n", + "feature_0 | \n", + "feature_1 | \n", + "feature_2 | \n", + "i | \n", + "s | \n", + "
|---|---|---|---|---|---|---|
| 0 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.2428163280710578 | \n", + "0.2446760144084692 | \n", + "0.878678847104311 | \n", + "1 | \n", + "1 | \n", + "
| 1 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.458672939799726 | \n", + "0.4403486642986536 | \n", + "0.5951908086426556 | \n", + "2 | \n", + "2 | \n", + "
| 2 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.4268499561585486 | \n", + "0.70259142620489 | \n", + "0.6676120953634381 | \n", + "3 | \n", + "0 | \n", + "
| 3 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.9911085437051952 | \n", + "0.7537638866342604 | \n", + "0.8423880040645599 | \n", + "4 | \n", + "1 | \n", + "
| 4 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.2864162167534232 | \n", + "0.4240174447186291 | \n", + "0.7597004366107285 | \n", + "5 | \n", + "2 | \n", + "
| 5 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.9403447071090341 | \n", + "0.10794003773480654 | \n", + "0.22778158355504274 | \n", + "6 | \n", + "0 | \n", + "
| 6 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.6541405455209315 | \n", + "0.7657363642938435 | \n", + "0.07344387145712972 | \n", + "7 | \n", + "1 | \n", + "
| 7 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.8196326880715787 | \n", + "0.34731235541403294 | \n", + "0.8556739939376712 | \n", + "8 | \n", + "2 | \n", + "
| 8 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.3521619248203933 | \n", + "0.04771727975457907 | \n", + "0.07742329593747854 | \n", + "9 | \n", + "0 | \n", + "
| 9 | \n", + "2022-10-12T15:58:22.000+02:00 | \n", + "0.2476972616277635 | \n", + "0.5393188064917922 | \n", + "0.7553935945034027 | \n", + "10 | \n", + "1 | \n", + "
| \n", + " | _time | \n", + "i | \n", + "feature_1 | \n", + "feature_2 | \n", + "feature_0 | \n", + "
|---|---|---|---|---|---|
| 0 | \n", + "1665565121 | \n", + "1 | \n", + "0.749423 | \n", + "0.861980 | \n", + "0.063747 | \n", + "
| 1 | \n", + "1665565121 | \n", + "2 | \n", + "0.328421 | \n", + "0.494055 | \n", + "0.578063 | \n", + "
| 2 | \n", + "1665565121 | \n", + "3 | \n", + "0.456588 | \n", + "0.135485 | \n", + "0.935327 | \n", + "
| 3 | \n", + "1665565121 | \n", + "4 | \n", + "0.034384 | \n", + "0.457241 | \n", + "0.043726 | \n", + "
| 4 | \n", + "1665565121 | \n", + "5 | \n", + "0.319659 | \n", + "0.867864 | \n", + "0.595515 | \n", + "
| ... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "... | \n", + "
| 995 | \n", + "1665565121 | \n", + "996 | \n", + "0.171754 | \n", + "0.162497 | \n", + "0.923288 | \n", + "
| 996 | \n", + "1665565121 | \n", + "997 | \n", + "0.500971 | \n", + "0.899659 | \n", + "0.607057 | \n", + "
| 997 | \n", + "1665565121 | \n", + "998 | \n", + "0.209019 | \n", + "0.751987 | \n", + "0.469225 | \n", + "
| 998 | \n", + "1665565121 | \n", + "999 | \n", + "0.163475 | \n", + "0.825084 | \n", + "0.158101 | \n", + "
| 999 | \n", + "1665565121 | \n", + "1000 | \n", + "0.208661 | \n", + "0.545487 | \n", + "0.872765 | \n", + "
1000 rows × 5 columns
\n", + "