diff --git a/Signatures/Splunk/panorama-config-change-spike.md b/Signatures/Splunk/panorama-config-change-spike.md new file mode 100644 index 0000000..c98929f --- /dev/null +++ b/Signatures/Splunk/panorama-config-change-spike.md @@ -0,0 +1,5 @@ +index=pan_logs sourcetype=pan:config NOT command IN (request, commit) earliest=-1h +| fields index, host, src_user, src, dest, command, path +| bucket _time span=1h +| stats count as change_count values(path) as targets by _time, index, host, src_user, src, dest, command +| where change_count > 10 \ No newline at end of file diff --git a/Signatures/Splunk/panorama-failed-logon-spike.md b/Signatures/Splunk/panorama-failed-logon-spike.md new file mode 100644 index 0000000..0ce9ff8 --- /dev/null +++ b/Signatures/Splunk/panorama-failed-logon-spike.md @@ -0,0 +1,6 @@ +index=pan_logs sourcetype=pan:system event_id=auth-fail earliest =-1h +| rex field=body "From: (?(?:\d{1,3}\.){3}\d{1,3})" +| stats count as failed_attempts by _time, index, host, src_ip +| where failed_attempts > 5 +| table _time, index, host, src_ip, failed_attempts +| sort - _time \ No newline at end of file diff --git a/Signatures/Splunk/panorama-large-transfer.md b/Signatures/Splunk/panorama-large-transfer.md new file mode 100644 index 0000000..e02a84a --- /dev/null +++ b/Signatures/Splunk/panorama-large-transfer.md @@ -0,0 +1,9 @@ +index=pan_logs sourcetype=pan:traffic earliest=-1h +| eval transfer_mb=bytes_out/1024/1024 +| eval hour_of_day=strftime(_time, "%H") +```| where hour_of_day < "08" OR hour_of_day > "18" ``` +| stats sum(transfer_mb) as total_transfer_mb by src_ip, dest_ip, app, hour_of_day +| where total_transfer_mb > 1024 +| table _time, src_ip, dest_ip, app, total_transfer_mb, hour_of_day +| eval total_transfer_mb=round(total_transfer_mb, 2) +| sort - total_transfer_mb \ No newline at end of file diff --git a/Signatures/Splunk/panorama-src_ip-dest_port-spike.md b/Signatures/Splunk/panorama-src_ip-dest_port-spike.md new file mode 100644 index 0000000..dd2b001 --- /dev/null +++ b/Signatures/Splunk/panorama-src_ip-dest_port-spike.md @@ -0,0 +1,4 @@ +index=pan_logs sourcetype=pan:traffic earliest=-1h +| stats dc(dest_port) as dest_port_count by index, src_ip +| where dest_port_count > 100 +| table index, src_ip, dest_port_count \ No newline at end of file diff --git a/Signatures/Splunk/panorama-src_ip-distinct-dest_ip-spike.md b/Signatures/Splunk/panorama-src_ip-distinct-dest_ip-spike.md new file mode 100644 index 0000000..829c75c --- /dev/null +++ b/Signatures/Splunk/panorama-src_ip-distinct-dest_ip-spike.md @@ -0,0 +1,4 @@ +index=pan_logs sourcetype=pan:traffic earliest=-1h +| stats dc(dest_ip) as dest_ip_count values(dest_ip) as dest_ips by index, src_ip +| where dest_ip_count > 10 +| table index, src_ip, dest_ips, dest_ip_count \ No newline at end of file diff --git a/Signatures/Splunk/panorama-src_ip-unknown-dest_ip-spike.md b/Signatures/Splunk/panorama-src_ip-unknown-dest_ip-spike.md new file mode 100644 index 0000000..74ab97b --- /dev/null +++ b/Signatures/Splunk/panorama-src_ip-unknown-dest_ip-spike.md @@ -0,0 +1,4 @@ +index=pan_logs sourcetype=pan:traffic action!=blocked NOT (dest_ip IN ("192.*", "172.*", "10.*")) earliest=-1h +| stats dc(dest_ip) as dest_ip_count values(dest_ip) as dest_ips by index, src_ip +| where dest_ip_count > 2 +| table index, src_ip, dest_ips, dest_ip_count \ No newline at end of file diff --git a/Signatures/Splunk/panorama-suspicious-dest_port.md b/Signatures/Splunk/panorama-suspicious-dest_port.md new file mode 100644 index 0000000..6c3faa4 --- /dev/null +++ b/Signatures/Splunk/panorama-suspicious-dest_port.md @@ -0,0 +1,2 @@ +index=pan_logs sourcetype=pan:traffic action!=blocked NOT (dest_port IN (1197, 1198, 123, 14000, 2638, 3389, 443, 445, 5001, 53, 5450, 9997, 22)) earliest=-1h +| stats count by index, src_ip, transport, dest_port \ No newline at end of file diff --git a/Signatures/Splunk/panorama-threat-detected.md b/Signatures/Splunk/panorama-threat-detected.md new file mode 100644 index 0000000..162a5bc --- /dev/null +++ b/Signatures/Splunk/panorama-threat-detected.md @@ -0,0 +1,35 @@ +[Palo Alto - Threat Detected] +action.email = 1 +action.email.include.search = 1 +action.email.inline = 1 +action.email.sendcsv = 1 +action.email.sendresults = 1 +action.email.to = someone@example.com +action.email.useNSSubject = 1 +action.webhook.enable_allowlist = 0 +alert.expires = 5m +alert.suppress = 0 +alert.track = 0 +counttype = number of events +cron_schedule = 0 */2 * * * +dispatch.earliest_time = -2h +dispatch.latest_time = now +display.events.fields = ["host","source","sourcetype","eventid","Commandline"] +display.general.type = statistics +display.page.search.mode = verbose +display.page.search.tab = statistics +display.visualizations.chartHeight = 267 +display.visualizations.charting.chart = line +enableSched = 1 +quantity = 0 +relation = greater than +request.ui_dispatch_app = search +request.ui_dispatch_view = search +search = index="pan_logs" sourcetype=pan:threat src_ip!="your-scanner"\ +| rename "app:category" as app_category \ +| fields _time host log_subtype, threat, threat_category, severity, action, app, app_category, category, src_ip, src_port, dest_ip, dest_port\ +| foreach log_subtype, threat, threat_category, severity, action, app, app_category, category, src_ip, src_port, dest_ip, dest_port \ + [ eval <> = if( (len(<>)=0 OR (<>)="" OR isnull(<>)), "-", <>) ] \ +| rename host as PaloAlto\ +| table _time PaloAlto log_subtype, threat, threat_category, severity, action, app, app_category, category, src_ip, src_port, dest_ip, dest_port\ +| sort - _time \ No newline at end of file diff --git a/Signatures/Splunk/panorama-unkown-app-protocol.md b/Signatures/Splunk/panorama-unkown-app-protocol.md new file mode 100644 index 0000000..362c14a --- /dev/null +++ b/Signatures/Splunk/panorama-unkown-app-protocol.md @@ -0,0 +1,6 @@ +index=pan_logs sourcetype=pan:traffic earliest=-1h +| search NOT(app IN (dns-base, ssl, paloalto-updates, pan-db-cloud, sybase, ntp-base, ms-rdp, ms-ds-smbv3, osisoft-pi-v3, unknown-udp, unknown-tcp, insufficient-data, incomplete, splunk, ssh, paloalto-shared-services)) +| stats count by index, src_ip, dest_ip, app, action +| where action="allowed" +| table _time, index, src_ip, dest_ip, app, action, count +| sort - count \ No newline at end of file diff --git a/Signatures/Splunk/sourcetype-outage-dynamic.md b/Signatures/Splunk/sourcetype-outage-dynamic.md new file mode 100644 index 0000000..6f01a57 --- /dev/null +++ b/Signatures/Splunk/sourcetype-outage-dynamic.md @@ -0,0 +1,65 @@ +``` +[SourceType Outage Dynamic] +action.email = 1 +action.email.inline = 1 +action.email.sendresults = 1 +action.email.to = someone@example.com +action.email.useNSSubject = 1 +action.webhook.enable_allowlist = 0 +alert.expires = 7d +alert.suppress = 0 +alert.track = 0 +counttype = number of events +cron_schedule = 0 */12 * * * +description = Triggered when sourcetypes/index pairs that typically produce data have stopped, ignoring sourcetypes that do not reliably produce events. +dispatch.earliest_time = -24h@h +dispatch.latest_time = now +display.general.type = statistics +display.page.search.mode = verbose +display.page.search.tab = statistics +enableSched = 1 +quantity = 0 +relation = greater than +request.ui_dispatch_app = search +request.ui_dispatch_view = search +search = | eventcount summarize=false index=* \ +| stats sum(count) as IndexEventCount by index \ +| where IndexEventCount > 0\ +| map [|metadata type=sourcetypes index="$index$" | eval index="$index$"] maxsearches=1000\ +| lookup eventcount_stats.csv index sourcetype OUTPUT Perc10EventCount\ +| where totalCount > 100 ``` Do not monitor empty or temporarily used sourcetypes```\ +| where Perc10EventCount >= 5 ``` Do not monitor event types that produce infrequent or a very small number of results, as they can produce an overly sensitive alert unrelated to the actual data pipeline health ```\ +| where recentTime > relative_time(now(),"-7d") ``` Do not monitor sourcetypes not seen in 7 days```\ +| where recentTime < relative_time(now(),"-1d") ``` Alert on sourcetypes not seen in over 1 day```\ +| eval age = now()-recentTime\ +| eval TimeSince = tostring(age,"duration")\ +| convert timeformat="%F %T %Z" ctime(lastTime), ctime(recentTime), ctime(firstTime)\ +| eval Perc10EventCount = round(Perc10EventCount,1)\ +| fields index sourcetype TimeSince Perc10EventCount recentTime lastTime firstTime totalCount +``` + + +``` +[LookupTable - eventcount_stats.csv] +action.email.useNSSubject = 1 +action.webhook.enable_allowlist = 0 +alert.track = 0 +cron_schedule = 0 21 * * 3 +dispatch.earliest_time = -30d@d +dispatch.latest_time = now +display.general.type = statistics +display.page.search.mode = fast +display.page.search.tab = statistics +display.visualizations.show = 0 +enableSched = 1 +request.ui_dispatch_app = search +request.ui_dispatch_view = search +search = | eventcount summarize=false index=* \ +| stats sum(count) as IndexEventCount by index \ +| where IndexEventCount > 0\ +| map [| tstats count WHERE index=$index$ by _time sourcetype span=1d | timechart sum(count) as count by sourcetype limit=0 span=1d | fillnull value=0 | untable _time sourcetype count | stats perc5(count) as Perc05EventCount, perc10(count) as Perc10EventCount, perc25(count) as Perc25EventCount, perc50(count) as Perc50EventCount, perc95(count) as Perc95EventCount, avg(count) as AvgEventCount, sum(count) as TotalEventCount, min(_time) as StartTime, max(_time) as EndTime by sourcetype | eval index="$index$" ] maxsearches=1000 ``` timechart & untable required to create time bins with 0 events ```\ +| table index, sourcetype, StartTime, EndTime, *EventCount\ +| fieldformat EndTime = strftime(EndTime, "%F %T %Z")\ +| fieldformat StartTime = strftime(StartTime, "%F %T %Z")\ +| outputlookup eventcount_stats.csv override_if_empty=false +``` diff --git a/Signatures/splunk.md b/Signatures/Splunk/splunk-general.md similarity index 100% rename from Signatures/splunk.md rename to Signatures/Splunk/splunk-general.md diff --git a/Splunk/apps/Splunk_TA_paloalto/local/props.conf b/Splunk/apps/Splunk_TA_paloalto/local/props.conf new file mode 100644 index 0000000..a04afa7 --- /dev/null +++ b/Splunk/apps/Splunk_TA_paloalto/local/props.conf @@ -0,0 +1,6 @@ +[pan:system] +EXTRACT-user = authenticated for user \'(?[^']+) +EXTRACT-src1 = From: (?[^,]+) +EVAL-src = rtrim(src1, ".\"") +EXTRACT-user = failed authentication for user \'(?[^']+) +EXTRACT-Reason = Reason: (?[^,]+) \ No newline at end of file diff --git a/Splunk/output/savedsearches.conf b/Splunk/sigma/output/savedsearches.conf similarity index 100% rename from Splunk/output/savedsearches.conf rename to Splunk/sigma/output/savedsearches.conf diff --git a/Splunk/pipelines/.gitkeep b/Splunk/sigma/pipelines/.gitkeep similarity index 100% rename from Splunk/pipelines/.gitkeep rename to Splunk/sigma/pipelines/.gitkeep diff --git a/Splunk/pipelines/cloudtrail.yml b/Splunk/sigma/pipelines/cloudtrail.yml similarity index 100% rename from Splunk/pipelines/cloudtrail.yml rename to Splunk/sigma/pipelines/cloudtrail.yml diff --git a/Splunk/pipelines/evtx2splunk.yml b/Splunk/sigma/pipelines/evtx2splunk.yml similarity index 100% rename from Splunk/pipelines/evtx2splunk.yml rename to Splunk/sigma/pipelines/evtx2splunk.yml diff --git a/Splunk/pipelines/linux_builtin.yml b/Splunk/sigma/pipelines/linux_builtin.yml similarity index 100% rename from Splunk/pipelines/linux_builtin.yml rename to Splunk/sigma/pipelines/linux_builtin.yml diff --git a/Splunk/pipelines/webserver_generic.yml b/Splunk/sigma/pipelines/webserver_generic.yml similarity index 100% rename from Splunk/pipelines/webserver_generic.yml rename to Splunk/sigma/pipelines/webserver_generic.yml diff --git a/Splunk/sigma-splunk-library.md b/Splunk/sigma/sigma-splunk-library.md similarity index 100% rename from Splunk/sigma-splunk-library.md rename to Splunk/sigma/sigma-splunk-library.md diff --git a/Tactics/Network-Activity-by-IP.md b/Tactics/Network-Activity-by-IP.md index d037e0f..7340fa0 100644 --- a/Tactics/Network-Activity-by-IP.md +++ b/Tactics/Network-Activity-by-IP.md @@ -8,7 +8,7 @@ Grouped by [Detection Method](/Detection-Methods.md) ## Blacklist Alert - Egress Traffic to Known-Bad Port -- Engress Traffic to Known Bad IP +- ingress Traffic to Known Bad IP - Egress Traffic to Known Sinkhole IP - Allowed Ingress Border Traffic on port 3389 (RDP) - Allowed Ingress Border Traffic on port 6568 (Anydesk)