Branch was auto-updated.

This commit is contained in:
github-actions[bot]
2021-06-18 07:45:39 +00:00
committed by GitHub
9 changed files with 157 additions and 19 deletions
@@ -16,8 +16,14 @@ class GithubService:
def __init__(self, security_content_branch):
self.security_content_branch = security_content_branch
self.security_content_repo_obj = self.clone_project(SECURITY_CONTENT_URL, f"security_content", f"develop")
self.security_content_repo_obj.git.checkout(security_content_branch)
if os.path.exists('security_content'):
LOGGER.warning(f"Found Existing Security Content Project")
self.created_repo = False
else:
self.security_content_repo_obj = self.clone_project(SECURITY_CONTENT_URL, f"security_content", f"develop")
self.security_content_repo_obj.git.checkout(security_content_branch)
self.created_repo = True
def clone_project(self, url, project, branch):
LOGGER.info(f"Clone Security Content Project")
@@ -102,6 +102,23 @@ class DSPApi:
return response_body
def get_pipelines(self):
"""
Returns the list of pipelines
@return:
list of pipelines
"""
headers = {"Content-Type": "application/json", "Authorization": self.header_token}
response = requests.get(self.return_api_endpoint(PIPELINES_ENDPOINT), headers=headers)
response_body = response.json()
if response.status_code == HTTPStatus.OK:
return response_body.get('items')
else:
LOGGER.error(f"Failed to get pipelines: %s", response.text)
def create_pipeline(self, upl):
"""
POST pipelines endpoint to create a pipeline based on the valid upl
@@ -176,12 +193,12 @@ class DSPApi:
response_body = response.json()
if response.status_code == HTTPStatus.OK:
pipeline_id = response_body.get("id")
LOGGER.info(f"Pipeline {pipeline_id} successfully created")
return response_body
pipeline_id = response_body.get("activated")
LOGGER.info(f"Pipeline {pipeline_id} successfully activated")
else:
LOGGER.error(f"Failed to activate pipeline {pipeline_id}")
return
LOGGER.error(f"Failed to activate pipeline {pipeline_id}: {response.text}")
return response_body
def deactivate_pipeline(self, pipeline_id):
@@ -501,4 +518,3 @@ class DSPApi:
delete_url = f"{datasets_endpoint_api}/{index_id}"
response = requests.delete(delete_url, headers=request_headers(self.header_token))
return response.status_code
@@ -64,7 +64,7 @@ class SSADetectionTesting:
def test_ssa_detections(self, test_obj):
LOGGER.info('Test SSA Detection: ' + test_obj["detection_obj"]["name"])
self.max_execution_time = MAX_EXECUTION_TIME_LIMIT
file_path_attack_data = os.path.join(os.path.dirname(__file__), "../", test_obj["attack_data_file_path"])
file_path_attack_data = test_obj["attack_data_file_path"]
test_results = self.ssa_detection_test(test_obj["detection_obj"]["search"], file_path_attack_data,
"SSA Smoke Test " + test_obj["test_obj"]["name"])
@@ -85,12 +85,31 @@ class SSADetectionTesting:
return self.update_execution_time(time_in_s)
def ssa_detection_test_init(self):
self.cleanup_old_pipelines()
self.test_results["result"] = True
self.test_results["msg"] = ""
self.results_index = self.api.create_temp_index("mc")
self.created_pipelines = []
self.activated_pipelines = []
def cleanup_old_pipelines(self):
pipelines = self.api.get_pipelines()
yesterday = (time.time() - 24*3600) * 1000 # milliseconds
for pipeline in pipelines:
if pipeline['name'].startswith("ssa_smoke_test_pipeline_helper") and pipeline['createDate'] < yesterday:
if pipeline['status'] == 'ACTIVATED':
# deactivate pipeline
resp, _ = self.api.deactivate_pipeline(pipeline['id'])
if resp.status_code != HTTPStatus.OK:
LOGGER.error("Error deactivating old pipeline %s: %s", pipeline['name'], resp.text)
# delete pipeline
resp = self.api.delete_pipeline(pipeline['id'])
if resp.status_code != HTTPStatus.NO_CONTENT:
LOGGER.error("Error deleting old pipeline %s: %s", pipeline['name'], resp.text)
else:
LOGGER.warning("Found and deleted an old pipeline: %s", pipeline['name'])
def ssa_detection_test_main(self, spl, source, test_name):
self.execution_passed = True
@@ -192,8 +211,7 @@ class SSADetectionTesting:
"msg": f"Detection test failure for {test_name}"}
except Exception as e:
self.ssa_detection_test_teardown()
LOGGER.error(e)
LOGGER.error(f"Detection test failure for {test_name} (perhaps SCS problems)")
LOGGER.exception(f"Detection test failure for {test_name} (perhaps SCS problems)")
return {"result": False,
"msg": f"Detection test failure for {test_name} (perhaps SCS problems)"}
+2 -3
View File
@@ -14,7 +14,7 @@ LOGGER = logging.getLogger(__name__)
# Macros
PULSAR_SOURCE_CONNECTION_ID_PLAYGROUND = f"29fb61f1-9342-48f5-9793-1afa008c377b"
PULSAR_SOURCE_TOPIC_PLAYGROUND = f"persistent://ssa/egress/decorated-events-research2"
PULSAR_SOURCE_CONNECTION_ID_STAGING = f"fd92bf9f-5d40-4c2e-bb75-bf0c3fc13980"
PULSAR_SOURCE_CONNECTION_ID_STAGING = f"b8c81601-a7e0-4501-802c-cb2831c72b6f"
PULSAR_SOURCE_TOPIC_STAGING = f"persistent://ssa/egress/decorated-events-research"
READ_SSA_ENRICHED_EVENTS = f"| from read_ssa_enriched_events()"
@@ -110,8 +110,7 @@ def replace_ssa_macros(source, sink, spl):
return spl
def read_data(file_name):
file_path = os.path.join(os.path.dirname(__file__), 'data', file_name)
def read_data(file_path):
data_manipulation = DataManipulation()
modified_file = data_manipulation.manipulate_timestamp(file_path, 'xmlwineventlog', 'WinEventLog:Security')
data = []
@@ -80,7 +80,8 @@ def main(args):
LOGGER.info(test_result['msg'])
LOGGER.info('-----------------------------------')
remove_security_content()
if github_service.created_repo:
remove_security_content()
exit_code = not test_passed
sys.exit(exit_code)
+1 -1
View File
@@ -101,7 +101,7 @@ def test_detection(test, args):
# Download data to temporal folder
for unit in test_desc['tests']:
detection = get_detection(unit)
if detection['type'] == "SSA":
if detection['type'] == 'streaming':
log(logging.INFO, "Testing %s" % name)
# Prepare data
data_dir = tempfile.TemporaryDirectory(prefix="data", dir=get_path("%s" % SSML_CWD))
+4 -3
View File
@@ -7,7 +7,7 @@ from modules.ssa_utils import *
from modules.testing_utils import *
DUMB_PIPELINE_INPUT = '| from read_text("/")' \
DUMB_PIPELINE_INPUT = '| from read_text("test.spl2")' \
'| select from_json_object(value) as input_event' \
'| eval timestamp=parse_long(ucast(map_get(input_event, "_time"), "string", null))'
@@ -71,12 +71,13 @@ def extract_ssa_fields(spl2):
fields_file = os.path.join(data_dir.name, "fields.out")
write_validation_pipeline(spl2, pipeline_file)
subprocess.run(["/usr/bin/java",
"-jar", get_path("%s/humvee.jar" % SSML_CWD),
"-jar", "humvee.jar",
'cli', '-i',
pipeline_file, '-o',
fields_file,
'-f'],
stderr=subprocess.DEVNULL,
#stderr=subprocess.DEVNULL,
cwd=get_path(SSML_CWD),
check=True)
spl2_ssa_fields = set()
with open(fields_file, 'r') as test_out_fh:
@@ -0,0 +1,86 @@
name: Rare Parent-Child Process Relationship
id: cf090c78-bcc6-11eb-8529-0242ac130003
version: 1
date: '2021-05-20'
author: Peter Gael, Splunk; Ignacio Bermudez Corrales, Splunk
type: streaming
datamodel: []
description: An attacker may use LOLBAS tools spawned from vulnerable applications
not typically used by system administrators. This search leverages the Splunk Streaming
ML DSP plugin to find rare parent/child relationships. The list of application has
been extracted from https://github.com/LOLBAS-Project/LOLBAS/tree/master/yml/OSBinaries
search: '| from read_ssa_enriched_events() | eval timestamp=parse_long(ucast(map_get(input_event,
"_time"), "string", null)) | eval parent_process=lower(ucast(map_get(input_event,
"parent_process_name"), "string", null)), parent_process_name=mvindex(split(parent_process,
"\\"), -1), process_name=lower(ucast(map_get(input_event, "process_name"), "string",
null)), cmd_line=ucast(map_get(input_event, "process"), "string",
null), dest_user_id=ucast(map_get(input_event, "dest_user_id"), "string", null),
dest_device_id=ucast(map_get(input_event, "dest_device_id"), "string", null)
| where parent_process_name!=null
| select parent_process_name, process_name, cmd_line, timestamp, dest_device_id, dest_user_id
| conditional_anomaly conditional="parent_process_name" target="process_name"
| where (process_name="powershell.exe" OR process_name="regsvcs.exe"
OR process_name="ftp.exe" OR process_name="dfsvc.exe" OR process_name="rasautou.exe"
OR process_name="schtasks.exe" OR process_name="xwizard.exe" OR process_name="findstr.exe"
OR process_name="esentutl.exe" OR process_name="cscript.exe" OR process_name="reg.exe"
OR process_name="csc.exe" OR process_name="atbroker.exe" OR process_name="print.exe"
OR process_name="pcwrun.exe" OR process_name="vbc.exe" OR process_name="rpcping.exe"
OR process_name="wsreset.exe" OR process_name="ilasm.exe" OR process_name="certutil.exe"
OR process_name="replace.exe" OR process_name="mshta.exe" OR process_name="bitsadmin.exe"
OR process_name="wscript.exe" OR process_name="ieexec.exe" OR process_name="cmd.exe"
OR process_name="microsoft.workflow.compiler.exe" OR process_name="runscripthelper.exe"
OR process_name="makecab.exe" OR process_name="forfiles.exe" OR process_name="desktopimgdownldr.exe"
OR process_name="control.exe" OR process_name="msbuild.exe" OR process_name="register-cimprovider.exe"
OR process_name="tttracer.exe" OR process_name="ie4uinit.exe" OR process_name="sc.exe"
OR process_name="bash.exe" OR process_name="hh.exe" OR process_name="cmstp.exe"
OR process_name="mmc.exe" OR process_name="jsc.exe" OR process_name="scriptrunner.exe"
OR process_name="odbcconf.exe" OR process_name="extexport.exe" OR process_name="msdt.exe"
OR process_name="diskshadow.exe" OR process_name="extrac32.exe" OR process_name="eventvwr.exe"
OR process_name="mavinject.exe" OR process_name="regasm.exe" OR process_name="gpscript.exe"
OR process_name="rundll32.exe" OR process_name="regsvr32.exe" OR process_name="regedit.exe"
OR process_name="msiexec.exe" OR process_name="gfxdownloadwrapper.exe" OR process_name="presentationhost.exe"
OR process_name="regini.exe" OR process_name="wmic.exe" OR process_name="runonce.exe"
OR process_name="syncappvpublishingserver.exe" OR process_name="verclsid.exe" OR
process_name="psr.exe" OR process_name="infdefaultinstall.exe" OR process_name="explorer.exe"
OR process_name="expand.exe" OR process_name="installutil.exe" OR process_name="netsh.exe"
OR process_name="wab.exe" OR process_name="dnscmd.exe" OR process_name="at.exe"
OR process_name="pcalua.exe" OR process_name="cmdkey.exe" OR process_name="msconfig.exe")
| eval input = (-1)*log(output)
| adaptive_threshold algorithm="gaussian" threshold=0.001 window=604800000L
| where label AND input > mean
| eval start_time = timestamp, end_time = timestamp, entities = mvappend(dest_device_id,
dest_user_id), body = create_map(["process_name", process_name, "parent_process_name", parent_process_name, "input", input, "mean", mean, "variance", variance, "output", output, "cmd_line", cmd_line])
| into write_ssa_detected_events();'
how_to_implement: Collect endpoint data such as sysmon or 4688 events.
known_false_positives: 'Some custom tools used by admins could be used rarely to launch
remotely applications. This might trigger false positives at the beginning when
it hasn''t collected yet enough data to construct the baseline.
'
references: []
tags:
analytic_story:
- Unusual Processes
cis20:
- CIS 8
kill_chain_phases:
- Exploitation
mitre_attack_id:
- T1203
- T1059
- T1053
- T1072
nist:
- PR.PT
- DE.CM
product:
- Splunk Behavioral Analytics
required_fields:
- process
- process_name
- parent_process_name
- _time
- dest_device_id
- dest_user_id
risk_severity: low
security_domain: endpoint
@@ -0,0 +1,11 @@
name: Rare Parent/Child Process Relationship with LOLBAS - SSA Unit Test
tests:
- name: Rare Parent/Child Process Relationship with LOLBAS
file: endpoint/ssa___rare_parent_process_relationship_lolbas.yml
pass_condition: '@count_gt(0)'
description: Test detection looking for LOLBAS processes spawned by other processes that are rarely seen together
attack_data:
- file_name: windows-sec-events.out
data: https://raw.githubusercontent.com/splunk/attack_data/master/datasets/attack_techniques/T1003.003/atomic_red_team/windows-sec-events.out
source: WinEventLog:Security