Merge pull request #12616 from Security-Onion-Solutions/2.4/dev

2.4.60
This commit is contained in:
Mike Reeves
2024-03-20 10:55:42 -04:00
committed by GitHub
63 changed files with 1514 additions and 231 deletions

190
.github/DISCUSSION_TEMPLATE/2-4.yml vendored Normal file
View File

@@ -0,0 +1,190 @@
body:
- type: markdown
attributes:
value: |
⚠️ This category is solely for conversations related to Security Onion 2.4 ⚠️
If your organization needs more immediate, enterprise grade professional support, with one-on-one virtual meetings and screensharing, contact us via our website: https://securityonion.com/support
- type: dropdown
attributes:
label: Version
description: Which version of Security Onion 2.4.x are you asking about?
options:
-
- 2.4 Pre-release (Beta, Release Candidate)
- 2.4.10
- 2.4.20
- 2.4.30
- 2.4.40
- 2.4.50
- 2.4.60
- 2.4.70
- 2.4.80
- 2.4.90
- 2.4.100
- Other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Installation Method
description: How did you install Security Onion?
options:
-
- Security Onion ISO image
- Network installation on Red Hat derivative like Oracle, Rocky, Alma, etc.
- Network installation on Ubuntu
- Network installation on Debian
- Other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Description
description: >
Is this discussion about installation, configuration, upgrading, or other?
options:
-
- installation
- configuration
- upgrading
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Installation Type
description: >
When you installed, did you choose Import, Eval, Standalone, Distributed, or something else?
options:
-
- Import
- Eval
- Standalone
- Distributed
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Location
description: >
Is this deployment in the cloud, on-prem with Internet access, or airgap?
options:
-
- cloud
- on-prem with Internet access
- airgap
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Hardware Specs
description: >
Does your hardware meet or exceed the minimum requirements for your installation type as shown at https://docs.securityonion.net/en/2.4/hardware.html?
options:
-
- Meets minimum requirements
- Exceeds minimum requirements
- Does not meet minimum requirements
- other (please provide detail below)
validations:
required: true
- type: input
attributes:
label: CPU
description: How many CPU cores do you have?
validations:
required: true
- type: input
attributes:
label: RAM
description: How much RAM do you have?
validations:
required: true
- type: input
attributes:
label: Storage for /
description: How much storage do you have for the / partition?
validations:
required: true
- type: input
attributes:
label: Storage for /nsm
description: How much storage do you have for the /nsm partition?
validations:
required: true
- type: dropdown
attributes:
label: Network Traffic Collection
description: >
Are you collecting network traffic from a tap or span port?
options:
-
- tap
- span port
- other (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Network Traffic Speeds
description: >
How much network traffic are you monitoring?
options:
-
- Less than 1Gbps
- 1Gbps to 10Gbps
- more than 10Gbps
validations:
required: true
- type: dropdown
attributes:
label: Status
description: >
Does SOC Grid show all services on all nodes as running OK?
options:
-
- Yes, all services on all nodes are running OK
- No, one or more services are failed (please provide detail below)
validations:
required: true
- type: dropdown
attributes:
label: Salt Status
description: >
Do you get any failures when you run "sudo salt-call state.highstate"?
options:
-
- Yes, there are salt failures (please provide detail below)
- No, there are no failures
validations:
required: true
- type: dropdown
attributes:
label: Logs
description: >
Are there any additional clues in /opt/so/log/?
options:
-
- Yes, there are additional clues in /opt/so/log/ (please provide detail below)
- No, there are no additional clues
validations:
required: true
- type: textarea
attributes:
label: Detail
description: Please read our discussion guidelines at https://github.com/Security-Onion-Solutions/securityonion/discussions/1720 and then provide detailed information to help us help you.
placeholder: |-
STOP! Before typing, please read our discussion guidelines at https://github.com/Security-Onion-Solutions/securityonion/discussions/1720 in their entirety!
If your organization needs more immediate, enterprise grade professional support, with one-on-one virtual meetings and screensharing, contact us via our website: https://securityonion.com/support
validations:
required: true
- type: checkboxes
attributes:
label: Guidelines
options:
- label: I have read the discussion guidelines at https://github.com/Security-Onion-Solutions/securityonion/discussions/1720 and assert that I have followed the guidelines.
required: true

42
.github/workflows/lock-threads.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: 'Lock Threads'
on:
schedule:
- cron: '50 1 * * *'
workflow_dispatch:
permissions:
issues: write
pull-requests: write
discussions: write
concurrency:
group: lock-threads
jobs:
close-threads:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v5
with:
days-before-issue-stale: -1
days-before-issue-close: 60
stale-issue-message: "This issue is stale because it has been inactive for an extended period. Stale issues convey that the issue, while important to someone, is not critical enough for the author, or other community members to work on, sponsor, or otherwise shepherd the issue through to a resolution."
close-issue-message: "This issue was closed because it has been stale for an extended period. It will be automatically locked in 30 days, after which no further commenting will be available."
days-before-pr-stale: 45
days-before-pr-close: 60
stale-pr-message: "This PR is stale because it has been inactive for an extended period. The longer a PR remains stale the more out of date with the main branch it becomes."
close-pr-message: "This PR was closed because it has been stale for an extended period. It will be automatically locked in 30 days. If there is still a commitment to finishing this PR re-open it before it is locked."
lock-threads:
runs-on: ubuntu-latest
steps:
- uses: jertel/lock-threads@main
with:
include-discussion-currently-open: true
discussion-inactive-days: 90
issue-inactive-days: 30
pr-inactive-days: 30

View File

@@ -1,17 +1,17 @@
### 2.4.50-20240220 ISO image released on 2024/02/20
### 2.4.60-20240320 ISO image released on 2024/03/20
### Download and Verify
2.4.50-20240220 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.4.50-20240220.iso
2.4.60-20240320 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.4.60-20240320.iso
MD5: BCA6476EF1BF79773D8EFB11700FDE8E
SHA1: 9FF0A304AA368BCD2EF2BE89AD47E65650241927
SHA256: 49D7695EFFF6F3C4840079BF564F3191B585639816ADE98672A38017F25E9570
MD5: 178DD42D06B2F32F3870E0C27219821E
SHA1: 73EDCD50817A7F6003FE405CF1808A30D034F89D
SHA256: DD334B8D7088A7B78160C253B680D645E25984BA5CCAB5CC5C327CA72137FC06
Signature for ISO image:
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.50-20240220.iso.sig
https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.60-20240320.iso.sig
Signing key:
https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.4/main/KEYS
@@ -25,22 +25,22 @@ wget https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/2.
Download the signature file for the ISO:
```
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.50-20240220.iso.sig
wget https://github.com/Security-Onion-Solutions/securityonion/raw/2.4/main/sigs/securityonion-2.4.60-20240320.iso.sig
```
Download the ISO image:
```
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.50-20240220.iso
wget https://download.securityonion.net/file/securityonion/securityonion-2.4.60-20240320.iso
```
Verify the downloaded ISO image using the signature file:
```
gpg --verify securityonion-2.4.50-20240220.iso.sig securityonion-2.4.50-20240220.iso
gpg --verify securityonion-2.4.60-20240320.iso.sig securityonion-2.4.60-20240320.iso
```
The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
```
gpg: Signature made Fri 16 Feb 2024 11:36:25 AM EST using RSA key ID FE507013
gpg: Signature made Tue 19 Mar 2024 03:17:58 PM EDT using RSA key ID FE507013
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner.

View File

@@ -1 +1 @@
2.4.50
2.4.60

View File

@@ -1,7 +1,10 @@
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% if GLOBALS.pcap_engine == "TRANSITION" %}
{% set PCAPBPF = ["ip and host 255.255.255.1 and port 1"] %}
{% else %}
{% import_yaml 'bpf/defaults.yaml' as BPFDEFAULTS %}
{% set BPFMERGED = salt['pillar.get']('bpf', BPFDEFAULTS.bpf, merge=True) %}
{% import 'bpf/macros.jinja' as MACROS %}
{{ MACROS.remove_comments(BPFMERGED, 'pcap') }}
{% set PCAPBPF = BPFMERGED.pcap %}
{% endif %}

View File

@@ -47,12 +47,16 @@ def check_for_fps():
fps = 1
except FileNotFoundError:
fn = '/proc/sys/crypto/' + feat_full + '_enabled'
try:
with open(fn, 'r') as f:
contents = f.read()
if '1' in contents:
fps = 1
except:
# Unknown, so assume 0
fps = 0
with open('/opt/so/log/sostatus/lks_enabled', 'w') as f:
with open('/opt/so/log/sostatus/fps_enabled', 'w') as f:
f.write(str(fps))
def check_for_lks():
@@ -76,7 +80,7 @@ def check_for_lks():
lks = 1
if lks:
break
with open('/opt/so/log/sostatus/fps_enabled', 'w') as f:
with open('/opt/so/log/sostatus/lks_enabled', 'w') as f:
f.write(str(lks))
def fail(msg):

View File

@@ -65,6 +65,7 @@ elasticfleet:
- http_endpoint
- httpjson
- iis
- journald
- juniper
- juniper_srx
- kafka_log

View File

@@ -46,7 +46,7 @@ do
done
printf "\n### Stripping out unused components"
find /nsm/elastic-agent-workspace/elastic-agent-*/data/elastic-agent-*/components -maxdepth 1 -regex '.*fleet.*\|.*packet.*\|.*apm.*\|.*audit.*\|.*heart.*\|.*cloud.*' -delete
find /nsm/elastic-agent-workspace/elastic-agent-*/data/elastic-agent-*/components -maxdepth 1 -regex '.*fleet.*\|.*packet.*\|.*apm.*\|.*heart.*\|.*cloud.*' -delete
printf "\n### Tarring everything up again"
for OS in "${OSARCH[@]}"

View File

@@ -198,6 +198,35 @@ elasticsearch:
sort:
field: '@timestamp'
order: desc
so-detection:
index_sorting: false
index_template:
composed_of:
- detection-mappings
- detection-settings
index_patterns:
- so-detection*
priority: 500
template:
mappings:
date_detection: false
dynamic_templates:
- strings_as_keyword:
mapping:
ignore_above: 1024
type: keyword
match_mapping_type: string
settings:
index:
mapping:
total_fields:
limit: 1500
number_of_replicas: 0
number_of_shards: 1
refresh_interval: 30s
sort:
field: '@timestamp'
order: desc
so-common:
close: 30
delete: 365
@@ -1078,6 +1107,50 @@ elasticsearch:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_cloudfront_logs:
index_sorting: False
index_template:
index_patterns:
- "logs-aws.cloudfront_logs-*"
template:
settings:
index:
lifecycle:
name: so-logs-aws.cloudfront_logs-logs
number_of_replicas: 0
composed_of:
- "logs-aws.cloudfront_logs@package"
- "logs-aws.cloudfront_logs@custom"
- "so-fleet_globals-1"
- "so-fleet_agent_id_verification-1"
priority: 501
data_stream:
hidden: false
allow_custom_routing: false
policy:
phases:
cold:
actions:
set_priority:
priority: 0
min_age: 30d
delete:
actions:
delete: {}
min_age: 365d
hot:
actions:
rollover:
max_age: 30d
max_primary_shard_size: 50gb
set_priority:
priority: 100
min_age: 0ms
warm:
actions:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_cloudtrail:
index_sorting: false
index_template:
@@ -1298,6 +1371,94 @@ elasticsearch:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_guardduty:
index_sorting: False
index_template:
index_patterns:
- "logs-aws.guardduty-*"
template:
settings:
index:
lifecycle:
name: so-logs-aws.guardduty-logs
number_of_replicas: 0
composed_of:
- "logs-aws.guardduty@package"
- "logs-aws.guardduty@custom"
- "so-fleet_globals-1"
- "so-fleet_agent_id_verification-1"
priority: 501
data_stream:
hidden: false
allow_custom_routing: false
policy:
phases:
cold:
actions:
set_priority:
priority: 0
min_age: 30d
delete:
actions:
delete: {}
min_age: 365d
hot:
actions:
rollover:
max_age: 30d
max_primary_shard_size: 50gb
set_priority:
priority: 100
min_age: 0ms
warm:
actions:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_inspector:
index_sorting: False
index_template:
index_patterns:
- "logs-aws.inspector-*"
template:
settings:
index:
lifecycle:
name: so-logs-aws.inspector-logs
number_of_replicas: 0
composed_of:
- "logs-aws.inspector@package"
- "logs-aws.inspector@custom"
- "so-fleet_globals-1"
- "so-fleet_agent_id_verification-1"
priority: 501
data_stream:
hidden: false
allow_custom_routing: false
policy:
phases:
cold:
actions:
set_priority:
priority: 0
min_age: 30d
delete:
actions:
delete: {}
min_age: 365d
hot:
actions:
rollover:
max_age: 30d
max_primary_shard_size: 50gb
set_priority:
priority: 100
min_age: 0ms
warm:
actions:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_route53_public_logs:
index_sorting: false
index_template:
@@ -1430,6 +1591,94 @@ elasticsearch:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_securityhub_findings:
index_sorting: False
index_template:
index_patterns:
- "logs-aws.securityhub_findings-*"
template:
settings:
index:
lifecycle:
name: so-logs-aws.securityhub_findings-logs
number_of_replicas: 0
composed_of:
- "logs-aws.securityhub_findings@package"
- "logs-aws.securityhub_findings@custom"
- "so-fleet_globals-1"
- "so-fleet_agent_id_verification-1"
priority: 501
data_stream:
hidden: false
allow_custom_routing: false
policy:
phases:
cold:
actions:
set_priority:
priority: 0
min_age: 30d
delete:
actions:
delete: {}
min_age: 365d
hot:
actions:
rollover:
max_age: 30d
max_primary_shard_size: 50gb
set_priority:
priority: 100
min_age: 0ms
warm:
actions:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_securityhub_insights:
index_sorting: False
index_template:
index_patterns:
- "logs-aws.securityhub_insights-*"
template:
settings:
index:
lifecycle:
name: so-logs-aws.securityhub_insights-logs
number_of_replicas: 0
composed_of:
- "logs-aws.securityhub_insights@package"
- "logs-aws.securityhub_insights@custom"
- "so-fleet_globals-1"
- "so-fleet_agent_id_verification-1"
priority: 501
data_stream:
hidden: false
allow_custom_routing: false
policy:
phases:
cold:
actions:
set_priority:
priority: 0
min_age: 30d
delete:
actions:
delete: {}
min_age: 365d
hot:
actions:
rollover:
max_age: 30d
max_primary_shard_size: 50gb
set_priority:
priority: 100
min_age: 0ms
warm:
actions:
set_priority:
priority: 50
min_age: 30d
so-logs-aws_x_vpcflow:
index_sorting: false
index_template:
@@ -3897,7 +4146,7 @@ elasticsearch:
allow_custom_routing: false
hidden: false
index_patterns:
- logs-endpoint.diagnostic.collection-*
- .logs-endpoint.diagnostic.collection-*
priority: 501
template:
settings:
@@ -10568,7 +10817,7 @@ elasticsearch:
hot:
actions:
rollover:
max_age: 30d
max_age: 1d
max_primary_shard_size: 50gb
set_priority:
priority: 100

View File

@@ -95,6 +95,7 @@ elasticsearch:
description: The order to sort by. Must set index_sorting to True.
global: True
helpLink: elasticsearch.html
policy:
phases:
hot:
max_age:

View File

@@ -0,0 +1,22 @@
{
"template": {
"mappings": {
"properties": {
"error": {
"properties": {
"message": {
"type": "match_only_text"
}
}
}
}
}
},
"_meta": {
"package": {
"name": "system"
},
"managed_by": "fleet",
"managed": true
}
}

View File

@@ -0,0 +1,138 @@
{
"template": {
"mappings": {
"properties": {
"so_audit_doc_id": {
"ignore_above": 1024,
"type": "keyword"
},
"@timestamp": {
"type": "date"
},
"so_kind": {
"ignore_above": 1024,
"type": "keyword"
},
"so_operation": {
"ignore_above": 1024,
"type": "keyword"
},
"so_detection": {
"properties": {
"publicId": {
"type": "text"
},
"title": {
"type": "text"
},
"severity": {
"ignore_above": 1024,
"type": "keyword"
},
"author": {
"type": "text"
},
"description": {
"type": "text"
},
"content": {
"type": "text"
},
"isEnabled": {
"type": "boolean"
},
"isReporting": {
"type": "boolean"
},
"isCommunity": {
"type": "boolean"
},
"tags": {
"type": "text"
},
"ruleset": {
"ignore_above": 1024,
"type": "keyword"
},
"engine": {
"ignore_above": 1024,
"type": "keyword"
},
"language": {
"ignore_above": 1024,
"type": "keyword"
},
"license": {
"ignore_above": 1024,
"type": "keyword"
},
"overrides": {
"properties": {
"type": {
"ignore_above": 1024,
"type": "keyword"
},
"isEnabled": {
"type": "boolean"
},
"createdAt": {
"type": "date"
},
"updatedAt": {
"type": "date"
},
"regex": {
"type": "text"
},
"value": {
"type": "text"
},
"thresholdType": {
"ignore_above": 1024,
"type": "keyword"
},
"track": {
"ignore_above": 1024,
"type": "keyword"
},
"ip": {
"type": "text"
},
"count": {
"type": "long"
},
"seconds": {
"type": "long"
},
"customFilter": {
"type": "text"
}
}
}
}
},
"so_detectioncomment": {
"properties": {
"createTime": {
"type": "date"
},
"detectionId": {
"ignore_above": 1024,
"type": "keyword"
},
"value": {
"type": "text"
},
"userId": {
"ignore_above": 1024,
"type": "keyword"
}
}
}
}
}
},
"_meta": {
"ecs_version": "1.12.2"
}
}

View File

@@ -0,0 +1,7 @@
{
"template": {},
"version": 1,
"_meta": {
"description": "default settings for common Security Onion Detections indices"
}
}

View File

@@ -1295,6 +1295,10 @@ firewall:
portgroups:
- redis
- beats_5644
managersearch:
portgroups:
- redis
- beats_5644
self:
portgroups:
- redis

View File

@@ -0,0 +1,2 @@
global:
pcapengine: STENO

2
salt/global/map.jinja Normal file
View File

@@ -0,0 +1,2 @@
{% import_yaml 'global/defaults.yaml' as GLOBALDEFAULTS %}
{% set GLOBALMERGED = salt['pillar.get']('global', GLOBALDEFAULTS.global, merge=True) %}

View File

@@ -10,10 +10,15 @@ global:
regex: ^(([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?)?$
regexFailureMessage: You must enter a valid IP address or CIDR.
mdengine:
description: What engine to use for meta data generation. Options are ZEEK and SURICATA.
description: Which engine to use for meta data generation. Options are ZEEK and SURICATA.
regex: ^(ZEEK|SURICATA)$
regexFailureMessage: You must enter either ZEEK or SURICATA.
global: True
pcapengine:
description: Which engine to use for generating pcap. Options are STENO, SURICATA or TRANSITION.
regex: ^(STENO|SURICATA|TRANSITION)$
regexFailureMessage: You must enter either STENO, SURICATA or TRANSITION.
global: True
ids:
description: Which IDS engine to use. Currently only Suricata is supported.
global: True

View File

@@ -6,9 +6,10 @@ idstools:
description: Enter your registration code or oinkcode for paid NIDS rulesets.
title: Registration Code
global: True
forcedType: string
helpLink: rules.html
ruleset:
description: Defines the ruleset you want to run. Options are ETOPEN or ETPRO.
description: 'Defines the ruleset you want to run. Options are ETOPEN or ETPRO. WARNING! Changing the ruleset will remove all existing Suricata rules of the previous ruleset and their associated overrides. This removal cannot be undone.'
global: True
regex: ETPRO\b|ETOPEN\b
helpLink: rules.html

View File

@@ -0,0 +1,2 @@
https://repo.securityonion.net/file/so-repo/prod/2.4/oracle/9
https://repo-alt.securityonion.net/prod/2.4/oracle/9

View File

@@ -0,0 +1,13 @@
[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=True
best=True
skip_if_unavailable=False
cachedir=/opt/so/conf/reposync/cache
keepcache=0
[securityonionsync]
name=Security Onion Repo repo
mirrorlist=file:///opt/so/conf/reposync/mirror.txt
enabled=1
gpgcheck=1

View File

@@ -75,6 +75,20 @@ yara_update_scripts:
- defaults:
EXCLUDEDRULES: {{ STRELKAMERGED.rules.excluded }}
so-repo-file:
file.managed:
- name: /opt/so/conf/reposync/repodownload.conf
- source: salt://manager/files/repodownload.conf
- user: socore
- group: socore
so-repo-mirrorlist:
file.managed:
- name: /opt/so/conf/reposync/mirror.txt
- source: salt://manager/files/mirror.txt
- user: socore
- group: socore
so-repo-sync:
{% if MANAGERMERGED.reposync.enabled %}
cron.present:
@@ -104,7 +118,6 @@ rules_dir:
- makedirs: True
{% if STRELKAMERGED.rules.enabled %}
strelkarepos:
file.managed:
- name: /opt/so/conf/strelka/repos.txt
@@ -113,7 +126,6 @@ strelkarepos:
- defaults:
STRELKAREPOS: {{ STRELKAMERGED.rules.repos }}
- makedirs: True
strelka-yara-update:
{% if MANAGERMERGED.reposync.enabled and not GLOBALS.airgap %}
cron.present:
@@ -125,7 +137,6 @@ strelka-yara-update:
- identifier: strelka-yara-update
- hour: '7'
- minute: '1'
strelka-yara-download:
{% if MANAGERMERGED.reposync.enabled and not GLOBALS.airgap %}
cron.present:
@@ -137,14 +148,12 @@ strelka-yara-download:
- identifier: strelka-yara-download
- hour: '7'
- minute: '1'
{% if not GLOBALS.airgap %}
update_yara_rules:
cmd.run:
- name: /usr/sbin/so-yara-update
- onchanges:
- file: yara_update_scripts
download_yara_rules:
cmd.run:
- name: /usr/sbin/so-yara-download
@@ -152,6 +161,7 @@ download_yara_rules:
- file: yara_update_scripts
{% endif %}
{% endif %}
{% else %}
{{sls}}_state_not_allowed:

View File

@@ -79,6 +79,32 @@ function getinstallinfo() {
source <(echo $INSTALLVARS)
}
function pcapspace() {
if [[ "$OPERATION" == "setup" ]]; then
# Use 25% for PCAP
PCAP_PERCENTAGE=1
DFREEPERCENT=21
local SPACESIZE=$(df -k /nsm | tail -1 | awk '{print $2}' | tr -d \n)
else
local NSMSIZE=$(salt "$MINION_ID" disk.usage --out=json | jq -r '.[]."/nsm"."1K-blocks" ')
local ROOTSIZE=$(salt "$MINION_ID" disk.usage --out=json | jq -r '.[]."/"."1K-blocks" ')
if [[ "$NSMSIZE" == "null" ]]; then
# Looks like there is no dedicated nsm partition. Using root
local SPACESIZE=$ROOTSIZE
else
local SPACESIZE=$NSMSIZE
fi
fi
local s=$(( $SPACESIZE / 1000000 ))
local s1=$(( $s / 4 * $PCAP_PERCENTAGE ))
MAX_PCAP_SPACE=$s1
}
function testMinion() {
# Always run on the host, since this is going to be the manager of a distributed grid, or an eval/standalone.
# Distributed managers must run this in order for the sensor nodes to have access to the so-tcpreplay image.
@@ -244,6 +270,10 @@ function add_sensor_to_minion() {
echo " lb_procs: '$CORECOUNT'" >> $PILLARFILE
echo "suricata:" >> $PILLARFILE
echo " enabled: True " >> $PILLARFILE
if [[ $is_pcaplimit ]]; then
echo " pcap:" >> $PILLARFILE
echo " maxsize: $MAX_PCAP_SPACE" >> $PILLARFILE
fi
echo " config:" >> $PILLARFILE
echo " af-packet:" >> $PILLARFILE
echo " threads: '$CORECOUNT'" >> $PILLARFILE
@@ -251,7 +281,7 @@ function add_sensor_to_minion() {
echo " enabled: True" >> $PILLARFILE
if [[ $is_pcaplimit ]]; then
echo " config:" >> $PILLARFILE
echo " diskfreepercentage: 60" >> $PILLARFILE
echo " diskfreepercentage: $DFREEPERCENT" >> $PILLARFILE
fi
echo " " >> $PILLARFILE
}
@@ -422,6 +452,7 @@ function updateMine() {
function createEVAL() {
is_pcaplimit=true
pcapspace
add_elasticsearch_to_minion
add_sensor_to_minion
add_strelka_to_minion
@@ -442,6 +473,7 @@ function createEVAL() {
function createSTANDALONE() {
is_pcaplimit=true
pcapspace
add_elasticsearch_to_minion
add_logstash_to_minion
add_sensor_to_minion
@@ -531,6 +563,9 @@ function createIDH() {
function createHEAVYNODE() {
is_pcaplimit=true
PCAP_PERCENTAGE=1
DFREEPERCENT=21
pcapspace
add_elasticsearch_to_minion
add_elastic_agent_to_minion
add_logstash_to_minion
@@ -541,6 +576,10 @@ function createHEAVYNODE() {
}
function createSENSOR() {
is_pcaplimit=true
DFREEPERCENT=10
PCAP_PERCENTAGE=3
pcapspace
add_sensor_to_minion
add_strelka_to_minion
add_telegraf_to_minion

View File

@@ -47,7 +47,7 @@ got_root(){
got_root
if [ $# -ne 1 ] ; then
BRANCH=master
BRANCH=2.4/main
else
BRANCH=$1
fi

View File

@@ -247,67 +247,6 @@ check_sudoers() {
fi
}
check_log_size_limit() {
local num_minion_pillars
num_minion_pillars=$(find /opt/so/saltstack/local/pillar/minions/ -type f | wc -l)
if [[ $num_minion_pillars -gt 1 ]]; then
if find /opt/so/saltstack/local/pillar/minions/ -type f | grep -q "_heavynode"; then
lsl_msg='distributed'
fi
else
local minion_id
minion_id=$(lookup_salt_value "id" "" "grains" "" "local")
local minion_arr
IFS='_' read -ra minion_arr <<< "$minion_id"
local node_type="${minion_arr[0]}"
local current_limit
# since it is possible for the salt-master service to be stopped when this is run, we need to check the pillar values locally
# we need to combine default local and default pillars before doing this so we can define --pillar-root in salt-call
local epoch_date=$(date +%s%N)
mkdir -vp /opt/so/saltstack/soup_tmp_${epoch_date}/
cp -r /opt/so/saltstack/default/pillar/ /opt/so/saltstack/soup_tmp_${epoch_date}/
# use \cp here to overwrite any pillar files from default with those in local for the tmp directory
\cp -r /opt/so/saltstack/local/pillar/ /opt/so/saltstack/soup_tmp_${epoch_date}/
current_limit=$(salt-call pillar.get elasticsearch:log_size_limit --local --pillar-root=/opt/so/saltstack/soup_tmp_${epoch_date}/pillar --out=newline_values_only)
rm -rf /opt/so/saltstack/soup_tmp_${epoch_date}/
local percent
case $node_type in
'standalone' | 'eval')
percent=50
;;
*)
percent=80
;;
esac
local disk_dir="/"
if [ -d /nsm ]; then
disk_dir="/nsm"
fi
local disk_size_1k
disk_size_1k=$(df $disk_dir | grep -v "^Filesystem" | awk '{print $2}')
local ratio="1048576"
local disk_size_gb
disk_size_gb=$( echo "$disk_size_1k" "$ratio" | awk '{print($1/$2)}' )
local new_limit
new_limit=$( echo "$disk_size_gb" "$percent" | awk '{printf("%.0f", $1 * ($2/100))}')
if [[ $current_limit != "$new_limit" ]]; then
lsl_msg='single-node'
lsl_details=( "$current_limit" "$new_limit" "$minion_id" )
fi
fi
}
check_os_updates() {
# Check to see if there are OS updates
echo "Checking for OS updates."
@@ -417,6 +356,7 @@ preupgrade_changes() {
[[ "$INSTALLEDVERSION" == 2.4.20 ]] && up_to_2.4.30
[[ "$INSTALLEDVERSION" == 2.4.30 ]] && up_to_2.4.40
[[ "$INSTALLEDVERSION" == 2.4.40 ]] && up_to_2.4.50
[[ "$INSTALLEDVERSION" == 2.4.50 ]] && up_to_2.4.60
true
}
@@ -432,6 +372,7 @@ postupgrade_changes() {
[[ "$POSTVERSION" == 2.4.20 ]] && post_to_2.4.30
[[ "$POSTVERSION" == 2.4.30 ]] && post_to_2.4.40
[[ "$POSTVERSION" == 2.4.40 ]] && post_to_2.4.50
[[ "$POSTVERSION" == 2.4.50 ]] && post_to_2.4.60
true
}
@@ -488,6 +429,12 @@ post_to_2.4.50() {
POSTVERSION=2.4.50
}
post_to_2.4.60() {
echo "Regenerating Elastic Agent Installers..."
so-elastic-agent-gen-installers
POSTVERSION=2.4.60
}
repo_sync() {
echo "Sync the local repo."
su socore -c '/usr/sbin/so-repo-sync' || fail "Unable to complete so-repo-sync."
@@ -591,6 +538,8 @@ up_to_2.4.40() {
up_to_2.4.50() {
echo "Creating additional pillars.."
mkdir -p /opt/so/saltstack/local/pillar/stig/
mkdir -p /opt/so/saltstack/local/salt/stig/
chown socore:socore /opt/so/saltstack/local/salt/stig/
touch /opt/so/saltstack/local/pillar/stig/adv_stig.sls
touch /opt/so/saltstack/local/pillar/stig/soc_stig.sls
@@ -617,6 +566,14 @@ up_to_2.4.50() {
INSTALLEDVERSION=2.4.50
}
up_to_2.4.60() {
echo "Creating directory to store Suricata classification.config"
mkdir -vp /opt/so/saltstack/local/salt/suricata/classification
chown socore:socore /opt/so/saltstack/local/salt/suricata/classification
INSTALLEDVERSION=2.4.60
}
determine_elastic_agent_upgrade() {
if [[ $is_airgap -eq 0 ]]; then
update_elastic_agent_airgap
@@ -664,6 +621,10 @@ update_airgap_rules() {
if [ -d /nsm/repo/rules/sigma ]; then
rsync -av $UPDATE_DIR/agrules/sigma/* /nsm/repo/rules/sigma/
fi
# SOC Detections Airgap
rsync -av $UPDATE_DIR/agrules/detect-sigma/* /nsm/rules/detect-sigma/
rsync -av $UPDATE_DIR/agrules/detect-yara/* /nsm/rules/detect-yara/
}
update_airgap_repo() {

0
salt/manager/tools/sbin_jinja/so-yara-update Executable file → Normal file
View File

View File

@@ -3,5 +3,11 @@
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 %}
{% import_yaml 'pcap/defaults.yaml' as PCAPDEFAULTS %}
{% set PCAPMERGED = salt['pillar.get']('pcap', PCAPDEFAULTS.pcap, merge=True) %}
{# disable stenographer if the pcap engine is set to SURICATA #}
{% if GLOBALS.pcap_engine == "SURICATA" %}
{% do PCAPMERGED.update({'enabled': False}) %}
{% endif %}

View File

@@ -72,13 +72,6 @@ stenoca:
- user: 941
- group: 939
pcapdir:
file.directory:
- name: /nsm/pcap
- user: 941
- group: 941
- makedirs: True
pcaptmpdir:
file.directory:
- name: /nsm/pcaptmp

View File

@@ -15,3 +15,12 @@ include:
{% else %}
- pcap.disabled
{% endif %}
# This directory needs to exist regardless of whether STENO is enabled or not, in order for
# Sensoroni to be able to look at old steno PCAP data
pcapdir:
file.directory:
- name: /nsm/pcap
- user: 941
- group: 941
- makedirs: True

View File

@@ -4,32 +4,32 @@ pcap:
helpLink: stenographer.html
config:
maxdirectoryfiles:
description: The maximum number of packet/index files to create before deleting old files.
description: By default, Stenographer limits the number of files in the pcap directory to 30000 to avoid limitations with the ext3 filesystem. However, if you're using the ext4 or xfs filesystems, then it is safe to increase this value. So if you have a large amount of storage and find that you only have 3 weeks worth of PCAP on disk while still having plenty of free space, then you may want to increase this default setting.
helpLink: stenographer.html
diskfreepercentage:
description: The disk space percent to always keep free for PCAP
description: Stenographer will purge old PCAP on a regular basis to keep the disk free percentage at this level. If you have a distributed deployment with dedicated forward nodes, then the default value of 10 should be reasonable since Stenographer should be the main consumer of disk space in the /nsm partition. However, if you have systems that run both Stenographer and Elasticsearch at the same time (like eval and standalone installations), then youll want to make sure that this value is no lower than 21 so that you avoid Elasticsearch hitting its watermark setting at 80% disk usage. If you have an older standalone installation, then you may need to manually change this value to 21.
helpLink: stenographer.html
blocks:
description: The number of 1MB packet blocks used by AF_PACKET to store packets in memory, per thread. You shouldn't need to change this.
description: The number of 1MB packet blocks used by Stenographer and AF_PACKET to store packets in memory, per thread. You shouldn't need to change this.
advanced: True
helpLink: stenographer.html
preallocate_file_mb:
description: File size to pre-allocate for individual PCAP files. You shouldn't need to change this.
description: File size to pre-allocate for individual Stenographer PCAP files. You shouldn't need to change this.
advanced: True
helpLink: stenographer.html
aiops:
description: The max number of async writes to allow at once.
description: The max number of async writes to allow for Stenographer at once.
advanced: True
helpLink: stenographer.html
pin_to_cpu:
description: Enable CPU pinning for PCAP.
description: Enable CPU pinning for Stenographer PCAP.
advanced: True
helpLink: stenographer.html
cpus_to_pin_to:
description: CPU to pin PCAP to. Currently only a single CPU is supported.
description: CPU to pin Stenographer PCAP to. Currently only a single CPU is supported.
advanced: True
helpLink: stenographer.html
disks:
description: List of disks to use for PCAP. This is currently not used.
description: List of disks to use for Stenographer PCAP. This is currently not used.
advanced: True
helpLink: stenographer.html

View File

@@ -10,3 +10,4 @@ salt_bootstrap:
- name: /usr/sbin/bootstrap-salt.sh
- source: salt://salt/scripts/bootstrap-salt.sh
- mode: 755
- show_changes: False

View File

@@ -8,6 +8,8 @@ sensoroni:
node_checkin_interval_ms: 10000
sensoronikey:
soc_host:
suripcap:
pcapMaxCount: 999999
analyzers:
echotrail:
base_url: https://api.echotrail.io/insights/

View File

@@ -23,6 +23,7 @@ so-sensoroni:
- /opt/so/conf/sensoroni/sensoroni.json:/opt/sensoroni/sensoroni.json:ro
- /opt/so/conf/sensoroni/analyzers:/opt/sensoroni/analyzers:rw
- /opt/so/log/sensoroni:/opt/sensoroni/logs:rw
- /nsm/suripcap/:/nsm/suripcap:rw
{% if DOCKER.containers['so-sensoroni'].custom_bind_mounts %}
{% for BIND in DOCKER.containers['so-sensoroni'].custom_bind_mounts %}
- {{ BIND }}

View File

@@ -1,6 +1,5 @@
{%- from 'vars/globals.map.jinja' import GLOBALS %}
{%- from 'sensoroni/map.jinja' import SENSORONIMERGED %}
{%- from 'pcap/config.map.jinja' import PCAPMERGED %}
{% from 'vars/globals.map.jinja' import GLOBALS %}
{%- from 'sensoroni/map.jinja' import SENSORONIMERGED -%}
{
"logFilename": "/opt/sensoroni/logs/sensoroni.log",
"logLevel":"info",
@@ -23,16 +22,19 @@
"importer": {},
"statickeyauth": {
"apiKey": "{{ GLOBALS.sensoroni_key }}"
{%- if PCAPMERGED.enabled %}
{% if GLOBALS.is_sensor %}
},
"stenoquery": {
"executablePath": "/opt/sensoroni/scripts/stenoquery.sh",
"pcapInputPath": "/nsm/pcap",
"pcapOutputPath": "/nsm/pcapout"
}
{%- else %}
}
},
"suriquery": {
"pcapInputPath": "/nsm/suripcap",
"pcapOutputPath": "/nsm/pcapout",
"pcapMaxCount": {{ SENSORONIMERGED.config.suripcap.pcapMaxCount }}
{%- endif %}
}
}
}
}

View File

@@ -37,6 +37,11 @@ sensoroni:
helpLink: grid.html
global: True
advanced: True
suripcap:
pcapMaxCount:
description: The maximum number of PCAP packets to extract from eligible PCAP files, for PCAP jobs. If there are issues fetching excessively large packet streams consider lowering this value to reduce the number of collected packets returned to the user interface.
helpLink: sensoroni.html
advanced: True
analyzers:
echotrail:
api_key:

View File

@@ -9,9 +9,16 @@
include:
- manager.sync_es_users
socdirtest:
file.directory:
- name: /opt/so/rules/elastalert/rules
- user: 939
- group: 939
- makedirs: True
socdir:
file.directory:
- name: /opt/so/conf/soc
- name: /opt/so/conf/soc/fingerprints
- user: 939
- group: 939
- makedirs: True
@@ -57,6 +64,22 @@ socmotd:
- mode: 600
- template: jinja
socsigmafinalpipeline:
file.managed:
- name: /opt/so/conf/soc/sigma_final_pipeline.yaml
- source: salt://soc/files/soc/sigma_final_pipeline.yaml
- user: 939
- group: 939
- mode: 600
socsigmasopipeline:
file.managed:
- name: /opt/so/conf/soc/sigma_so_pipeline.yaml
- source: salt://soc/files/soc/sigma_so_pipeline.yaml
- user: 939
- group: 939
- mode: 600
socbanner:
file.managed:
- name: /opt/so/conf/soc/banner.md
@@ -114,6 +137,13 @@ socuploaddir:
- group: 939
- makedirs: True
socsigmarepo:
file.directory:
- name: /opt/so/rules
- user: 939
- group: 939
- mode: 775
{% else %}
{{sls}}_state_not_allowed:

View File

@@ -20,7 +20,7 @@ soc:
- dashboards
- name: actionCorrelate
description: actionCorrelateHelp
icon: fab fa-searchengin
icon: fa-magnifying-glass-arrow-right
target: ''
links:
- '/#/hunt?q=("{:log.id.fuid}" OR "{:log.id.uid}" OR "{:network.community_id}") | groupby event.module* | groupby -sankey event.module* event.dataset | groupby event.dataset | groupby source.ip source.port destination.ip destination.port | groupby network.protocol | groupby source_geo.organization_name source.geo.country_name | groupby destination_geo.organization_name destination.geo.country_name | groupby rule.name rule.category event.severity_label | groupby dns.query.name | groupby file.mime_type | groupby http.virtual_host http.uri | groupby notice.note notice.message notice.sub_message | groupby ssl.server_name | groupby source.ip host.hostname user.name event.action event.type process.executable process.pid'
@@ -65,12 +65,18 @@ soc:
target: _blank
links:
- 'https://{:sublime.url}/messages/{:sublime.message_group_id}'
- name: actionProcessInfo
description: actionProcessInfoHelp
icon: fa-person-running
target: ''
links:
- '/#/hunt?q=(process.entity_id:"{:process.entity_id}") | groupby event.dataset | groupby -sankey event.dataset event.action | groupby event.action | groupby process.name | groupby host.name user.name | groupby source.ip source.port destination.ip destination.port | groupby dns.question.name | groupby dns.answers.data | groupby file.path | groupby registry.path | groupby dll.path'
- name: actionProcessAncestors
description: actionProcessAncestorsHelp
icon: fa-people-roof
target: ''
links:
- '/#/hunt?q=(process.entity_id:"{:process.entity_id}" OR process.entity_id:"{:process.Ext.ancestry|processAncestors}") | groupby process.parent.name | groupby -sankey process.parent.name process.name | groupby process.name | groupby event.module event.dataset | table soc_timestamp event.dataset host.name user.name process.parent.name process.name process.working_directory'
- '/#/hunt?q=(process.entity_id:"{:process.entity_id}" OR process.entity_id:"{:process.Ext.ancestry|processAncestors}") | groupby event.dataset | groupby -sankey event.dataset event.action | groupby event.action | groupby process.parent.name | groupby -sankey process.parent.name process.name | groupby process.name | groupby host.name user.name | groupby source.ip source.port destination.ip destination.port | groupby dns.question.name | groupby dns.answers.data | groupby file.path | groupby registry.path | groupby dll.path'
eventFields:
default:
- soc_timestamp
@@ -995,6 +1001,69 @@ soc:
- tds.header_type
- log.id.uid
- event.dataset
':endpoint:events_x_api':
- soc_timestamp
- host.name
- user.name
- process.name
- process.Ext.api.name
- process.thread.Ext.call_stack_final_user_module.path
- event.dataset
':endpoint:events_x_file':
- soc_timestamp
- host.name
- user.name
- process.name
- event.action
- file.path
- event.dataset
':endpoint:events_x_library':
- soc_timestamp
- host.name
- user.name
- process.name
- event.action
- dll.path
- dll.code_signature.status
- dll.code_signature.subject_name
- event.dataset
':endpoint:events_x_network':
- soc_timestamp
- host.name
- user.name
- process.name
- event.action
- source.ip
- source.port
- destination.ip
- destination.port
- network.community_id
- event.dataset
':endpoint:events_x_process':
- soc_timestamp
- host.name
- user.name
- process.parent.name
- process.name
- event.action
- process.working_directory
- event.dataset
':endpoint:events_x_registry':
- soc_timestamp
- host.name
- user.name
- process.name
- event.action
- registry.path
- event.dataset
':endpoint:events_x_security':
- soc_timestamp
- host.name
- user.name
- process.executable
- event.action
- event.outcome
- event.dataset
server:
bindAddress: 0.0.0.0:9822
baseUrl: /
@@ -1008,6 +1077,16 @@ soc:
jobDir: jobs
kratos:
hostUrl:
elastalertengine:
allowRegex: ''
autoUpdateEnabled: false
communityRulesImportFrequencySeconds: 86400
denyRegex: ''
elastAlertRulesFolder: /opt/sensoroni/elastalert
rulesFingerprintFile: /opt/sensoroni/fingerprints/sigma.fingerprint
sigmaRulePackages:
- core
- emerging_threats_addon
elastic:
hostUrl:
remoteHostUrls: []
@@ -1026,6 +1105,7 @@ soc:
esSearchOffsetMs: 1800000
maxLogLength: 1024
asyncThreshold: 10
lookupTunnelParent: true
influxdb:
hostUrl:
token:
@@ -1049,6 +1129,21 @@ soc:
- rbac/custom_roles
userFiles:
- rbac/users_roles
strelkaengine:
allowRegex: ''
autoUpdateEnabled: false
compileYaraPythonScriptPath: /opt/so/conf/strelka/compile_yara.py
denyRegex: '.*'
reposFolder: /opt/sensoroni/yara/repos
rulesRepos:
- repo: https://github.com/Security-Onion-Solutions/securityonion-yara
license: DRL
yaraRulesFolder: /opt/sensoroni/yara/rules
suricataengine:
allowRegex: ''
communityRulesFile: /nsm/rules/suricata/emerging-all.rules
denyRegex: '.*'
rulesFingerprintFile: /opt/sensoroni/fingerprints/emerging-all.fingerprint
client:
enableReverseLookup: false
docsUrl: /docs/
@@ -1059,6 +1154,7 @@ soc:
tipTimeoutMs: 6000
cacheExpirationMs: 300000
casesEnabled: true
detectionsEnabled: false
inactiveTools: ['toolUnused']
tools:
- name: toolKibana
@@ -1114,6 +1210,9 @@ soc:
- name: caseExcludeToggle
filter: 'NOT _index:"*:so-case*"'
enabled: true
- name: detectionsExcludeToggle
filter: 'NOT _index:"*:so-detection*"'
enabled: true
- name: socExcludeToggle
filter: 'NOT event.module:"soc"'
enabled: true
@@ -1384,6 +1483,9 @@ soc:
- name: caseExcludeToggle
filter: 'NOT _index:"*:so-case*"'
enabled: true
- name: detectionsExcludeToggle
filter: 'NOT _index:"*:so-detection*"'
enabled: true
- name: socExcludeToggle
filter: 'NOT event.module:"soc"'
enabled: true
@@ -1417,13 +1519,22 @@ soc:
query: 'event.category: network AND _exists_:process.executable AND (_exists_:dns.question.name OR _exists_:dns.answers.data) | groupby -sankey host.name dns.question.name | groupby event.dataset event.type | groupby host.name | groupby process.executable | groupby dns.question.name | groupby dns.answers.data'
- name: Host Process Activity
description: Process activity captured on an endpoint
query: 'event.category:process | groupby -sankey host.name user.name* | groupby event.dataset event.action | groupby host.name | groupby user.name | groupby process.working_directory | groupby process.executable | groupby process.command_line | groupby process.parent.executable | groupby process.parent.command_line | groupby -sankey process.parent.executable process.executable | table soc_timestamp event.dataset host.name user.name process.parent.name process.name process.working_directory'
query: 'event.category:process | groupby -sankey host.name user.name* | groupby event.dataset event.action | groupby host.name | groupby user.name | groupby process.working_directory | groupby process.executable | groupby process.command_line | groupby process.parent.executable | groupby process.parent.command_line | groupby -sankey process.parent.executable process.executable | table soc_timestamp host.name user.name process.parent.name process.name event.action process.working_directory event.dataset'
- name: Host File Activity
description: File activity captured on an endpoint
query: 'event.category: file AND _exists_:process.executable | groupby -sankey host.name process.executable | groupby host.name | groupby event.dataset event.action event.type | groupby file.name | groupby process.executable'
- name: Host Network & Process Mappings
description: Network activity mapped to originating processes
query: 'event.category: network AND _exists_:process.executable | groupby -sankey event.action host.name | groupby -sankey host.name user.name | groupby event.dataset* event.type* event.action* | groupby host.name | groupby user.name | groupby dns.question.name | groupby process.executable | groupby winlog.event_data.TargetObject | groupby process.name | groupby source.ip | groupby destination.ip | groupby destination.port'
- name: Host API Events
description: API (Application Programming Interface) events from endpoints
query: 'event.dataset:endpoint.events.api | groupby host.name | groupby -sankey host.name user.name | groupby user.name | groupby process.name | groupby process.Ext.api.name'
- name: Host Library Events
description: Library events from endpoints
query: 'event.dataset:endpoint.events.library | groupby host.name | groupby -sankey host.name user.name | groupby user.name | groupby process.name | groupby event.action | groupby dll.path | groupby dll.code_signature.status | groupby dll.code_signature.subject_name'
- name: Host Security Events
description: Security events from endpoints
query: 'event.dataset:endpoint.events.security | groupby host.name | groupby -sankey host.name user.name | groupby user.name | groupby process.executable | groupby event.action | groupby event.outcome'
- name: Strelka
description: Strelka file analysis
query: 'event.module:strelka | groupby file.mime_type | groupby -sankey file.mime_type file.source | groupby file.source | groupby file.name'
@@ -1754,3 +1865,55 @@ soc:
- amber+strict
- red
customEnabled: false
detections:
viewEnabled: true
createLink: /detection/create
eventFetchLimit: 500
eventItemsPerPage: 50
groupFetchLimit: 50
mostRecentlyUsedLimit: 5
safeStringMaxLength: 100
queryBaseFilter: '_index:"*:so-detection" AND so_kind:detection'
eventFields:
default:
- so_detection.title
- so_detection.isEnabled
- so_detection.language
- so_detection.severity
queries:
- name: "All Detections"
query: "_id:*"
- name: "Custom Detections"
query: "so_detection.isCommunity:false"
- name: "All Detections - Enabled"
query: "so_detection.isEnabled:true"
- name: "All Detections - Disabled"
query: "so_detection.isEnabled:false"
- name: "Detection Type - Suricata (NIDS)"
query: "so_detection.language:suricata"
- name: "Detection Type - Sigma - All"
query: "so_detection.language:sigma"
- name: "Detection Type - Sigma - Windows"
query: 'so_detection.language:sigma AND so_detection.content: "*product: windows*"'
- name: "Detection Type - Yara (Strelka)"
query: "so_detection.language:yara"
detection:
presets:
severity:
customEnabled: false
labels:
- unknown
- informational
- low
- medium
- high
- critical
language:
customEnabled: false
labels:
- suricata
- sigma
- yara
severityTranslations:
minor: low
major: high

View File

@@ -22,12 +22,18 @@ so-soc:
- sobridge:
- ipv4_address: {{ DOCKER.containers['so-soc'].ip }}
- binds:
- /nsm/rules:/nsm/rules:rw
- /opt/so/conf/strelka:/opt/sensoroni/yara:rw
- /opt/so/rules/elastalert/rules:/opt/sensoroni/elastalert:rw
- /opt/so/conf/soc/fingerprints:/opt/sensoroni/fingerprints:rw
- /nsm/soc/jobs:/opt/sensoroni/jobs:rw
- /nsm/soc/uploads:/nsm/soc/uploads:rw
- /opt/so/log/soc/:/opt/sensoroni/logs/:rw
- /opt/so/conf/soc/soc.json:/opt/sensoroni/sensoroni.json:ro
- /opt/so/conf/soc/motd.md:/opt/sensoroni/html/motd.md:ro
- /opt/so/conf/soc/banner.md:/opt/sensoroni/html/login/banner.md:ro
- /opt/so/conf/soc/sigma_so_pipeline.yaml:/opt/sensoroni/sigma_so_pipeline.yaml:ro
- /opt/so/conf/soc/sigma_final_pipeline.yaml:/opt/sensoroni/sigma_final_pipeline.yaml:rw
- /opt/so/conf/soc/custom.js:/opt/sensoroni/html/js/custom.js:ro
- /opt/so/conf/soc/custom_roles:/opt/sensoroni/rbac/custom_roles:ro
- /opt/so/conf/soc/soc_users_roles:/opt/sensoroni/rbac/users_roles:rw

View File

@@ -0,0 +1,14 @@
import os
import yara
import glob
import sys
def compile_yara_rules(rules_dir: str) -> None:
compiled_rules_path: str = os.path.join(rules_dir, "rules.yar.compiled")
rule_files: list[str] = glob.glob(os.path.join(rules_dir, '**/*.yar'), recursive=True)
if rule_files:
rules: yara.Rules = yara.compile(filepaths={os.path.basename(f): f for f in rule_files})
rules.save(compiled_rules_path)
compile_yara_rules(sys.argv[1])

View File

@@ -0,0 +1,7 @@
name: Security Onion - Final Pipeline
priority: 95
transformations:
- id: override_field_name_mapping
type: field_name_mapping
mapping:
FieldNameToOverride: NewFieldName

View File

@@ -0,0 +1,81 @@
name: Security Onion Baseline Pipeline
priority: 90
transformations:
- id: baseline_field_name_mapping
type: field_name_mapping
mapping:
cs-method: http.method
c-uri: http.uri
c-useragent: http.useragent
cs-version: http.version
uid: user.uid
sid: rule.uuid
answer: answers
query: dns.query.name
src_ip: source.ip.keyword
src_port: source.port
dst_ip: destination.ip.keyword
dst_port: destination.port
winlog.event_data.User: user.name
# Maps "antivirus" category to Windows Defender logs shipped by Elastic Agent Winlog Integration
# winlog.event_data.threat_name has to be renamed prior to ingestion, it is originally winlog.event_data.Threat Name
- id: antivirus_field-mappings_windows-defender
type: field_name_mapping
mapping:
Signature: winlog.event_data.threat_name
rule_conditions:
- type: logsource
category: antivirus
- id: antivirus_add-fields_windows-defender
type: add_condition
conditions:
winlog.channel: 'Microsoft-Windows-Windows Defender/Operational'
winlog.provider_name: 'Microsoft-Windows-Windows Defender'
event.code: "1116"
rule_conditions:
- type: logsource
category: antivirus
# Drops the Hashes field which is specific to Sysmon logs
# Ingested sysmon logs will have the Hashes field mapped to ECS specific fields
- id: hashes_drop_sysmon-specific-field
type: drop_detection_item
field_name_conditions:
- type: include_fields
fields:
- winlog.event_data.Hashes
rule_conditions:
- type: logsource
product: windows
- id: hashes_process-creation
type: field_name_mapping
mapping:
winlog.event_data.sha256: process.hash.sha256
winlog.event_data.sha1: process.hash.sha1
winlog.event_data.md5: process.hash.md5
winlog.event_data.Imphash: process.pe.imphash
rule_conditions:
- type: logsource
product: windows
category: process_creation
- id: hashes_image-load
type: field_name_mapping
mapping:
winlog.event_data.sha256: dll.hash.sha256
winlog.event_data.sha1: dll.hash.sha1
winlog.event_data.md5: dll.hash.md5
winlog.event_data.Imphash: dll.pe.imphash
rule_conditions:
- type: logsource
product: windows
category: image_load
- id: hashes_driver-load
type: field_name_mapping
mapping:
winlog.event_data.sha256: dll.hash.sha256
winlog.event_data.sha1: dll.hash.sha1
winlog.event_data.md5: dll.hash.md5
winlog.event_data.Imphash: dll.pe.imphash
rule_conditions:
- type: logsource
product: windows
category: driver_load

View File

@@ -30,6 +30,17 @@
{# since cases is not a valid soc config item and only used for the map files, remove it from being placed in the config #}
{% do SOCMERGED.config.server.modules.pop('cases') %}
{# remove these modules if detections is disabled #}
{% if not SOCMERGED.config.server.client.detectionsEnabled %}
{% do SOCMERGED.config.server.modules.pop('elastalertengine') %}
{% do SOCMERGED.config.server.modules.pop('strelkaengine') %}
{% do SOCMERGED.config.server.modules.pop('suricataengine') %}
{% elif pillar.global.airgap %}
{# if system is Airgap, don't autoupdate Yara & Sigma rules #}
{% do SOCMERGED.config.server.modules.elastalertengine.update({'autoUpdateEnabled': false}) %}
{% do SOCMERGED.config.server.modules.strelkaengine.update({'autoUpdateEnabled': false}) %}
{% endif %}
{% if pillar.manager.playbook == 0 %}
{% do SOCMERGED.config.server.client.inactiveTools.append('toolPlaybook') %}
{% endif %}
@@ -66,6 +77,14 @@
{% do SOCMERGED.config.server.client.alerts.update({'actions': standard_actions}) %}
{% do SOCMERGED.config.server.client.cases.update({'actions': standard_actions}) %}
{# replace the _x_ with . for soc ui to config conversion #}
{% do SOCMERGED.config.eventFields.update({':endpoint:events.api': SOCMERGED.config.eventFields.pop(':endpoint:events_x_api') }) %}
{% do SOCMERGED.config.eventFields.update({':endpoint:events.file': SOCMERGED.config.eventFields.pop(':endpoint:events_x_file') }) %}
{% do SOCMERGED.config.eventFields.update({':endpoint:events.library': SOCMERGED.config.eventFields.pop(':endpoint:events_x_library') }) %}
{% do SOCMERGED.config.eventFields.update({':endpoint:events.network': SOCMERGED.config.eventFields.pop(':endpoint:events_x_network') }) %}
{% do SOCMERGED.config.eventFields.update({':endpoint:events.process': SOCMERGED.config.eventFields.pop(':endpoint:events_x_process') }) %}
{% do SOCMERGED.config.eventFields.update({':endpoint:events.registry': SOCMERGED.config.eventFields.pop(':endpoint:events_x_registry') }) %}
{% do SOCMERGED.config.eventFields.update({':endpoint:events.security': SOCMERGED.config.eventFields.pop(':endpoint:events_x_security') }) %}
{% set standard_eventFields = SOCMERGED.config.pop('eventFields') %}
{% do SOCMERGED.config.server.client.hunt.update({'eventFields': standard_eventFields}) %}
{% do SOCMERGED.config.server.client.dashboards.update({'eventFields': standard_eventFields}) %}

View File

@@ -32,6 +32,14 @@ soc:
global: True
advanced: True
helpLink: soc-customization.html
sigma_final_pipeline__yaml:
title: Final Sigma Pipeline
description: Final Processing Pipeline for Sigma Rules (future use, not yet complete)
syntax: yaml
file: True
global: True
advanced: True
helpLink: soc-customization.html
config:
licenseKey:
title: License Key
@@ -47,10 +55,17 @@ soc:
global: True
forcedType: "[]{}"
eventFields:
default:
description: Event fields mappings are defined by the format ":event.module:event.dataset". For example, to customize which fields show for 'syslog' events originating from 'zeek', find the eventField item in the left panel that looks like ':zeek:syslog'. This 'default' entry is used for all events that do not match an existing mapping defined in the list to the left.
default: &eventFields
description: Event fields mappings are defined by the format ":event.module:event.dataset". For example, to customize which fields show for 'syslog' events originating from 'zeek', find the eventField item in the left panel that looks like ':zeek:syslog'. The 'default' entry is used for all events that do not match an existing mapping defined in the list to the left.
global: True
advanced: True
':endpoint:events_x_api': *eventFields
':endpoint:events_x_file': *eventFields
':endpoint:events_x_library': *eventFields
':endpoint:events_x_network': *eventFields
':endpoint:events_x_process': *eventFields
':endpoint:events_x_registry': *eventFields
':endpoint:events_x_security': *eventFields
server:
srvKey:
description: Unique key for protecting the integrity of user submitted data via the web browser.
@@ -62,6 +77,15 @@ soc:
global: True
advanced: True
modules:
elastalertengine:
sigmaRulePackages:
description: 'Defines the Sigma Community Ruleset you want to run. One of these (core | core+ | core++ | all ) as well as an optional Add-on (emerging_threats_addon). WARNING! Changing the ruleset will remove all existing Sigma rules of the previous ruleset and their associated overrides. This removal cannot be undone. (future use, not yet complete)'
global: True
advanced: False
autoUpdateEnabled:
description: 'Set to true to enable automatic Internet-connected updates of the Sigma Community Ruleset. If this is an Airgap system, this setting will be overridden and set to false. (future use, not yet complete)'
global: True
advanced: True
elastic:
index:
description: Comma-separated list of indices or index patterns (wildcard "*" supported) that SOC will search for records.
@@ -102,6 +126,9 @@ soc:
description: Maximum number of events that can be acknowledged synchronously. When acknowledging large numbers of events, where the count exceeds this value, the acknowledge update will be performed in the background, as it can take several minutes to complete.
global: True
advanced: True
lookupTunnelParent:
description: When true, if a pivoted event appears to be encapsulated, such as in a VXLAN packet, then SOC will pivot to the VXLAN packet stream. When false, SOC will attempt to pivot to the encapsulated packet stream itself, but at the risk that it may be unable to locate it in the stored PCAP data.
global: True
sostatus:
refreshIntervalMs:
description: Duration (in milliseconds) between refreshes of the grid status. Shortening this duration may not have expected results, as the backend systems feeding this sostatus data will continue their updates as scheduled.
@@ -120,6 +147,11 @@ soc:
description: Duration (in milliseconds) to wait for a response from the Salt API when executing common grid management tasks before giving up and showing an error on the SOC UI.
global: True
advanced: True
strelkaengine:
autoUpdateEnabled:
description: 'Set to true to enable automatic Internet-connected updates of the Yara rulesets. If this is an Airgap system, this setting will be overridden and set to false. (future use, not yet complete)'
global: True
advanced: True
client:
enableReverseLookup:
description: Set to true to enable reverse DNS lookups for IP addresses in the SOC UI.
@@ -142,6 +174,9 @@ soc:
casesEnabled:
description: Set to true to enable case management in SOC.
global: True
detectionsEnabled:
description: Set to true to enable the Detections module in SOC. (future use, not yet complete)
global: True
inactiveTools:
description: List of external tools to remove from the SOC UI.
global: True

View File

@@ -48,15 +48,17 @@ update_stig_profile:
{% if not salt['file.file_exists'](OSCAP_OUTPUT_DIR ~ '/pre-oscap-report.html') %}
run_initial_scan:
module.run:
- name: openscap.xccdf
- params: 'eval --profile {{ OSCAP_PROFILE_NAME }} --results {{ OSCAP_OUTPUT_DIR }}/pre-oscap-results.xml --report {{ OSCAP_OUTPUT_DIR }}/pre-oscap-report.html {{ OSCAP_PROFILE_LOCATION }}'
cmd.run:
- name: 'oscap xccdf eval --profile {{ OSCAP_PROFILE_NAME }} --results {{ OSCAP_OUTPUT_DIR }}/pre-oscap-results.xml --report {{ OSCAP_OUTPUT_DIR }}/pre-oscap-report.html {{ OSCAP_PROFILE_LOCATION }}'
- success_retcodes:
- 2
{% endif %}
run_remediate:
module.run:
- name: openscap.xccdf
- params: 'eval --remediate --profile {{ OSCAP_PROFILE_NAME }} --results {{ OSCAP_OUTPUT_DIR }}/post-oscap-results.xml --report {{ OSCAP_PROFILE_LOCATION }}'
cmd.run:
- name: 'oscap xccdf eval --remediate --profile {{ OSCAP_PROFILE_NAME }} {{ OSCAP_PROFILE_LOCATION }}'
- success_retcodes:
- 2
{# OSCAP rule id: xccdf_org.ssgproject.content_rule_disable_ctrlaltdel_burstaction #}
disable_ctrl_alt_del_action:
@@ -82,9 +84,10 @@ remove_nullok_from_system_auth_auth:
- backup: '.bak'
run_post_scan:
module.run:
- name: openscap.xccdf
- params: 'eval --profile {{ OSCAP_PROFILE_NAME }} --results {{ OSCAP_OUTPUT_DIR }}/post-oscap-results.xml --report {{ OSCAP_OUTPUT_DIR }}/post-oscap-report.html {{ OSCAP_PROFILE_LOCATION }}'
cmd.run:
- name: 'oscap xccdf eval --profile {{ OSCAP_PROFILE_NAME }} --results {{ OSCAP_OUTPUT_DIR }}/post-oscap-results.xml --report {{ OSCAP_OUTPUT_DIR }}/post-oscap-report.html /usr/share/xml/scap/ssg/content/ssg-ol9-ds.xml'
- success_retcodes:
- 2
{% else %}
{{sls}}_no_license_detected:

View File

@@ -611,7 +611,7 @@ the release. Additionally, the original security profile has been modified by Se
<ns5:select idref="xccdf_org.ssgproject.content_rule_account_emergency_expire_date" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_account_password_pam_faillock_password_auth" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_account_password_pam_faillock_system_auth" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_account_password_selinux_faillock_dir" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_account_password_selinux_faillock_dir" selected="false" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_account_temp_expire_date" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_account_unique_id" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_accounts_authorized_local_users" selected="true" />
@@ -1007,8 +1007,8 @@ the release. Additionally, the original security profile has been modified by Se
<ns5:select idref="xccdf_org.ssgproject.content_rule_rsyslog_remote_access_monitoring" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_rsyslog_remote_loghost" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_security_patches_up_to_date" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_selinux_policytype" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_selinux_state" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_selinux_policytype" selected="false" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_selinux_state" selected="false" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_service_auditd_enabled" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_service_autofs_disabled" selected="true" />
<ns5:select idref="xccdf_org.ssgproject.content_rule_service_chronyd_enabled" selected="true" />

View File

@@ -21,6 +21,13 @@ strelkarulesdir:
- group: 939
- makedirs: True
strelkareposdir:
file.directory:
- name: /opt/so/conf/strelka/repos
- user: 939
- group: 939
- makedirs: True
strelkadatadir:
file.directory:
- name: /nsm/strelka

View File

@@ -0,0 +1,51 @@
#
# config classification:shortname,short description,priority
#
config classification: not-suspicious,Not Suspicious Traffic,3
config classification: unknown,Unknown Traffic,3
config classification: bad-unknown,Potentially Bad Traffic, 2
config classification: attempted-recon,Attempted Information Leak,2
config classification: successful-recon-limited,Information Leak,2
config classification: successful-recon-largescale,Large Scale Information Leak,2
config classification: attempted-dos,Attempted Denial of Service,2
config classification: successful-dos,Denial of Service,2
config classification: attempted-user,Attempted User Privilege Gain,1
config classification: unsuccessful-user,Unsuccessful User Privilege Gain,1
config classification: successful-user,Successful User Privilege Gain,1
config classification: attempted-admin,Attempted Administrator Privilege Gain,1
config classification: successful-admin,Successful Administrator Privilege Gain,1
# NEW CLASSIFICATIONS
config classification: rpc-portmap-decode,Decode of an RPC Query,2
config classification: shellcode-detect,Executable code was detected,1
config classification: string-detect,A suspicious string was detected,3
config classification: suspicious-filename-detect,A suspicious filename was detected,2
config classification: suspicious-login,An attempted login using a suspicious username was detected,2
config classification: system-call-detect,A system call was detected,2
config classification: tcp-connection,A TCP connection was detected,4
config classification: trojan-activity,A Network Trojan was detected, 1
config classification: unusual-client-port-connection,A client was using an unusual port,2
config classification: network-scan,Detection of a Network Scan,3
config classification: denial-of-service,Detection of a Denial of Service Attack,2
config classification: non-standard-protocol,Detection of a non-standard protocol or event,2
config classification: protocol-command-decode,Generic Protocol Command Decode,3
config classification: web-application-activity,access to a potentially vulnerable web application,2
config classification: web-application-attack,Web Application Attack,1
config classification: misc-activity,Misc activity,3
config classification: misc-attack,Misc Attack,2
config classification: icmp-event,Generic ICMP event,3
config classification: inappropriate-content,Inappropriate Content was Detected,1
config classification: policy-violation,Potential Corporate Privacy Violation,1
config classification: default-login-attempt,Attempt to login by a default username and password,2
# Update
config classification: targeted-activity,Targeted Malicious Activity was Detected,1
config classification: exploit-kit,Exploit Kit Activity Detected,1
config classification: external-ip-check,Device Retrieving External IP Address Detected,2
config classification: domain-c2,Domain Observed Used for C2 Detected,1
config classification: pup-activity,Possibly Unwanted Program Detected,2
config classification: credential-theft,Successful Credential Theft Detected,1
config classification: social-engineering,Possible Social Engineering Attempted,2
config classification: coin-mining,Crypto Currency Mining Activity Detected,2
config classification: command-and-control,Malware Command and Control Activity Detected,1

View File

@@ -129,6 +129,13 @@ surithresholding:
- group: 940
- template: jinja
suriclassifications:
file.managed:
- name: /opt/so/conf/suricata/classification.config
- source: salt://suricata/classification/classification.config
- 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') %}

View File

@@ -1,5 +1,16 @@
suricata:
enabled: False
pcap:
filesize: 1000mb
maxsize: 25
compression: "none"
lz4-checksum: "no"
lz4-level: 8
filename: "%n/so-pcap.%t"
mode: "multi"
use-stream-depth: "no"
conditional: "all"
dir: "/nsm/suripcap"
config:
threading:
set-cpu-affinity: "no"

View File

@@ -27,11 +27,13 @@ so-suricata:
- binds:
- /opt/so/conf/suricata/suricata.yaml:/etc/suricata/suricata.yaml:ro
- /opt/so/conf/suricata/threshold.conf:/etc/suricata/threshold.conf:ro
- /opt/so/conf/suricata/classification.config:/etc/suricata/classification.config:ro
- /opt/so/conf/suricata/rules:/etc/suricata/rules:ro
- /opt/so/log/suricata/:/var/log/suricata/:rw
- /nsm/suricata/:/nsm/:rw
- /nsm/suricata/extracted:/var/log/suricata//filestore:rw
- /opt/so/conf/suricata/bpf:/etc/suricata/bpf:ro
- /nsm/suripcap/:/nsm/suripcap:rw
{% if DOCKER.containers['so-suricata'].custom_bind_mounts %}
{% for BIND in DOCKER.containers['so-suricata'].custom_bind_mounts %}
- {{ BIND }}
@@ -49,10 +51,12 @@ so-suricata:
- file: surithresholding
- file: /opt/so/conf/suricata/rules/
- file: /opt/so/conf/suricata/bpf
- file: suriclassifications
- require:
- file: suriconfig
- file: surithresholding
- file: suribpf
- file: suriclassifications
delete_so-suricata_so-status.disabled:
file.uncomment:

View File

@@ -7,6 +7,7 @@
{% from 'suricata/map.jinja' import SURICATAMERGED %}
include:
- suricata.pcap
{% if SURICATAMERGED.enabled and GLOBALS.role != 'so-import' %}
- suricata.enabled
{% elif GLOBALS.role == 'so-import' %}

View File

@@ -8,6 +8,24 @@
{% set surimeta_evelog_index = [] %}
{% set surimeta_filestore_index = [] %}
{# before we change outputs back to list, enable pcap-log if suricata is the pcapengine #}
{% if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %}
{% 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}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'lz4-checksum': SURICATAMERGED.pcap['lz4-checksum']}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'lz4-level': SURICATAMERGED.pcap['lz4-level']}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'filename': SURICATAMERGED.pcap.filename}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'limit': SURICATAMERGED.pcap.filesize}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'mode': SURICATAMERGED.pcap.mode}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'use-stream-depth': SURICATAMERGED.pcap['use-stream-depth']}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'conditional': SURICATAMERGED.pcap.conditional}) %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'dir': SURICATAMERGED.pcap.dir}) %}
{# multiply maxsize by 1000 since it is saved in GB, i.e. 52 = 52000MB. filesize is also saved in MB and we strip the MB and convert to int #}
{% set maxfiles = (SURICATAMERGED.pcap.maxsize * 1000 / (SURICATAMERGED.pcap.filesize[:-2] | int) / SURICATAMERGED.config['af-packet'].threads | int) | round | int %}
{% do SURICATAMERGED.config.outputs['pcap-log'].update({'max-files': maxfiles}) %}
{% endif %}
{# suricata.config.af-packet has to be rewritten here since we cant display '- interface' in the ui #}
{# we are limited to only one iterface #}
{% load_yaml as afpacket %}

28
salt/suricata/pcap.sls Normal file
View File

@@ -0,0 +1,28 @@
{% from 'vars/globals.map.jinja' import GLOBALS %}
{% from 'suricata/map.jinja' import SURICATAMERGED %}
# This directory needs to exist regardless of whether SURIPCAP is enabled or not, in order for
# Sensoroni to be able to look at old Suricata PCAP data
suripcapdir:
file.directory:
- name: /nsm/suripcap
- user: 940
- group: 939
- mode: 775
- makedirs: True
{% if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %}
{# there should only be 1 interface in af-packet so we can just reference the first list item #}
{% for i in range(1, SURICATAMERGED.config['af-packet'][0].threads + 1) %}
suripcapthread{{i}}dir:
file.directory:
- name: /nsm/suripcap/{{i}}
- user: 940
- group: 939
- mode: 775
{% endfor %}
{% endif %}

View File

@@ -11,6 +11,60 @@ suricata:
multiline: True
title: SIDS
helpLink: suricata.html
classification:
classification__config:
description: Classifications config file.
file: True
global: True
multiline: True
title: Classifications
helpLink: suricata.html
pcap:
filesize:
description: Max file size for individual PCAP files written by Suricata. Increasing this number could improve write performance at the expense of pcap retrieval times.
advanced: True
helplink: suricata.html
maxsize:
description: Size in GB for total usage size of PCAP on disk.
helplink: suricata.html
compression:
description: Enable compression of Suricata PCAP.
advanced: True
helpLink: suricata.html
lz4-checksum:
description: Enable PCAP lz4 checksum.
advanced: True
helpLink: suricata.html
lz4-level:
description: lz4 compression level of PCAP. 0 for no compression 16 for max compression.
advanced: True
helpLink: suricata.html
filename:
description: Filename output for Suricata PCAP.
advanced: True
readonly: True
helpLink: suricata.html
mode:
description: Suricata PCAP mode. Currently only multi is supported.
advanced: True
readonly: True
helpLink: suricata.html
use-stream-depth:
description: Set to "no" to ignore the stream depth and capture the entire flow. Set this to "yes" to truncate the flow based on the stream depth.
advanced: True
regex: ^(yes|no)$
regexFailureMessage: You must enter either yes or no.
helpLink: suricata.html
conditional:
description: Set to "all" to capture PCAP for all flows. Set to "alerts" to capture PCAP just for alerts or set to "tag" to capture PCAP for just tagged rules.
regex: ^(all|alerts|tag)$
regexFailureMessage: You must enter either all, alert or tag.
helpLink: suricata.html
dir:
description: Parent directory to store PCAP.
advanced: True
readonly: True
helpLink: suricata.html
config:
af-packet:
interface:
@@ -44,6 +98,7 @@ suricata:
set-cpu-affinity:
description: Bind(yes) or unbind(no) management and worker threads to a core or range of cores.
regex: ^(yes|no)$
regexFailureMessage: You must enter either yes or no.
helpLink: suricata.html
cpu-affinity:
management-cpu-set:
@@ -153,6 +208,12 @@ suricata:
header:
description: Header name where the actual IP address will be reported.
helpLink: suricata.html
pcap-log:
enabled:
description: This value is ignored by SO. pcapengine in globals takes precidence.
readonly: True
helpLink: suricata.html
advanced: True
asn1-max-frames:
description: Maximum nuber of asn1 frames to decode.
helpLink: suricata.html
@@ -209,6 +270,9 @@ suricata:
memcap:
description: Can be specified in kb,mb,gb.
helpLink: suricata.html
depth:
description: Controls how far into a stream that reassembly is done.
helpLink: suricata.html
host:
hash-size:
description: Hash size in bytes.

View File

@@ -41,6 +41,8 @@ tgraf_sync_script_{{script}}:
- mode: 770
- template: jinja
- source: salt://telegraf/scripts/{{script}}
- defaults:
GLOBALS: {{ GLOBALS }}
{% endfor %}
telegraf_sbin:

View File

@@ -14,4 +14,11 @@
{% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('zeekloss.sh') %}
{% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('zeekcaptureloss.sh') %}
{% endif %}
{% from 'pcap/config.map.jinja' import PCAPMERGED %}
{# PCAPMERGED.enabled is set false in soc ui or if suricata is the pcap engine #}
{% if not PCAPMERGED.enabled %}
{% do TELEGRAFMERGED.scripts[GLOBALS.role.split('-')[1]].remove('stenoloss.sh') %}
{% endif %}
{% endif %}

View File

@@ -5,13 +5,17 @@
# https://securityonion.net/license; you may not use this file except in compliance with the
# Elastic License 2.0.
{%- if GLOBALS.pcap_engine in ["SURICATA", "TRANSITION"] %}
PCAPLOC=/host/nsm/suripcap
{%- else %}
PCAPLOC=/host/nsm/pcap
{%- endif %}
# if this script isn't already running
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
# Get the data
OLDPCAP=$(find /host/nsm/pcap -type f -exec stat -c'%n %Z' {} + | sort | grep -v "\." | head -n 1 | awk {'print $2'})
OLDPCAP=$(find $PCAPLOC -type f -exec stat -c'%n %Z' {} + | sort | grep -v "/\." | head -n 1 | awk {'print $2'})
DATE=$(date +%s)
AGE=$(($DATE - $OLDPCAP))

View File

@@ -10,8 +10,8 @@
# if this script isn't already running
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
CHECKIT=$(grep "Thread 0" /var/log/stenographer/stenographer.log |tac |head -2|wc -l)
STENOGREP=$(grep "Thread 0" /var/log/stenographer/stenographer.log |tac |head -2)
CHECKIT=$(grep "Thread 0 stats" /var/log/stenographer/stenographer.log |tac |head -2|wc -l)
STENOGREP=$(grep "Thread 0 stats" /var/log/stenographer/stenographer.log |tac |head -2)
declare RESULT=($STENOGREP)

View File

@@ -1,5 +1,6 @@
{% import 'vars/init.map.jinja' as INIT %}
{% from 'docker/docker.map.jinja' import DOCKER %}
{% from 'global/map.jinja' import GLOBALMERGED %}
{% from 'vars/' ~ INIT.GRAINS.role.split('-')[1] ~ '.map.jinja' import ROLE_GLOBALS %} {# role is so-role so we have to split off the 'so' #}
@@ -7,6 +8,7 @@
set GLOBALS = {
'hostname': INIT.GRAINS.nodename,
'is_manager': false,
'is_sensor': false,
'manager': INIT.GRAINS.master,
'minion_id': INIT.GRAINS.id,
'main_interface': INIT.PILLAR.host.mainint,
@@ -20,6 +22,7 @@
'influxdb_host': INIT.PILLAR.global.influxdb_host,
'manager_ip': INIT.PILLAR.global.managerip,
'md_engine': INIT.PILLAR.global.mdengine,
'pcap_engine': GLOBALMERGED.pcapengine,
'pipeline': INIT.PILLAR.global.pipeline,
'so_version': INIT.PILLAR.global.soversion,
'so_docker_gateway': DOCKER.gateway,
@@ -61,5 +64,8 @@
{% do GLOBALS.update({'is_manager': true}) %}
{% endif %}
{% if GLOBALS.role in GLOBALS.sensor_roles %}
{% do GLOBALS.update({'is_sensor': true}) %}
{% endif %}
{% do salt['defaults.merge'](GLOBALS, ROLE_GLOBALS, merge_lists=False, in_place=True) %}

View File

@@ -1812,7 +1812,7 @@ repo_sync_local() {
mkdir -p /nsm/repo
mkdir -p /opt/so/conf/reposync/cache
echo "https://repo.securityonion.net/file/so-repo/prod/2.4/oracle/9" > /opt/so/conf/reposync/mirror.txt
echo "https://so-repo-east.s3.us-east-005.backblazeb2.com/prod/2.4/oracle/9" >> /opt/so/conf/reposync/mirror.txt
echo "https://repo-alt.securityonion.net/prod/2.4/oracle/9" >> /opt/so/conf/reposync/mirror.txt
echo "[main]" > /opt/so/conf/reposync/repodownload.conf
echo "gpgcheck=1" >> /opt/so/conf/reposync/repodownload.conf
echo "installonly_limit=3" >> /opt/so/conf/reposync/repodownload.conf

View File

@@ -687,10 +687,8 @@ if ! [[ -f $install_opt_file ]]; then
logCmd "so-minion -o=setup"
title "Creating Global SLS"
if [[ $is_airgap ]]; then
# Airgap Rules
airgap_rules
fi
manager_pillar

View File

@@ -195,10 +195,12 @@ whiptail_create_web_user() {
[ -n "$TESTING" ] && return
WEBUSER=$(whiptail --title "$whiptail_title" --inputbox \
"Please enter an email address to create an administrator account for the Security Onion Console (SOC) web interface.\n\nThis will also be used for Elasticsearch and Kibana." 12 60 "$1" 3>&1 1>&2 2>&3)
"Please enter an email address to create an administrator account for the Security Onion Console (SOC) web interface.\n\nThis will also be used for Elasticsearch and Kibana.\n\nMust only include letters, numbers, or + - _ % . @ characters. All capitalized letters will be converted to lowercase." 15 60 "$1" 3>&1 1>&2 2>&3)
local exitstatus=$?
whiptail_check_exitstatus $exitstatus
WEBUSER=${WEBUSER,,}
}
whiptail_create_web_user_password1() {

Binary file not shown.