[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*(?.*?)\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*(?.*?)\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 "^(?[^-]*)" | 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=(\"|)(?[^\"\s]*)(|\")" \ | rex field=definition max_match=0 "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="(?"+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="(?"+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="(?"+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="(?"+regex_pattern+")" \ | tail 300 \ | stats values(rexValue) AS regexMerge \ | eval regexMerge=mvjoin(regexMerge,"|") \ | eval search="\"(".regexMerge.")\"" \ | fields search \ ]\ | foreach P_* \ [| eval PatternStringMatch=if('<>'!="", mvappend(PatternStringMatch,'<>'),PatternStringMatch) \ | eval PatternStringDescription=if('<>'!="", mvappend(PatternStringDescription,"<>"),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|:|=)(\"|)(?[a-z,A-Z,_]*)"\ | rex field=qualifiedSearch ".*datamodel(=\"|:\"|\(\"|\s|:|=)(\"|)[a-z,A-Z,_]*(\"|)\.(\"|)(?[a-z,A-Z,_]*)"\ | eval datamodel=if(isnotnull(nodeName), datamodel.".".nodeName, datamodel)\ | rex field=qualifiedSearch max_match=0 "sourcetype=(\"|)(?[^\"\s]*)(|\")" \ | rex field=qualifiedSearch max_match=0 "source=(\"|)(?[^\"]*)(|\")" \ | rex field=qualifiedSearch max_match=0 "`(?[^`]*)`" \ | rex field=qualifiedSearch max_match=0 ".*(?:input| )lookup (?:[a-z,A-Z,_]*=[a-z,A-Z,_]{1,4} |)(?[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="(?"+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="(?"+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="(?"+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="(?"+regex_pattern+")" \ | tail 300 \ | stats values(rexValue) AS regexMerge \ | eval regexMerge=mvjoin(regexMerge,"|") \ | eval search="\"(".regexMerge.")\"" \ | fields search \ ]\ | foreach P_* \ [| eval PatternStringMatch=if('<>'!="", mvappend(PatternStringMatch,'<>'),PatternStringMatch) \ | eval PatternStringDescription=if('<>'!="", mvappend(PatternStringDescription,"<>"),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 "<>" = mvcount('<>')\ ]\ | 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