diff --git a/salt/bpf/pcap.map.jinja b/salt/bpf/pcap.map.jinja index 4d8fef460..953b01a08 100644 --- a/salt/bpf/pcap.map.jinja +++ b/salt/bpf/pcap.map.jinja @@ -1,4 +1,7 @@ {% from 'vars/globals.map.jinja' import GLOBALS %} +{% set PCAP_BPF_STATUS = 0 %} +{% set STENO_BPF_COMPILED = "" %} + {% if GLOBALS.pcap_engine == "TRANSITION" %} {% set PCAPBPF = ["ip and host 255.255.255.1 and port 1"] %} {% else %} @@ -8,3 +11,11 @@ {{ MACROS.remove_comments(BPFMERGED, 'pcap') }} {% set PCAPBPF = BPFMERGED.pcap %} {% endif %} + +{% if PCAPBPF %} + {% set PCAP_BPF_CALC = salt['cmd.run_all']('/usr/sbin/so-bpf-compile ' ~ GLOBALS.sensor.interface ~ ' ' ~ PCAPBPF|join(" "), cwd='/root') %} + {% if PCAP_BPF_CALC['retcode'] == 0 %} + {% set PCAP_BPF_STATUS = 1 %} + {% set STENO_BPF_COMPILED = ",\\\"--filter=" + PCAP_BPF_CALC['stdout'] + "\\\"" %} + {% endif %} +{% endif %} diff --git a/salt/bpf/soc_bpf.yaml b/salt/bpf/soc_bpf.yaml index d93ec98fd..416c5fc60 100644 --- a/salt/bpf/soc_bpf.yaml +++ b/salt/bpf/soc_bpf.yaml @@ -1,11 +1,11 @@ bpf: pcap: - description: List of BPF filters to apply to Stenographer. + description: List of BPF filters to apply to the PCAP engine. multiline: True forcedType: "[]string" helpLink: bpf.html suricata: - description: List of BPF filters to apply to Suricata. + description: List of BPF filters to apply to Suricata. This will apply to alerts and, if enabled, to metadata and PCAP logs generated by Suricata. multiline: True forcedType: "[]string" helpLink: bpf.html diff --git a/salt/bpf/suricata.map.jinja b/salt/bpf/suricata.map.jinja index fe4adb663..5ee1e5a92 100644 --- a/salt/bpf/suricata.map.jinja +++ b/salt/bpf/suricata.map.jinja @@ -1,7 +1,16 @@ +{% from 'vars/globals.map.jinja' import GLOBALS %} {% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %} {% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %} +{% set SURICATA_BPF_STATUS = 0 %} {% import 'bpf/macros.jinja' as MACROS %} {{ MACROS.remove_comments(BPFMERGED, 'suricata') }} {% set SURICATABPF = BPFMERGED.suricata %} + +{% if SURICATABPF %} + {% set SURICATA_BPF_CALC = salt['cmd.run_all']('/usr/sbin/so-bpf-compile ' ~ GLOBALS.sensor.interface ~ ' ' ~ SURICATABPF|join(" "), cwd='/root') %} + {% if SURICATA_BPF_CALC['retcode'] == 0 %} + {% set SURICATA_BPF_STATUS = 1 %} + {% endif %} +{% endif %} diff --git a/salt/bpf/zeek.map.jinja b/salt/bpf/zeek.map.jinja index fdcc5e99f..789648bdb 100644 --- a/salt/bpf/zeek.map.jinja +++ b/salt/bpf/zeek.map.jinja @@ -1,7 +1,16 @@ +{% from 'vars/globals.map.jinja' import GLOBALS %} {% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %} {% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %} +{% set ZEEK_BPF_STATUS = 0 %} {% import 'bpf/macros.jinja' as MACROS %} {{ MACROS.remove_comments(BPFMERGED, 'zeek') }} {% set ZEEKBPF = BPFMERGED.zeek %} + +{% if ZEEKBPF %} + {% set ZEEK_BPF_CALC = salt['cmd.run_all']('/usr/sbin/so-bpf-compile ' ~ GLOBALS.sensor.interface ~ ' ' ~ ZEEKBPF|join(" "), cwd='/root') %} + {% if ZEEK_BPF_CALC['retcode'] == 0 %} + {% set ZEEK_BPF_STATUS = 1 %} + {% endif %} +{% endif %} diff --git a/salt/common/tools/sbin/so-bpf-compile b/salt/common/tools/sbin/so-bpf-compile index f1136cd0e..316a26775 100755 --- a/salt/common/tools/sbin/so-bpf-compile +++ b/salt/common/tools/sbin/so-bpf-compile @@ -29,9 +29,26 @@ fi interface="$1" shift -tcpdump -i $interface -ddd $@ | tail -n+2 | -while read line; do + +# Capture tcpdump output and exit code +tcpdump_output=$(tcpdump -i "$interface" -ddd "$@" 2>&1) +tcpdump_exit=$? + +if [ $tcpdump_exit -ne 0 ]; then + echo "$tcpdump_output" >&2 + exit $tcpdump_exit +fi + +# Process the output, skipping the first line +echo "$tcpdump_output" | tail -n+2 | while read -r line; do cols=( $line ) - printf "%04x%02x%02x%08x" ${cols[0]} ${cols[1]} ${cols[2]} ${cols[3]} + printf "%04x%02x%02x%08x" "${cols[0]}" "${cols[1]}" "${cols[2]}" "${cols[3]}" done + +# Check if the pipeline succeeded +if [ "${PIPESTATUS[0]}" -ne 0 ]; then + exit 1 +fi + echo "" +exit 0 diff --git a/salt/pcap/config.sls b/salt/pcap/config.sls index 173fecfd1..c37da9694 100644 --- a/salt/pcap/config.sls +++ b/salt/pcap/config.sls @@ -8,12 +8,9 @@ {% from 'vars/globals.map.jinja' import GLOBALS %} {% from "pcap/config.map.jinja" import PCAPMERGED %} -{% from 'bpf/pcap.map.jinja' import PCAPBPF %} - -{% set BPF_COMPILED = "" %} +{% from 'bpf/pcap.map.jinja' import PCAPBPF, PCAP_BPF_STATUS, PCAP_BPF_CALC, STENO_BPF_COMPILED %} # PCAP Section - stenographergroup: group.present: - name: stenographer @@ -40,18 +37,12 @@ pcap_sbin: - group: 939 - file_mode: 755 -{% if PCAPBPF %} - {% set BPF_CALC = salt['cmd.script']('salt://common/tools/sbin/so-bpf-compile', GLOBALS.sensor.interface + ' ' + PCAPBPF|join(" "),cwd='/root') %} - {% if BPF_CALC['stderr'] == "" %} - {% set BPF_COMPILED = ",\\\"--filter=" + BPF_CALC['stdout'] + "\\\"" %} - {% else %} - -bpfcompilationfailure: +{% if PCAPBPF and not PCAP_BPF_STATUS %} +stenoPCAPbpfcompilationfailure: test.configurable_test_state: - changes: False - result: False - - comment: "BPF Compilation Failed - Discarding Specified BPF" - {% endif %} + - comment: "BPF Syntax Error - Discarding Specified BPF. Error: {{ PCAP_BPF_CALC['stderr'] }}" {% endif %} stenoconf: @@ -64,7 +55,7 @@ stenoconf: - template: jinja - defaults: PCAPMERGED: {{ PCAPMERGED }} - BPF_COMPILED: "{{ BPF_COMPILED }}" + STENO_BPF_COMPILED: "{{ STENO_BPF_COMPILED }}" stenoca: file.directory: diff --git a/salt/pcap/files/config.jinja b/salt/pcap/files/config.jinja index f0a4fc51d..90c197938 100644 --- a/salt/pcap/files/config.jinja +++ b/salt/pcap/files/config.jinja @@ -6,6 +6,6 @@ , "Interface": "{{ pillar.sensor.interface }}" , "Port": 1234 , "Host": "127.0.0.1" - , "Flags": ["-v", "--blocks={{ PCAPMERGED.config.blocks }}", "--preallocate_file_mb={{ PCAPMERGED.config.preallocate_file_mb }}", "--aiops={{ PCAPMERGED.config.aiops }}", "--uid=stenographer", "--gid=stenographer"{{ BPF_COMPILED }}] + , "Flags": ["-v", "--blocks={{ PCAPMERGED.config.blocks }}", "--preallocate_file_mb={{ PCAPMERGED.config.preallocate_file_mb }}", "--aiops={{ PCAPMERGED.config.aiops }}", "--uid=stenographer", "--gid=stenographer"{{ STENO_BPF_COMPILED }}] , "CertPath": "/etc/stenographer/certs" } diff --git a/salt/suricata/config.sls b/salt/suricata/config.sls index 00364f384..7de1a0fd4 100644 --- a/salt/suricata/config.sls +++ b/salt/suricata/config.sls @@ -7,9 +7,47 @@ {% if sls.split('.')[0] in allowed_states %} {% from 'vars/globals.map.jinja' import GLOBALS %} -{% from 'bpf/suricata.map.jinja' import SURICATABPF %} {% from 'suricata/map.jinja' import SURICATAMERGED %} -{% set BPF_STATUS = 0 %} +{% from 'bpf/suricata.map.jinja' import SURICATABPF, SURICATA_BPF_STATUS, SURICATA_BPF_CALC %} + +suridir: + file.directory: + - name: /opt/so/conf/suricata + - user: 940 + - group: 940 + +{% if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %} +{% from 'bpf/pcap.map.jinja' import PCAPBPF, PCAP_BPF_STATUS, PCAP_BPF_CALC %} +# BPF compilation and configuration +{% if PCAPBPF and not PCAP_BPF_STATUS %} +suriPCAPbpfcompilationfailure: + test.configurable_test_state: + - changes: False + - result: False + - comment: "BPF Syntax Error - Discarding Specified BPF. Error: {{ PCAP_BPF_CALC['stderr'] }}" +{% endif %} +{% endif %} + +# BPF applied to all of Suricata - alerts/metadata/pcap +suribpf: + file.managed: + - name: /opt/so/conf/suricata/bpf + - user: 940 + - group: 940 + {% if SURICATA_BPF_STATUS %} + - contents: {{ SURICATABPF }} + {% else %} + - contents: + - "" + {% endif %} + +{% if SURICATABPF and not SURICATA_BPF_STATUS %} +suribpfcompilationfailure: + test.configurable_test_state: + - changes: False + - result: False + - comment: "BPF Syntax Error - Discarding Specified BPF. Error: {{ SURICATA_BPF_CALC['stderr'] }}" +{% endif %} # Add Suricata Group suricatagroup: @@ -49,18 +87,11 @@ suricata_sbin_jinja: - file_mode: 755 - template: jinja -suridir: - file.directory: - - name: /opt/so/conf/suricata - - user: 940 - - group: 940 - suriruledir: file.directory: - name: /opt/so/conf/suricata/rules - user: 940 - group: 940 - - makedirs: True surilogdir: file.directory: @@ -136,32 +167,6 @@ suriclassifications: - user: 940 - group: 940 -# BPF compilation and configuration -{% if SURICATABPF %} - {% set BPF_CALC = salt['cmd.script']('salt://common/tools/sbin/so-bpf-compile', GLOBALS.sensor.interface + ' ' + SURICATABPF|join(" "),cwd='/root') %} - {% if BPF_CALC['stderr'] == "" %} - {% set BPF_STATUS = 1 %} - {% else %} -suribpfcompilationfailure: - test.configurable_test_state: - - changes: False - - result: False - - comment: "BPF Syntax Error - Discarding Specified BPF" - {% endif %} -{% endif %} - -suribpf: - file.managed: - - name: /opt/so/conf/suricata/bpf - - user: 940 - - group: 940 - {% if BPF_STATUS %} - - contents: {{ SURICATABPF }} - {% else %} - - contents: - - "" - {% endif %} - so-suricata-eve-clean: file.managed: - name: /usr/sbin/so-suricata-eve-clean diff --git a/salt/suricata/defaults.yaml b/salt/suricata/defaults.yaml index d819d1cf9..9c9a7a8ed 100644 --- a/salt/suricata/defaults.yaml +++ b/salt/suricata/defaults.yaml @@ -34,7 +34,7 @@ suricata: threads: 1 tpacket-v3: "yes" ring-size: 5000 - block-size: 32768 + block-size: 69632 block-timeout: 10 use-emergency-flush: "yes" buffer-size: 32768 @@ -97,6 +97,11 @@ suricata: - 4789 TEREDO_PORTS: - 3544 + SIP_PORTS: + - 5060 + - 5061 + GENEVE_PORTS: + - 6081 default-log-dir: /var/log/suricata/ stats: enabled: "yes" @@ -134,14 +139,6 @@ suricata: header: X-Forwarded-For unified2-alert: enabled: "no" - http-log: - enabled: "no" - filename: http.log - append: "yes" - tls-log: - enabled: "no" - filename: tls.log - append: "yes" tls-store: enabled: "no" pcap-log: @@ -157,9 +154,6 @@ suricata: totals: "yes" threads: "no" null-values: "yes" - syslog: - enabled: "no" - facility: local5 drop: enabled: "no" file-store: @@ -206,6 +200,9 @@ suricata: enabled: "yes" detection-ports: dp: 443 + ja3-fingerprints: auto + ja4-fingerprints: auto + encryption-handling: track-only dcerpc: enabled: "yes" ftp: @@ -255,19 +252,21 @@ suricata: libhtp: default-config: personality: IDS - request-body-limit: 100kb - response-body-limit: 100kb - request-body-minimal-inspect-size: 32kb - request-body-inspect-window: 4kb - response-body-minimal-inspect-size: 40kb - response-body-inspect-window: 16kb + request-body-limit: 100 KiB + response-body-limit: 100 KiB + request-body-minimal-inspect-size: 32 KiB + request-body-inspect-window: 4 KiB + response-body-minimal-inspect-size: 40 KiB + response-body-inspect-window: 16 KiB response-body-decompress-layer-limit: 2 http-body-inline: auto swf-decompression: - enabled: "yes" + enabled: "no" type: both - compress-depth: 0 - decompress-depth: 0 + compress-depth: 100 KiB + decompress-depth: 100 KiB + randomize-inspection-sizes: "yes" + randomize-inspection-range: 10 double-decode-path: "no" double-decode-query: "no" server-config: @@ -401,8 +400,12 @@ suricata: vxlan: enabled: true ports: $VXLAN_PORTS - erspan: + geneve: enabled: true + ports: $GENEVE_PORTS + max-layers: 16 + recursion-level: + use-for-tracking: true detect: profile: medium custom-values: @@ -422,7 +425,12 @@ suricata: spm-algo: auto luajit: states: 128 - + security: + lua: + allow-rules: false + max-bytes: 500000 + max-instructions: 500000 + allow-restricted-functions: false profiling: rules: enabled: "yes" diff --git a/salt/suricata/map.jinja b/salt/suricata/map.jinja index a2c7072e0..3d378b69d 100644 --- a/salt/suricata/map.jinja +++ b/salt/suricata/map.jinja @@ -10,6 +10,12 @@ {# before we change outputs back to list, enable pcap-log if suricata is the pcapengine #} {% if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %} + +{% from 'bpf/pcap.map.jinja' import PCAPBPF, PCAP_BPF_STATUS %} +{% if PCAPBPF and PCAP_BPF_STATUS %} +{% do SURICATAMERGED.config.outputs['pcap-log'].update({'bpf-filter': PCAPBPF|join(" ")}) %} +{% endif %} + {% do SURICATAMERGED.config.outputs['pcap-log'].update({'enabled': 'yes'}) %} {# move the items in suricata.pcap into suricata.config.outputs.pcap-log. these items were placed under suricata.config for ease of access in SOC #} {% do SURICATAMERGED.config.outputs['pcap-log'].update({'compression': SURICATAMERGED.pcap.compression}) %} diff --git a/salt/suricata/soc_suricata.yaml b/salt/suricata/soc_suricata.yaml index 8b5ce7b11..03f30be75 100644 --- a/salt/suricata/soc_suricata.yaml +++ b/salt/suricata/soc_suricata.yaml @@ -190,6 +190,8 @@ suricata: FTP_PORTS: *suriportgroup VXLAN_PORTS: *suriportgroup TEREDO_PORTS: *suriportgroup + SIP_PORTS: *suriportgroup + GENEVE_PORTS: *suriportgroup outputs: eve-log: types: @@ -209,7 +211,7 @@ suricata: helpLink: suricata.html pcap-log: enabled: - description: This value is ignored by SO. pcapengine in globals takes precidence. + description: This value is ignored by SO. pcapengine in globals takes precedence. readonly: True helpLink: suricata.html advanced: True @@ -297,3 +299,10 @@ suricata: ports: description: Ports to listen for. This should be a variable. helpLink: suricata.html + geneve: + enabled: + description: Enable VXLAN capabilities. + helpLink: suricata.html + ports: + description: Ports to listen for. This should be a variable. + helpLink: suricata.html diff --git a/salt/suricata/tools/sbin/so-suricata-reload-rules b/salt/suricata/tools/sbin/so-suricata-reload-rules index 2d60c3422..e21e28e2f 100644 --- a/salt/suricata/tools/sbin/so-suricata-reload-rules +++ b/salt/suricata/tools/sbin/so-suricata-reload-rules @@ -7,5 +7,5 @@ . /usr/sbin/so-common -retry 60 3 'docker exec so-suricata /opt/suricata/bin/suricatasc -c reload-rules /var/run/suricata/suricata-command.socket' '{"message": "done", "return": "OK"}' || fail "The Suricata container was not ready in time." -retry 60 3 'docker exec so-suricata /opt/suricata/bin/suricatasc -c ruleset-reload-nonblocking /var/run/suricata/suricata-command.socket' '{"message": "done", "return": "OK"}' || fail "The Suricata container was not ready in time." +retry 60 3 'docker exec so-suricata /opt/suricata/bin/suricatasc -c reload-rules /var/run/suricata/suricata-command.socket' '{"message":"done","return":"OK"}' || fail "The Suricata container was not ready in time." +retry 60 3 'docker exec so-suricata /opt/suricata/bin/suricatasc -c ruleset-reload-nonblocking /var/run/suricata/suricata-command.socket' '{"message":"done","return":"OK"}' || fail "The Suricata container was not ready in time." diff --git a/salt/zeek/config.sls b/salt/zeek/config.sls index b3ea97507..42ea74fc9 100644 --- a/salt/zeek/config.sls +++ b/salt/zeek/config.sls @@ -8,8 +8,7 @@ {% from 'vars/globals.map.jinja' import GLOBALS %} {% from "zeek/config.map.jinja" import ZEEKMERGED %} -{% from 'bpf/zeek.map.jinja' import ZEEKBPF %} -{% set BPF_STATUS = 0 %} +{% from 'bpf/zeek.map.jinja' import ZEEKBPF, ZEEK_BPF_STATUS, ZEEK_BPF_CALC %} # Add Zeek group zeekgroup: @@ -158,18 +157,13 @@ zeekja4cfg: - user: 937 - group: 939 -# BPF compilation and configuration -{% if ZEEKBPF %} - {% set BPF_CALC = salt['cmd.script']('salt://common/tools/sbin/so-bpf-compile', GLOBALS.sensor.interface + ' ' + ZEEKBPF|join(" "),cwd='/root') %} - {% if BPF_CALC['stderr'] == "" %} - {% set BPF_STATUS = 1 %} - {% else %} +# BPF compilation failed +{% if ZEEKBPF and not ZEEK_BPF_STATUS %} zeekbpfcompilationfailure: test.configurable_test_state: - changes: False - result: False - - comment: "BPF Syntax Error - Discarding Specified BPF" - {% endif %} + - comment: "BPF Syntax Error - Discarding Specified BPF. Error: {{ ZEEK_BPF_CALC['stderr'] }}" {% endif %} zeekbpf: @@ -177,7 +171,7 @@ zeekbpf: - name: /opt/so/conf/zeek/bpf - user: 940 - group: 940 -{% if BPF_STATUS %} +{% if ZEEK_BPF_STATUS %} - contents: {{ ZEEKBPF }} {% else %} - contents: