From 34a5985311bd64ccb30aab66eac4eaf2a7694262 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Thu, 16 May 2024 21:14:57 -0400 Subject: [PATCH 1/7] Create tpm enrollment script Signed-off-by: reyesj2 <94730068+reyesj2@users.noreply.github.com> --- salt/common/tools/sbin/so-luks-tpm-enroll | 60 +++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 salt/common/tools/sbin/so-luks-tpm-enroll diff --git a/salt/common/tools/sbin/so-luks-tpm-enroll b/salt/common/tools/sbin/so-luks-tpm-enroll new file mode 100644 index 000000000..f08fe5e0b --- /dev/null +++ b/salt/common/tools/sbin/so-luks-tpm-enroll @@ -0,0 +1,60 @@ +#!/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." + +# This script is intended to be used in the case the ISO install did not properly setup TPM decrypt for LUKS partitions at boot. + +check_for_tpm() { + echo -n "Checking for TPM: " + if [ -d /sys/class/tpm/tpm0 ]; then + echo -e "tpm0 found." + TPM="yes" + # Check if TPM is using sha1 or sha256 + if [ -d /sys/class/tpm/tpm0/pcr-sha1 ]; then + echo -e "TPM is using sha1.\n" + TPM_PCR="sha1" + elif [ -d /sys/class/tpm/tpm0/pcr-sha256 ]; then + echo -e "TPM is using sha256.\n" + TPM_PCR="sha256" + fi + else + echo -e "No TPM found.\n" + exit 1 + fi +} + +check_for_luks_partitions() { + echo "Checking for LUKS partitions" + for part in $(lsblk -o NAME,FSTYPE -ln | grep crypto_LUKS | awk '{print $1}'); do + echo "Found LUKS partition: $part" + LUKS_PARTITIONS+=("$part") + done + if [ ${#LUKS_PARTITIONS[@]} -eq 0 ]; then + echo -e "No LUKS partitions found.\n" + exit 1 + fi + echo "" +} + +enroll_tpm_in_luks() { + read -s -p "Enter the LUKS passphrase used during ISO install: " LUKS_PASSPHRASE + echo "" + for part in "${LUKS_PARTITIONS[@]}"; do + echo "Enrolling TPM for LUKS device: /dev/$part" + if [ "$TPM_PCR" == "sha1" ]; then + clevis luks bind -d /dev/$part tpm2 '{"pcr_bank":"sha1","pcr_ids":"7"}' <<< $LUKS_PASSPHRASE + elif [ "$TPM_PCR" == "sha256" ]; then + clevis luks bind -d /dev/$part tpm2 '{"pcr_bank":"sha256","pcr_ids":"7"}' <<< $LUKS_PASSPHRASE + fi + done + echo "Running dracut" + dracut -fv --no-kernel +} + +check_for_tpm +check_for_luks_partitions +enroll_tpm_in_luks +echo -e "\nTPM enrollment complete. Reboot the system to verify the TPM is correctly decrypting the LUKS partition(s) at boot.\n" \ No newline at end of file From d9edff38df40ebe31618c311049a455f4feb8798 Mon Sep 17 00:00:00 2001 From: weslambert Date: Fri, 17 May 2024 16:10:10 -0400 Subject: [PATCH 2/7] Create compile report for SOC integrity check --- salt/strelka/compile_yara/compile_yara.py | 41 +++++++++++++++++++---- 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/salt/strelka/compile_yara/compile_yara.py b/salt/strelka/compile_yara/compile_yara.py index b6fa95899..cac60ad60 100644 --- a/salt/strelka/compile_yara/compile_yara.py +++ b/salt/strelka/compile_yara/compile_yara.py @@ -3,10 +3,13 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0. +import argparse +import glob +import hashlib +import json import os import yara -import glob -import json +from datetime import datetime from concurrent.futures import ThreadPoolExecutor def check_syntax(rule_file): @@ -25,19 +28,24 @@ def compile_yara_rules(rules_dir): files_to_compile = {} removed_count = 0 success_count = 0 - + # Use ThreadPoolExecutor to parallelize syntax checks with ThreadPoolExecutor() as executor: results = executor.map(check_syntax, rule_files) - + # Collect yara files and prepare for batch compilation + ts = str(datetime.utcnow().isoformat()) + failure_ids = [] + success_ids = [] for success, rule_file, error_message in results: + rule_id = os.path.splitext(os.path.basename(rule_file))[0] if success: files_to_compile[os.path.basename(rule_file)] = rule_file success_count += 1 + success_ids.append(rule_id) else: + failure_ids.append(rule_id) # Extract just the UUID from the rule file name - rule_id = os.path.splitext(os.path.basename(rule_file))[0] log_entry = { "event_module": "soc", "event_dataset": "soc.detections", @@ -55,16 +63,37 @@ def compile_yara_rules(rules_dir): removed_count += 1 # Compile all remaining valid rules into a single file + compiled_sha256="" if files_to_compile: compiled_rules = yara.compile(filepaths=files_to_compile) compiled_rules.save(compiled_rules_path) print(f"All remaining rules compiled and saved into {compiled_rules_path}") + # Hash file + with open(compiled_rules_path, 'rb') as hash_file: + compiled_sha256=hashlib.sha256(hash_file.read()).hexdigest() # Remove the rules.compiled if there aren't any files to be compiled else: if os.path.exists(compiled_rules_path): os.remove(compiled_rules_path) + # Create compilation report + compilation_report = { + "timestamp": ts, + "compiled_sha256": compiled_sha256, + "failure": failure_ids, + "success": success_ids + } + + # Write total + with open('/opt/sensoroni/logs/detections_yara_compilation-total.log', 'w+') as report_file: + json.dump(compilation_report, report_file) + # Print summary of compilation results print(f"Summary: {success_count} rules compiled successfully, {removed_count} rules removed due to errors.") -compile_yara_rules("/opt/sensoroni/yara/rules/") +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Compile YARA rules from the specified directory") + parser.add_argument("rules_dir", help="Directory containing YARA rules to compile") + args = parser.parse_args() + +compile_yara_rules(args.rules_dir) From 0cc57fc24092145839fbee701867ef3132f6add1 Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Fri, 17 May 2024 15:47:23 -0600 Subject: [PATCH 3/7] Change Compilation Report Path Move compilation report path to /opt/so/state and mount that foulder in SOC --- salt/soc/enabled.sls | 1 + salt/strelka/compile_yara/compile_yara.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/soc/enabled.sls b/salt/soc/enabled.sls index 990bf210c..4d4b5f6fd 100644 --- a/salt/soc/enabled.sls +++ b/salt/soc/enabled.sls @@ -46,6 +46,7 @@ so-soc: - /opt/so/saltstack:/opt/so/saltstack:rw - /opt/so/conf/soc/migrations:/opt/so/conf/soc/migrations:rw - /nsm/backup/detections-migration:/nsm/backup/detections-migration:ro + - /opt/so/state:/opt/so/state:rw - extra_hosts: {% for node in DOCKER_EXTRA_HOSTS %} {% for hostname, ip in node.items() %} diff --git a/salt/strelka/compile_yara/compile_yara.py b/salt/strelka/compile_yara/compile_yara.py index cac60ad60..09e3f4680 100644 --- a/salt/strelka/compile_yara/compile_yara.py +++ b/salt/strelka/compile_yara/compile_yara.py @@ -85,7 +85,7 @@ def compile_yara_rules(rules_dir): } # Write total - with open('/opt/sensoroni/logs/detections_yara_compilation-total.log', 'w+') as report_file: + with open('/opt/so/state/detections_yara_compilation-total.log', 'w+') as report_file: json.dump(compilation_report, report_file) # Print summary of compilation results From fcc72a4f4ec9d31843bd7e620223735cc649a222 Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Mon, 20 May 2024 11:23:25 -0600 Subject: [PATCH 4/7] Add Default IntegrityCheck Frequency Values --- salt/soc/defaults.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/salt/soc/defaults.yaml b/salt/soc/defaults.yaml index 1f9fe686b..0113f22cc 100644 --- a/salt/soc/defaults.yaml +++ b/salt/soc/defaults.yaml @@ -1305,6 +1305,7 @@ soc: reposFolder: /opt/sensoroni/sigma/repos rulesFingerprintFile: /opt/sensoroni/fingerprints/sigma.fingerprint stateFilePath: /opt/sensoroni/fingerprints/elastalertengine.state + integrityCheckFrequencySeconds: 600 rulesRepos: default: - repo: https://github.com/Security-Onion-Solutions/securityonion-resources @@ -1383,6 +1384,7 @@ soc: community: true yaraRulesFolder: /opt/sensoroni/yara/rules stateFilePath: /opt/sensoroni/fingerprints/strelkaengine.state + integrityCheckFrequencySeconds: 600 suricataengine: allowRegex: '' autoUpdateEnabled: true @@ -1393,6 +1395,7 @@ soc: denyRegex: '' rulesFingerprintFile: /opt/sensoroni/fingerprints/emerging-all.fingerprint stateFilePath: /opt/sensoroni/fingerprints/suricataengine.state + integrityCheckFrequencySeconds: 600 client: enableReverseLookup: false docsUrl: /docs/ From 6fac6eebceeacc74b6b595e9c7eedf26fa907305 Mon Sep 17 00:00:00 2001 From: reyesj2 <94730068+reyesj2@users.noreply.github.com> Date: Mon, 20 May 2024 14:37:54 -0400 Subject: [PATCH 5/7] Helper script for enrolling tpm into luks Signed-off-by: reyesj2 <94730068+reyesj2@users.noreply.github.com> --- .../{so-luks-tpm-enroll => so-luks-tpm-regen} | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) rename salt/common/tools/sbin/{so-luks-tpm-enroll => so-luks-tpm-regen} (67%) diff --git a/salt/common/tools/sbin/so-luks-tpm-enroll b/salt/common/tools/sbin/so-luks-tpm-regen similarity index 67% rename from salt/common/tools/sbin/so-luks-tpm-enroll rename to salt/common/tools/sbin/so-luks-tpm-regen index f08fe5e0b..50058b504 100644 --- a/salt/common/tools/sbin/so-luks-tpm-enroll +++ b/salt/common/tools/sbin/so-luks-tpm-regen @@ -5,7 +5,33 @@ # https://securityonion.net/license; you may not use this file except in compliance with the # Elastic License 2.0." +set -e # This script is intended to be used in the case the ISO install did not properly setup TPM decrypt for LUKS partitions at boot. +if [ -z $NOROOT ]; then + # Check for prerequisites + if [ "$(id -u)" -ne 0 ]; then + echo "This script must be run using sudo!" + exit 1 + fi +fi +ENROLL_TPM=N + +while [[ $# -gt 0 ]]; do + case $1 in + --enroll-tpm) + ENROLL_TPM=Y + ;; + *) + echo "Usage: $0 [options]" + echo "" + echo "where options are:" + echo " --enroll-tpm for when TPM enrollment was not selected during ISO install." + echo "" + exit 1 + ;; + esac + shift +done check_for_tpm() { echo -n "Checking for TPM: " @@ -50,11 +76,23 @@ enroll_tpm_in_luks() { clevis luks bind -d /dev/$part tpm2 '{"pcr_bank":"sha256","pcr_ids":"7"}' <<< $LUKS_PASSPHRASE fi done - echo "Running dracut" - dracut -fv --no-kernel + } + +regenerate_tpm_enrollment_token() { + for part in "${LUKS_PARTITIONS[@]}"; do + clevis luks regen -d /dev/$part -s 1 -q + done } check_for_tpm check_for_luks_partitions -enroll_tpm_in_luks -echo -e "\nTPM enrollment complete. Reboot the system to verify the TPM is correctly decrypting the LUKS partition(s) at boot.\n" \ No newline at end of file + +if [[ $ENROLL_TPM == "Y" ]]; then + enroll_tpm_in_luks +else + regenerate_tpm_enrollment_token +fi + +echo "Running dracut" +dracut -fv +echo -e "\nTPM configuration complete. Reboot the system to verify the TPM is correctly decrypting the LUKS partition(s) at boot.\n" \ No newline at end of file From 026023fd0a2c1643b5972d2198391c33972ba602 Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Mon, 20 May 2024 14:35:11 -0600 Subject: [PATCH 6/7] Annotate integrityCheckFrequencySeconds per det engine --- salt/soc/soc_soc.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/salt/soc/soc_soc.yaml b/salt/soc/soc_soc.yaml index bc1c49185..1e6a915b0 100644 --- a/salt/soc/soc_soc.yaml +++ b/salt/soc/soc_soc.yaml @@ -113,6 +113,9 @@ soc: global: True advanced: True helpLink: sigma.html + integrityCheckFrequencySeconds: + description: 'How often the ElastAlert integrity checker runs (in seconds). This verifies the integrity of deployed rules.' + global: True rulesRepos: default: &eerulesRepos description: "Custom Git repos to pull Sigma rules from. 'license' field is required, 'folder' is optional. 'community' disables some management options for the imported rules - they can't be deleted or edited, just tuned, duplicated and Enabled | Disabled." @@ -211,6 +214,9 @@ soc: global: True advanced: True helpLink: yara.html + integrityCheckFrequencySeconds: + description: 'How often the Strelka integrity checker runs (in seconds). This verifies the integrity of deployed rules.' + global: True rulesRepos: default: &serulesRepos description: "Custom Git repos to pull YARA rules from. 'license' field is required, 'folder' is optional. 'community' disables some management options for the imported rules - they can't be deleted or edited, just tuned, duplicated and Enabled | Disabled." @@ -235,6 +241,9 @@ soc: global: True advanced: True helpLink: suricata.html + integrityCheckFrequencySeconds: + description: 'How often the Suricata integrity checker runs (in seconds). This verifies the integrity of deployed rules.' + global: True client: enableReverseLookup: description: Set to true to enable reverse DNS lookups for IP addresses in the SOC UI. From 6e97c39f5886c4e6816fd82c2472961f775c4a30 Mon Sep 17 00:00:00 2001 From: Corey Ogburn Date: Mon, 20 May 2024 14:52:05 -0600 Subject: [PATCH 7/7] Marked as Advanced --- salt/soc/soc_soc.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/salt/soc/soc_soc.yaml b/salt/soc/soc_soc.yaml index 1e6a915b0..0cbb99e62 100644 --- a/salt/soc/soc_soc.yaml +++ b/salt/soc/soc_soc.yaml @@ -116,6 +116,7 @@ soc: integrityCheckFrequencySeconds: description: 'How often the ElastAlert integrity checker runs (in seconds). This verifies the integrity of deployed rules.' global: True + advanced: True rulesRepos: default: &eerulesRepos description: "Custom Git repos to pull Sigma rules from. 'license' field is required, 'folder' is optional. 'community' disables some management options for the imported rules - they can't be deleted or edited, just tuned, duplicated and Enabled | Disabled." @@ -217,6 +218,7 @@ soc: integrityCheckFrequencySeconds: description: 'How often the Strelka integrity checker runs (in seconds). This verifies the integrity of deployed rules.' global: True + advanced: True rulesRepos: default: &serulesRepos description: "Custom Git repos to pull YARA rules from. 'license' field is required, 'folder' is optional. 'community' disables some management options for the imported rules - they can't be deleted or edited, just tuned, duplicated and Enabled | Disabled." @@ -244,6 +246,7 @@ soc: integrityCheckFrequencySeconds: description: 'How often the Suricata integrity checker runs (in seconds). This verifies the integrity of deployed rules.' global: True + advanced: True client: enableReverseLookup: description: Set to true to enable reverse DNS lookups for IP addresses in the SOC UI.