mirror of
https://github.com/Security-Onion-Solutions/securityonion.git
synced 2025-12-06 17:22:49 +01:00
Merge pull request #12296 from Security-Onion-Solutions/cogburn/detection_playbooks
Cogburn/detection playbooks
This commit is contained in:
@@ -117,6 +117,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
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"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"
|
||||
},
|
||||
"note": {
|
||||
"type": "text"
|
||||
},
|
||||
"engine": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"_meta": {
|
||||
"ecs_version": "1.12.2"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"template": {},
|
||||
"version": 1,
|
||||
"_meta": {
|
||||
"description": "default settings for common Security Onion Detections indices"
|
||||
}
|
||||
}
|
||||
@@ -103,55 +103,6 @@ rules_dir:
|
||||
- group: socore
|
||||
- makedirs: True
|
||||
|
||||
{% if STRELKAMERGED.rules.enabled %}
|
||||
|
||||
strelkarepos:
|
||||
file.managed:
|
||||
- name: /opt/so/conf/strelka/repos.txt
|
||||
- source: salt://strelka/rules/repos.txt.jinja
|
||||
- template: jinja
|
||||
- defaults:
|
||||
STRELKAREPOS: {{ STRELKAMERGED.rules.repos }}
|
||||
- makedirs: True
|
||||
|
||||
strelka-yara-update:
|
||||
{% if MANAGERMERGED.reposync.enabled and not GLOBALS.airgap %}
|
||||
cron.present:
|
||||
{% else %}
|
||||
cron.absent:
|
||||
{% endif %}
|
||||
- user: socore
|
||||
- name: '/usr/sbin/so-yara-update >> /opt/so/log/yarasync/yara-update.log 2>&1'
|
||||
- identifier: strelka-yara-update
|
||||
- hour: '7'
|
||||
- minute: '1'
|
||||
|
||||
strelka-yara-download:
|
||||
{% if MANAGERMERGED.reposync.enabled and not GLOBALS.airgap %}
|
||||
cron.present:
|
||||
{% else %}
|
||||
cron.absent:
|
||||
{% endif %}
|
||||
- user: socore
|
||||
- name: '/usr/sbin/so-yara-download >> /opt/so/log/yarasync/yara-download.log 2>&1'
|
||||
- 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
|
||||
- onchanges:
|
||||
- file: yara_update_scripts
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% else %}
|
||||
|
||||
{{sls}}_state_not_allowed:
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
NOROOT=1
|
||||
. /usr/sbin/so-common
|
||||
|
||||
{%- set proxy = salt['pillar.get']('manager:proxy') %}
|
||||
{%- set noproxy = salt['pillar.get']('manager:no_proxy', '') %}
|
||||
|
||||
# Download the rules from the internet
|
||||
{%- if proxy %}
|
||||
export http_proxy={{ proxy }}
|
||||
export https_proxy={{ proxy }}
|
||||
export no_proxy="{{ noproxy }}"
|
||||
{%- endif %}
|
||||
|
||||
repos="/opt/so/conf/strelka/repos.txt"
|
||||
output_dir=/nsm/rules/yara
|
||||
gh_status=$(curl -s -o /dev/null -w "%{http_code}" https://github.com)
|
||||
clone_dir="/tmp"
|
||||
if [ "$gh_status" == "200" ] || [ "$gh_status" == "301" ]; then
|
||||
|
||||
while IFS= read -r repo; do
|
||||
if ! $(echo "$repo" | grep -qE '^#'); then
|
||||
# Remove old repo if existing bc of previous error condition or unexpected disruption
|
||||
repo_name=`echo $repo | awk -F '/' '{print $NF}'`
|
||||
[ -d $output_dir/$repo_name ] && rm -rf $output_dir/$repo_name
|
||||
|
||||
# Clone repo and make appropriate directories for rules
|
||||
git clone $repo $clone_dir/$repo_name
|
||||
echo "Analyzing rules from $clone_dir/$repo_name..."
|
||||
mkdir -p $output_dir/$repo_name
|
||||
# Ensure a copy of the license is available for the rules
|
||||
[ -f $clone_dir/$repo_name/LICENSE ] && cp $clone_dir/$repo_name/LICENSE $output_dir/$repo_name
|
||||
|
||||
# Copy over rules
|
||||
for i in $(find $clone_dir/$repo_name -name "*.yar*"); do
|
||||
rule_name=$(echo $i | awk -F '/' '{print $NF}')
|
||||
cp $i $output_dir/$repo_name
|
||||
done
|
||||
rm -rf $clone_dir/$repo_name
|
||||
fi
|
||||
done < $repos
|
||||
|
||||
echo "Done!"
|
||||
|
||||
/usr/sbin/so-yara-update
|
||||
|
||||
else
|
||||
echo "Server returned $gh_status status code."
|
||||
echo "No connectivity to Github...exiting..."
|
||||
exit 1
|
||||
fi
|
||||
@@ -1,41 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Copyright Security Onion Solutions LLC and/or licensed to Security Onion Solutions LLC under one
|
||||
# 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.
|
||||
|
||||
NOROOT=1
|
||||
. /usr/sbin/so-common
|
||||
|
||||
echo "Starting to check for yara rule updates at $(date)..."
|
||||
|
||||
newcounter=0
|
||||
excludedcounter=0
|
||||
excluded_rules=({{ EXCLUDEDRULES | join(' ') }})
|
||||
|
||||
# Pull down the SO Rules
|
||||
SORULEDIR=/nsm/rules/yara
|
||||
OUTPUTDIR=/opt/so/saltstack/local/salt/strelka/rules
|
||||
|
||||
mkdir -p $OUTPUTDIR
|
||||
# remove all rules prior to copy so we can clear out old rules
|
||||
rm -f $OUTPUTDIR/*
|
||||
|
||||
for i in $(find $SORULEDIR -name "*.yar" -o -name "*.yara"); do
|
||||
rule_name=$(echo $i | awk -F '/' '{print $NF}')
|
||||
if [[ ! "${excluded_rules[*]}" =~ ${rule_name} ]]; then
|
||||
echo "Adding rule: $rule_name..."
|
||||
cp $i $OUTPUTDIR/$rule_name
|
||||
((newcounter++))
|
||||
else
|
||||
echo "Excluding rule: $rule_name..."
|
||||
((excludedcounter++))
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$newcounter" -gt 0 ] || [ "$excludedcounter" -gt 0 ];then
|
||||
echo "$newcounter rules added."
|
||||
echo "$excludedcounter rule(s) excluded."
|
||||
fi
|
||||
|
||||
echo "Finished rule updates at $(date)..."
|
||||
@@ -114,6 +114,13 @@ socuploaddir:
|
||||
- group: 939
|
||||
- makedirs: True
|
||||
|
||||
socsigmarepo:
|
||||
file.directory:
|
||||
- name: /opt/so/rules
|
||||
- user: 939
|
||||
- group: 939
|
||||
- mode: 775
|
||||
|
||||
{% else %}
|
||||
|
||||
{{sls}}_state_not_allowed:
|
||||
|
||||
14
salt/soc/files/bin/compile_yara.py
Normal file
14
salt/soc/files/bin/compile_yara.py
Normal 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])
|
||||
@@ -50,16 +50,6 @@ backend_taste:
|
||||
- user: 939
|
||||
- group: 939
|
||||
|
||||
{% if STRELKAMERGED.rules.enabled %}
|
||||
strelkarules:
|
||||
file.recurse:
|
||||
- name: /opt/so/conf/strelka/rules
|
||||
- source: salt://strelka/rules
|
||||
- user: 939
|
||||
- group: 939
|
||||
- clean: True
|
||||
{% endif %}
|
||||
|
||||
{% else %}
|
||||
|
||||
{{sls}}_state_not_allowed:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user