From 742b59713799aaf6afb4b9895d8bfcc996f44a64 Mon Sep 17 00:00:00 2001 From: patel-bhavin Date: Tue, 24 Aug 2021 14:02:43 -0700 Subject: [PATCH 1/6] tst --- bin/newcontent.py | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/bin/newcontent.py b/bin/newcontent.py index 1192bcf690..921f9e4341 100644 --- a/bin/newcontent.py +++ b/bin/newcontent.py @@ -64,13 +64,26 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): 'name': 'detection_type', 'choices': [ { - 'name': 'batch' + 'name': 'TTP' }, { - 'name': 'streaming' + 'name': 'Anomaly' }, + { + 'name': 'Hunting' + }, + { + 'name': 'Baseline' + }, + { + 'name': 'Investigation' + }, + { + 'name': 'Correlation' + } + ], - 'default': 'batch' + 'default': 'TTP' }, { # get provider @@ -203,11 +216,13 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): j2_env = Environment(loader=FileSystemLoader(TEMPLATE_PATH), trim_blocks=True, autoescape=True) + answers['products'] = ['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud'] + answers['references'] = [] - if answers['detection_type'] == 'batch': - answers['products'] = ['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud'] - elif answers['detection_type'] == 'streaming': - answers['products'] = ['Splunk Behavioral Analytics'] + # if answers['detection_type'] == 'batch': + # answers['products'] = ['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud'] + # elif answers['detection_type'] == 'streaming': + # answers['products'] = ['Splunk Behavioral Analytics'] # grab some vars for the test detection_kind = answers['detection_kind'] @@ -221,7 +236,7 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): output = template.render(uuid=uuid.uuid1(), date=date.today().strftime('%Y-%m-%d'), author=answers['detection_author'], name=answers['detection_name'], description='|\n\tUPDATE_DESCRIPTION\n\tWHAT IS THIS?\n\tWHAT DOES IT LOOK LIKE?\n\tHOW DO YOU TRIAGE IT?', how_to_implement='UPDATE_HOW_TO_IMPLEMENT', known_false_positives='UPDATE_KNOWN_FALSE_POSITIVES', - references='',datamodels=answers['datamodels'], + references=' ',datamodels=answers['datamodels'], search= answers['detection_search'] + ' | `' + detection_file_name + '_filter`', type=answers['detection_type'], analytic_story_name='UPDATE_STORY_NAME', mitre_attack_id=mitre_attack_id, kill_chain_phases=answers['kill_chain_phases'], dataset_url='UPDATE_DATASET_URL', @@ -270,7 +285,7 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): output_path = path.join(security_content_path, 'tests/' + detection_kind + '/' + test_name) output = template.render(name=detection_name + ' Unit Test', detection_name=detection_name, - detection_path='detections/' + detection_kind + '/' + detection_file_name + '.yml', pass_condition=answers['pass_condition'], + detection_path= detection_kind + '/' + detection_file_name + '.yml', pass_condition=answers['pass_condition'], earliest_time=answers['earliest_time'], latest_time=answers['latest_time'], file_name='UPDATE_FILE_NAME', splunk_source='UPDATE_SPLUNK_SOURCE',splunk_sourcetype='UPDATE_SPLUNK_SOURCETYPE',dataset_url='UPDATE_DATASET_URL') with open(output_path, 'w', encoding="utf-8") as f: From 4f409f850ca9f26e4edb84bdc2ebe45ef812c697 Mon Sep 17 00:00:00 2001 From: patel-bhavin Date: Thu, 26 Aug 2021 10:51:42 -0700 Subject: [PATCH 2/6] minor --- bin/newcontent.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/bin/newcontent.py b/bin/newcontent.py index 921f9e4341..b57454f5b5 100644 --- a/bin/newcontent.py +++ b/bin/newcontent.py @@ -219,11 +219,7 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): answers['products'] = ['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud'] answers['references'] = [] - # if answers['detection_type'] == 'batch': - # answers['products'] = ['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud'] - # elif answers['detection_type'] == 'streaming': - # answers['products'] = ['Splunk Behavioral Analytics'] - + # grab some vars for the test detection_kind = answers['detection_kind'] @@ -235,7 +231,7 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): output_path = path.join(security_content_path, 'detections/' + detection_kind + '/' + detection_file_name + '.yml') output = template.render(uuid=uuid.uuid1(), date=date.today().strftime('%Y-%m-%d'), author=answers['detection_author'], name=answers['detection_name'], - description='|\n\tUPDATE_DESCRIPTION\n\tWHAT IS THIS?\n\tWHAT DOES IT LOOK LIKE?\n\tHOW DO YOU TRIAGE IT?', how_to_implement='UPDATE_HOW_TO_IMPLEMENT', known_false_positives='UPDATE_KNOWN_FALSE_POSITIVES', + description='\n\tUPDATE_DESCRIPTION\n\tWHAT IS THIS?\n\tWHAT DOES IT LOOK LIKE?\n\tHOW DO YOU TRIAGE IT?', how_to_implement='UPDATE_HOW_TO_IMPLEMENT', known_false_positives='UPDATE_KNOWN_FALSE_POSITIVES', references=' ',datamodels=answers['datamodels'], search= answers['detection_search'] + ' | `' + detection_file_name + '_filter`', type=answers['detection_type'], analytic_story_name='UPDATE_STORY_NAME', mitre_attack_id=mitre_attack_id, From 6391ec32aafc1dae63c76e299af0e99c2effb21a Mon Sep 17 00:00:00 2001 From: patel-bhavin Date: Thu, 26 Aug 2021 11:19:24 -0700 Subject: [PATCH 3/6] remove type from story and delete baseline --- bin/jinja2_templates/baseline.j2 | 27 ------------- bin/jinja2_templates/story.j2 | 1 - bin/newcontent.py | 67 ++++++++++++-------------------- 3 files changed, 25 insertions(+), 70 deletions(-) delete mode 100644 bin/jinja2_templates/baseline.j2 diff --git a/bin/jinja2_templates/baseline.j2 b/bin/jinja2_templates/baseline.j2 deleted file mode 100644 index 3c48684ff2..0000000000 --- a/bin/jinja2_templates/baseline.j2 +++ /dev/null @@ -1,27 +0,0 @@ -name: {{name}} -id: {{uuid}} -version: 1 -date: '{{date}}' -author: {{author}} -type: {{type}} -datamodel: -{% for datamodel in datamodels -%} - - {{datamodel}} -{% endfor -%} -description: {{description}} -search: '{{search}}' -how_to_implement: {{how_to_implement}} -known_false_positives: {{known_false_positives}} -references: -{% for reference in references -%} - - {{reference}} -{% endfor -%} -tags: - analytic_story: - - {{analytic_story_name}} - detections: - - {{detection_name}} - product: - {% for product in products -%} - - {{product}} - {% endfor -%} diff --git a/bin/jinja2_templates/story.j2 b/bin/jinja2_templates/story.j2 index be09c2f78f..94d419c14f 100644 --- a/bin/jinja2_templates/story.j2 +++ b/bin/jinja2_templates/story.j2 @@ -3,7 +3,6 @@ id: {{uuid}} version: 1 date: '{{date}}' author: {{author}} -type: {{type}} description: {{description}} narrative: {{narrative}} references: diff --git a/bin/newcontent.py b/bin/newcontent.py index b57454f5b5..07baf11e93 100644 --- a/bin/newcontent.py +++ b/bin/newcontent.py @@ -313,20 +313,6 @@ def story_wizard(security_content_path,type, TEMPLATE_PATH): 'message': 'enter author name', 'name': 'story_author', }, - { - 'type': 'list', - 'message': 'select a story type', - 'name': 'story_type', - 'choices': [ - { - 'name': 'batch' - }, - { - 'name': 'streaming' - }, - ], - 'default': 'batch' - }, { 'type': 'checkbox', 'message': 'select a category', @@ -393,19 +379,17 @@ def story_wizard(security_content_path,type, TEMPLATE_PATH): answers = prompt(questions) j2_env = Environment(loader=FileSystemLoader(TEMPLATE_PATH), trim_blocks=True, autoescape=True) - if answers['story_type'] == 'batch': - answers['products'] = ['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud'] - elif answers['story_type'] == 'streaming': - answers['products'] = ['Splunk Behavioral Analytics'] + template = j2_env.get_template('story.j2') + answers['products'] = ['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud'] + answers['references'] = [] story_name = answers['story_name'] story_file_name = story_name.replace(' ', '_').replace('-','_').replace('.','_').replace('/','_').lower() output_path = path.join(security_content_path, 'stories/' + story_file_name + '.yml') output = template.render(uuid=uuid.uuid1(), date=date.today().strftime('%Y-%m-%d'), author=answers['story_author'], name=answers['story_name'], description='UPDATE_DESCRIPTION', - narrative='UPDATE_NARRATIVE', references=['https://www.destroyallsoftware.com/talks/wat'], - type=answers['story_type'], analytic_story_name=answers['story_name'], + narrative='UPDATE_NARRATIVE', references=['https://www.destroyallsoftware.com/talks/wat'],analytic_story_name=answers['story_name'], categories=answers['category'], usecase=answers['usecase'], products=answers['products']) with open(output_path, 'w', encoding="utf-8") as f: f.write(output) @@ -430,7 +414,7 @@ def create_example(security_content_path,type, TEMPLATE_PATH): known_false_positives='UPDATE_KNOWN_FALSE_POSITIVES', references=['https://html5zombo.com/'], datamodels=['Endpoint'], search='| UPDATE_SPL | `' + getpass.getuser() + '_' + type + '_filter`', - type='batch', analytic_story_name=' UPDATE_STORY_NAME', mitre_attack_id = 'T1003.01', + type='TTP', analytic_story_name=' UPDATE_STORY_NAME', mitre_attack_id = 'T1003.01', kill_chain_phases=['Exploitation'], dataset_url='UPDATE_DATASET_URL', products=['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud']) with open(output_path, 'w', encoding="utf-8") as f: @@ -459,36 +443,35 @@ def create_example(security_content_path,type, TEMPLATE_PATH): author='UPDATE_AUTHOR', name=getpass.getuser().capitalize() + ' ' + type.capitalize(), description='UPDATE_DESCRIPTION', narrative='UPDATE_NARRATIVE', - references=['https://www.destroyallsoftware.com/talks/wat'], - type='batch', analytic_story_name=getpass.getuser().capitalize() + ' ' + type.capitalize(), + references=['https://www.destroyallsoftware.com/talks/wat'], analytic_story_name=getpass.getuser().capitalize() + ' ' + type.capitalize(), categories=['Adversary Tactics'], usecase='Advanced Threat Detection', products=['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud']) with open(output_path, 'w', encoding="utf-8") as f: f.write(output) print("contentctl wrote a example story to: {0}".format(output_path)) - elif type == 'baseline': - # write a baseline example - template = j2_env.get_template('baseline.j2') - baseline_name = getpass.getuser() + '_' + type + '.yml.example' - output_path = path.join(security_content_path, 'baselines/' + baseline_name) - output = template.render(uuid=uuid.uuid1(), date=date.today().strftime('%Y-%m-%d'), - author='UPDATE_AUTHOR', name=getpass.getuser().capitalize() + ' ' + type.capitalize(), - description='UPDATE_DESCRIPTION', - how_to_implement='UPDATE_HOW_TO_IMPLENT', - known_false_positives='UPDATE_KNOWN_FALSE_POSITIVES', - references=['https://html5zombo.com/'], - datamodels=['Endpoint'], search='| UPDATE_SPL', - type='batch', analytic_story_name='UPDATE_STORY_NAME', - detection_name = 'UPDATE_DETECTION_NAME', dataset_url='UPDATE_DATASET_URL', - products=['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud']) - with open(output_path, 'w', encoding="utf-8") as f: - f.write(output) - print("contentctl wrote a example baseline to: {0}".format(output_path)) + # elif type == 'baseline': + # # write a baseline example + # template = j2_env.get_template('baseline.j2') + # baseline_name = getpass.getuser() + '_' + type + '.yml.example' + # output_path = path.join(security_content_path, 'baselines/' + baseline_name) + # output = template.render(uuid=uuid.uuid1(), date=date.today().strftime('%Y-%m-%d'), + # author='UPDATE_AUTHOR', name=getpass.getuser().capitalize() + ' ' + type.capitalize(), + # description='UPDATE_DESCRIPTION', + # how_to_implement='UPDATE_HOW_TO_IMPLENT', + # known_false_positives='UPDATE_KNOWN_FALSE_POSITIVES', + # references=['https://html5zombo.com/'], + # datamodels=['Endpoint'], search='| UPDATE_SPL', + # type='batch', analytic_story_name='UPDATE_STORY_NAME', + # detection_name = 'UPDATE_DETECTION_NAME', dataset_url='UPDATE_DATASET_URL', + # products=['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud']) + # with open(output_path, 'w', encoding="utf-8") as f: + # f.write(output) + # print("contentctl wrote a example baseline to: {0}".format(output_path)) def new(security_content_path, VERBOSE, type, example_only): - valid_content_objects = ['detection','story', 'baseline'] + valid_content_objects = ['detection','story'] if type not in valid_content_objects: print("ERROR: content type: {0} is not valid, please use: {1}".format(type, str(valid_content_objects))) sys.exit(1) From 57a8034586b16ace49951f20b9cd07fef33928bf Mon Sep 17 00:00:00 2001 From: patel-bhavin Date: Thu, 26 Aug 2021 11:42:28 -0700 Subject: [PATCH 4/6] removed net_traffic --- bin/newcontent.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bin/newcontent.py b/bin/newcontent.py index 07baf11e93..aaa54399c3 100644 --- a/bin/newcontent.py +++ b/bin/newcontent.py @@ -95,18 +95,12 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): 'name': 'Endpoint', 'checked': True }, - { - 'name': 'Network_Traffic' - }, { 'name': 'Authentication' }, { 'name': 'Change' }, - { - 'name': 'Change_Analysis' - }, { 'name': 'Email' }, From faa645fd146b31d292ea41a61ee318c818f63f7e Mon Sep 17 00:00:00 2001 From: divious1 Date: Fri, 27 Aug 2021 12:03:52 -0400 Subject: [PATCH 5/6] added new dm for risk --- bin/newcontent.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bin/newcontent.py b/bin/newcontent.py index aaa54399c3..3d3673b08d 100644 --- a/bin/newcontent.py +++ b/bin/newcontent.py @@ -122,6 +122,9 @@ def detection_wizard(security_content_path,type,TEMPLATE_PATH): { 'name': 'Web' }, + { + 'name': 'Risk' + }, ], }, { From 33df34d50c47c64b9fd0efece64b4b9119388c53 Mon Sep 17 00:00:00 2001 From: divious1 Date: Fri, 27 Aug 2021 12:05:28 -0400 Subject: [PATCH 6/6] remove baseline code --- bin/newcontent.py | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/bin/newcontent.py b/bin/newcontent.py index 3d3673b08d..736e0ada0b 100644 --- a/bin/newcontent.py +++ b/bin/newcontent.py @@ -446,26 +446,6 @@ def create_example(security_content_path,type, TEMPLATE_PATH): f.write(output) print("contentctl wrote a example story to: {0}".format(output_path)) - # elif type == 'baseline': - # # write a baseline example - # template = j2_env.get_template('baseline.j2') - # baseline_name = getpass.getuser() + '_' + type + '.yml.example' - # output_path = path.join(security_content_path, 'baselines/' + baseline_name) - # output = template.render(uuid=uuid.uuid1(), date=date.today().strftime('%Y-%m-%d'), - # author='UPDATE_AUTHOR', name=getpass.getuser().capitalize() + ' ' + type.capitalize(), - # description='UPDATE_DESCRIPTION', - # how_to_implement='UPDATE_HOW_TO_IMPLENT', - # known_false_positives='UPDATE_KNOWN_FALSE_POSITIVES', - # references=['https://html5zombo.com/'], - # datamodels=['Endpoint'], search='| UPDATE_SPL', - # type='batch', analytic_story_name='UPDATE_STORY_NAME', - # detection_name = 'UPDATE_DETECTION_NAME', dataset_url='UPDATE_DATASET_URL', - # products=['Splunk Enterprise','Splunk Enterprise Security','Splunk Cloud']) - # with open(output_path, 'w', encoding="utf-8") as f: - # f.write(output) - # print("contentctl wrote a example baseline to: {0}".format(output_path)) - - def new(security_content_path, VERBOSE, type, example_only): valid_content_objects = ['detection','story']