Merge pull request #8769 from Security-Onion-Solutions/funstuff

Firewall and Sensoroni Fix
This commit is contained in:
Mike Reeves
2022-09-19 11:05:46 -04:00
committed by GitHub
43 changed files with 315 additions and 53 deletions

4
salt/bpf/defaults.yaml Normal file
View File

@@ -0,0 +1,4 @@
bpf:
pcap: []
suricata: []
zeek: []

7
salt/bpf/soc_bpf.yaml Normal file
View File

@@ -0,0 +1,7 @@
bpf:
pcap:
description: List of BPF filters to apply to PCAP.
suricata:
description: List of BPF filters to apply to Suricata.
zeek:
description: List of BPF filters to apply to Zeek.

View File

@@ -5,6 +5,10 @@
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
if [ -f /usr/sbin/so-common ]; then
. /usr/sbin/so-common
fi
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run using sudo!"
exit 1
@@ -171,6 +175,8 @@ function add_sensor_to_minion() {
echo " config:" >> $PILLARFILE
echo " af-packet:" >> $PILLARFILE
echo " threads: '$CORECOUNT'" >> $PILLARFILE
echo "pcap:" >> $PILLARFILE
echo " enabled: True" >> $PILLARFILE
}
function createSTANDALONE() {
@@ -209,10 +215,12 @@ function createIDHNODE() {
}
function testConnection() {
salt "$MINION_ID" test.ping
retry 5 10 "salt '$MINION_ID' test.ping" 0
local ret=$?
if [[ $ret != 0 ]]; then
echo "The Minion has been accepted but is not online. Try again later"
echo "Deleting the key"
deleteminion
exit 1
fi
}

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

@@ -0,0 +1,19 @@
playbook
mysql
kibana
redis
influxdb
elasticsearch_rest
elasticsearch_node
docker_registry
yum
sensoroni
beats_5044
beats_5644
elastic_agent_control
elastic_agent_data
elasticsearch_rest
endgame
strelka_frontend
syslog
nginx

View File

@@ -0,0 +1,78 @@
firewall:
ports:
all:
tcp:
- '0:65535'
udp:
- '0:65535'
agrules:
tcp:
- 7788
beats_5044:
tcp:
- 5044
beats_5644:
tcp:
- 5644
beats_5066:
tcp:
- 5066
docker_registry:
tcp:
- 5000
elasticsearch_node:
tcp:
- 9300
elasticsearch_rest:
tcp:
- 9200
elastic_agent_control:
tcp:
- 8220
elastic_agent_data:
tcp:
- 5055
endgame:
tcp:
- 3765
influxdb:
tcp:
- 8086
kibana:
tcp:
- 5601
mysql:
tcp:
- 3306
nginx:
tcp:
- 80
- 443
playbook:
tcp:
- 3200
redis:
tcp:
- 6379
- 9696
salt_manager:
tcp:
- 4505
- 4506
sensoroni:
tcp:
- 443
ssh:
tcp:
- 22
strelka_frontend:
tcp:
- 57314
syslog:
tcp:
- 514
udp:
- 514
yum:
tcp:
- 443

View File

@@ -0,0 +1,77 @@
firewall:
hostgroups:
analyst_workstations:
description: List of IP Addresses or CIDR blocks to allow analyst workstations.
file: True
global: True
title: Analyst Workstations
analyst:
description: List of IP Addresses or CIDR blocks to allow analyst connections.
file: True
global: True
title: Analysts
standalone:
description: List of IP Addresses or CIDR blocks to allow standalone connections.
file: True
global: True
title: Standalone
advanced: True
eval:
description: List of IP Addresses or CIDR blocks to allow eval connections.
file: True
global: True
title: Eval
advanced: True
idh:
description: List of IP Addresses or CIDR blocks to allow idh connections.
file: True
global: True
title: IDH Nodes
manager:
description: List of IP Addresses or CIDR blocks to allow manager connections.
file: True
global: True
title: Manager
advanced: True
heavynodes:
description: List of IP Addresses or CIDR blocks to allow heavynode connections.
file: True
global: True
title: Heavy Nodes
searchnodes:
description: List of IP Addresses or CIDR blocks to allow searchnode connections.
file: True
global: True
title: Search Nodes
sensors:
description: List of IP Addresses or CIDR blocks to allow Sensor connections.
file: True
global: True
title: Sensors
receivers:
description: List of IP Addresses or CIDR blocks to allow receiver connections.
file: True
global: True
title: Receivers
portgroups:
analyst:
description: List of ports for use with Analyst connections.
file: True
global: True
title: Analyst Ports
analyst_workstations:
description: List of ports for use with analyst workstations.
file: True
global: True
title: Analyst Workstation Ports
standalone:
description: List of ports for use with Standalone.
file: True
global: True
title: Standalone
ports:
ports__yaml:
description: Ports in YAML.
file: True
global: True
title: Ports

View File

@@ -2,14 +2,10 @@
# or more contributor license agreements. Licensed under the Elastic License 2.0 as shown at
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% from 'allowed_states.map.jinja' import allowed_states %}
{% if sls in allowed_states %}
{% set VERSION = salt['pillar.get']('global:soversion') %}
{% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %}
{% set MANAGER = salt['grains.get']('master') %}
{% set ENGINE = salt['pillar.get']('global:mdengine') %}
{% set proxy = salt['pillar.get']('manager:proxy') %}
include:
@@ -33,7 +29,7 @@ so-ruleupdatecron:
so-idstools:
docker_container.running:
- image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-idstools:{{ VERSION }}
- image: {{ GLOBALS.manager }}:5000/{{ GLOBALS.image_repo }}/so-idstools:{{ GLOBALS.so_version }}
- hostname: so-idstools
- user: socore
{% if proxy %}

View File

@@ -0,0 +1,26 @@
# Extract all PDF mime type
alert http any any -> any any (msg:"FILE pdf detected"; filemagic:"PDF document"; filestore; sid:1100000; rev:1;)
alert smtp any any -> any any (msg:"FILE pdf detected"; filemagic:"PDF document"; filestore; sid:1100001; rev:1;)
alert nfs any any -> any any (msg:"FILE pdf detected"; filemagic:"PDF document"; filestore; sid:1100002; rev:1;)
alert smb any any -> any any (msg:"FILE pdf detected"; filemagic:"PDF document"; filestore; sid:1100003; rev:1;)
# Extract EXE/DLL file types
alert http any any -> any any (msg:"FILE EXE detected"; filemagic:"PE32 executable"; filestore; sid:1100004; rev:1;)
alert smtp any any -> any any (msg:"FILE EXE detected"; filemagic:"PE32 executable"; filestore; sid:1100005; rev:1;)
alert nfs any any -> any any (msg:"FILE EXE detected"; filemagic:"PE32 executable"; filestore; sid:1100006; rev:1;)
alert smb any any -> any any (msg:"FILE EXE detected"; filemagic:"PE32 executable"; filestore; sid:1100007; rev:1;)
alert http any any -> any any (msg:"FILE EXE detected"; filemagic:"MS-DOS executable"; filestore; sid:1100008; rev:1;)
alert smtp any any -> any any (msg:"FILE EXE detected"; filemagic:"MS-DOS executable"; filestore; sid:1100009; rev:1;)
alert nfs any any -> any any (msg:"FILE EXE detected"; filemagic:"MS-DOS executable"; filestore; sid:1100010; rev:1;)
alert smb any any -> any any (msg:"FILE EXE detected"; filemagic:"MS-DOS executable"; filestore; sid:1100011; rev:1;)
# Extract all Zip files
alert http any any -> any any (msg:"FILE ZIP detected"; filemagic:"Zip"; filestore; sid:1100012; rev:1;)
alert smtp any any -> any any (msg:"FILE ZIP detected"; filemagic:"Zip"; filestore; sid:1100013; rev:1;)
alert nfs any any -> any any (msg:"FILE ZIP detected"; filemagic:"Zip"; filestore; sid:1100014; rev:1;)
alert smb any any -> any any (msg:"FILE ZIP detected"; filemagic:"Zip"; filestore; sid:1100015; rev:1;)
# Extract Word Docs
alert http any any -> any any (msg:"FILE WORDDOC detected"; filemagic:"Composite Document File V2 Document"; filestore; sid:1100016; rev:1;)
alert smtp any any -> any any (msg:"FILE WORDDOC detected"; filemagic:"Composite Document File V2 Document"; filestore; sid:1100017; rev:1;)
alert nfs any any -> any any (msg:"FILE WORDDOC detected"; filemagic:"Composite Document File V2 Document"; filestore; sid:1100018; rev:1;)
alert smb any any -> any any (msg:"FILE WORDDOC detected"; filemagic:"Composite Document File V2 Document"; filestore; sid:1100019; rev:1;)

View File

@@ -0,0 +1,11 @@
# Start the filters at sid 1200000
# Example of filtering out *google.com from being in the dns log.
#config dns any any -> any any (dns.query; content:"google.com"; config: logging disable, type tx, scope tx; sid:1200000;)
# Example of filtering out *google.com from being in the http log.
#config http any any -> any any (http.host; content:"google.com"; config: logging disable, type tx, scope tx; sid:1200001;)
# Example of filtering out someuseragent from being in the http log.
#config http any any -> any any (http.user_agent; content:"someuseragent"; config: logging disable, type tx, scope tx; sid:1200002;)
# Example of filtering out Google's certificate from being in the ssl log.
#config tls any any -> any any (tls.fingerprint; content:"4f:a4:5e:58:7e:d9:db:20:09:d7:b6:c7:ff:58:c4:7b:dc:3f:55:b4"; config: logging disable, type tx, scope tx; sid:1200003;)
# Example of filtering out a md5 of a file from being in the files log.
#config fileinfo any any -> any any (fileinfo.filemd5; content:"7a125dc69c82d5caf94d3913eecde4b5"; config: logging disable, type tx, scope tx; sid:1200004;)

View File

@@ -0,0 +1 @@
# Add your custom Suricata rules in this file.

View File

@@ -19,3 +19,22 @@ idstools:
modify:
description: List of SIDS that are modified.
global: True
rules:
local__rules:
description: This is where custom Suricata rules are entered.
file: True
global: True
advanced: True
title: Local Rules
filters__rules:
description: You can set custom filters for Suricata when using it for meta data creation.
file: True
global: True
advanced: True
title: Filter Rules
extraction__rules:
description: This is a list of mime types for file extraction when Suricata is used for meta data creation.
file: True
global: True
advanced: True
title: Extraction Rules

View File

@@ -0,0 +1,3 @@
{% import_yaml 'pcap/defaults.yaml' as pcap_defaults with context %}
{% set pcap_pillar = pillar.pcap %}
{% set PCAPMERGED = salt['defaults.merge'](pcap_defaults, pcap_pillar, in_place=False) %}

View File

@@ -1,23 +0,0 @@
{%- set INTERFACE = salt['pillar.get']('sensor:interface', 'bond0') %}
{%- set DISKFREEPERCENTAGE = salt['pillar.get']('steno:diskfreepercentage', 10) %}
{%- set MAXFILES = salt['pillar.get']('steno:maxfiles', 30000) %}
{%- set BLOCKS = salt['pillar.get']('steno:blocks', 2048) %}
{%- set FILEMB = salt['pillar.get']('steno:filemb', 4096) %}
{%- set AIOPS = salt['pillar.get']('steno:aiops', 128) %}
{%- set THREADS = salt['pillar.get']('steno:threads', 1) %}
{
"Threads": [
{ "PacketsDirectory": "/nsm/pcap", "IndexDirectory": "/nsm/pcapindex", "MaxDirectoryFiles": {{ MAXFILES }}, "DiskFreePercentage": {{ DISKFREEPERCENTAGE }} }
{%- if THREADS > 1 %}
{%- for i in range(2,THREADS+1) %}
, { "PacketsDirectory": "/nsm/pcap" , "IndexDirectory": "/nsm/pcapindex", "MaxDirectoryFiles": {{ MAXFILES }}, "DiskFreePercentage": {{ DISKFREEPERCENTAGE }} }
{%- endfor %}
{%- endif %}
]
, "StenotypePath": "/usr/bin/stenotype"
, "Interface": "{{ INTERFACE }}"
, "Port": 1234
, "Host": "127.0.0.1"
, "Flags": ["-v", "--blocks={{ BLOCKS }}", "--preallocate_file_mb={{ FILEMB }}", "--aiops={{ AIOPS }}", "--uid=stenographer", "--gid=stenographer"{{ BPF_COMPILED }}]
, "CertPath": "/etc/stenographer/certs"
}

View File

@@ -0,0 +1,11 @@
{
"Threads": [
{ "PacketsDirectory": "/nsm/pcap", "IndexDirectory": "/nsm/pcapindex", "MaxDirectoryFiles": {{ PCAPMERGED.pcap.config.maxdirectoryfiles }}, "DiskFreePercentage": {{ PCAPMERGED.pcap.config.diskfreepercentage }} }
]
, "StenotypePath": "/usr/bin/stenotype"
, "Interface": "{{ pillar.sensor.interface }}"
, "Port": 1234
, "Host": "127.0.0.1"
, "Flags": ["-v", "--blocks={{ PCAPMERGED.pcap.config.blocks }}", "--preallocate_file_mb={{ PCAPMERGED.pcap.config.preallocate_file_mb }}", "--aiops={{ PCAPMERGED.pcap.config.aiops }}", "--uid=stenographer", "--gid=stenographer"{{ BPF_COMPILED }}]
, "CertPath": "/etc/stenographer/certs"
}

View File

@@ -7,12 +7,13 @@
{% if sls in allowed_states %}
{% from "pcap/map.jinja" import STENOOPTIONS with context %}
{% from "pcap/config.map.jinja" import PCAPMERGED with context %}
{% set VERSION = salt['pillar.get']('global:soversion') %}
{% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %}
{% set MANAGER = salt['grains.get']('master') %}
{% set INTERFACE = salt['pillar.get']('sensor:interface', 'bond0') %}
{% set BPF_STENO = salt['pillar.get']('steno:bpf', None) %}
{% set BPF_STENO = salt['pillar.get']('bpf:pcap', None) %}
{% set BPF_COMPILED = "" %}
# PCAP Section
@@ -52,12 +53,13 @@ bpfcompilationfailure:
stenoconf:
file.managed:
- name: /opt/so/conf/steno/config
- source: salt://pcap/files/config
- source: salt://pcap/files/config.jinja
- user: stenographer
- group: stenographer
- mode: 644
- template: jinja
- defaults:
PCAPMERGED: {{ PCAPMERGED }}
BPF_COMPILED: "{{ BPF_COMPILED }}"
stenoca:

View File

@@ -1,10 +1,6 @@
{%- set URLBASE = salt['pillar.get']('global:url_base') %}
{%- set DESCRIPTION = salt['pillar.get']('sensoroni:node_description', '') %}
{%- set MODEL = salt['grains.get']('sosmodel', '') %}
{%- set ADDRESS = salt['pillar.get']('sensoroni:node_address') %}
{%- from 'vars/globals.map.jinja' import GLOBALS -%}
{%- set ANALYZE_TIMEOUT_MS = salt['pillar.get']('sensoroni:analyze_timeout_ms', 900000) %}
{%- set ANALYZE_PARALLEL_LIMIT = salt['pillar.get']('sensoroni:analyze_parallel_limit', 5) %}
{%- set SENSORONIKEY = salt['pillar.get']('sensoroni:sensoronikey', '') %}
{%- set CHECKININTERVALMS = salt['pillar.get']('sensoroni:node_checkin_interval_ms', 10000) %}
{%- set ROLE = grains.id.split('_') | last %}
{%- if ROLE in ['eval', 'standalone', 'sensor', 'heavynode'] %}
@@ -23,13 +19,13 @@
"logFilename": "/opt/sensoroni/logs/sensoroni.log",
"logLevel":"info",
"agent": {
"nodeId": "{{ grains.host | lower }}",
"role": "{{ grains.role }}",
"description": {{ DESCRIPTION | tojson }},
"address": "{{ ADDRESS }}",
"model": "{{ MODEL }}",
"nodeId": "{{ GLOBALS.hostname | lower }}",
"role": "{{ GLOBALS.role }}",
"description": {{ GLOBALS.description | tojson }},
"address": "{{ GLOBALS.node_ip }}",
"model": "{{ GLOBALS.so_model }}",
"pollIntervalMs": {{ CHECKININTERVALMS if CHECKININTERVALMS else 10000 }},
"serverUrl": "https://{{ URLBASE }}/sensoroniagents",
"serverUrl": "https://{{ GLOBALS.url_base }}/sensoroniagents",
"verifyCert": false,
"modules": {
{%- if ANALYZEENABLED %}
@@ -40,7 +36,7 @@
{%- endif %}
"importer": {},
"statickeyauth": {
"apiKey": "{{ SENSORONIKEY }}"
"apiKey": "{{ GLOBALS.sensoroni_key }}"
{%- if STENOENABLED %}
},
"stenoquery": {

View File

@@ -1,6 +1,4 @@
{% set VERSION = salt['pillar.get']('global:soversion', 'HH1.2.2') %}
{% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %}
{% set MANAGER = salt['grains.get']('master') %}
{% from 'vars/globals.map.jinja' import GLOBALS %}
sensoroniconfdir:
file.directory:
@@ -43,7 +41,7 @@ analyzerscripts:
so-sensoroni:
docker_container.running:
- image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-soc:{{ VERSION }}
- image: {{ GLOBALS.manager }}:5000/{{ GLOBALS.image_repo }}/so-soc:{{ GLOBALS.so_version }}
- network_mode: host
- binds:
- /opt/so/conf/steno/certs:/etc/stenographer/certs:rw

View File

@@ -12,7 +12,7 @@
{% set VERSION = salt['pillar.get']('global:soversion') %}
{% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %}
{% set MANAGER = salt['grains.get']('master') %}
{% set BPF_NIDS = salt['pillar.get']('nids:bpf') %}
{% set BPF_NIDS = salt['pillar.get']('bpf:suricata', None) %}
{% set BPF_STATUS = 0 %}
{# import_yaml 'suricata/files/defaults2.yaml' as suricata #}

View File

@@ -20,7 +20,10 @@
'pipeline': INIT.PILLAR.global.pipeline,
'so_version': INIT.PILLAR.global.soversion,
'url_base': INIT.PILLAR.global.url_base,
'so_model': INIT.GRAINS.get('sosmodel',''),
'description': INIT.PILLAR.sensoroni.get('node_description',''),
'docker_range': INIT.PILLAR.docker.range,
'sensoroni_key': INIT.PILLAR.sensoroni.sensoronikey,
'application_urls': {},
'manager_roles': [
'so-eval',

View File

@@ -11,7 +11,7 @@
{% set VERSION = salt['pillar.get']('global:soversion') %}
{% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %}
{% set MANAGER = salt['grains.get']('master') %}
{% set BPF_ZEEK = salt['pillar.get']('zeek:bpf', {}) %}
{% set BPF_ZEEK = salt['pillar.get']('bpf:zeek', {}) %}
{% set BPF_STATUS = 0 %}
{% set INTERFACE = salt['pillar.get']('sensor:interface') %}

View File

@@ -0,0 +1,19 @@
module Filterconn;
export {
global ignore_services: set[string] = {"dns", "krb", "krb_tcp"};
}
hook Conn::log_policy(rec: Conn::Info, id: Log::ID, filter: Log::Filter)
{
# Record only connections not in the ignored services
if ( ! rec?$service || rec$service in ignore_services )
break;
}
event zeek_init()
{
Log::remove_default_filter(Conn::LOG);
local filter: Log::Filter = [$name="conn-filter"];
Log::add_filter(Conn::LOG, filter);
}

View File

@@ -17,6 +17,13 @@ zeek:
CompressLogs:
description: Enable compression of zeek logs. If you are seeing packet loss at the top of the hour in zeek or pcap you might need to set this to 0. This will use more disk space but save IO and CPU.
policy:
custom:
filters:
conn:
description: Conn Filter for Zeek. This is an advanced setting and will take further action to enable.
file: True
global: True
advanced: True
file_extraction:
description: This is a list of mime types Zeek will extract from the network streams.
load:

View File

@@ -1810,7 +1810,7 @@ drop_install_options() {
# Drop the install Variable
echo "MAINIP=$MAINIP" > /opt/so/install.txt
echo "MNIC=$MNIC" >> /opt/so/install.txt
echo "NODE_DESCRIPTION=$NODE_DESCRIPTION" >> /opt/so/install.txt
echo "NODE_DESCRIPTION='$NODE_DESCRIPTION'" >> /opt/so/install.txt
echo "ES_HEAP_SIZE=$ES_HEAP_SIZE" >> /opt/so/install.txt
echo "PATCHSCHEDULENAME=$PATCHSCHEDULENAME" >> /opt/so/install.txt
echo "INTERFACE=$INTERFACE" >> /opt/so/install.txt

View File

@@ -81,7 +81,7 @@ export whiptail_title
mkdir -p $local_salt_dir/pillar/minions
for THEDIR in elasticsearch firewall redis backup strelka sensoroni curator soc soctopus docker zeek suricata nginx filebeat logstash soc manager kratos idstools idh elastalert
for THEDIR in bpf pcap elasticsearch firewall redis backup strelka sensoroni curator soc soctopus docker zeek suricata nginx filebeat logstash soc manager kratos idstools idh elastalert
do
mkdir -p $local_salt_dir/pillar/$THEDIR
touch $local_salt_dir/pillar/$THEDIR/adv_$THEDIR.sls