Skip to content

Commit

Permalink
[filteradd] Support Cisco Firepower MC (#659)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Faircloth authored and GitHub committed Aug 21, 2020
1 parent e772e06 commit 87cb894
Show file tree
Hide file tree
Showing 7 changed files with 147 additions and 16 deletions.
4 changes: 3 additions & 1 deletion docs/sources/Cisco/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ Including Legacy FWSM and PIX
| sourcetype | notes |
|----------------|---------------------------------------------------------------------------------------------------------|
| cisco:asa | cisco FTD Firepower will also use this source type except those noted below |
| cisco:ftd | cisco FTD Firepower will also use this source type except those noted below |
| cisco:fwsm | Splunk has |
| cisco:pix | cisco PIX will also use this source type except those noted below |
| cisco:firepower:syslog | FTD Unified events see https://www.cisco.com/c/en/us/td/docs/security/firepower/Syslogs/b_fptd_syslog_guide.pdf |
Expand All @@ -131,7 +132,8 @@ Including Legacy FWSM and PIX
| cisco_asa | cisco:asa | netfw | none |
| cisco_fwsm | cisco:fwsm | netfw | none |
| cisco_pix | cisco:pix | netfw | none |
| cisco_ftd | cisco:firepower:syslog | netfw | none |
| cisco_firepower | cisco:firepower:syslog | netids | none |
| cisco_ftd | cisco:ftd | netfw | none |


### Filter type
Expand Down
3 changes: 3 additions & 0 deletions package/etc/conf.d/filters/cisco/firepower.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
filter f_cisco_firepower {
program('SFIMS');
};
2 changes: 1 addition & 1 deletion package/etc/conf.d/log_paths/lp-cisco_asa.conf.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ log {
filter(f_cisco_ftd);
rewrite {
set("cisco_ftd", value("fields.sc4s_vendor_product"));
r_set_splunk_dest_default(sourcetype("cisco:firepower:syslog"))
r_set_splunk_dest_default(sourcetype("cisco:ftd"))
};
parser {p_add_context_splunk(key("cisco_ftd")); };
parser (compliance_meta_by_source);
Expand Down
63 changes: 63 additions & 0 deletions package/etc/conf.d/log_paths/lp-cisco_firepower.conf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# cisco_firepower
{{- /* The following provides a unique port source configuration if env var(s) are set */}}
{{- $context := dict "port_id" "CISCO_FIREPOWER" "parser" "rfc3164" }}
{{- tmpl.Exec "t/source_network.t" $context }}

log {
junction {
{{- if or (or (getenv (print "SC4S_LISTEN_CISCO_FIREPOWER_TCP_PORT")) (getenv (print "SC4S_LISTEN_CISCO_FIREPOWER_UDP_PORT"))) (getenv (print "SC4S_LISTEN_CISCO_FIREPOWER_TLS_PORT")) }}
channel {
# Listen on the specified dedicated port(s) for CISCO_FIREPOWER traffic
source (s_CISCO_FIREPOWER);
flags (final);
};
{{- end}}
channel {
# Listen on the default port (typically 514) for CISCO_FIREPOWER traffic
source (s_DEFAULT);
filter(f_cisco_firepower);
flags(final);
};
};

if {
filter{program("SFIMS")};
rewrite {
set("cisco_firepower", value("fields.sc4s_vendor_product"));
r_set_splunk_dest_default(sourcetype("cisco:firepower:syslog"))
};
parser { p_add_context_splunk(key("cisco_firepower")); };
parser (compliance_meta_by_source);
rewrite { set("$(template ${.splunk.sc4s_template} $(template t_hdr_msg))" value("MSG")); };
} else {
rewrite {
set("cisco_firepower", value("fields.sc4s_vendor_product"));
subst("^[^\t]+\t", "", value("MESSAGE"), flags("global"));
set("${PROGRAM}", value(".PROGRAM"));
subst('^\/(?:[^\/]+\/)+', "" , value(".PROGRAM"));
r_set_splunk_dest_default(sourcetype("cisco_firepower:${.PROGRAM}"), source("program:${.PROGRAM}"))
};
parser { p_add_context_splunk(key("cisco_firepower")); };
parser (compliance_meta_by_source);
rewrite { set("$(template ${.splunk.sc4s_template} $(template t_legacy_hdr_msg))" value("MSG")); };
};


{{- if or (conv.ToBool (getenv "SC4S_DEST_SPLUNK_HEC_GLOBAL" "yes")) (conv.ToBool (getenv "SC4S_DEST_CISCO_FIREPOWER_HEC" "no")) }}
destination(d_hec);
{{- end}}

{{- if or (conv.ToBool (getenv "SC4S_ARCHIVE_GLOBAL" "no")) (conv.ToBool (getenv "SC4S_ARCHIVE_CISCO_FIREPOWER" "no")) }}
destination(d_archive);
{{- end}}

{{- if (print (getenv "SC4S_DEST_GLOBAL_ALTERNATES")) }}
{{ getenv "SC4S_DEST_GLOBAL_ALTERNATES" | regexp.ReplaceLiteral "^" "destination(" | regexp.ReplaceLiteral "[, ]+" ");\n destination(" }});
{{- end }}

{{- if (print (getenv "SC4S_DEST_CISCO_FIREPOWER_ALTERNATES")) }}
{{ getenv "SC4S_DEST_CISCO_FIREPOWER_ALTERNATES" | regexp.ReplaceLiteral "^" "destination(" | regexp.ReplaceLiteral "[, ]+" ");\n destination(" }});
{{- end }}

flags(flow-control,final);
};
1 change: 1 addition & 0 deletions package/etc/context_templates/splunk_metadata.csv.example
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Cisco_C100V Email Security Virtual Appliance_ESA_CONSOLIDATED_LOG_EVENT,sc4s_tem
Cisco_C100V Email Security Virtual Appliance_ESA_CONSOLIDATED_LOG_EVENT,source,esa:consolidated
Cisco_C100V Email Security Virtual Appliance_ESA_CONSOLIDATED_LOG_EVENT,sourcetype,cisco:esa:cef
cisco_esa,index,email
cisco_firepower,index,netids
cisco_ftd,index,netfw
cisco_fwsm,index,netfw
cisco_ios,index,netops
Expand Down
46 changes: 32 additions & 14 deletions tests/test_cisco_asa.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
# Apr 15 2017 00:21:14 192.168.12.1 : %ASA-5-111010: User 'john', running 'CLI' from IP 0.0.0.0, executed 'dir disk0:/dap.xml'
# Apr 15 2017 00:22:27 192.168.12.1 : %ASA-4-313005: No matching connection for ICMP error message: icmp src outside:81.24.28.226 dst inside:72.142.17.10 (type 3, code 0) on outside interface. Original IP payload: udp src 72.142.17.10/40998 dst 194.153.237.66/53.
# Apr 15 2017 00:22:42 192.168.12.1 : %ASA-3-710003: TCP access denied by ACL from 179.236.133.160/8949 to outside:72.142.18.38/23
def test_cisco_asa_traditional(record_property, setup_wordlist, setup_splunk, setup_sc4s):
def test_cisco_asa_traditional(
record_property, setup_wordlist, setup_splunk, setup_sc4s
):
host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))

dt = datetime.datetime.now()
Expand All @@ -27,12 +29,15 @@ def test_cisco_asa_traditional(record_property, setup_wordlist, setup_splunk, se
epoch = epoch[:-7]

mt = env.from_string(
"{{ mark }} {{ bsd }} {{ host }} : %ASA-3-003164: TCP access denied by ACL from 179.236.133.160/3624 to outside:72.142.18.38/23\n")
"{{ mark }} {{ bsd }} {{ host }} : %ASA-3-003164: TCP access denied by ACL from 179.236.133.160/3624 to outside:72.142.18.38/23\n"
)
message = mt.render(mark="<111>", bsd=bsd, host=host)

sendsingle(message, setup_sc4s[0], setup_sc4s[1][514])

st = env.from_string("search _time={{ epoch }} index=netfw host=\"{{ host }}\" sourcetype=\"cisco:asa\" \"%ASA-3-003164\"")
st = env.from_string(
'search _time={{ epoch }} index=netfw host="{{ host }}" sourcetype="cisco:asa" "%ASA-3-003164"'
)
search = st.render(epoch=epoch, host=host)

resultCount, eventCount = splunk_single(setup_splunk, search)
Expand All @@ -43,8 +48,11 @@ def test_cisco_asa_traditional(record_property, setup_wordlist, setup_splunk, se

assert resultCount == 1


# <164>Jan 31 2020 17:24:03: %ASA-4-402119: IPSEC: Received an ESP packet (SPI= 0x0C190BF9, sequence number= 0x598243) from 192.0.0.1 (user= 192.0.0.1) to 192.0.0.2 that failed anti-replay checking.
def test_cisco_asa_traditional_nohost(record_property, setup_wordlist, setup_splunk, setup_sc4s):
def test_cisco_asa_traditional_nohost(
record_property, setup_wordlist, setup_splunk, setup_sc4s
):
host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))

dt = datetime.datetime.now()
Expand All @@ -54,12 +62,15 @@ def test_cisco_asa_traditional_nohost(record_property, setup_wordlist, setup_spl
epoch = epoch[:-7]

mt = env.from_string(
"{{ mark }} {{ bsd }}: %ASA-4-402119: IPSEC: Received an ESP packet (SPI= 0x0C190BF9, sequence number= 0x598243) from {{host}} (user= 192.0.0.1) to 192.0.0.2 that failed anti-replay checking.\n")
"{{ mark }} {{ bsd }}: %ASA-4-402119: IPSEC: Received an ESP packet (SPI= 0x0C190BF9, sequence number= 0x598243) from {{host}} (user= 192.0.0.1) to 192.0.0.2 that failed anti-replay checking.\n"
)
message = mt.render(mark="<111>", bsd=bsd, host=host)

sendsingle(message, setup_sc4s[0], setup_sc4s[1][514])

st = env.from_string("search _time={{ epoch }} index=netfw sourcetype=\"cisco:asa\" \"%ASA-4-402119\" \"{{ host }}\"")
st = env.from_string(
'search _time={{ epoch }} index=netfw sourcetype="cisco:asa" "%ASA-4-402119" "{{ host }}"'
)
search = st.render(epoch=epoch, host=host)

resultCount, eventCount = splunk_single(setup_splunk, search)
Expand All @@ -75,7 +86,7 @@ def test_cisco_asa_traditional_nohost(record_property, setup_wordlist, setup_spl
def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk, setup_sc4s):
host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))

# Get UTC-based 'dt' time structure
# Get UTC-based 'dt' time structure
dt = datetime.datetime.now(datetime.timezone.utc)
iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt)

Expand All @@ -85,12 +96,15 @@ def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk, setup_
epoch = epoch[:-7]

mt = env.from_string(
"{{ mark }} {{ iso }}Z {{ host }} : %ASA-3-005424: TCP access denied by ACL from 179.236.133.160/5424 to outside:72.142.18.38/23 epoch={{ epoch }}\n")
"{{ mark }} {{ iso }}Z {{ host }} : %ASA-3-005424: TCP access denied by ACL from 179.236.133.160/5424 to outside:72.142.18.38/23 epoch={{ epoch }}\n"
)
message = mt.render(mark="<166>", iso=iso, epoch=epoch, host=host)

sendsingle(message, setup_sc4s[0], setup_sc4s[1][514])

st = env.from_string("search _time={{ epoch }} index=netfw host=\"{{ host }}\" sourcetype=\"cisco:asa\" \"%ASA-3-005424\"")
st = env.from_string(
'search _time={{ epoch }} index=netfw host="{{ host }}" sourcetype="cisco:asa" "%ASA-3-005424"'
)
search = st.render(epoch=epoch, host=host)

resultCount, eventCount = splunk_single(setup_splunk, search)
Expand All @@ -101,11 +115,12 @@ def test_cisco_asa_rfc5424(record_property, setup_wordlist, setup_splunk, setup_

assert resultCount == 1

#<118>2020-02-04T11:00:54Z %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity

# <118>2020-02-04T11:00:54Z %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity
def test_cisco_ftd(record_property, setup_wordlist, setup_splunk, setup_sc4s):
host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))

# Get UTC-based 'dt' time structure
# Get UTC-based 'dt' time structure
dt = datetime.datetime.now(datetime.timezone.utc)
iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt)

Expand All @@ -115,12 +130,15 @@ def test_cisco_ftd(record_property, setup_wordlist, setup_splunk, setup_sc4s):
epoch = epoch[:-7]

mt = env.from_string(
"{{ mark }} {{ iso }}Z {{ host }} : %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity\n")
"{{ mark }} {{ iso }}Z {{ host }} : %FTD-6-430003: DeviceUUID: 90e14378-2081-11e8-a7fa-d34972ba379f, AccessControlRuleAction: Allow, SrcIP: 75.150.94.75, DstIP: 172.30.0.2, SrcPort: 59698, DstPort: 8027, Protocol: tcp, IngressInterface: Outside2, EgressInterface: DMZ, IngressZone: Outside, EgressZone: DMZ, ACPolicy: Rapid7 5525X, AccessControlRuleName: Allow MDM - Out to DMZ, Prefilter Policy: Default Prefilter Policy, User: No Authentication Required, ConnectionDuration: 600, InitiatorPackets: 0, ResponderPackets: 0, InitiatorBytes: 31, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity\n"
)
message = mt.render(mark="<166>", iso=iso, epoch=epoch, host=host)

sendsingle(message, setup_sc4s[0], setup_sc4s[1][514])

st = env.from_string("search _time={{ epoch }} index=netfw host=\"{{ host }}\" sourcetype=\"cisco:firepower:syslog\"")
st = env.from_string(
'search _time={{ epoch }} index=netfw host="{{ host }}" sourcetype="cisco:ftd"'
)
search = st.render(epoch=epoch, host=host)

resultCount, eventCount = splunk_single(setup_splunk, search)
Expand All @@ -129,4 +147,4 @@ def test_cisco_ftd(record_property, setup_wordlist, setup_splunk, setup_sc4s):
record_property("resultCount", resultCount)
record_property("message", message)

assert resultCount == 1
assert resultCount == 1
44 changes: 44 additions & 0 deletions tests/test_cisco_firepower.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Copyright 2019 Splunk, Inc.
#
# Use of this source code is governed by a BSD-2-clause-style
# license that can be found in the LICENSE-BSD2 file or at
# https://opensource.org/licenses/BSD-2-Clause
import random

from jinja2 import Environment

from .sendmessage import *
from .splunkutils import *
from .timeutils import *

env = Environment()


def test_cisco_firepower(record_property, setup_wordlist, setup_splunk, setup_sc4s):
host = "{}-{}".format(random.choice(setup_wordlist), random.choice(setup_wordlist))

dt = datetime.datetime.now()
iso, bsd, time, date, tzoffset, tzname, epoch = time_operations(dt)

# Tune time functions
epoch = epoch[:-7]

mt = env.from_string(
"{{ mark }} {{ bsd }} {{ host }} SFIMS: Protocol: TCP, SrcIP: 1.1.1.1, OriginalClientIP: ::, DstIP: 2.2.2.2, SrcPort: 47097, DstPort: 33897, TCPFlags: 0x0, DE: Primary Detection Engine (asdf912a-ad91-d192-adsf-12aadf32910d), Policy: device-policy, ConnectType: Start, AccessControlRuleName: EU-NoLicense-Block-All, AccessControlRuleAction: Block with reset, Prefilter Policy: Default Prefilter Policy, InitiatorPackets: 1, ResponderPackets: 0, InitiatorBytes: 54, ResponderBytes: 0, NAPPolicy: Balanced Security and Connectivity, DNSResponseType: No Error, Sinkhole: Unknown, URLCategory: Unknown, URLReputation: Risk unknown\n"
)
message = mt.render(mark="<111>", bsd=bsd, host=host)

sendsingle(message, setup_sc4s[0], setup_sc4s[1][514])

st = env.from_string(
'search _time={{ epoch }} index=netids host="{{ host }}" sourcetype="cisco:firepower:syslog"'
)
search = st.render(epoch=epoch, host=host)

resultCount, eventCount = splunk_single(setup_splunk, search)

record_property("host", host)
record_property("resultCount", resultCount)
record_property("message", message)

assert resultCount == 1

0 comments on commit 87cb894

Please sign in to comment.