You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

646 lines
33 KiB

[Generate MITRE Enterprise List]
alert.track = 0
display.general.type = statistics
display.page.search.tab = statistics
description = This search formats the MITRE ATT&CK framework table into a list format.
dispatch.earliest_time = -24h@h
dispatch.latest_time = now
search = | mitremap output="list"
[Saved Searches and the Data that Enables Them]
dispatch.earliest_time = -24h@h
dispatch.latest_time = now
display.general.timeRangePicker.show = 0
display.general.type = statistics
display.page.search.tab = statistics
display.visualizations.show = 0
description = This expects that you have completed the Data Inventory configuration, and mapped your active content on the Manage Bookmarks page. You will then be get a list oriented to the saved searches, showing each saved search and the data set and products that enable it
request.ui_dispatch_app = Splunk_Security_Essentials
request.ui_dispatch_view = search
search = | inputlookup data_inventory_products_lookup \
| search stage!=step-sourcetype stage!=step-cim \
| rex field=basesearch "^\s*(?<basesearch>.*?)\s*$" \
| eval basesearch=if(like(basesearch, "(%") AND like(basesearch, "%)"), basesearch, "(" . basesearch . ")") \
| makemv delim="|" eventtypeId \
| mvexpand eventtypeId \
| rename eventtypeId as data_source_categories \
| join data_source_categories \
[| sseanalytics \
| search search_title!="" \
| stats count count(eval(bookmark_status="successfullyImplemented")) as count_successfullyImplemented values(search_title) as search_title by bookmark_status data_source_categories \
| eval search_title=mvjoin(search_title, "|")] \
| eval Product = vendorName . " " . productName \
| makemv search_title delim="|" \
| mvexpand search_title\
| stats values(basesearch) as basesearch values(Product) as Product by search_title\
| eval basesearch = "(" . mvjoin(basesearch, " OR ") . ")", "Products That Provide Visibility"=mvjoin(mvfilter(Product!=" "), ", ")\
| rename basesearch as "Dataset That Provides Visibility" search_title as "Saved Search Name"\
| table "Saved Search Name" "Dataset That Provides Visibility" "Products That Provide Visibility"
[Products and the Content Mapped to Them]
dispatch.earliest_time = -24h@h
dispatch.latest_time = now
display.general.timeRangePicker.show = 0
display.general.type = statistics
display.page.search.tab = statistics
display.visualizations.show = 0
description = This expects that you have completed the Data Inventory configuration, and mapped your active content on the Manage Bookmarks page. You will then get a complete view from product to the content that it enables.
request.ui_dispatch_app = Splunk_Security_Essentials
request.ui_dispatch_view = search
search = | inputlookup data_inventory_products_lookup \
| search stage!=step-sourcetype stage!=step-cim \
| rex field=basesearch "^\s*(?<basesearch>.*?)\s*$"\
| eval basesearch=if(like(basesearch, "(%") AND like(basesearch, "%)"), basesearch, "(" . basesearch . ")") \
| makemv delim="|" eventtypeId \
| mvexpand eventtypeId \
| rename eventtypeId as data_source_categories \
| join data_source_categories \
[| sseanalytics \
| search search_title!="" \
| stats count count(eval(bookmark_status="successfullyImplemented")) as count_successfullyImplemented values(search_title) as search_title by data_source_categories \
| eval search_title=mvjoin(search_title, "|")] \
| eval Product = vendorName . " " . productName\
| makemv delim="|" data_source_categories | mvexpand data_source_categories\
| rex field=data_source_categories "^(?<ds>[^-]*)" | sseidenrichment type=datasourceid field=ds | sseidenrichment type=dscid field=data_source_categories | eval data_source_categories = data_source . " > " . data_source_category| stats values(*) as * by Product | search Product!=" " \
| table Product basesearch data_source_categories metadata_json search_title count \
| spath input=metadata_json | fields - metadata_json\
| table Product basesearch data_source_categories search_title * count \
| rename count as "Total Mapped Content for This Product" basesearch as "Dataset That Provides Visibility" search_title as "Saved Search Name" data_source_categories as "Data Source Category" description as Description
[Generate Data Availability ML Model for Latency]
disabled = 1
action.email.useNSSubject = 1
alert.track = 0
dispatch.earliest_time = -24h@h
dispatch.latest_time = now
display.general.type = statistics
display.page.search.tab = statistics
display.visualizations.show = 0
request.ui_dispatch_app = Splunk_Security_Essentials
request.ui_dispatch_view = search
search = | tstats count values(source) as source avg(_indextime) as indextime where \
[| inputlookup data_inventory_products_lookup \
| eval category=case(isnotnull(daily_event_volume) AND daily_event_volume > 50000, "highvolumelowlatency", stage!="step-sourcetype", "normal", 1=1,"unused") \
| lookup SSE-data-availability-products-categorization productId OUTPUT category as category_override \
| eval category=coalesce(category_override, category) \
| search category="highvolumelowlatency" OR category="normal" \
| eval termsearch = if(len(termsearch)>0,"(" . termsearch . ")",null()) \
| stats values(termsearch) as search \
| eval search="(" . mvjoin(search, " OR ") . ")" ] earliest=-30d by index sourcetype _time span=5m \
| eval reduce_factor_to_limit_memory_explosion = 10\
| where random()%reduce_factor_to_limit_memory_explosion = 1 \
| eval lag = indextime - _time - 180 \
| stats values(lag) as lag values(source) as source by index sourcetype _time \
| where lag > 0 \
| eval productId=null, \
[| inputlookup data_inventory_products_lookup \
| eval category=case(isnotnull(daily_event_volume) AND daily_event_volume > 50000, "highvolumelowlatency", stage!="step-sourcetype", "normal", 1=1,"unused") \
| lookup SSE-data-availability-products-categorization productId OUTPUT category as category_override \
| eval category=coalesce(category_override, category) \
| search category="highvolumelowlatency" OR category="normal" \
| eval termsearch = if(len(termsearch)>0,"(" . termsearch . ")",null()) \
| rex field=termsearch mode=sed "s/\"/\\\"/g" \
| eval search = "productId=if(searchmatch(\"" . termsearch . "\"), mvappend(productId, \"" . productId . "\"), productId)" \
| stats values(search) as search \
| eval search=mvjoin(search, ", ")]\
| mvexpand productId\
| fit DensityFunction lag by productId upper_threshold=0.01 dist=norm into app:sse_event_lag_model\
| stats count as baseline_num_data_samples avg(lag) as baseline_avg_lag min(_time) as baseline_earliest max(_time) as baseline_latest by productId | eval baseline_update_last_run = now(), baseline_lag_at_last_update = now() - baseline_latest | outputlookup SSE-data_availability_latency_status.csv
[Generate Datamodels Lookup]
action.email.useNSSubject = 1
action.keyindicator.invert = 0
action.makestreams.param.verbose = 0
action.nbtstat.param.verbose = 0
action.notable.param.verbose = 0
action.nslookup.param.verbose = 0
action.ping.param.verbose = 0
action.risk.forceCsvResults = 1
action.risk.param.verbose = 0
action.send2uba.param.verbose = 0
action.threat_add.param.verbose = 0
alert.track = 0
search = | datamodel \
| spath input=_raw output=modelName path=modelName \
| spath input=_raw output=objectName path=objects{}.objectName \
| spath input=_raw output=parentName path=objects{}.parentName \
| spath input=_raw output=tags path=objects{}.comment \
| fields modelName objectName parentName tags \
| eval objectName=mvappend(objectName,"ROOT - "+modelName) \
| eval tags=mvappend(tags,mvindex(tags,0)) \
| eval nodeNameMerge=mvzip(objectName,tags) \
| mvexpand nodeNameMerge \
| eval nodeName=mvindex(split(nodeNameMerge,","),0) \
| eval tags=mvindex(split(nodeNameMerge,",{\"tags\":"),1) \
| eval tags=replace(tags,"[\[\]\"\}]","") \
| eval datamodel=if(like(nodeName,"ROOT%"),modelName,modelName.".".nodeName) \
| eval nodeName=if(like(nodeName,"ROOT%"),null(),nodeName) \
| table datamodel modelName nodeName tags \
| join modelName \
[| rest splunk_server=local count=0 /servicesNS/-/-/admin/datamodel-files \
| rename title AS modelName,eai:acl.app AS app \
| table modelName, app \
| search NOT app IN(SplunkAppForWebAnalytics, search) \
| join app \
[| rest /services/apps/local \
| table title version \
| rename title as app\
]\
] \
| join datamodel type=outer \
[| ssedata config="data_inventory" \
| fields data_source data_source_category data_source_category_tags data_source_category_datamodel \
| eval data_source_category_datamodel=split(data_source_category_datamodel,"|") \
| stats values(data_source_category) AS data_source_category BY data_source_category_datamodel \
| rename data_source_category_datamodel AS datamodel \
| eval data_source_category=mvjoin(data_source_category,"|")\
]\
| outputlookup datamodels
[Generate STRT Macros to Data Source Categories Lookup]
search = | generatestrt | outputlookup createinapp=t SSE-STRT-macros-to-data_source_categories
[Generate STRT Macros to Data Source Categories Lookup - Backup]
search = | inputlookup sse_json_doc_storage_lookup \
| eval len=len(json), key=_key \
| search key="*macros*" \
| table key description version len json \
| spath input=json path="macros{}" output="macros" \
| fields macros \
| mvexpand macros \
| spath input=macros \
| table name definition \
| rename name AS macro\
\
| search definition=*source* OR definition=*eventtype*\
| rex field=definition max_match=0 "sourcetype=(\"|)(?<sourcetype>[^\"\s]*)(|\")" \
| rex field=definition max_match=0 "source=(\"|)(?<source>[^\"\s]*)(|\")" \
| eval sourcetype=case(\
like(definition,"%eventtype%") AND like(definition,"%cisco_ios%"),"eventtype=cisco_ios",\
like(definition,"%eventtype%") AND like(definition,"%osquery-process%"),"osquery:results",\
like(definition,"%eventtype%") AND like(definition,"%okta_log%"),"Okta",\
1=1,sourcetype\
)\
| eval source=case(\
like(definition,"%eventtype%") AND like(definition,"%wineventlog_security%"),"WinEventLog:Security",\
like(definition,"%eventtype%") AND like(definition,"%wineventlog_system%"),"WinEventLog:System",\
1=1,source\
)\
| rex field="sourcetype" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| head 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| rex field="sourcetype" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| tail 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| rex field="source" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| head 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| rex field="source" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| tail 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| foreach P_* \
[| eval PatternStringMatch=if('<<FIELD>>'!="", mvappend(PatternStringMatch,'<<FIELD>>'),PatternStringMatch) \
| eval PatternStringDescription=if('<<FIELD>>'!="", mvappend(PatternStringDescription,"<<MATCHSTR>>"),PatternStringDescription)\
] \
| fields - P_*\
| join PatternStringDescription type=outer[\
| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval PatternStringDescription="row_"+count \
\
| fields PatternStringDescription eventtypeId productId\
| eventstats values(eventtypeId) AS eventtypeId BY productId\
| eval eventtypeId=mvjoin(eventtypeId,"|")\
]\
| fields - Pattern*\
```Filter our matches against non-Vendor specific data source categories. If a detection uses this specific vendor technology it will only rely on that and not of datamodels```\
| eval eventtypeId=split(eventtypeId,"|")\
| eval eventtypeId_VendorOnly=mvfilter(match(eventtypeId, "Vendor"))\
| eval eventtypeId=coalesce(eventtypeId_VendorOnly,eventtypeId)\
| fields - eventtypeId_VendorOnly\
```END ```\
[Generate Local Saved Search Lookup]
action.keyindicator.invert = 0
action.makestreams.param.verbose = 0
action.nbtstat.param.verbose = 0
action.notable.param.verbose = 0
action.nslookup.param.verbose = 0
action.ping.param.verbose = 0
action.risk.forceCsvResults = 1
action.risk.param.verbose = 0
action.send2uba.param.verbose = 0
action.threat_add.param.verbose = 0
alert.track = 0
search = | rest splunk_server=local count=0 /servicesNS/-/-/saved/searches \
| rex field=qualifiedSearch ".*datamodel(=\"|:\"|\(\"|\s|:|=)(\"|)(?<datamodel>[a-z,A-Z,_]*)"\
| rex field=qualifiedSearch ".*datamodel(=\"|:\"|\(\"|\s|:|=)(\"|)[a-z,A-Z,_]*(\"|)\.(\"|)(?<nodeName>[a-z,A-Z,_]*)"\
| eval datamodel=if(isnotnull(nodeName), datamodel.".".nodeName, datamodel)\
| rex field=qualifiedSearch max_match=0 "sourcetype=(\"|)(?<sourcetype>[^\"\s]*)(|\")" \
| rex field=qualifiedSearch max_match=0 "source=(\"|)(?<source>[^\"]*)(|\")" \
| rex field=qualifiedSearch max_match=0 "`(?<macro>[^`]*)`" \
| rex field=qualifiedSearch max_match=0 ".*(?:input| )lookup (?:[a-z,A-Z,_]*=[a-z,A-Z,_]{1,4} |)(?<lookup>[a-z,A-Z,_,0-9]*)" \
\
| eval isCorrelationSearch=if('action.notable'=1 OR 'action.risk'=1 OR 'action.correlationsearch.enabled'=1,"true","false")\
| eval isEnabled=if('disabled'="0","true","false")\
| eval isScheduled=if(len('cron_schedule') >= 9,"true","false")\
| rename title AS name\
| rename \
qualifiedSearch AS search,\
action.correlationsearch.label as displayTitle, \
cron_schedule AS schedule,\
eai:acl.owner AS owner,\
eai:acl.app as app,\
action.correlationsearch.annotations AS annotations\
| eval displayTitle=coalesce(name,displayTitle)\
| eval link=id\
| lookup datamodels datamodel\
| lookup SSE-STRT-macros-to-data_source_categories.csv macro OUTPUTNEW eventtypeId AS data_source_category\
| eval data_source_category=mvdedup(data_source_category)\
| eval sourcetype=mvjoin(mvdedup(sourcetype),"|")\
| eval source=mvjoin(mvdedup(source),"|")\
| eval macro=mvjoin(mvdedup(macro),"|")\
| eval lookup=mvjoin(mvdedup(lookup),"|")\
| eval datamodel=mvjoin(mvdedup(datamodel),"|")\
\
| eval sourcetype_regex_match=if(isnull(data_source_category) AND isnotnull(sourcetype),sourcetype,null())\
| eval source_regex_match=if(isnull(data_source_category) AND isnotnull(source),source,null())\
\
| rex field="sourcetype_regex_match" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| head 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| rex field="sourcetype_regex_match" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| tail 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| rex field="source_regex_match" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| head 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| rex field="source_regex_match" max_match=0 \
[| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval row_id="row_"+count \
| fields row_id regex_pattern \
| eval rexValue="(?<P_"+row_id+">"+regex_pattern+")" \
| tail 300 \
| stats values(rexValue) AS regexMerge \
| eval regexMerge=mvjoin(regexMerge,"|") \
| eval search="\"(".regexMerge.")\"" \
| fields search \
]\
| foreach P_* \
[| eval PatternStringMatch=if('<<FIELD>>'!="", mvappend(PatternStringMatch,'<<FIELD>>'),PatternStringMatch) \
| eval PatternStringDescription=if('<<FIELD>>'!="", mvappend(PatternStringDescription,"<<MATCHSTR>>"),PatternStringDescription)\
] \
| fields - P_*\
| join PatternStringDescription type=outer[\
| inputlookup SSE-default-data-inventory-products.csv \
| eval eventtypeId=split(eventtypeId,"|") \
| mvexpand eventtypeId \
| search regex_pattern=* \
| search NOT productId IN (MSSQL*, SQL*,MySQL*, Oracle*, ESXi* , VMWare*, Linux*, FireEye*, Fortinet*, Cylance*, Check*, Juniper*)\
| sort 0 eventtypeId \
| streamstats count \
| eval PatternStringDescription="row_"+count \
\
| fields PatternStringDescription eventtypeId productId\
| eventstats values(eventtypeId) AS eventtypeId BY productId\
| eval eventtypeId=mvjoin(eventtypeId,"|")\
]\
| fields - Pattern*\
| eval data_source_category=coalesce(data_source_category,eventtypeId)\
| table app description displayTitle id isCorrelationSearch isEnabled isScheduled link name next_scheduled_time owner schedule search updated annotations data_source_category datamodel sourcetype source macro lookup\
| table app description displayTitle id isCorrelationSearch isEnabled isScheduled link name next_scheduled_time owner schedule search updated annotations data_source_category datamodel sourcetype source macro lookup\
| outputlookup createinapp=t SSE-local_savedsearches.csv
[Generate MITRE Environment Count]
action.email.useNSSubject = 1
action.keyindicator.invert = 0
action.makestreams.param.verbose = 0
action.nbtstat.param.verbose = 0
action.notable.param.verbose = 0
action.nslookup.param.verbose = 0
action.ping.param.verbose = 0
action.risk.forceCsvResults = 1
action.risk.param.verbose = 0
action.send2uba.param.verbose = 0
action.threat_add.param.verbose = 0
alert.track = 0
dispatch.earliest_time = 0
display.general.type = statistics
display.page.search.mode = verbose
display.page.search.tab = statistics
display.statistics.rowNumbers = 1
display.visualizations.charting.chart = pie
display.visualizations.charting.chart.style = minimal
display.visualizations.custom.type = custom-radar-chart-viz.radar_chart
display.visualizations.show = 0
request.ui_dispatch_app = Splunk_Security_Essentials
request.ui_dispatch_view = search
search = | sseanalytics \
| lookup use_cases.csv title AS "usecase" OUTPUT order_title AS use_case_order_title \
| eval "Use Case Orig"=if(isnull('usecase'),"Other",'usecase') \
| eval "Use Case"=if(isnull(use_case_order_title), "9_Other",use_case_order_title) \
| eval "Has Data"=if(data_available="Available" OR data_available="Mixed", "Yes", "No") \
| eval displayapp=mvappend(displayapp,"Any")\
| eval Status=case(\
'enabled'="Yes" AND 'Has Data'="Yes","Active",\
'enabled'!="Yes" AND 'Has Data'="Yes","Available",\
1=1,"Needs data"\
) \
| eval App=displayapp, Enabled=enabled, Title=name, Journey=journey, "Data Source"=datasource, "Data Source Category"=data_source_categories_display \
| where (mitre_tactic_display!="" AND mitre_tactic_display!="None") OR (mitre_technique_display!="" AND mitre_technique_display!="None" AND mvcount(mitre_technique_display)>0) \
| eval mitre_sub_technique_display=if(mitre_sub_technique_display="None","",mitre_sub_technique_display) \
| eval "MITRE Tactic"=if('mitre_tactic_display'="","-",'mitre_tactic_display'), "MITRE Technique"=mitre_technique_display, "MITRE Sub-Technique"=mitre_sub_technique_display, "MITRE Threat Group"=mitre_threat_groups, "MITRE Platforms"=mitre_platforms, Industry=split(industryMapping,"|") \
| table mitre_matrix "MITRE Tactic" "MITRE Technique" "MITRE Sub-Technique" Status "Data Source" App bookmark_status mitre_id Title\
| rename mitre_matrix AS "MITRE Matrix" \
| mvexpand "mitre_id" \
| lookup mitre_enterprise_list TechniqueIdCombined AS "mitre_id" OUTPUT Sub_Technique AS "MITRE Sub-Technique" Technique AS "MITRE Technique" Tactic AS "MITRE Tactic" \
| mvexpand "MITRE Tactic" \
| eval "MITRE Sub-Technique"=mvdedup('MITRE Sub-Technique'),"MITRE Technique"=mvdedup('MITRE Technique'),"MITRE Tactic"=mvdedup('MITRE Tactic') \
| eval mitre_technique_datasource_merge=mvzip('MITRE Technique','Data Source',"::") \
| eventstats sum(eval(if(len('MITRE Sub-Technique')=1,1,0))) AS MITRE_Technique_Datasource_Total BY "mitre_technique_datasource_merge" \
| eval mitre_technique_datasource_merge=mvzip('Data Source','MITRE_Technique_Datasource_Total',"::") \
\
| eventstats sum(eval(if(len('MITRE Sub-Technique')<=1,1,0))) AS MITRE_Tactic_Total BY "MITRE Tactic" \
| eventstats sum(eval(if(len('MITRE Sub-Technique')<=1,1,0))) AS MITRE_Technique_Total BY "MITRE Technique" "MITRE Tactic" \
| eventstats count AS MITRE_Technique_Total BY "MITRE Technique" "MITRE Tactic" \
| eventstats sum(eval(if(len('MITRE Sub-Technique')>1,1,0))) AS MITRE_Sub_Technique_Total BY "MITRE Tactic" "MITRE Sub-Technique" \
| eventstats sum(eval(if(len('MITRE Sub-Technique')<=1,1,0))) AS MITRE_Tactic_Technique_Total BY "MITRE Tactic" "MITRE Technique" \
\
| mvexpand App\
| eventstats delim=","\
values(eval(if(Status="Active",Title,null()))) AS "Active_TechniqueTotal",\
values(eval(if(Status="Available",Title,null()))) AS "Available_TechniqueTotal",\
values(eval(if(Status="Needs data",Title,null()))) AS "Needs data_TechniqueTotal",\
BY "MITRE Tactic","MITRE Technique","MITRE Matrix" App\
| foreach *_TechniqueTotal [\
| eval "<<FIELD>>" = mvcount('<<FIELD>>')\
]\
| fields - Title\
\
| stats delim=","\
sum(eval(if(len('MITRE Sub-Technique')<=1 AND Status="Active",1,0))) AS "Active",\
sum(eval(if(len('MITRE Sub-Technique')<=1 AND Status="Available",1,0))) AS "Available",\
sum(eval(if(len('MITRE Sub-Technique')<=1 AND Status="Needs data",1,0))) AS "Needs data",\
sum(eval(if(len('MITRE Sub-Technique')<=1 AND bookmark_status!="none",1,0))) AS "Bookmarked_Technique",\
sum(eval(if(len('MITRE Sub-Technique')>1 AND Status="Active",1,0))) AS "Active_SubTechnique",\
sum(eval(if(len('MITRE Sub-Technique')>1 AND Status="Available",1,0))) AS "Available_SubTechnique",\
sum(eval(if(len('MITRE Sub-Technique')>1 AND Status="Needs data",1,0))) AS "Needs data_SubTechnique",\
sum(eval(if(len('MITRE Sub-Technique')>1 AND bookmark_status!="none",1,0))) AS "Bookmarked_SubTechnique",\
max(MITRE_Tactic_Total) AS MITRE_Tactic_Total,\
max(MITRE_Technique_Total) AS MITRE_Technique_Total\
max(MITRE_Sub_Technique_Total) AS MITRE_Sub_Technique_Total,\
max(MITRE_Tactic_Technique_Total) AS MITRE_Tactic_Technique_Total,\
values(mitre_technique_datasource_merge) AS "Data Source",\
max(Active_TechniqueTotal) AS Active_TechniqueTotal,\
max(Available_TechniqueTotal) AS Available_TechniqueTotal,\
max("Needs data_TechniqueTotal") AS "Needs data_TechniqueTotal"\
BY "MITRE Tactic","MITRE Technique","MITRE Sub-Technique","MITRE Matrix" App\
| eval c="This fixes the counts for Techniques that have Sub-Techniques" \
| eval "Active"=if(isnull('Sub-Technique'), 'Active_TechniqueTotal', 'Active') \
| eval "Available"=if(isnull('Sub-Technique'), 'Available_TechniqueTotal', 'Available') \
| eval "Needs data"=if(isnull('Sub-Technique'), 'Needs data_TechniqueTotal', 'Needs data') \
| eval "Active"=if(len('MITRE Sub-Technique')>1, 'Active_SubTechnique', 'Active') \
| eval "Available"=if(len('MITRE Sub-Technique')>1, 'Available_SubTechnique', 'Available') \
| eval "Needs data"=if(len('MITRE Sub-Technique')>1, 'Needs data_SubTechnique', 'Needs data') \
| eval "Bookmarked"='Bookmarked_Technique'+'Bookmarked_SubTechnique' \
| fields - *_TechniqueTotal *_SubTechnique \
| rename "MITRE *" AS *,"MITRE_*" AS * \
| eval "Sub-Technique"=if('Sub-Technique'="", "-", 'Sub-Technique') \
| eval IsSubTechnique=if('Sub-Technique'="-", "No", "Yes") \
| table Matrix Tactic Tactic_Total Technique Technique_Total "Sub-Technique" "Sub_Technique_Total" IsSubTechnique Active "Available" "Needs data" Technique_Total "Data Source" App Bookmarked \
| eval c="This appends all techniques and sub-techniques for which we have no detections" \
| lookup mitre_enterprise_list Matrix Tactic Technique Sub_Technique AS "Sub-Technique" OUTPUT Technique_Order Sub_Technique_Order \
| append \
[| inputlookup mitre_enterprise_list \
| fields Matrix Tactic Sub_Technique Technique Technique_Order Sub_Technique_Order \
| rename Sub_Technique AS "Sub-Technique"] \
| eventstats values(App) AS AllApps\
| eval Technique_Order=coalesce(Technique_Order,"-"),Sub_Technique_Order=coalesce(Sub_Technique_Order,"-"),App=coalesce(App,AllApps) \
| stats delim=","\
sum(Active) AS Active,\
sum(Available) AS Available,\
sum("Needs data") AS "Needs data",\
sum(Sub_Technique_Total) AS Sub_Technique_Total,\
sum(Tactic_Total) AS Tactic_Total,\
sum(Technique_Total) AS Technique_Total,\
sum(Bookmarked) AS Bookmarked,\
values("Data Source") AS "Data Source",\
values("IsSubTechnique") AS "IsSubTechnique"\
BY\
Matrix, Tactic Technique Sub-Technique Technique_Order Sub_Technique_Order, App\
| fillnull Active Available "Needs data" Sub_Technique_Total Tactic_Total Technique_Total value="0" \
| eval IsSubTechnique=if('Sub-Technique'="-", "No", "Yes") \
| eval Bookmarked=coalesce(Bookmarked, 0) \
| sort 0 Technique_Order Sub_Technique_Order \
| fields - Technique_Order Sub_Technique_Order\
| outputlookup mitre_environment_count.csv
[Generate MITRE Data Source Lookup]
action.webhook.enable_allowlist = 0
alert.track = 0
description = This search formats the MITRE ATT&CK framework Data Sources into a lookup
dispatch.earliest_time = -24h@h
dispatch.latest_time = now
display.general.type = statistics
display.page.search.tab = statistics
search = | ssedata config="mitreattack"\
| where type="x-mitre-data-source" OR type="x-mitre-data-component"\
| spath input=json path="x_mitre_data_source_ref" output="x_mitre_data_source_ref"\
| table type id name description external_id x_mitre_data_source_ref\
| eval ds_id=coalesce(x_mitre_data_source_ref,id)\
| sort 0 ds_id\
\
\
| eventstats\
first(eval(if(type="x-mitre-data-source",name, null()))) AS Name \
first(eval(if(type="x-mitre-data-source",description, null()))) AS Description \
BY ds_id\
| rename external_id AS Id\
| filldown Id\
| where type="x-mitre-data-component"\
| rename name AS Data_Component\
| rename description AS Data_Component_Description\
| eval Data_Source=Name.": ".Data_Component\
| table Id Name Data_Source Description Data_Component Data_Component_Description\
| outputlookup mitre_data_sources
[Generate MITRE Detections Lookup]
action.webhook.enable_allowlist = 0
alert.track = 0
description = This search formats the MITRE ATT&CK framework Detections into a lookup
dispatch.earliest_time = -24h@h
dispatch.latest_time = now
display.general.type = statistics
display.page.search.tab = statistics
search = | ssedata config="mitreattack"\
| where type="relationship" \
| spath input=json path="relationship_type" output="relationship_type"\
| where relationship_type="detects"\
| spath input=json path="source_ref" output="source_ref"\
| spath input=json path="target_ref" output="target_ref"\
| join type=outer target_ref [\
| ssedata config="mitreattack"\
| where type="attack-pattern"\
| table id external_id name description\
| rename id AS target_ref\
| rename external_id AS TechniqueIdCombined\
| rename name AS Technique\
| rename description AS MitreDescription\
]\
| join type=outer source_ref [\
| ssedata config="mitreattack"\
| where type="x-mitre-data-component"\
| table id name description\
| rename id AS source_ref\
| rename name AS Data_Component\
| rename description AS Data_Component_Description\
]\
| eval Type="Detection"\
| rename description AS Description\
| table Type Description TechniqueIdCombined Technique Data_Component Data_Component_Description\
| outputlookup mitre_detections
[Generate MITRE Threat Group Lookup]
action.webhook.enable_allowlist = 0
alert.track = 0
description = This search formats the MITRE ATT&CK framework Threat Groups into a lookup. It also attaches the Industry field based on keyword matching.
dispatch.earliest_time = -24h@h
dispatch.latest_time = now
display.general.type = statistics
display.page.search.tab = statistics
search = | ssedata config="mitreattack"\
| where type="intrusion-set"\
| spath input="json" path="aliases{}" output="Alias"\
| rename name AS Threat_Group, description AS Description, external_id AS Id\
| fields Threat_Group Industry Description Alias Id\
\
``` Logic for splitting the description text to match the industry keywords to something that is close to the sentence break words below ```\
| eval description_words=lower(Description)\
| eval description_words=case(\
like(description_words, "%target%"), mvindex(split(description_words,"target"),1)+coalesce(mvindex(split(description_words,"target"),2),"")+coalesce(mvindex(split(description_words,"target"),3),""),\
like(description_words, "%against%"), mvindex(split(description_words,"against"),1),\
like(description_words, "%industries%"), mvindex(split(description_words,"industries"),1),\
like(description_words, "%interest in%"), mvindex(split(description_words,"interest in"),1),\
like(description_words, "%interested in%"), mvindex(split(description_words,"interested in"),1),\
like(description_words, "%victims%"), mvindex(split(description_words,"victims"),1),\
1=1, ""\
)\
``` Lookup contains wildcard matches to industry keyqords ```\
| lookup sse_industries IndustryAlias AS description_words OUTPUT Industry\
| eval Industry=mvsort(mvdedup(Industry))\
| fields - description_words\
| eval Industry=if(isnull(Industry),"-",Industry)\
| table Threat_Group Industry Description Alias Id\
| outputlookup mitre_threat_groups output_format=splunk_mv_csv