Merge pull request #7853 from Security-Onion-Solutions/dev

2.3.120
This commit is contained in:
Mike Reeves
2022-04-25 11:33:05 -04:00
committed by GitHub
123 changed files with 2116 additions and 1704 deletions

546
.github/.gitleaks.toml vendored Normal file
View File

@@ -0,0 +1,546 @@
title = "gitleaks config"
# Gitleaks rules are defined by regular expressions and entropy ranges.
# Some secrets have unique signatures which make detecting those secrets easy.
# Examples of those secrets would be GitLab Personal Access Tokens, AWS keys, and GitHub Access Tokens.
# All these examples have defined prefixes like `glpat`, `AKIA`, `ghp_`, etc.
#
# Other secrets might just be a hash which means we need to write more complex rules to verify
# that what we are matching is a secret.
#
# Here is an example of a semi-generic secret
#
# discord_client_secret = "8dyfuiRyq=vVc3RRr_edRk-fK__JItpZ"
#
# We can write a regular expression to capture the variable name (identifier),
# the assignment symbol (like '=' or ':='), and finally the actual secret.
# The structure of a rule to match this example secret is below:
#
# Beginning string
# quotation
# │ End string quotation
# │ │
# ▼ ▼
# (?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9=_\-]{32})['\"]
#
# ▲ ▲ ▲
# │ │ │
# │ │ │
# identifier assignment symbol
# Secret
#
[[rules]]
id = "gitlab-pat"
description = "GitLab Personal Access Token"
regex = '''glpat-[0-9a-zA-Z\-\_]{20}'''
[[rules]]
id = "aws-access-token"
description = "AWS"
regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}'''
# Cryptographic keys
[[rules]]
id = "PKCS8-PK"
description = "PKCS8 private key"
regex = '''-----BEGIN PRIVATE KEY-----'''
[[rules]]
id = "RSA-PK"
description = "RSA private key"
regex = '''-----BEGIN RSA PRIVATE KEY-----'''
[[rules]]
id = "OPENSSH-PK"
description = "SSH private key"
regex = '''-----BEGIN OPENSSH PRIVATE KEY-----'''
[[rules]]
id = "PGP-PK"
description = "PGP private key"
regex = '''-----BEGIN PGP PRIVATE KEY BLOCK-----'''
[[rules]]
id = "github-pat"
description = "GitHub Personal Access Token"
regex = '''ghp_[0-9a-zA-Z]{36}'''
[[rules]]
id = "github-oauth"
description = "GitHub OAuth Access Token"
regex = '''gho_[0-9a-zA-Z]{36}'''
[[rules]]
id = "SSH-DSA-PK"
description = "SSH (DSA) private key"
regex = '''-----BEGIN DSA PRIVATE KEY-----'''
[[rules]]
id = "SSH-EC-PK"
description = "SSH (EC) private key"
regex = '''-----BEGIN EC PRIVATE KEY-----'''
[[rules]]
id = "github-app-token"
description = "GitHub App Token"
regex = '''(ghu|ghs)_[0-9a-zA-Z]{36}'''
[[rules]]
id = "github-refresh-token"
description = "GitHub Refresh Token"
regex = '''ghr_[0-9a-zA-Z]{76}'''
[[rules]]
id = "shopify-shared-secret"
description = "Shopify shared secret"
regex = '''shpss_[a-fA-F0-9]{32}'''
[[rules]]
id = "shopify-access-token"
description = "Shopify access token"
regex = '''shpat_[a-fA-F0-9]{32}'''
[[rules]]
id = "shopify-custom-access-token"
description = "Shopify custom app access token"
regex = '''shpca_[a-fA-F0-9]{32}'''
[[rules]]
id = "shopify-private-app-access-token"
description = "Shopify private app access token"
regex = '''shppa_[a-fA-F0-9]{32}'''
[[rules]]
id = "slack-access-token"
description = "Slack token"
regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})?'''
[[rules]]
id = "stripe-access-token"
description = "Stripe"
regex = '''(?i)(sk|pk)_(test|live)_[0-9a-z]{10,32}'''
[[rules]]
id = "pypi-upload-token"
description = "PyPI upload token"
regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}'''
[[rules]]
id = "gcp-service-account"
description = "Google (GCP) Service-account"
regex = '''\"type\": \"service_account\"'''
[[rules]]
id = "heroku-api-key"
description = "Heroku API Key"
regex = ''' (?i)(heroku[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})['\"]'''
secretGroup = 3
[[rules]]
id = "slack-web-hook"
description = "Slack Webhook"
regex = '''https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}'''
[[rules]]
id = "twilio-api-key"
description = "Twilio API Key"
regex = '''SK[0-9a-fA-F]{32}'''
[[rules]]
id = "age-secret-key"
description = "Age secret key"
regex = '''AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}'''
[[rules]]
id = "facebook-token"
description = "Facebook token"
regex = '''(?i)(facebook[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-f0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "twitter-token"
description = "Twitter token"
regex = '''(?i)(twitter[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-f0-9]{35,44})['\"]'''
secretGroup = 3
[[rules]]
id = "adobe-client-id"
description = "Adobe Client ID (Oauth Web)"
regex = '''(?i)(adobe[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-f0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "adobe-client-secret"
description = "Adobe Client Secret"
regex = '''(p8e-)(?i)[a-z0-9]{32}'''
[[rules]]
id = "alibaba-access-key-id"
description = "Alibaba AccessKey ID"
regex = '''(LTAI)(?i)[a-z0-9]{20}'''
[[rules]]
id = "alibaba-secret-key"
description = "Alibaba Secret Key"
regex = '''(?i)(alibaba[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{30})['\"]'''
secretGroup = 3
[[rules]]
id = "asana-client-id"
description = "Asana Client ID"
regex = '''(?i)(asana[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9]{16})['\"]'''
secretGroup = 3
[[rules]]
id = "asana-client-secret"
description = "Asana Client Secret"
regex = '''(?i)(asana[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "atlassian-api-token"
description = "Atlassian API token"
regex = '''(?i)(atlassian[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{24})['\"]'''
secretGroup = 3
[[rules]]
id = "bitbucket-client-id"
description = "Bitbucket client ID"
regex = '''(?i)(bitbucket[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "bitbucket-client-secret"
description = "Bitbucket client secret"
regex = '''(?i)(bitbucket[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9_\-]{64})['\"]'''
secretGroup = 3
[[rules]]
id = "beamer-api-token"
description = "Beamer API token"
regex = '''(?i)(beamer[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"](b_[a-z0-9=_\-]{44})['\"]'''
secretGroup = 3
[[rules]]
id = "clojars-api-token"
description = "Clojars API token"
regex = '''(CLOJARS_)(?i)[a-z0-9]{60}'''
[[rules]]
id = "contentful-delivery-api-token"
description = "Contentful delivery API token"
regex = '''(?i)(contentful[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9\-=_]{43})['\"]'''
secretGroup = 3
[[rules]]
id = "databricks-api-token"
description = "Databricks API token"
regex = '''dapi[a-h0-9]{32}'''
[[rules]]
id = "discord-api-token"
description = "Discord API key"
regex = '''(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{64})['\"]'''
secretGroup = 3
[[rules]]
id = "discord-client-id"
description = "Discord client ID"
regex = '''(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9]{18})['\"]'''
secretGroup = 3
[[rules]]
id = "discord-client-secret"
description = "Discord client secret"
regex = '''(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9=_\-]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "doppler-api-token"
description = "Doppler API token"
regex = '''['\"](dp\.pt\.)(?i)[a-z0-9]{43}['\"]'''
[[rules]]
id = "dropbox-api-secret"
description = "Dropbox API secret/key"
regex = '''(?i)(dropbox[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{15})['\"]'''
[[rules]]
id = "dropbox--api-key"
description = "Dropbox API secret/key"
regex = '''(?i)(dropbox[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{15})['\"]'''
[[rules]]
id = "dropbox-short-lived-api-token"
description = "Dropbox short lived API token"
regex = '''(?i)(dropbox[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"](sl\.[a-z0-9\-=_]{135})['\"]'''
[[rules]]
id = "dropbox-long-lived-api-token"
description = "Dropbox long lived API token"
regex = '''(?i)(dropbox[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"][a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43}['\"]'''
[[rules]]
id = "duffel-api-token"
description = "Duffel API token"
regex = '''['\"]duffel_(test|live)_(?i)[a-z0-9_-]{43}['\"]'''
[[rules]]
id = "dynatrace-api-token"
description = "Dynatrace API token"
regex = '''['\"]dt0c01\.(?i)[a-z0-9]{24}\.[a-z0-9]{64}['\"]'''
[[rules]]
id = "easypost-api-token"
description = "EasyPost API token"
regex = '''['\"]EZAK(?i)[a-z0-9]{54}['\"]'''
[[rules]]
id = "easypost-test-api-token"
description = "EasyPost test API token"
regex = '''['\"]EZTK(?i)[a-z0-9]{54}['\"]'''
[[rules]]
id = "fastly-api-token"
description = "Fastly API token"
regex = '''(?i)(fastly[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9\-=_]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "finicity-client-secret"
description = "Finicity client secret"
regex = '''(?i)(finicity[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{20})['\"]'''
secretGroup = 3
[[rules]]
id = "finicity-api-token"
description = "Finicity API token"
regex = '''(?i)(finicity[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-f0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "flutterwave-public-key"
description = "Flutterwave public key"
regex = '''FLWPUBK_TEST-(?i)[a-h0-9]{32}-X'''
[[rules]]
id = "flutterwave-secret-key"
description = "Flutterwave secret key"
regex = '''FLWSECK_TEST-(?i)[a-h0-9]{32}-X'''
[[rules]]
id = "flutterwave-enc-key"
description = "Flutterwave encrypted key"
regex = '''FLWSECK_TEST[a-h0-9]{12}'''
[[rules]]
id = "frameio-api-token"
description = "Frame.io API token"
regex = '''fio-u-(?i)[a-z0-9\-_=]{64}'''
[[rules]]
id = "gocardless-api-token"
description = "GoCardless API token"
regex = '''['\"]live_(?i)[a-z0-9\-_=]{40}['\"]'''
[[rules]]
id = "grafana-api-token"
description = "Grafana API token"
regex = '''['\"]eyJrIjoi(?i)[a-z0-9\-_=]{72,92}['\"]'''
[[rules]]
id = "hashicorp-tf-api-token"
description = "HashiCorp Terraform user/org API token"
regex = '''['\"](?i)[a-z0-9]{14}\.atlasv1\.[a-z0-9\-_=]{60,70}['\"]'''
[[rules]]
id = "hubspot-api-token"
description = "HubSpot API token"
regex = '''(?i)(hubspot[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{8}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{12})['\"]'''
secretGroup = 3
[[rules]]
id = "intercom-api-token"
description = "Intercom API token"
regex = '''(?i)(intercom[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9=_]{60})['\"]'''
secretGroup = 3
[[rules]]
id = "intercom-client-secret"
description = "Intercom client secret/ID"
regex = '''(?i)(intercom[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{8}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{12})['\"]'''
secretGroup = 3
[[rules]]
id = "ionic-api-token"
description = "Ionic API token"
regex = '''(?i)(ionic[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"](ion_[a-z0-9]{42})['\"]'''
[[rules]]
id = "linear-api-token"
description = "Linear API token"
regex = '''lin_api_(?i)[a-z0-9]{40}'''
[[rules]]
id = "linear-client-secret"
description = "Linear client secret/ID"
regex = '''(?i)(linear[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-f0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "lob-api-key"
description = "Lob API Key"
regex = '''(?i)(lob[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]((live|test)_[a-f0-9]{35})['\"]'''
secretGroup = 3
[[rules]]
id = "lob-pub-api-key"
description = "Lob Publishable API Key"
regex = '''(?i)(lob[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]((test|live)_pub_[a-f0-9]{31})['\"]'''
secretGroup = 3
[[rules]]
id = "mailchimp-api-key"
description = "Mailchimp API key"
regex = '''(?i)(mailchimp[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-f0-9]{32}-us20)['\"]'''
secretGroup = 3
[[rules]]
id = "mailgun-private-api-token"
description = "Mailgun private API token"
regex = '''(?i)(mailgun[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"](key-[a-f0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "mailgun-pub-key"
description = "Mailgun public validation key"
regex = '''(?i)(mailgun[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"](pubkey-[a-f0-9]{32})['\"]'''
secretGroup = 3
[[rules]]
id = "mailgun-signing-key"
description = "Mailgun webhook signing key"
regex = '''(?i)(mailgun[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})['\"]'''
secretGroup = 3
[[rules]]
id = "mapbox-api-token"
description = "Mapbox API token"
regex = '''(?i)(pk\.[a-z0-9]{60}\.[a-z0-9]{22})'''
[[rules]]
id = "messagebird-api-token"
description = "MessageBird API token"
regex = '''(?i)(messagebird[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{25})['\"]'''
secretGroup = 3
[[rules]]
id = "messagebird-client-id"
description = "MessageBird API client ID"
regex = '''(?i)(messagebird[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{8}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{4}-[a-h0-9]{12})['\"]'''
secretGroup = 3
[[rules]]
id = "new-relic-user-api-key"
description = "New Relic user API Key"
regex = '''['\"](NRAK-[A-Z0-9]{27})['\"]'''
[[rules]]
id = "new-relic-user-api-id"
description = "New Relic user API ID"
regex = '''(?i)(newrelic[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([A-Z0-9]{64})['\"]'''
secretGroup = 3
[[rules]]
id = "new-relic-browser-api-token"
description = "New Relic ingest browser API token"
regex = '''['\"](NRJS-[a-f0-9]{19})['\"]'''
[[rules]]
id = "npm-access-token"
description = "npm access token"
regex = '''['\"](npm_(?i)[a-z0-9]{36})['\"]'''
[[rules]]
id = "planetscale-password"
description = "PlanetScale password"
regex = '''pscale_pw_(?i)[a-z0-9\-_\.]{43}'''
[[rules]]
id = "planetscale-api-token"
description = "PlanetScale API token"
regex = '''pscale_tkn_(?i)[a-z0-9\-_\.]{43}'''
[[rules]]
id = "postman-api-token"
description = "Postman API token"
regex = '''PMAK-(?i)[a-f0-9]{24}\-[a-f0-9]{34}'''
[[rules]]
id = "pulumi-api-token"
description = "Pulumi API token"
regex = '''pul-[a-f0-9]{40}'''
[[rules]]
id = "rubygems-api-token"
description = "Rubygem API token"
regex = '''rubygems_[a-f0-9]{48}'''
[[rules]]
id = "sendgrid-api-token"
description = "SendGrid API token"
regex = '''SG\.(?i)[a-z0-9_\-\.]{66}'''
[[rules]]
id = "sendinblue-api-token"
description = "Sendinblue API token"
regex = '''xkeysib-[a-f0-9]{64}\-(?i)[a-z0-9]{16}'''
[[rules]]
id = "shippo-api-token"
description = "Shippo API token"
regex = '''shippo_(live|test)_[a-f0-9]{40}'''
[[rules]]
id = "linkedin-client-secret"
description = "LinkedIn Client secret"
regex = '''(?i)(linkedin[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z]{16})['\"]'''
secretGroup = 3
[[rules]]
id = "linkedin-client-id"
description = "LinkedIn Client ID"
regex = '''(?i)(linkedin[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{14})['\"]'''
secretGroup = 3
[[rules]]
id = "twitch-api-token"
description = "Twitch API token"
regex = '''(?i)(twitch[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-z0-9]{30})['\"]'''
secretGroup = 3
[[rules]]
id = "typeform-api-token"
description = "Typeform API token"
regex = '''(?i)(typeform[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}(tfp_[a-z0-9\-_\.=]{59})'''
secretGroup = 3
[[rules]]
id = "generic-api-key"
description = "Generic API Key"
regex = '''(?i)((key|api[^Version]|token|secret|password)[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9a-zA-Z\-_=]{8,64})['\"]'''
entropy = 3.7
secretGroup = 4
[allowlist]
description = "global allow lists"
regexes = ['''219-09-9999''', '''078-05-1120''', '''(9[0-9]{2}|666)-\d{2}-\d{4}''']
paths = [
'''gitleaks.toml''',
'''(.*?)(jpg|gif|doc|pdf|bin|svg|socket)$''',
'''(go.mod|go.sum)$''',
'''salt/nginx/files/enterprise-attack.json'''
]

View File

@@ -13,3 +13,5 @@ jobs:
- name: Gitleaks - name: Gitleaks
uses: zricethezav/gitleaks-action@master uses: zricethezav/gitleaks-action@master
with:
config-path: .github/.gitleaks.toml

2
HOTFIX
View File

@@ -1 +1 @@
04012022 04052022 04072022

View File

@@ -1,6 +1,6 @@
## Security Onion 2.3.110 ## Security Onion 2.3.120
Security Onion 2.3.110 is here! Security Onion 2.3.120 is here!
## Screenshots ## Screenshots

View File

@@ -1,18 +1,18 @@
### 2.3.110-20220407 ISO image built on 2022/04/07 ### 2.3.120-20220425 ISO image built on 2022/04/25
### Download and Verify ### Download and Verify
2.3.110-20220407 ISO image: 2.3.120-20220425 ISO image:
https://download.securityonion.net/file/securityonion/securityonion-2.3.110-20220407.iso https://download.securityonion.net/file/securityonion/securityonion-2.3.120-20220425.iso
MD5: 928D589709731EFE9942CA134A6F4C6B MD5: C99729E452B064C471BEF04532F28556
SHA1: CA588A684586CC0D5BDE5E0E41C935FFB939B6C7 SHA1: 60BF07D5347C24568C7B793BFA9792E98479CFBF
SHA256: CBF8743838AF2C7323E629FB6B28D5DD00AE6658B0E29E4D0916411D2D526BD2 SHA256: CD17D0D7CABE21D45FA45E1CF91C5F24EB9608C79FF88480134E5592AFDD696E
Signature for ISO image: Signature for ISO image:
https://github.com/Security-Onion-Solutions/securityonion/raw/master/sigs/securityonion-2.3.110-20220407.iso.sig https://github.com/Security-Onion-Solutions/securityonion/raw/master/sigs/securityonion-2.3.120-20220425.iso.sig
Signing key: Signing key:
https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/master/KEYS https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/master/KEYS
@@ -26,22 +26,22 @@ wget https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/ma
Download the signature file for the ISO: Download the signature file for the ISO:
``` ```
wget https://github.com/Security-Onion-Solutions/securityonion/raw/master/sigs/securityonion-2.3.110-20220407.iso.sig wget https://github.com/Security-Onion-Solutions/securityonion/raw/master/sigs/securityonion-2.3.120-20220425.iso.sig
``` ```
Download the ISO image: Download the ISO image:
``` ```
wget https://download.securityonion.net/file/securityonion/securityonion-2.3.110-20220407.iso wget https://download.securityonion.net/file/securityonion/securityonion-2.3.120-20220425.iso
``` ```
Verify the downloaded ISO image using the signature file: Verify the downloaded ISO image using the signature file:
``` ```
gpg --verify securityonion-2.3.110-20220407.iso.sig securityonion-2.3.110-20220407.iso gpg --verify securityonion-2.3.120-20220425.iso.sig securityonion-2.3.120-20220425.iso
``` ```
The output should show "Good signature" and the Primary key fingerprint should match what's shown below: The output should show "Good signature" and the Primary key fingerprint should match what's shown below:
``` ```
gpg: Signature made Thu 07 Apr 2022 03:30:03 PM EDT using RSA key ID FE507013 gpg: Signature made Mon 25 Apr 2022 08:20:40 AM EDT using RSA key ID FE507013
gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>" gpg: Good signature from "Security Onion Solutions, LLC <info@securityonionsolutions.com>"
gpg: WARNING: This key is not certified with a trusted signature! gpg: WARNING: This key is not certified with a trusted signature!
gpg: There is no indication that the signature belongs to the owner. gpg: There is no indication that the signature belongs to the owner.

View File

@@ -1 +1 @@
2.3.110 2.3.120

View File

@@ -0,0 +1,2 @@
elasticsearch:
index_settings:

View File

@@ -13,4 +13,5 @@ logstash:
- so/9600_output_ossec.conf.jinja - so/9600_output_ossec.conf.jinja
- so/9700_output_strelka.conf.jinja - so/9700_output_strelka.conf.jinja
- so/9800_output_logscan.conf.jinja - so/9800_output_logscan.conf.jinja
- so/9801_output_rita.conf.jinja
- so/9900_output_endgame.conf.jinja - so/9900_output_endgame.conf.jinja

View File

@@ -15,12 +15,12 @@ base:
- logstash - logstash
- logstash.manager - logstash.manager
- logstash.search - logstash.search
- elasticsearch.search - elasticsearch.index_templates
'*_manager': '*_manager':
- logstash - logstash
- logstash.manager - logstash.manager
- elasticsearch.manager - elasticsearch.index_templates
'*_manager or *_managersearch': '*_manager or *_managersearch':
- match: compound - match: compound
@@ -46,7 +46,7 @@ base:
- zeeklogs - zeeklogs
- secrets - secrets
- healthcheck.eval - healthcheck.eval
- elasticsearch.eval - elasticsearch.index_templates
{% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} {% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %}
- elasticsearch.auth - elasticsearch.auth
{% endif %} {% endif %}
@@ -60,7 +60,7 @@ base:
- logstash - logstash
- logstash.manager - logstash.manager
- logstash.search - logstash.search
- elasticsearch.search - elasticsearch.index_templates
{% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} {% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %}
- elasticsearch.auth - elasticsearch.auth
{% endif %} {% endif %}
@@ -106,7 +106,7 @@ base:
'*_searchnode': '*_searchnode':
- logstash - logstash
- logstash.search - logstash.search
- elasticsearch.search - elasticsearch.index_templates
- elasticsearch.auth - elasticsearch.auth
- global - global
- minions.{{ grains.id }} - minions.{{ grains.id }}
@@ -122,7 +122,7 @@ base:
'*_import': '*_import':
- zeeklogs - zeeklogs
- secrets - secrets
- elasticsearch.eval - elasticsearch.index_templates
{% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %} {% if salt['file.file_exists']('/opt/so/saltstack/local/pillar/elasticsearch/auth.sls') %}
- elasticsearch.auth - elasticsearch.auth
{% endif %} {% endif %}
@@ -131,3 +131,6 @@ base:
{% endif %} {% endif %}
- global - global
- minions.{{ grains.id }} - minions.{{ grains.id }}
'*_workstation':
- minions.{{ grains.id }}

View File

@@ -1,6 +1,5 @@
{% set ZEEKVER = salt['pillar.get']('global:mdengine', '') %} {% set ZEEKVER = salt['pillar.get']('global:mdengine', '') %}
{% set WAZUH = salt['pillar.get']('global:wazuh', '0') %} {% set WAZUH = salt['pillar.get']('global:wazuh', '0') %}
{% set THEHIVE = salt['pillar.get']('manager:thehive', '0') %}
{% set PLAYBOOK = salt['pillar.get']('manager:playbook', '0') %} {% set PLAYBOOK = salt['pillar.get']('manager:playbook', '0') %}
{% set FREQSERVER = salt['pillar.get']('manager:freq', '0') %} {% set FREQSERVER = salt['pillar.get']('manager:freq', '0') %}
{% set DOMAINSTATS = salt['pillar.get']('manager:domainstats', '0') %} {% set DOMAINSTATS = salt['pillar.get']('manager:domainstats', '0') %}
@@ -218,6 +217,8 @@
'schedule', 'schedule',
'docker_clean' 'docker_clean'
], ],
'so-workstation': [
],
}, grain='role') %} }, grain='role') %}
{% if FILEBEAT and grains.role in ['so-helixsensor', 'so-eval', 'so-manager', 'so-standalone', 'so-node', 'so-managersearch', 'so-heavynode', 'so-import', 'so-receiver'] %} {% if FILEBEAT and grains.role in ['so-helixsensor', 'so-eval', 'so-manager', 'so-standalone', 'so-node', 'so-managersearch', 'so-heavynode', 'so-import', 'so-receiver'] %}
@@ -273,10 +274,6 @@
{% do allowed_states.append('elastalert') %} {% do allowed_states.append('elastalert') %}
{% endif %} {% endif %}
{% if (THEHIVE != 0) and grains.role in ['so-eval', 'so-manager', 'so-standalone', 'so-managersearch'] %}
{% do allowed_states.append('thehive') %}
{% endif %}
{% if (PLAYBOOK !=0) and grains.role in ['so-eval', 'so-manager', 'so-standalone', 'so-managersearch'] %} {% if (PLAYBOOK !=0) and grains.role in ['so-eval', 'so-manager', 'so-standalone', 'so-managersearch'] %}
{% do allowed_states.append('playbook') %} {% do allowed_states.append('playbook') %}
{% endif %} {% endif %}

View File

@@ -300,8 +300,17 @@ sostatus_log:
- month: '*' - month: '*'
- dayweek: '*' - dayweek: '*'
{% if role in ['eval', 'manager', 'managersearch', 'standalone'] %} {% if role in ['eval', 'manager', 'managersearch', 'standalone'] %}
# Install cron job to determine size of influxdb for telegraf
'du -s -k /nsm/influxdb | cut -f1 > /opt/so/log/telegraf/influxdb_size.log 2>&1':
cron.present:
- user: root
- minute: '*/1'
- hour: '*'
- daymonth: '*'
- month: '*'
- dayweek: '*'
# Lock permissions on the backup directory # Lock permissions on the backup directory
backupdir: backupdir:
file.directory: file.directory:

View File

@@ -15,295 +15,86 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
if [ "$(id -u)" -ne 0 ]; then doc_workstation_url="https://docs.securityonion.net/en/2.3/analyst-vm.html"
echo "This script must be run using sudo!" {# we only want the script to install the workstation if it is CentOS -#}
exit 1 {% if grains.os == 'CentOS' -%}
fi {# if this is a manager -#}
{% if grains.master == grains.id.split('_')|first -%}
INSTALL_LOG=/root/so-analyst-install.log source /usr/sbin/so-common
exec &> >(tee -a "$INSTALL_LOG") pillar_file="/opt/so/saltstack/local/pillar/minions/{{grains.id}}.sls"
log() { if [ -f "$pillar_file" ]; then
msg=$1 if ! grep -q "^workstation:$" "$pillar_file"; then
level=${2:-I}
now=$(TZ=GMT date +"%Y-%m-%dT%H:%M:%SZ")
echo -e "$now | $level | $msg" >> "$INSTALL_LOG" 2>&1
}
error() {
log "$1" "E"
}
info() {
log "$1" "I"
}
title() {
echo -e "\n-----------------------------\n $1\n-----------------------------\n" >> "$INSTALL_LOG" 2>&1
}
logCmd() {
cmd=$1
info "Executing command: $cmd"
$cmd >> "$INSTALL_LOG" 2>&1
}
analyze_system() {
title "System Characteristics"
logCmd "uptime"
logCmd "uname -a"
logCmd "free -h"
logCmd "lscpu"
logCmd "df -h"
logCmd "ip a"
}
analyze_system
OS=$(grep PRETTY_NAME /etc/os-release | grep 'CentOS Linux 7')
if [ $? -ne 0 ]; then
echo "This is an unsupported OS. Please use CentOS 7 to install the analyst node."
exit 1
fi
if [[ "$manufacturer" == "Security Onion Solutions" && "$family" == "Automated" ]]; then
INSTALL=yes
CURLCONTINUE=no
else
INSTALL=''
CURLCONTINUE=''
fi
FIRSTPASS=yes
while [[ $INSTALL != "yes" ]] && [[ $INSTALL != "no" ]]; do
if [[ "$FIRSTPASS" == "yes" ]]; then
clear
echo "###########################################"
echo "## ** W A R N I N G ** ##"
echo "## _______________________________ ##"
echo "## ##"
echo "## Installing the Security Onion ##"
echo "## analyst node on this device will ##"
echo "## make permanent changes to ##"
echo "## the system. ##"
echo "## ##"
echo "###########################################"
echo "Do you wish to continue? (Type the entire word 'yes' to proceed or 'no' to exit)"
FIRSTPASS=no
else
echo "Please type 'yes' to continue or 'no' to exit."
fi
read INSTALL
done
if [[ $INSTALL == "no" ]]; then
echo "Exiting analyst node installation."
exit 0
fi
echo "Testing for internet connection with curl https://securityonionsolutions.com/"
CANCURL=$(curl -sI https://securityonionsolutions.com/ | grep "200 OK")
if [ $? -ne 0 ]; then
FIRSTPASS=yes FIRSTPASS=yes
while [[ $CURLCONTINUE != "yes" ]] && [[ $CURLCONTINUE != "no" ]]; do while [[ $INSTALL != "yes" ]] && [[ $INSTALL != "no" ]]; do
if [[ "$FIRSTPASS" == "yes" ]]; then if [[ "$FIRSTPASS" == "yes" ]]; then
echo "We could not access https://securityonionsolutions.com/." echo "###########################################"
echo "Since packages are downloaded from the internet, internet access is required." echo "## ** W A R N I N G ** ##"
echo "If you would like to ignore this warning and continue anyway, please type 'yes'." echo "## _______________________________ ##"
echo "Otherwise, type 'no' to exit." echo "## ##"
echo "## Installing the Security Onion ##"
echo "## analyst node on this device will ##"
echo "## make permanent changes to ##"
echo "## the system. ##"
echo "## A system reboot will be required ##"
echo "## to complete the install. ##"
echo "## ##"
echo "###########################################"
echo "Do you wish to continue? (Type the entire word 'yes' to proceed or 'no' to exit)"
FIRSTPASS=no FIRSTPASS=no
else else
echo "Please type 'yes' to continue or 'no' to exit." echo "Please type 'yes' to continue or 'no' to exit."
fi fi
read CURLCONTINUE read INSTALL
done done
if [[ "$CURLCONTINUE" == "no" ]]; then
if [[ $INSTALL == "no" ]]; then
echo "Exiting analyst node installation." echo "Exiting analyst node installation."
exit 0 exit 0
fi fi
else
echo "We were able to curl https://securityonionsolutions.com/." # Add workstation pillar to the minion's pillar file
sleep 3 printf '%s\n'\
"workstation:"\
" gui:"\
" enabled: true"\
"" >> "$pillar_file"
echo "Applying the workstation state. This could take some time since there are many packages that need to be installed."
if salt-call state.apply workstation -linfo queue=True; then # make sure the state ran successfully
echo ""
echo "Analyst workstation has been installed!"
echo "Press ENTER to reboot or Ctrl-C to cancel."
read pause
reboot;
else
echo "There was an issue applying the workstation state. Please review the log above or at /opt/so/logs/salt/minion."
fi
else # workstation is already added
echo "The workstation pillar already exists in $pillar_file."
echo "To enable/disable the gui, set 'workstation:gui:enabled' to true or false in $pillar_file."
echo "Additional documentation can be found at $doc_workstation_url."
fi fi
else # if the pillar file doesn't exist
# Install a GUI text editor echo "Could not find $pillar_file and add the workstation pillar."
yum -y install gedit
# Install misc utils
yum -y install wget curl unzip epel-release yum-plugin-versionlock;
# Install xWindows
yum -y groupinstall "X Window System";
yum -y install gnome-classic-session gnome-terminal nautilus-open-terminal control-center liberation-mono-fonts;
unlink /etc/systemd/system/default.target;
ln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target;
yum -y install file-roller
# Install Mono - prereq for NetworkMiner
yum -y install mono-core mono-basic mono-winforms expect
# Install NetworkMiner
yum -y install libcanberra-gtk2;
wget https://www.netresec.com/?download=NetworkMiner -O /tmp/nm.zip;
mkdir -p /opt/networkminer/
unzip /tmp/nm.zip -d /opt/networkminer/;
rm /tmp/nm.zip;
mv /opt/networkminer/NetworkMiner_*/* /opt/networkminer/
chmod +x /opt/networkminer/NetworkMiner.exe;
chmod -R go+w /opt/networkminer/AssembledFiles/;
chmod -R go+w /opt/networkminer/Captures/;
# Create networkminer shim
cat << EOF >> /bin/networkminer
#!/bin/bash
/bin/mono /opt/networkminer/NetworkMiner.exe --noupdatecheck "\$@"
EOF
chmod +x /bin/networkminer
# Convert networkminer ico file to png format
yum -y install ImageMagick
convert /opt/networkminer/networkminericon.ico /opt/networkminer/networkminericon.png
# Create menu entry
cat << EOF >> /usr/share/applications/networkminer.desktop
[Desktop Entry]
Name=NetworkMiner
Comment=NetworkMiner
Encoding=UTF-8
Exec=/bin/networkminer %f
Icon=/opt/networkminer/networkminericon-4.png
StartupNotify=true
Terminal=false
X-MultipleArgs=false
Type=Application
MimeType=application/x-pcap;
Categories=Network;
EOF
# Set default monospace font to Liberation
cat << EOF >> /etc/fonts/local.conf
<match target="pattern">
<test name="family" qual="any">
<string>monospace</string>
</test>
<edit binding="strong" mode="prepend" name="family">
<string>Liberation Mono</string>
</edit>
</match>
EOF
# Install Wireshark for Gnome
yum -y install wireshark-gnome;
# Install dnsiff
yum -y install dsniff;
# Install hping3
yum -y install hping3;
# Install netsed
yum -y install netsed;
# Install ngrep
yum -y install ngrep;
# Install scapy
yum -y install python36-scapy;
# Install ssldump
yum -y install ssldump;
# Install tcpdump
yum -y install tcpdump;
# Install tcpflow
yum -y install tcpflow;
# Install tcpxtract
yum -y install tcpxtract;
# Install whois
yum -y install whois;
# Install foremost
yum -y install https://forensics.cert.org/centos/cert/7/x86_64//foremost-1.5.7-13.1.el7.x86_64.rpm;
# Install chromium
yum -y install chromium;
# Install tcpstat
yum -y install https://github.com/Security-Onion-Solutions/securityonion-docker-rpm/releases/download/securityonion-tcpstat-1.5.0/securityonion-tcpstat-1.5.0.rpm;
# Install tcptrace
yum -y install https://github.com/Security-Onion-Solutions/securityonion-docker-rpm/releases/download/securityonion-tcptrace-6.6.7/securityonion-tcptrace-6.6.7.rpm;
# Install sslsplit
yum -y install libevent;
yum -y install sslsplit;
# Install Bit-Twist
yum -y install https://github.com/Security-Onion-Solutions/securityonion-docker-rpm/releases/download/securityonion-bittwist-2.0.0/securityonion-bittwist-2.0.0.rpm;
# Install chaosreader
yum -y install perl-IO-Compress perl-Net-DNS;
yum -y install https://github.com/Security-Onion-Solutions/securityonion-docker-rpm/releases/download/securityonion-chaosreader-0.95.10/securityonion-chaosreader-0.95.10.rpm;
chmod +x /bin/chaosreader;
if [ -f ../../files/analyst/README ]; then
cp ../../files/analyst/README /;
cp ../../files/analyst/so-wallpaper.jpg /usr/share/backgrounds/;
cp ../../files/analyst/so-lockscreen.jpg /usr/share/backgrounds/;
cp ../../files/analyst/so-login-logo-dark.svg /usr/share/pixmaps/;
else
cp /opt/so/saltstack/default/salt/common/files/analyst/README /;
cp /opt/so/saltstack/default/salt/common/files/analyst/so-wallpaper.jpg /usr/share/backgrounds/;
cp /opt/so/saltstack/default/salt/common/files/analyst/so-lockscreen.jpg /usr/share/backgrounds/;
cp /opt/so/saltstack/default/salt/common/files/analyst/so-login-logo-dark.svg /usr/share/pixmaps/;
fi fi
# Set background wallpaper {#- if this is not a manager #}
cat << EOF >> /etc/dconf/db/local.d/00-background {% else -%}
# Specify the dconf path
[org/gnome/desktop/background]
# Specify the path to the desktop background image file echo "Since this is not a manager, the pillar values to enable analyst workstation must be set manually. Please view the documentation at $doc_workstation_url."
picture-uri='file:///usr/share/backgrounds/so-wallpaper.jpg'
# Specify one of the rendering options for the background image:
# 'none', 'wallpaper', 'centered', 'scaled', 'stretched', 'zoom', 'spanned'
picture-options='zoom'
# Specify the left or top color when drawing gradients or the solid color
primary-color='000000'
# Specify the right or bottom color when drawing gradients
secondary-color='FFFFFF'
EOF
# Set lock screen {#- endif if this is a manager #}
cat << EOF >> /etc/dconf/db/local.d/00-screensaver {% endif -%}
[org/gnome/desktop/session]
idle-delay=uint32 180
[org/gnome/desktop/screensaver] {#- if not CentOS #}
lock-enabled=true {%- else %}
lock-delay=uint32 120
picture-options='zoom'
picture-uri='file:///usr/share/backgrounds/so-lockscreen.jpg'
EOF
cat << EOF >> /etc/dconf/db/local.d/locks/screensaver echo "The Analyst Workstation can only be installed on CentOS. Please view the documentation at $doc_workstation_url."
/org/gnome/desktop/session/idle-delay
/org/gnome/desktop/screensaver/lock-enabled
/org/gnome/desktop/screensaver/lock-delay
EOF
# Do not show the user list at login screen {#- endif grains.os == CentOS #}
cat << EOF >> /etc/dconf/db/local.d/00-login-screen {% endif -%}
[org/gnome/login-screen]
logo='/usr/share/pixmaps/so-login-logo-dark.svg'
disable-user-list=true
EOF
dconf update; exit 0
echo
echo "Analyst workstation has been installed!"
echo "Press ENTER to reboot or Ctrl-C to cancel."
read pause
reboot;

View File

@@ -120,6 +120,30 @@ check_elastic_license() {
fi fi
} }
check_salt_master_status() {
local timeout=$1
echo "Checking if we can talk to the salt master"
salt-call state.show_top concurrent=true
return
}
check_salt_minion_status() {
local timeout=$1
echo "Checking if the salt minion will respond to jobs" >> "$setup_log" 2>&1
salt "$MINION_ID" test.ping -t $timeout > /dev/null 2>&1
local status=$?
if [ $status -gt 0 ]; then
echo " Minion did not respond" >> "$setup_log" 2>&1
else
echo " Received job response from salt minion" >> "$setup_log" 2>&1
fi
return $status
}
copy_new_files() { copy_new_files() {
# Copy new files over to the salt dir # Copy new files over to the salt dir
cd $UPDATE_DIR cd $UPDATE_DIR
@@ -367,6 +391,7 @@ run_check_net_err() {
exit $exit_code exit $exit_code
fi fi
} }
set_cron_service_name() { set_cron_service_name() {
if [[ "$OS" == "centos" ]]; then if [[ "$OS" == "centos" ]]; then
cron_service_name="crond" cron_service_name="crond"

View File

@@ -17,5 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-stop cortex $1 echo "TheHive and its components are no longer part of Security Onion"
/usr/sbin/so-start thehive $1

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-start thehive $1 echo "TheHive and its components are no longer part of Security Onion"

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-stop cortex $1 echo "TheHive and its components are no longer part of Security Onion"

View File

@@ -17,38 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
usage() { echo "TheHive and its components are no longer part of Security Onion"
echo "Usage: $0 <new-user-name>"
echo ""
echo "Adds a new user to Cortex. The new password will be read from STDIN."
exit 1
}
if [ $# -ne 1 ]; then
usage
fi
USER=$1
CORTEX_KEY=$(lookup_pillar cortexorguserkey)
CORTEX_API_URL="$(lookup_pillar url_base)/cortex/api"
CORTEX_ORG_NAME=$(lookup_pillar cortexorgname)
CORTEX_USER=$USER
# Read password for new user from stdin
test -t 0
if [[ $? == 0 ]]; then
echo "Enter new password:"
fi
read -rs CORTEX_PASS
# Create new user in Cortex
resp=$(curl -sk -XPOST -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/user" -d "{\"name\": \"$CORTEX_USER\",\"roles\": [\"read\",\"analyze\",\"orgadmin\"],\"organization\": \"$CORTEX_ORG_NAME\",\"login\": \"$CORTEX_USER\",\"password\" : \"$CORTEX_PASS\" }")
if [[ "$resp" =~ \"status\":\"Ok\" ]]; then
echo "Successfully added user to Cortex."
else
echo "Unable to add user to Cortex; user might already exist."
echo $resp
exit 2
fi

View File

@@ -17,41 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
usage() { echo "TheHive and its components are no longer part of Security Onion"
echo "Usage: $0 <user-name> <true|false>"
echo ""
echo "Enables or disables a user in Cortex."
exit 1
}
if [ $# -ne 2 ]; then
usage
fi
USER=$1
CORTEX_KEY=$(lookup_pillar cortexorguserkey)
CORTEX_API_URL="$(lookup_pillar url_base)/cortex/api"
CORTEX_USER=$USER
case "${2^^}" in
FALSE | NO | 0)
CORTEX_STATUS=Locked
;;
TRUE | YES | 1)
CORTEX_STATUS=Ok
;;
*)
usage
;;
esac
resp=$(curl -sk -XPATCH -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "https://$CORTEX_API_URL/user/${CORTEX_USER}" -d "{\"status\":\"${CORTEX_STATUS}\" }")
if [[ "$resp" =~ \"status\":\"Locked\" || "$resp" =~ \"status\":\"Ok\" ]]; then
echo "Successfully updated user in Cortex."
else
echo "Failed to update user in Cortex."
echo $resp
exit 2
fi

View File

@@ -17,9 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
IP={{ salt['grains.get']('ip_interfaces').get(salt['pillar.get']('sensor:mainint', salt['pillar.get']('manager:mainint', salt['pillar.get']('elasticsearch:mainint', salt['pillar.get']('host:mainint')))))[0] }} IP={{ salt['grains.get']('ip_interfaces').get(salt['pillar.get']('sensor:mainint', salt['pillar.get']('manager:mainint', salt['pillar.get']('elasticsearch:mainint', salt['pillar.get']('host:mainint')))))[0] }}
ESPORT=9200 ESPORT=9200
THEHIVEESPORT=9400
echo "Removing read only attributes for indices..." echo "Removing read only attributes for indices..."
echo echo
{{ ELASTICCURL }} -s -k -XPUT -H "Content-Type: application/json" -L https://$IP:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}' 2>&1 | if grep -q ack; then echo "Index settings updated..."; else echo "There was any issue updating the read-only attribute. Please ensure Elasticsearch is running.";fi; {{ ELASTICCURL }} -s -k -XPUT -H "Content-Type: application/json" -L https://$IP:9200/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}' 2>&1 | if grep -q ack; then echo "Index settings updated..."; else echo "There was any issue updating the read-only attribute. Please ensure Elasticsearch is running.";fi;
{{ ELASTICCURL }} -XPUT -H "Content-Type: application/json" -L http://$IP:9400/_all/_settings -d '{"index.blocks.read_only_allow_delete": null}' 2>&1 | if grep -q ack; then echo "Index settings updated..."; else echo "There was any issue updating the read-only attribute. Please ensure Elasticsearch is running.";fi;

View File

@@ -75,9 +75,6 @@ container_list() {
"so-strelka-manager" "so-strelka-manager"
"so-suricata" "so-suricata"
"so-telegraf" "so-telegraf"
"so-thehive"
"so-thehive-cortex"
"so-thehive-es"
"so-wazuh" "so-wazuh"
"so-zeek" "so-zeek"
) )

View File

@@ -18,7 +18,7 @@
. /usr/sbin/so-common . /usr/sbin/so-common
# Check to see if we are already running # Check to see if we are already running
IS_RUNNING=$(ps aux | pgrep -f "so-playbook-sync" | wc -l) NUM_RUNNING=$(pgrep -cf "/bin/bash /usr/sbin/so-playbook-sync")
[ "$IS_RUNNING" -gt 3 ] && echo "$(date) - Multiple Playbook Sync processes already running...exiting." && exit 0 [ "$NUM_RUNNING" -gt 1 ] && echo "$(date) - $NUM_RUNNING Playbook sync processes running...exiting." && exit 0
docker exec so-soctopus python3 playbook_play-sync.py docker exec so-soctopus python3 playbook_play-sync.py

View File

@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# Usage: so-restart filebeat | kibana | playbook | thehive # Usage: so-restart filebeat | kibana | playbook
. /usr/sbin/so-common . /usr/sbin/so-common
@@ -31,7 +31,6 @@ if [ $# -ge 1 ]; then
fi fi
case $1 in case $1 in
"cortex") docker stop so-thehive-cortex so-thehive && docker rm so-thehive-cortex so-thehive && salt-call state.apply hive queue=True;;
"steno") docker stop so-steno && docker rm so-steno && salt-call state.apply pcap queue=True;; "steno") docker stop so-steno && docker rm so-steno && salt-call state.apply pcap queue=True;;
*) docker stop so-$1 ; docker rm so-$1 ; salt-call state.apply $1 queue=True;; *) docker stop so-$1 ; docker rm so-$1 ; salt-call state.apply $1 queue=True;;
esac esac

View File

@@ -32,11 +32,17 @@ copy_new_files() {
# Copy new files over to the salt dir # Copy new files over to the salt dir
cd /tmp/sogh/securityonion cd /tmp/sogh/securityonion
git checkout $BRANCH git checkout $BRANCH
VERSION=$(cat VERSION)
# We need to overwrite if there is a repo file
if [ -d /opt/so/repo ]; then
tar -czf /opt/so/repo/"$VERSION".tar.gz -C "$(pwd)/.." .
fi
rsync -a salt $default_salt_dir/ rsync -a salt $default_salt_dir/
rsync -a pillar $default_salt_dir/ rsync -a pillar $default_salt_dir/
chown -R socore:socore $default_salt_dir/salt chown -R socore:socore $default_salt_dir/salt
chown -R socore:socore $default_salt_dir/pillar chown -R socore:socore $default_salt_dir/pillar
chmod 755 $default_salt_dir/pillar/firewall/addfirewall.sh chmod 755 $default_salt_dir/pillar/firewall/addfirewall.sh
rm -rf /tmp/sogh rm -rf /tmp/sogh
} }

View File

@@ -115,8 +115,8 @@ clean() {
} }
# Check to see if we are already running # Check to see if we are already running
IS_RUNNING=$(ps aux | pgrep -f "so-sensor-clean" | wc -l) NUM_RUNNING=$(pgrep -cf "/bin/bash /usr/sbin/so-sensor-clean")
[ "$IS_RUNNING" -gt 3 ] && echo "$(date) - $IS_RUNNING sensor clean script processes running...exiting." >>$LOG && exit 0 [ "$NUM_RUNNING" -gt 1 ] && echo "$(date) - $NUM_RUNNING sensor clean script processes running...exiting." >>$LOG && exit 0
if [ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ]; then if [ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ]; then
while [ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ]; do while [ "$CUR_USAGE" -gt "$CRIT_DISK_USAGE" ]; do

View File

@@ -15,7 +15,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# Usage: so-start all | filebeat | kibana | playbook | thehive # Usage: so-start all | filebeat | kibana | playbook
. /usr/sbin/so-common . /usr/sbin/so-common

View File

@@ -17,5 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-stop thehive-es $1 echo "TheHive and its components are no longer part of Security Onion"
/usr/sbin/so-start thehive $1

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-start thehive $1 echo "TheHive and its components are no longer part of Security Onion"

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-stop thehive-es $1 echo "TheHive and its components are no longer part of Security Onion"

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-restart thehive $1 echo "TheHive and its components are no longer part of Security Onion"

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-start thehive $1 echo "TheHive and its components are no longer part of Security Onion"

View File

@@ -17,4 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
/usr/sbin/so-stop thehive $1 echo "TheHive and its components are no longer part of Security Onion"

View File

@@ -17,38 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
usage() { echo "TheHive and its components are no longer part of Security Onion"
echo "Usage: $0 <new-user-name>"
echo ""
echo "Adds a new user to TheHive. The new password will be read from STDIN."
exit 1
}
if [ $# -ne 1 ]; then
usage
fi
USER=$1
THEHIVE_KEY=$(lookup_pillar hivekey)
THEHVIE_API_URL="$(lookup_pillar url_base)/thehive/api"
THEHIVE_USER=$USER
# Read password for new user from stdin
test -t 0
if [[ $? == 0 ]]; then
echo "Enter new password:"
fi
read -rs THEHIVE_PASS
check_password_and_exit "$THEHIVE_PASS"
# Create new user in TheHive
resp=$(curl -sk -XPOST -H "Authorization: Bearer $THEHIVE_KEY" -H "Content-Type: application/json" -L "https://$THEHVIE_API_URL/user" -d "{\"login\" : \"$THEHIVE_USER\",\"name\" : \"$THEHIVE_USER\",\"roles\" : [\"read\",\"alert\",\"write\",\"admin\"],\"preferences\" : \"{}\",\"password\" : \"$THEHIVE_PASS\"}")
if [[ "$resp" =~ \"status\":\"Ok\" ]]; then
echo "Successfully added user to TheHive"
else
echo "Unable to add user to TheHive; user might already exist"
echo $resp
exit 2
fi

View File

@@ -17,41 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
usage() { echo "TheHive and its components are no longer part of Security Onion"
echo "Usage: $0 <user-name> <true|false>"
echo ""
echo "Enables or disables a user in TheHive."
exit 1
}
if [ $# -ne 2 ]; then
usage
fi
USER=$1
THEHIVE_KEY=$(lookup_pillar hivekey)
THEHVIE_API_URL="$(lookup_pillar url_base)/thehive/api"
THEHIVE_USER=$USER
case "${2^^}" in
FALSE | NO | 0)
THEHIVE_STATUS=Locked
;;
TRUE | YES | 1)
THEHIVE_STATUS=Ok
;;
*)
usage
;;
esac
resp=$(curl -sk -XPATCH -H "Authorization: Bearer $THEHIVE_KEY" -H "Content-Type: application/json" -L "https://$THEHVIE_API_URL/user/${THEHIVE_USER}" -d "{\"status\":\"${THEHIVE_STATUS}\" }")
if [[ "$resp" =~ \"status\":\"Locked\" || "$resp" =~ \"status\":\"Ok\" ]]; then
echo "Successfully updated user in TheHive"
else
echo "Failed to update user in TheHive"
echo "$resp"
exit 2
fi

View File

@@ -17,41 +17,4 @@
. /usr/sbin/so-common . /usr/sbin/so-common
usage() { echo "TheHive and its components are no longer part of Security Onion"
echo "Usage: $0 <user-name>"
echo ""
echo "Update password for an existing TheHive user. The new password will be read from STDIN."
exit 1
}
if [ $# -ne 1 ]; then
usage
fi
USER=$1
THEHIVE_KEY=$(lookup_pillar hivekey)
THEHVIE_API_URL="$(lookup_pillar url_base)/thehive/api"
THEHIVE_USER=$USER
# Read password for new user from stdin
test -t 0
if [[ $? == 0 ]]; then
echo "Enter new password:"
fi
read -rs THEHIVE_PASS
if ! check_password "$THEHIVE_PASS"; then
echo "Password is invalid. Please exclude single quotes, double quotes, dollar signs, and backslashes from the password."
exit 2
fi
# Change password for user in TheHive
resp=$(curl -sk -XPOST -H "Authorization: Bearer $THEHIVE_KEY" -H "Content-Type: application/json" -L "https://$THEHVIE_API_URL/user/${THEHIVE_USER}/password/set" -d "{\"password\" : \"$THEHIVE_PASS\"}")
if [[ -z "$resp" ]]; then
echo "Successfully updated TheHive user password"
else
echo "Unable to update TheHive user password"
echo $resp
exit 2
fi

View File

@@ -476,7 +476,6 @@ case "${operation}" in
createUser "$email" "${role:-$DEFAULT_ROLE}" createUser "$email" "${role:-$DEFAULT_ROLE}"
syncAll syncAll
echo "Successfully added new user to SOC" echo "Successfully added new user to SOC"
check_container thehive && echo "$password" | so-thehive-user-add "$email"
check_container fleet && echo "$password" | so-fleet-user-add "$email" check_container fleet && echo "$password" | so-fleet-user-add "$email"
;; ;;
@@ -528,7 +527,6 @@ case "${operation}" in
updateStatus "$email" 'active' updateStatus "$email" 'active'
syncAll syncAll
echo "Successfully enabled user" echo "Successfully enabled user"
check_container thehive && so-thehive-user-enable "$email" true
echo "Fleet user will need to be recreated manually with so-fleet-user-add" echo "Fleet user will need to be recreated manually with so-fleet-user-add"
;; ;;
@@ -540,7 +538,6 @@ case "${operation}" in
updateStatus "$email" 'locked' updateStatus "$email" 'locked'
syncAll syncAll
echo "Successfully disabled user" echo "Successfully disabled user"
check_container thehive && so-thehive-user-enable "$email" false
check_container fleet && so-fleet-user-delete "$email" check_container fleet && so-fleet-user-delete "$email"
;; ;;
@@ -552,7 +549,6 @@ case "${operation}" in
deleteUser "$email" deleteUser "$email"
syncAll syncAll
echo "Successfully deleted user" echo "Successfully deleted user"
check_container thehive && so-thehive-user-enable "$email" false
check_container fleet && so-fleet-user-delete "$email" check_container fleet && so-fleet-user-delete "$email"
;; ;;

View File

@@ -34,7 +34,15 @@ check_err() {
local err_msg="Unhandled error occured, please check $SOUP_LOG for details." local err_msg="Unhandled error occured, please check $SOUP_LOG for details."
[[ $ERR_HANDLED == true ]] && exit $exit_code [[ $ERR_HANDLED == true ]] && exit $exit_code
if [[ $exit_code -ne 0 ]]; then if [[ $exit_code -ne 0 ]]; then
set +e
systemctl_func "start" "$cron_service_name"
systemctl_func "start" "salt-master"
systemctl_func "start" "salt-minion"
enable_highstate
printf '%s' "Soup failed with error $exit_code: " printf '%s' "Soup failed with error $exit_code: "
case $exit_code in case $exit_code in
2) 2)
@@ -91,9 +99,7 @@ check_err() {
if [[ $exit_code -ge 64 && $exit_code -le 113 ]]; then if [[ $exit_code -ge 64 && $exit_code -le 113 ]]; then
echo "$err_msg" echo "$err_msg"
fi fi
set +e
systemctl_func "start" "$cron_service_name"
enable_highstate
exit $exit_code exit $exit_code
fi fi
@@ -416,6 +422,7 @@ preupgrade_changes() {
[[ "$INSTALLEDVERSION" == 2.3.80 ]] && up_to_2.3.90 [[ "$INSTALLEDVERSION" == 2.3.80 ]] && up_to_2.3.90
[[ "$INSTALLEDVERSION" == 2.3.90 || "$INSTALLEDVERSION" == 2.3.91 ]] && up_to_2.3.100 [[ "$INSTALLEDVERSION" == 2.3.90 || "$INSTALLEDVERSION" == 2.3.91 ]] && up_to_2.3.100
[[ "$INSTALLEDVERSION" == 2.3.100 ]] && up_to_2.3.110 [[ "$INSTALLEDVERSION" == 2.3.100 ]] && up_to_2.3.110
[[ "$INSTALLEDVERISON" == 2.3.110 ]] && up_to_2.3.120
true true
} }
@@ -429,6 +436,8 @@ postupgrade_changes() {
[[ "$POSTVERSION" == 2.3.60 || "$POSTVERSION" == 2.3.61 || "$POSTVERSION" == 2.3.70 || "$POSTVERSION" == 2.3.80 ]] && post_to_2.3.90 [[ "$POSTVERSION" == 2.3.60 || "$POSTVERSION" == 2.3.61 || "$POSTVERSION" == 2.3.70 || "$POSTVERSION" == 2.3.80 ]] && post_to_2.3.90
[[ "$POSTVERSION" == 2.3.90 || "$POSTVERSION" == 2.3.91 ]] && post_to_2.3.100 [[ "$POSTVERSION" == 2.3.90 || "$POSTVERSION" == 2.3.91 ]] && post_to_2.3.100
[[ "$POSTVERSION" == 2.3.100 ]] && post_to_2.3.110 [[ "$POSTVERSION" == 2.3.100 ]] && post_to_2.3.110
[[ "$POSTVERSION" == 2.3.110 ]] && post_to_2.3.120
true true
} }
@@ -492,6 +501,14 @@ post_to_2.3.110() {
POSTVERSION=2.3.110 POSTVERSION=2.3.110
} }
post_to_2.3.120() {
echo "Post Processing for 2.3.120"
POSTVERSION=2.3.120
sed -i '/so-thehive-es/d;/so-thehive/d;/so-cortex/d' /opt/so/conf/so-status/so-status.conf
}
stop_salt_master() { stop_salt_master() {
# kill all salt jobs across the grid because the hang indefinitely if they are queued and salt-master restarts # kill all salt jobs across the grid because the hang indefinitely if they are queued and salt-master restarts
set +e set +e
@@ -728,9 +745,6 @@ up_to_2.3.90() {
up_to_2.3.100() { up_to_2.3.100() {
fix_wazuh fix_wazuh
echo "Removing /opt/so/state files for patched Salt InfluxDB module and state. This is due to Salt being upgraded and needing to patch the files again."
rm -vrf /opt/so/state/influxdb_continuous_query.py.patched /opt/so/state/influxdb_retention_policy.py.patched /opt/so/state/influxdbmod.py.patched
echo "Adding receiver hostgroup with so-firewall" echo "Adding receiver hostgroup with so-firewall"
if so-firewall addhostgroup receiver 2>&1 | grep -q 'Already exists'; then if so-firewall addhostgroup receiver 2>&1 | grep -q 'Already exists'; then
echo 'receiver hostgroup already exists' echo 'receiver hostgroup already exists'
@@ -743,11 +757,16 @@ up_to_2.3.100() {
} }
up_to_2.3.110() { up_to_2.3.110() {
echo "Updating to Security Onion 2.3.110"
echo "Updating shard settings for Elasticsearch index templates"
sed -i 's|shards|index_template:\n template:\n settings:\n index:\n number_of_shards|g' /opt/so/saltstack/local/pillar/global.sls sed -i 's|shards|index_template:\n template:\n settings:\n index:\n number_of_shards|g' /opt/so/saltstack/local/pillar/global.sls
} }
up_to_2.3.120() {
# Stop thehive services since these will be broken in .120
so-thehive-stop
so-thehive-es-stop
so-cortex-stop
}
verify_upgradespace() { verify_upgradespace() {
CURRENTSPACE=$(df -BG / | grep -v Avail | awk '{print $4}' | sed 's/.$//') CURRENTSPACE=$(df -BG / | grep -v Avail | awk '{print $4}' | sed 's/.$//')
if [ "$CURRENTSPACE" -lt "10" ]; then if [ "$CURRENTSPACE" -lt "10" ]; then
@@ -770,29 +789,6 @@ upgrade_space() {
fi fi
} }
thehive_maint() {
echo -n "Waiting for TheHive..."
COUNT=0
THEHIVE_CONNECTED="no"
while [[ "$COUNT" -le 240 ]]; do
curl --output /dev/null --silent --head --fail -k "https://localhost/thehive/api/alert"
if [ $? -eq 0 ]; then
THEHIVE_CONNECTED="yes"
echo "connected!"
break
else
((COUNT+=1))
sleep 1
echo -n "."
fi
done
if [ "$THEHIVE_CONNECTED" == "yes" ]; then
echo "Migrating thehive databases if needed."
curl -v -k -XPOST -L "https://localhost/thehive/api/maintenance/migrate" >> "$SOUP_LOG" 2>&1
curl -v -k -XPOST -L "https://localhost/cortex/api/maintenance/migrate" >> "$SOUP_LOG" 2>&1
fi
}
unmount_update() { unmount_update() {
cd /tmp cd /tmp
umount /tmp/soagupdate umount /tmp/soagupdate
@@ -908,6 +904,8 @@ upgrade_salt() {
else else
echo "Salt upgrade success." echo "Salt upgrade success."
echo "" echo ""
echo "Removing /opt/so/state files for patched Salt InfluxDB module and state. This is due to Salt being upgraded and needing to patch the files again."
rm -vrf /opt/so/state/influxdb_continuous_query.py.patched /opt/so/state/influxdb_retention_policy.py.patched /opt/so/state/influxdbmod.py.patched
fi fi
} }
@@ -1037,6 +1035,17 @@ main() {
echo "### Preparing soup at $(date) ###" echo "### Preparing soup at $(date) ###"
echo "" echo ""
set_os
set_cron_service_name
if ! check_salt_master_status; then
echo "Could not talk to salt master"
echo "Please run 'systemctl status salt-master' to ensure the salt-master service is running and check the log at /opt/so/log/salt/master."
echo "SOUP will now attempt to start the salt-master service and exit."
exit 1
fi
echo "This node can communicate with the salt-master."
echo "Checking to see if this is a manager." echo "Checking to see if this is a manager."
echo "" echo ""
require_manager require_manager
@@ -1072,8 +1081,6 @@ main() {
echo "Verifying we have the latest soup script." echo "Verifying we have the latest soup script."
verify_latest_update_script verify_latest_update_script
echo "" echo ""
set_os
set_cron_service_name
set_palette set_palette
check_elastic_license check_elastic_license
echo "" echo ""
@@ -1222,7 +1229,6 @@ main() {
salt-call state.highstate -l info queue=True salt-call state.highstate -l info queue=True
postupgrade_changes postupgrade_changes
[[ $is_airgap -eq 0 ]] && unmount_update [[ $is_airgap -eq 0 ]] && unmount_update
thehive_maint
echo "" echo ""
echo "Upgrade to $NEWVERSION complete." echo "Upgrade to $NEWVERSION complete."

View File

@@ -4067,7 +4067,7 @@ elasticsearch:
field: "@timestamp" field: "@timestamp"
order: desc order: desc
refresh_interval: 30s refresh_interval: 30s
number_of_shards: 1 number_of_shards: 2
number_of_replicas: 0 number_of_replicas: 0
composed_of: composed_of:
- agent-mappings - agent-mappings

View File

@@ -0,0 +1,127 @@
{
"description": "RITA Beacons",
"processors": [
{
"set": {
"field": "_index",
"value": "so-rita",
"override": true
}
},
{
"csv": {
"field": "message",
"target_fields": [
"beacon.score",
"source.ip",
"destination.ip",
"network.connections",
"network.average_bytes",
"beacon.interval.range",
"beacon.size.range",
"beacon.interval.top",
"beacon.size.top",
"beacon.interval.top_count",
"beacon.size.top_count",
"beacon.interval.skew",
"beacon.size.skew",
"beacon.interval.dispersion",
"beacon.size.dispersion",
"network.bytes"
]
}
},
{
"convert": {
"field": "beacon.score",
"type": "float"
}
},
{
"convert": {
"field": "network.connections",
"type": "integer"
}
},
{
"convert": {
"field": "network.average_bytes",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.interval.range",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.size.range",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.interval.top",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.size.top",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.interval.top_count",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.size.top_count",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.interval.skew",
"type": "float"
}
},
{
"convert": {
"field": "beacon.size.skew",
"type": "float"
}
},
{
"convert": {
"field": "beacon.interval.dispersion",
"type": "integer"
}
},
{
"convert": {
"field": "beacon.size.dispersion",
"type": "integer"
}
},
{
"convert": {
"field": "network.bytes",
"type": "integer"
}
},
{ "set": { "if": "ctx.beacon?.score == 1", "field": "dataset", "value": "alert", "override": true }},
{ "set": { "if": "ctx.beacon?.score == 1", "field": "rule.name", "value": "Potential C2 Beacon Activity", "override": true }},
{ "set": { "if": "ctx.beacon?.score == 1", "field": "event.severity", "value": 3, "override": true }},
{
"pipeline": {
"name": "common"
}
}
]
}

View File

@@ -0,0 +1,36 @@
{
"description": "RITA Connections",
"processors": [
{
"set": {
"field": "_index",
"value": "so-rita",
"override": true
}
},
{
"dissect": {
"field": "message",
"pattern": "%{source.ip},%{destination.ip},%{network.port}:%{network.protocol}:%{network.service},%{connection.duration},%{connection.state}"
}
},
{
"convert": {
"field": "connection.duration",
"type": "float"
}
},
{
"set": {
"field": "event.duration",
"value": "{{ connection.duration }}",
"override": true
}
},
{
"pipeline": {
"name": "common"
}
}
]
}

View File

@@ -0,0 +1,39 @@
{
"description": "RITA DNS",
"processors": [
{
"set": {
"field": "_index",
"value": "so-rita",
"override": true
}
},
{
"csv": {
"field": "message",
"target_fields": [
"dns.question.name",
"dns.question.subdomain_count",
"dns.question.count"
]
}
},
{
"convert": {
"field": "dns.question.subdomain_count",
"type": "integer"
}
},
{
"convert": {
"field": "dns.question.count",
"type": "integer"
}
},
{
"pipeline": {
"name": "common"
}
}
]
}

View File

@@ -1,36 +1,157 @@
{ {
"description" : "syslog", "description" : "syslog pipeline",
"processors" : [ "processors" : [
{ {
"dissect": { "dissect": {
"field": "message", "field": "message",
"pattern" : "%{message}", "pattern" : "%{message}",
"on_failure": [ { "drop" : { } } ] "on_failure": [ { "drop" : { } } ]
}, },
"remove": { "remove": {
"field": [ "type", "agent" ], "field": [ "type", "agent" ],
"ignore_failure": true "ignore_failure": true
} }
}, {
"grok": {
"field": "message",
"patterns": [
"^<%{INT:syslog.priority:int}>%{TIMESTAMP_ISO8601:syslog.timestamp} +%{IPORHOST:syslog.host} +%{PROG:syslog.program}(?:\\[%{POSINT:syslog.pid:int}\\])?: %{GREEDYDATA:real_message}$",
"^<%{INT:syslog.priority}>%{DATA:syslog.timestamp} %{WORD:source.application}(\\[%{DATA:pid}\\])?: %{GREEDYDATA:real_message}$",
"^%{SYSLOGTIMESTAMP:syslog.timestamp} %{SYSLOGHOST:syslog.host} %{SYSLOGPROG:syslog.program}: CEF:0\\|%{DATA:vendor}\\|%{DATA:product}\\|%{GREEDYDATA:message2}$"
],
"ignore_failure": true
}
}, },
{ {
"grok": "convert" : {
{ "if": "ctx?.syslog?.priority != null",
"field": "message", "field" : "syslog.priority",
"patterns": [ "type": "integer"
"^<%{INT:syslog.priority}>%{DATA:syslog.timestamp} %{WORD:source.application}(\\[%{DATA:pid}\\])?: %{GREEDYDATA:real_message}$", }
"^%{SYSLOGTIMESTAMP:syslog.timestamp} %{SYSLOGHOST:syslog.host} %{SYSLOGPROG:syslog.program}: CEF:0\\|%{DATA:vendor}\\|%{DATA:product}\\|%{GREEDYDATA:message2}$"
],
"ignore_failure": true
}
}, },
{ "set": { "if": "ctx.source?.application == 'filterlog'", "field": "dataset", "value": "firewall", "ignore_failure": true } }, {
{ "set": { "if": "ctx.vendor != null", "field": "module", "value": "{{ vendor }}", "ignore_failure": true } }, "script": {
{ "set": { "if": "ctx.product != null", "field": "dataset", "value": "{{ product }}", "ignore_failure": true } }, "description": "Map syslog priority into facility and level",
{ "set": { "field": "event.ingested", "value": "{{ @timestamp }}" } }, "lang": "painless",
{ "date": { "if": "ctx.syslog?.timestamp != null", "field": "syslog.timestamp", "target_field": "@timestamp", "formats": ["MMM d HH:mm:ss", "MMM dd HH:mm:ss", "ISO8601", "UNIX"], "ignore_failure": true } }, "params" : {
{ "remove": { "field": ["pid", "program"], "ignore_missing": true, "ignore_failure": true } }, "level": [
{ "pipeline": { "if": "ctx.vendor != null && ctx.product != null", "name": "{{ vendor }}.{{ product }}", "ignore_failure": true } }, "emerg",
{ "pipeline": { "if": "ctx.dataset == 'firewall'", "name": "filterlog", "ignore_failure": true } }, "alert",
{ "pipeline": { "name": "common" } } "crit",
"err",
"warn",
"notice",
"info",
"debug"
],
"facility" : [
"kern",
"user",
"mail",
"daemon",
"auth",
"syslog",
"lpr",
"news",
"uucp",
"cron",
"authpriv",
"ftp",
"ntp",
"security",
"console",
"solaris-cron",
"local0",
"local1",
"local2",
"local3",
"local4",
"local5",
"local6",
"local7"
]
},
"source": "if (ctx['syslog'] != null && ctx['syslog']['priority'] != null) { int p = ctx['syslog']['priority']; int f = p / 8; int l = p - (f * 8); ctx['syslog']['facility_label'] = [ : ]; ctx['syslog']['severity_label'] = [ : ]; ctx['syslog'].put('severity', l); ctx['syslog'].put('severity_label', params.level[l].toUpperCase()); ctx['syslog'].put('facility', f); ctx['syslog'].put('facility_label', params.facility[f].toUpperCase()); }"
}
},
{
"set": {
"if": "ctx.syslog?.host != null",
"field": "host.name",
"value": "{{ syslog.host }}",
"ignore_failure": true
}
}, {
"set": {
"if": "ctx.syslog?.program != null",
"field": "process.name",
"value": "{{ syslog.program }}",
"ignore_failure": true
}
}, {
"set": {
"if": "ctx.syslog?.pid != null",
"field": "process.id",
"value": "{{ syslog.pid }}",
"ignore_failure": true
}
}, {
"set": {
"if": "ctx.source?.application == 'filterlog'",
"field": "dataset",
"value": "firewall",
"ignore_failure": true
}
}, {
"set": {
"if": "ctx.vendor != null",
"field": "module",
"value": "{{ vendor }}",
"ignore_failure": true
}
}, {
"set": {
"if": "ctx.product != null",
"field": "dataset",
"value": "{{ product }}",
"ignore_failure": true
}
}, {
"set": {
"field": "ingest.timestamp",
"value": "{{ @timestamp }}"
}
}, {
"date": {
"if": "ctx.syslog?.timestamp != null",
"field": "syslog.timestamp",
"target_field": "@timestamp",
"formats": ["MMM d HH:mm:ss", "MMM dd HH:mm:ss", "ISO8601", "UNIX"],
"ignore_failure": true
}
}, {
"remove": {
"field": ["pid", "program"],
"ignore_missing": true,
"ignore_failure": true
}
}, {
"pipeline": {
"if": "ctx.vendor != null && ctx.product != null",
"name": "{{ vendor }}.{{ product }}",
"ignore_failure": true
}
}, {
"pipeline": {
"if": "ctx.dataset == 'firewall'",
"name": "filterlog",
"ignore_failure": true
}
}, {
"pipeline": { "name": "common" }
}
] ]
} }

View File

@@ -11,10 +11,17 @@ appender.rolling.name = rolling
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.rolling.layout.type = PatternLayout appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}.log appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}.log.gz
appender.rolling.policies.type = Policies appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 1 appender.rolling.policies.time.interval = 1
appender.rolling.policies.time.modulate = true appender.rolling.policies.time.modulate = true
appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.action.type = Delete
appender.rolling.strategy.action.basepath = /var/log/elasticsearch
appender.rolling.strategy.action.condition.type = IfFileName
appender.rolling.strategy.action.condition.glob = *.gz
appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified
appender.rolling.strategy.action.condition.nested_condition.age = 7D
rootLogger.level = info rootLogger.level = info
rootLogger.appenderRef.rolling.ref = rolling rootLogger.appenderRef.rolling.ref = rolling

View File

@@ -207,6 +207,7 @@ escomponenttemplates:
# Auto-generate templates from defaults file # Auto-generate templates from defaults file
{% for index, settings in ES_INDEX_SETTINGS.items() %} {% for index, settings in ES_INDEX_SETTINGS.items() %}
{% if settings.index_template is defined %}
es_index_template_{{index}}: es_index_template_{{index}}:
file.managed: file.managed:
- name: /opt/so/conf/elasticsearch/templates/index/{{ index }}-template.json - name: /opt/so/conf/elasticsearch/templates/index/{{ index }}-template.json
@@ -216,6 +217,7 @@ es_index_template_{{index}}:
- template: jinja - template: jinja
- onchanges_in: - onchanges_in:
- cmd: so-elasticsearch-templates - cmd: so-elasticsearch-templates
{% endif %}
{% endfor %} {% endfor %}
{% if TEMPLATES %} {% if TEMPLATES %}

View File

@@ -1,7 +1,9 @@
{% import_yaml 'elasticsearch/defaults.yaml' as ESCONFIG with context %} {% import_yaml 'elasticsearch/defaults.yaml' as ESCONFIG with context %}
{%- set ES_INDEX_SETTINGS = salt['pillar.get']('elasticsearch:index_settings', default=ESCONFIG.elasticsearch.index_settings, merge=True) %} {%- set ES_INDEX_SETTINGS = salt['pillar.get']('elasticsearch:index_settings', default=ESCONFIG.elasticsearch.index_settings, merge=True) %}
{% for index, settings in ES_INDEX_SETTINGS.items() %} {% for index, settings in ES_INDEX_SETTINGS.items() %}
{% if settings.index_sorting, False %} {% if settings.index_template is defined %}
{% do settings.index_template.template.settings.index.pop('sort') %} {% if not settings.get('index_sorting', False) | to_bool and settings.index_template.template.settings.index.sort is defined %}
{% do settings.index_template.template.settings.index.pop('sort') %}
{% endif %}
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View File

@@ -60,6 +60,32 @@
}, },
"type": "wildcard" "type": "wildcard"
}, },
"entity_id": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
},
"executable": {
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
},
"ignore_above": 1024,
"type": "keyword"
},
"name": { "name": {
"fields": { "fields": {
"keyword": { "keyword": {
@@ -73,6 +99,133 @@
"ignore_above": 1024, "ignore_above": 1024,
"type": "keyword" "type": "keyword"
}, },
"parent": {
"properties": {
"command_line": {
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"text": {
"type": "match_only_text"
},
"keyword": {
"type": "keyword"
}
},
"type": "wildcard"
},
"entity_id": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
},
"executable": {
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
},
"ignore_above": 1024,
"type": "keyword"
}
}
},
"pe": {
"properties": {
"architecture": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
},
"company": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
},
"description": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
},
"file_version": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
},
"original_file_name": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
},
"product": {
"ignore_above": 1024,
"type": "keyword",
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
}
}
}
},
"pid": { "pid": {
"type": "long", "type": "long",
"fields": { "fields": {
@@ -88,6 +241,19 @@
"type": "keyword" "type": "keyword"
} }
} }
},
"working_directory": {
"fields": {
"security": {
"type": "text",
"analyzer": "es_security_analyzer"
},
"keyword": {
"type": "keyword"
}
},
"ignore_above": 1024,
"type": "keyword"
} }
} }
} }

View File

@@ -33,6 +33,8 @@ while [[ "$COUNT" -le 240 ]]; do
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
ELASTICSEARCH_CONNECTED="yes" ELASTICSEARCH_CONNECTED="yes"
echo "connected!" echo "connected!"
# Check cluster health once connected
so-elasticsearch-query _cluster/health?wait_for_status=yellow > /dev/null 2>&1
break break
else else
((COUNT+=1)) ((COUNT+=1))
@@ -48,7 +50,7 @@ fi
cd ${ELASTICSEARCH_ROLES} cd ${ELASTICSEARCH_ROLES}
echo "Loading templates..." echo "Loading roles..."
for role in *; do for role in *; do
name=$(echo "$role" | cut -d. -f1) name=$(echo "$role" | cut -d. -f1)
so-elasticsearch-query _security/role/$name -XPUT -d @"$role" so-elasticsearch-query _security/role/$name -XPUT -d @"$role"

View File

@@ -30,7 +30,7 @@ echo -n "Waiting for ElasticSearch..."
COUNT=0 COUNT=0
ELASTICSEARCH_CONNECTED="no" ELASTICSEARCH_CONNECTED="no"
while [[ "$COUNT" -le 240 ]]; do while [[ "$COUNT" -le 240 ]]; do
{{ ELASTICCURL }} -k --output /dev/null --silent --head --fail -L https://"$ELASTICSEARCH_HOST":"$ELASTICSEARCH_PORT" so-elasticsearch-query -k --output /dev/null --silent --head --fail
if [ $? -eq 0 ]; then if [ $? -eq 0 ]; then
ELASTICSEARCH_CONNECTED="yes" ELASTICSEARCH_CONNECTED="yes"
echo "connected!" echo "connected!"
@@ -50,21 +50,20 @@ fi
cd ${ELASTICSEARCH_TEMPLATES}/component/ecs cd ${ELASTICSEARCH_TEMPLATES}/component/ecs
echo "Loading ECS component templates..." echo "Loading ECS component templates..."
for i in *; do TEMPLATE=$(echo $i | cut -d '.' -f1); echo "$TEMPLATE-mappings"; {{ ELASTICCURL }} -k ${ELASTICSEARCH_AUTH} -s -XPUT -L https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/_component_template/$TEMPLATE-mappings -H 'Content-Type: application/json' -d@$i 2>/dev/null; echo; done for i in *; do TEMPLATE=$(echo $i | cut -d '.' -f1); echo "$TEMPLATE-mappings"; so-elasticsearch-query _component_template/$TEMPLATE-mappings -d@$i -XPUT 2>/dev/null; echo; done
echo
# Load SO-specific component templates # Load SO-specific component templates
cd ${ELASTICSEARCH_TEMPLATES}/component/so cd ${ELASTICSEARCH_TEMPLATES}/component/so
echo "Loading Security Onion component templates..." echo "Loading Security Onion component templates..."
for i in *; do TEMPLATE=$(echo $i | cut -d '.' -f1); echo "$TEMPLATE"; {{ ELASTICCURL }} -k ${ELASTICSEARCH_AUTH} -s -XPUT -L https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/_component_template/$TEMPLATE -H 'Content-Type: application/json' -d@$i 2>/dev/null; echo; done for i in *; do TEMPLATE=$(echo $i | cut -d '.' -f1); echo "$TEMPLATE"; so-elasticsearch-query _component_template/$TEMPLATE -d@$i -XPUT 2>/dev/null; echo; done
echo echo
# Load SO index templates # Load SO index templates
cd ${ELASTICSEARCH_TEMPLATES}/index cd ${ELASTICSEARCH_TEMPLATES}/index
echo "Loading Security Onion index templates..." echo "Loading Security Onion index templates..."
for i in *; do TEMPLATE=$(echo $i | cut -d '-' -f2); echo "so-$TEMPLATE"; {{ ELASTICCURL }} -k ${ELASTICSEARCH_AUTH} -s -XPUT -L https://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/_index_template/so-$TEMPLATE -H 'Content-Type: application/json' -d@$i 2>/dev/null; echo; done for i in *; do TEMPLATE=$(echo $i | cut -d '-' -f2); echo "so-$TEMPLATE"; so-elasticsearch-query _index_template/so-$TEMPLATE -d@$i -XPUT 2>/dev/null; echo; done
echo echo
cd - >/dev/null cd - >/dev/null

View File

@@ -10,6 +10,7 @@
{%- set ZEEKVER = salt['pillar.get']('global:mdengine', 'COMMUNITY') %} {%- set ZEEKVER = salt['pillar.get']('global:mdengine', 'COMMUNITY') %}
{%- set WAZUHENABLED = salt['pillar.get']('global:wazuh', '0') %} {%- set WAZUHENABLED = salt['pillar.get']('global:wazuh', '0') %}
{%- set STRELKAENABLED = salt['pillar.get']('strelka:enabled', '0') %} {%- set STRELKAENABLED = salt['pillar.get']('strelka:enabled', '0') %}
{%- set RITAENABLED = salt['pillar.get']('rita:enabled', False) -%}
{%- set FLEETMANAGER = salt['pillar.get']('global:fleet_manager', False) -%} {%- set FLEETMANAGER = salt['pillar.get']('global:fleet_manager', False) -%}
{%- set FLEETNODE = salt['pillar.get']('global:fleet_node', False) -%} {%- set FLEETNODE = salt['pillar.get']('global:fleet_node', False) -%}
{%- set FBMEMEVENTS = salt['pillar.get']('filebeat:mem_events', 2048) -%} {%- set FBMEMEVENTS = salt['pillar.get']('filebeat:mem_events', 2048) -%}
@@ -264,6 +265,54 @@ filebeat.inputs:
{%- endif %} {%- endif %}
{%- if RITAENABLED %}
- type: filestream
paths:
- /nsm/rita/beacons.csv
exclude_lines: ['^Score', '^Source', '^Domain', '^No results']
fields:
module: rita
dataset: beacon
category: network
processors:
- drop_fields:
fields: ["source", "prospector", "input", "offset", "beat"]
fields_under_root: true
pipeline: "rita.beacon"
index: "so-rita"
- type: filestream
paths:
- /nsm/rita/long-connections.csv
- /nsm/rita/open-connections.csv
exclude_lines: ['^Source', '^No results']
fields:
module: rita
dataset: connection
category: network
processors:
- drop_fields:
fields: ["source", "prospector", "input", "offset", "beat"]
fields_under_root: true
pipeline: "rita.connection"
index: "so-rita"
- type: filestream
paths:
- /nsm/rita/exploded-dns.csv
exclude_lines: ['^Domain', '^No results']
fields:
module: rita
dataset: dns
category: network
processors:
- drop_fields:
fields: ["source", "prospector", "input", "offset", "beat"]
fields_under_root: true
pipeline: "rita.dns"
index: "so-rita"
{%- endif %}
{%- if grains['role'] in ['so-eval', 'so-standalone', 'so-manager', 'so-managersearch', 'so-import'] %} {%- if grains['role'] in ['so-eval', 'so-standalone', 'so-manager', 'so-managersearch', 'so-import'] %}
- type: log - type: log
paths: paths:

View File

@@ -349,6 +349,9 @@ role:
osquery_endpoint: osquery_endpoint:
portgroups: portgroups:
- {{ portgroups.fleet_api }} - {{ portgroups.fleet_api }}
strelka_frontend:
portgroups:
- {{ portgroups.strelka_frontend }}
syslog: syslog:
portgroups: portgroups:
- {{ portgroups.syslog }} - {{ portgroups.syslog }}
@@ -482,6 +485,9 @@ role:
self: self:
portgroups: portgroups:
- {{ portgroups.syslog}} - {{ portgroups.syslog}}
strelka_frontend:
portgroups:
- {{ portgroups.strelka_frontend }}
INPUT: INPUT:
hostgroups: hostgroups:
anywhere: anywhere:
@@ -511,6 +517,9 @@ role:
self: self:
portgroups: portgroups:
- {{ portgroups.syslog}} - {{ portgroups.syslog}}
strelka_frontend:
portgroups:
- {{ portgroups.strelka_frontend }}
INPUT: INPUT:
hostgroups: hostgroups:
anywhere: anywhere:

View File

@@ -19,11 +19,37 @@
{% set VERSION = salt['pillar.get']('global:soversion', 'HH1.2.2') %} {% set VERSION = salt['pillar.get']('global:soversion', 'HH1.2.2') %}
{% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %} {% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %}
{% set MANAGER = salt['grains.get']('master') %} {% set MANAGER = salt['grains.get']('master') %}
{% set MAININT = salt['pillar.get']('host:mainint') %}
{% set MAINIP = salt['grains.get']('ip_interfaces').get(MAININT)[0] %}
{% set RESTRICTIDHSERVICES = salt['pillar.get']('idh:restrict_management_ip', False) %}
include: include:
- idh.openssh.config - idh.openssh.config
- firewall
# IDH State
# If True, block IDH Services from accepting connections on Managment IP
{% if RESTRICTIDHSERVICES %}
{% from 'idh/opencanary_config.map.jinja' import OPENCANARYCONFIG %}
{% set idh_services = salt['pillar.get']('idh:services', []) %}
{% for service in idh_services %}
{% if service in ["smnp","ntp", "tftp"] %}
{% set proto = 'udp' %}
{% else %}
{% set proto = 'tcp' %}
{% endif %}
block_mgt_ip_idh_services_{{ proto }}_{{ OPENCANARYCONFIG[service~'.port'] }} :
iptables.insert:
- table: filter
- chain: INPUT
- jump: DROP
- position: 1
- proto: {{ proto }}
- dport: {{ OPENCANARYCONFIG[service~'.port'] }}
- destination: {{ MAINIP }}
{% endfor %}
{% endif %}
# Create a config directory # Create a config directory
temp: temp:

View File

@@ -1,4 +1,4 @@
{% set measurements = salt['cmd.shell']('docker exec -t so-influxdb influx -format json -ssl -unsafeSsl -database telegraf -execute "show measurements" 2> /root/measurement_query.log | jq -r .results[0].series[0].values[]?[0] 2>> /root/measurement_query.log') %} {% set measurements = salt['cmd.shell']('docker exec -t so-influxdb influx -format json -ssl -unsafeSsl -database telegraf -execute "show measurements" 2> /root/measurement_query.log | jq -r .results[0].series[0].values[]?[0] 2>> /root/measurement_query.log', shell='/bin/bash') %}
influxdb: influxdb:
retention_policies: retention_policies:

View File

@@ -59,7 +59,7 @@ update() {
IFS=$'\r\n' GLOBIGNORE='*' command eval 'LINES=($(cat $1))' IFS=$'\r\n' GLOBIGNORE='*' command eval 'LINES=($(cat $1))'
for i in "${LINES[@]}"; do for i in "${LINES[@]}"; do
RESPONSE=$({{ ELASTICCURL }} -X PUT "localhost:5601/api/saved_objects/config/7.17.1" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d " $i ") RESPONSE=$({{ ELASTICCURL }} -X PUT "localhost:5601/api/saved_objects/config/7.17.3" -H 'kbn-xsrf: true' -H 'Content-Type: application/json' -d " $i ")
echo $RESPONSE; if [[ "$RESPONSE" != *"\"success\":true"* ]] && [[ "$RESPONSE" != *"updated_at"* ]] ; then RETURN_CODE=1;fi echo $RESPONSE; if [[ "$RESPONSE" != *"\"success\":true"* ]] && [[ "$RESPONSE" != *"updated_at"* ]] ; then RETURN_CODE=1;fi
done done

View File

@@ -1 +1 @@
{"attributes": {"buildNum": 39457,"defaultIndex": "2289a0c0-6970-11ea-a0cd-ffa0f6a1bc29","defaultRoute": "/app/dashboards#/view/a8411b30-6d03-11ea-b301-3d6c35840645","discover:sampleSize": 100,"theme:darkMode": true,"timepicker:timeDefaults": "{\n \"from\": \"now-24h\",\n \"to\": \"now\"\n}"},"coreMigrationVersion": "7.17.1","id": "7.17.1","migrationVersion": {"config": "7.13.0"},"references": [],"type": "config","updated_at": "2021-10-10T10:10:10.105Z","version": "WzI5NzUsMl0="} {"attributes": {"buildNum": 39457,"defaultIndex": "2289a0c0-6970-11ea-a0cd-ffa0f6a1bc29","defaultRoute": "/app/dashboards#/view/a8411b30-6d03-11ea-b301-3d6c35840645","discover:sampleSize": 100,"theme:darkMode": true,"timepicker:timeDefaults": "{\n \"from\": \"now-24h\",\n \"to\": \"now\"\n}"},"coreMigrationVersion": "7.17.3","id": "7.17.3","migrationVersion": {"config": "7.13.0"},"references": [],"type": "config","updated_at": "2021-10-10T10:10:10.105Z","version": "WzI5NzUsMl0="}

View File

@@ -18,7 +18,7 @@ appender.rolling.name = rolling
appender.rolling.fileName = /var/log/logstash/logstash.log appender.rolling.fileName = /var/log/logstash/logstash.log
appender.rolling.layout.type = PatternLayout appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n
appender.rolling.filePattern = /var/log/logstash/logstash-%d{yyyy-MM-dd}.log appender.rolling.filePattern = /var/log/logstash/logstash-%d{yyyy-MM-dd}.log.gz
appender.rolling.policies.type = Policies appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 1 appender.rolling.policies.time.interval = 1
@@ -27,7 +27,7 @@ appender.rolling.strategy.type = DefaultRolloverStrategy
appender.rolling.strategy.action.type = Delete appender.rolling.strategy.action.type = Delete
appender.rolling.strategy.action.basepath = /var/log/logstash appender.rolling.strategy.action.basepath = /var/log/logstash
appender.rolling.strategy.action.condition.type = IfFileName appender.rolling.strategy.action.condition.type = IfFileName
appender.rolling.strategy.action.condition.glob = logstash-*.log appender.rolling.strategy.action.condition.glob = *.gz
appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified appender.rolling.strategy.action.condition.nested_condition.type = IfLastModified
appender.rolling.strategy.action.condition.nested_condition.age = 7D appender.rolling.strategy.action.condition.nested_condition.age = 7D
rootLogger.level = info rootLogger.level = info

View File

@@ -0,0 +1,22 @@
{%- if grains['role'] == 'so-eval' -%}
{%- set ES = salt['pillar.get']('manager:mainip', '') -%}
{%- else %}
{%- set ES = salt['pillar.get']('elasticsearch:mainip', '') -%}
{%- endif %}
{%- set ES_USER = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:user', '') %}
{%- set ES_PASS = salt['pillar.get']('elasticsearch:auth:users:so_elastic_user:pass', '') %}
output {
if [module] =~ "rita" and "import" not in [tags] {
elasticsearch {
pipeline => "%{module}.%{dataset}"
hosts => "{{ ES }}"
{% if salt['pillar.get']('elasticsearch:auth:enabled') is sameas true %}
user => "{{ ES_USER }}"
password => "{{ ES_PASS }}"
{% endif %}
index => "so-rita"
ssl => true
ssl_certificate_verification => false
}
}
}

View File

@@ -334,30 +334,6 @@ http {
} }
{%- endif %} {%- endif %}
location /thehive/ {
proxy_pass http://{{ manager_ip }}:9000/thehive/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_set_header X-Forwarded-Proto $scheme;
}
location /cortex/ {
proxy_pass http://{{ manager_ip }}:9001/cortex/;
proxy_read_timeout 90;
proxy_connect_timeout 90;
proxy_http_version 1.1; # this is essential for chunked responses to work
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy "";
proxy_set_header X-Forwarded-Proto $scheme;
}
location /soctopus/ { location /soctopus/ {
auth_request /auth/sessions/whoami; auth_request /auth/sessions/whoami;

View File

@@ -11,6 +11,7 @@
{% set PYTHON3INFLUX= 'influxdb == ' ~ PYTHONINFLUXVERSION %} {% set PYTHON3INFLUX= 'influxdb == ' ~ PYTHONINFLUXVERSION %}
{% set PYTHON3INFLUXDEPS= ['certifi', 'chardet', 'python-dateutil', 'pytz', 'requests'] %} {% set PYTHON3INFLUXDEPS= ['certifi', 'chardet', 'python-dateutil', 'pytz', 'requests'] %}
{% set PYTHONINSTALLER = 'pip' %} {% set PYTHONINSTALLER = 'pip' %}
{% set SYSTEMD_UNIT_FILE = '/lib/systemd/system/salt-minion.service' %}
{% else %} {% else %}
{% set SPLITCHAR = '-' %} {% set SPLITCHAR = '-' %}
{% set SALTNOTHELD = salt['cmd.run']('yum versionlock list | grep -q salt ; echo $?', python_shell=True) %} {% set SALTNOTHELD = salt['cmd.run']('yum versionlock list | grep -q salt ; echo $?', python_shell=True) %}
@@ -21,6 +22,7 @@
{% set PYTHON3INFLUX= 'securityonion-python3-influxdb' %} {% set PYTHON3INFLUX= 'securityonion-python3-influxdb' %}
{% set PYTHON3INFLUXDEPS= ['python36-certifi', 'python36-chardet', 'python36-dateutil', 'python36-pytz', 'python36-requests'] %} {% set PYTHON3INFLUXDEPS= ['python36-certifi', 'python36-chardet', 'python36-dateutil', 'python36-pytz', 'python36-requests'] %}
{% set PYTHONINSTALLER = 'pkg' %} {% set PYTHONINSTALLER = 'pkg' %}
{% set SYSTEMD_UNIT_FILE = '/usr/lib/systemd/system/salt-minion.service' %}
{% endif %} {% endif %}
{% set INSTALLEDSALTVERSION = salt['pkg.version']('salt-minion').split(SPLITCHAR)[0] %} {% set INSTALLEDSALTVERSION = salt['pkg.version']('salt-minion').split(SPLITCHAR)[0] %}

View File

@@ -3,6 +3,7 @@
{% from 'salt/map.jinja' import INSTALLEDSALTVERSION %} {% from 'salt/map.jinja' import INSTALLEDSALTVERSION %}
{% from 'salt/map.jinja' import SALTNOTHELD %} {% from 'salt/map.jinja' import SALTNOTHELD %}
{% from 'salt/map.jinja' import SALTPACKAGES %} {% from 'salt/map.jinja' import SALTPACKAGES %}
{% from 'salt/map.jinja' import SYSTEMD_UNIT_FILE %}
{% import_yaml 'salt/minion.defaults.yaml' as SALTMINION %} {% import_yaml 'salt/minion.defaults.yaml' as SALTMINION %}
{% set service_start_delay = SALTMINION.salt.minion.service_start_delay %} {% set service_start_delay = SALTMINION.salt.minion.service_start_delay %}
@@ -82,7 +83,7 @@ set_log_levels:
salt_minion_service_unit_file: salt_minion_service_unit_file:
file.managed: file.managed:
- name: /etc/systemd/system/multi-user.target.wants/salt-minion.service - name: {{ SYSTEMD_UNIT_FILE }}
- source: salt://salt/service/salt-minion.service.jinja - source: salt://salt/service/salt-minion.service.jinja
- template: jinja - template: jinja
- defaults: - defaults:
@@ -110,6 +111,7 @@ salt_minion_service:
- file: set_log_levels - file: set_log_levels
- file: salt_minion_service_unit_file - file: salt_minion_service_unit_file
{% endif %} {% endif %}
- order: last
patch_pkg: patch_pkg:

View File

@@ -1,3 +1,3 @@
{ {
"default": ["soc_timestamp", "so_case.title", "so_case.status", "so_case.severity", "so_case.createTime"] "default": ["soc_timestamp", "so_case.title", "so_case.status", "so_case.severity", "so_case.assigneeId", "so_case.createTime"]
} }

View File

@@ -1,5 +1,6 @@
{ {
"default": ["soc_timestamp", "source.ip", "source.port", "destination.ip", "destination.port", "log.id.uid", "network.community_id", "event.dataset" ], "default": ["soc_timestamp", "source.ip", "source.port", "destination.ip", "destination.port", "log.id.uid", "network.community_id", "event.dataset" ],
":kratos:audit": ["soc_timestamp", "http_request.headers.x-real-ip", "identity_id", "http_request.headers.user-agent" ],
"::conn": ["soc_timestamp", "source.ip", "source.port", "destination.ip", "destination.port", "network.transport", "network.protocol", "log.id.uid", "network.community_id" ], "::conn": ["soc_timestamp", "source.ip", "source.port", "destination.ip", "destination.port", "network.transport", "network.protocol", "log.id.uid", "network.community_id" ],
"::dce_rpc": ["soc_timestamp", "source.ip", "source.port", "destination.ip", "destination.port", "dce_rpc.endpoint", "dce_rpc.named_pipe", "dce_rpc.operation", "log.id.uid" ], "::dce_rpc": ["soc_timestamp", "source.ip", "source.port", "destination.ip", "destination.port", "dce_rpc.endpoint", "dce_rpc.named_pipe", "dce_rpc.operation", "log.id.uid" ],
"::dhcp": ["soc_timestamp", "client.address", "server.address", "host.domain", "host.hostname", "dhcp.message_types", "log.id.uid" ], "::dhcp": ["soc_timestamp", "client.address", "server.address", "host.domain", "host.hostname", "dhcp.message_types", "log.id.uid" ],

View File

@@ -1,6 +1,7 @@
[ [
{ "name": "Default Query", "description": "Show all events grouped by the origin host", "query": "* | groupby observer.name"}, { "name": "Default Query", "description": "Show all events grouped by the origin host", "query": "* | groupby observer.name"},
{ "name": "Log Type", "description": "Show all events grouped by module and dataset", "query": "* | groupby event.module event.dataset"}, { "name": "Log Type", "description": "Show all events grouped by module and dataset", "query": "* | groupby event.module event.dataset"},
{ "name": "SOC Auth", "description": "Users authenticated to SOC grouped by IP address and identity", "query": "event.module:kratos AND event.dataset:audit AND msg:authenticated | groupby http_request.headers.x-real-ip identity_id"},
{ "name": "Elastalerts", "description": "", "query": "_type:elastalert | groupby rule.name"}, { "name": "Elastalerts", "description": "", "query": "_type:elastalert | groupby rule.name"},
{ "name": "Alerts", "description": "Show all alerts grouped by alert source", "query": "event.dataset: alert | groupby event.module"}, { "name": "Alerts", "description": "Show all alerts grouped by alert source", "query": "event.dataset: alert | groupby event.module"},
{ "name": "NIDS Alerts", "description": "Show all NIDS alerts grouped by alert", "query": "event.category: network AND event.dataset: alert | groupby rule.category rule.gid rule.uuid rule.name"}, { "name": "NIDS Alerts", "description": "Show all NIDS alerts grouped by alert", "query": "event.category: network AND event.dataset: alert | groupby rule.category rule.gid rule.uuid rule.name"},

View File

@@ -1,8 +1,8 @@
{%- set MANAGERIP = salt['pillar.get']('global:managerip', '') %} {%- set MANAGERIP = salt['pillar.get']('global:managerip', '') %}
{%- set SENSORONIKEY = salt['pillar.get']('global:sensoronikey', '') %} {%- set SENSORONIKEY = salt['pillar.get']('global:sensoronikey', '') %}
{%- set THEHIVEKEY = salt['pillar.get']('global:hivekey', '') %} {%- set THEHIVEKEY = salt['pillar.get']('global:hivekey', '') %}
{%- set THEHIVEURL = salt['pillar.get']('global:hiveurl', '') %}
{%- set PLAYBOOK = salt['pillar.get']('manager:playbook', '0') %} {%- set PLAYBOOK = salt['pillar.get']('manager:playbook', '0') %}
{%- set THEHIVE = salt['pillar.get']('manager:thehive', '0') %}
{%- set FLEETMANAGER = salt['pillar.get']('global:fleet_manager', False) %} {%- set FLEETMANAGER = salt['pillar.get']('global:fleet_manager', False) %}
{%- set FLEETNODE = salt['pillar.get']('global:fleet_node', False) %} {%- set FLEETNODE = salt['pillar.get']('global:fleet_node', False) %}
{%- set GRAFANA = salt['pillar.get']('manager:grafana', '0') %} {%- set GRAFANA = salt['pillar.get']('manager:grafana', '0') %}
@@ -91,7 +91,7 @@
}, },
{%- if CASE_MODULE == 'thehive' and THEHIVEKEY != '' %} {%- if CASE_MODULE == 'thehive' and THEHIVEKEY != '' %}
"thehive": { "thehive": {
"hostUrl": "http://{{ MANAGERIP }}:9000/thehive", "hostUrl": "http://{{ HIVEURL }}:9000/thehive",
"key": "{{ THEHIVEKEY }}", "key": "{{ THEHIVEKEY }}",
"verifyCert": false "verifyCert": false
}, },
@@ -140,9 +140,6 @@
{%- if PLAYBOOK == 0 %} {%- if PLAYBOOK == 0 %}
"toolPlaybook", "toolPlaybook",
{%- endif %} {%- endif %}
{%- if THEHIVE == 0 %}
"toolTheHive",
{%- endif %}
{%- if not FLEETMANAGER and not FLEETNODE %} {%- if not FLEETMANAGER and not FLEETNODE %}
"toolFleet", "toolFleet",
{%- endif %} {%- endif %}

View File

@@ -4,6 +4,5 @@
{ "name": "toolCyberchef", "description": "toolCyberchefHelp", "icon": "fa-external-link-alt", "target": "so-cyberchef", "link": "/cyberchef/" }, { "name": "toolCyberchef", "description": "toolCyberchefHelp", "icon": "fa-external-link-alt", "target": "so-cyberchef", "link": "/cyberchef/" },
{ "name": "toolPlaybook", "description": "toolPlaybookHelp", "icon": "fa-external-link-alt", "target": "so-playbook", "link": "/playbook/projects/detection-playbooks/issues/" }, { "name": "toolPlaybook", "description": "toolPlaybookHelp", "icon": "fa-external-link-alt", "target": "so-playbook", "link": "/playbook/projects/detection-playbooks/issues/" },
{ "name": "toolFleet", "description": "toolFleetHelp", "icon": "fa-external-link-alt", "target": "so-fleet", "link": "/fleet/" }, { "name": "toolFleet", "description": "toolFleetHelp", "icon": "fa-external-link-alt", "target": "so-fleet", "link": "/fleet/" },
{ "name": "toolTheHive", "description": "toolTheHiveHelp", "icon": "fa-external-link-alt", "target": "so-thehive", "link": "/thehive/" },
{ "name": "toolNavigator", "description": "toolNavigatorHelp", "icon": "fa-external-link-alt", "target": "so-navigator", "link": "/navigator/" } { "name": "toolNavigator", "description": "toolNavigatorHelp", "icon": "fa-external-link-alt", "target": "so-navigator", "link": "/navigator/" }
] ]

View File

@@ -1,6 +1,7 @@
{%- set MANAGER = salt['pillar.get']('manager:mainip', '') %} {%- set MANAGER = salt['pillar.get']('manager:mainip', '') %}
{%- set URLBASE = salt['pillar.get']('global:url_base', '') %} {%- set URLBASE = salt['pillar.get']('global:url_base', '') %}
{%- set HIVEKEY = salt['pillar.get']('global:hivekey', '') %} {%- set HIVEKEY = salt['pillar.get']('global:hivekey', '') %}
{%- set THEHIVEURL = salt['pillar.get']('global:hiveurl', '') %}
{%- set CORTEXKEY = salt['pillar.get']('global:cortexorguserkey', '') %} {%- set CORTEXKEY = salt['pillar.get']('global:cortexorguserkey', '') %}
{%- set PLAYBOOK_KEY = salt['pillar.get']('playbook:api_key', '') %} {%- set PLAYBOOK_KEY = salt['pillar.get']('playbook:api_key', '') %}
{%- if salt['pillar.get']('elasticsearch:auth:enabled') is sameas true %} {%- if salt['pillar.get']('elasticsearch:auth:enabled') is sameas true %}
@@ -21,7 +22,7 @@ es_verifycert = no
[cortex] [cortex]
auto_analyze_alerts = no auto_analyze_alerts = no
cortex_url = https://{{URLBASE}}/cortex/ cortex_url = https://{{THEHIVEURL}}/cortex/
cortex_key = {{ CORTEXKEY }} cortex_key = {{ CORTEXKEY }}
supported_analyzers = Urlscan_io_Search,CERTatPassiveDNS supported_analyzers = Urlscan_io_Search,CERTatPassiveDNS
@@ -42,7 +43,7 @@ grr_user = YOURGRRUSER
grr_pass = YOURGRRPASS grr_pass = YOURGRRPASS
[hive] [hive]
hive_url = https://{{URLBASE}}/thehive/ hive_url = https://{{THEHIVEURL}}/thehive/
hive_key = {{ HIVEKEY }} hive_key = {{ HIVEKEY }}
hive_tlp = 3 hive_tlp = 3
hive_verifycert = no hive_verifycert = no

View File

@@ -36,12 +36,12 @@ suricatagroup:
- name: suricata - name: suricata
- gid: 940 - gid: 940
# Add ES user # Add Suricata user
suricata: suricata:
user.present: user.present:
- uid: 940 - uid: 940
- gid: 940 - gid: 940
- home: /opt/so/conf/suricata - home: /nsm/suricata
- createhome: False - createhome: False
suridir: suridir:

View File

@@ -13,7 +13,12 @@ tgraflogdir:
file.directory: file.directory:
- name: /opt/so/log/telegraf - name: /opt/so/log/telegraf
- makedirs: True - makedirs: True
- user: 939
- group: 939
- recurse:
- user
- group
tgrafetcdir: tgrafetcdir:
file.directory: file.directory:
- name: /opt/so/conf/telegraf/etc - name: /opt/so/conf/telegraf/etc
@@ -29,7 +34,7 @@ tgrafsyncscripts:
- name: /opt/so/conf/telegraf/scripts - name: /opt/so/conf/telegraf/scripts
- user: root - user: root
- group: 939 - group: 939
- file_mode: 700 - file_mode: 770
- template: jinja - template: jinja
- source: salt://telegraf/scripts - source: salt://telegraf/scripts
{% if salt['pillar.get']('global:mdengine', 'ZEEK') == 'SURICATA' %} {% if salt['pillar.get']('global:mdengine', 'ZEEK') == 'SURICATA' %}
@@ -57,6 +62,8 @@ node_config:
so-telegraf: so-telegraf:
docker_container.running: docker_container.running:
- image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-telegraf:{{ VERSION }} - image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-telegraf:{{ VERSION }}
- user: 939
- group_add: 939,920
- environment: - environment:
- HOST_PROC=/host/proc - HOST_PROC=/host/proc
- HOST_ETC=/host/etc - HOST_ETC=/host/etc

View File

@@ -18,9 +18,12 @@
# if this script isn't already running # if this script isn't already running
if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then if [[ ! "`pidof -x $(basename $0) -o %PPID`" ]]; then
INFLUXSIZE=$(du -s -k /host/nsm/influxdb | awk {'print $1'}) INFLUXLOG=/var/log/telegraf/influxdb_size.log
echo "influxsize kbytes=$INFLUXSIZE"
if [ -f "$INFLUXLOG" ]; then
INFLUXSTATUS=$(cat $INFLUXLOG)
echo "influxsize kbytes=$INFLUXSTATUS"
fi
fi fi
exit 0 exit 0

View File

@@ -1,219 +0,0 @@
{%- set MANAGERIP = salt['pillar.get']('global:managerip', '') %}
{%- set CORTEXKEY = salt['pillar.get']('global:cortexorguserkey', '') %}
{%- set HIVEPLAYSECRET = salt['pillar.get']('global:hiveplaysecret', '') %}
# Secret Key
# The secret key is used to secure cryptographic functions.
# WARNING: If you deploy your application on several servers, make sure to use the same key.
play.http.secret.key="{{ HIVEPLAYSECRET }}"
play.http.context=/thehive/
search.uri = "http://{{ MANAGERIP }}:9400"
# Elasticsearch
search {
# Name of the index
index = the_hive
# Name of the Elasticsearch cluster
cluster = thehive
# Address of the Elasticsearch instance
host = ["{{ MANAGERIP }}:9500"]
#search.uri = "http://{{ MANAGERIP }}:9500"
# Scroll keepalive
keepalive = 1m
# Size of the page for scroll
pagesize = 50
# Number of shards
nbshards = 5
# Number of replicas
nbreplicas = 0
# Arbitrary settings
settings {
# Maximum number of nested fields
mapping.nested_fields.limit = 100
}
### XPack SSL configuration
# Username for XPack authentication
#username
# Password for XPack authentication
#password
# Enable SSL to connect to ElasticSearch
ssl.enabled = false
# Path to certificate authority file
#ssl.ca
# Path to certificate file
#ssl.certificate
# Path to key file
#ssl.key
### SearchGuard configuration
# Path to JKS file containing client certificate
#guard.keyStore.path
# Password of the keystore
#guard.keyStore.password
# Path to JKS file containing certificate authorities
#guard.trustStore.path
## Password of the truststore
#guard.trustStore.password
# Enforce hostname verification
#guard.hostVerification
# If hostname verification is enabled specify if hostname should be resolved
#guard.hostVerificationResolveHostname
}
# Authentication
auth {
# "provider" parameter contains authentication provider. It can be multi-valued (useful for migration)
# available auth types are:
# services.LocalAuthSrv : passwords are stored in user entity (in Elasticsearch). No configuration is required.
# ad : use ActiveDirectory to authenticate users. Configuration is under "auth.ad" key
# ldap : use LDAP to authenticate users. Configuration is under "auth.ldap" key
provider = [local]
# By default, basic authentication is disabled. You can enable it by setting "method.basic" to true.
#method.basic = true
ad {
# The Windows domain name in DNS format. This parameter is required if you do not use
# 'serverNames' below.
#domainFQDN = "mydomain.local"
# Optionally you can specify the host names of the domain controllers instead of using 'domainFQDN
# above. If this parameter is not set, TheHive uses 'domainFQDN'.
#serverNames = [ad1.mydomain.local, ad2.mydomain.local]
# The Windows domain name using short format. This parameter is required.
#domainName = "MYDOMAIN"
# If 'true', use SSL to connect to the domain controller.
#useSSL = true
}
ldap {
# The LDAP server name or address. The port can be specified using the 'host:port'
# syntax. This parameter is required if you don't use 'serverNames' below.
#serverName = "ldap.mydomain.local:389"
# If you have multiple LDAP servers, use the multi-valued setting 'serverNames' instead.
#serverNames = [ldap1.mydomain.local, ldap2.mydomain.local]
# Account to use to bind to the LDAP server. This parameter is required.
#bindDN = "cn=thehive,ou=services,dc=mydomain,dc=local"
# Password of the binding account. This parameter is required.
#bindPW = "***secret*password***"
# Base DN to search users. This parameter is required.
#baseDN = "ou=users,dc=mydomain,dc=local"
# Filter to search user in the directory server. Please note that {0} is replaced
# by the actual user name. This parameter is required.
#filter = "(cn={0})"
# If 'true', use SSL to connect to the LDAP directory server.
#useSSL = true
}
}
# Maximum time between two requests without requesting authentication
session {
warning = 5m
inactivity = 1h
}
# Max textual content length
play.http.parser.maxMemoryBuffer= 1M
# Max file size
play.http.parser.maxDiskBuffer = 1G
# Cortex
# TheHive can connect to one or multiple Cortex instances. Give each
# Cortex instance a name and specify the associated URL.
#
# In order to use Cortex, first you need to enable the Cortex module by uncommenting the next line
play.modules.enabled += connectors.cortex.CortexConnector
cortex {
"CORTEX-SERVER-ID" {
url = "http://{{ MANAGERIP }}:9001/cortex/"
key = "{{ CORTEXKEY }}"
# # HTTP client configuration (SSL and proxy)
# ws {}
}
}
# MISP
# TheHive can connect to one or multiple MISP instances. Give each MISP
# instance a name and specify the associated Authkey that must be used
# to poll events, the case template that should be used by default when
# importing events as well as the tags that must be added to cases upon
# import.
# Prior to configuring the integration with a MISP instance, you must
# enable the MISP connector. This will allow you to import events to
# and/or export cases to the MISP instance(s).
#play.modules.enabled += connectors.misp.MispConnector
misp {
# Interval between consecutive MISP event imports in hours (h) or
# minutes (m).
interval = 1h
#"MISP-SERVER-ID" {
# # MISP connection configuration requires at least an url and a key. The key must
# # be linked with a sync account on MISP.
# url = ""
# key = ""
#
# # Name of the case template in TheHive that shall be used to import
# # MISP events as cases by default.
# caseTemplate = "<Template_Name_goes_here>"
#
# # Optional tags to add to each observable imported from an event
# # available on this instance.
# tags = ["misp-server-id"]
#
# ## MISP event filters
# # MISP filters is used to exclude events from the import.
# # Filter criteria are:
# # The number of attribute
# max-attributes = 1000
# # The size of its JSON representation
# max-size = 1 MiB
# # The age of the last publish date
# max-age = 7 days
# # Organization and tags
# exclusion {
# organisation = ["bad organisation", "other organisations"]
# tags = ["tag1", "tag2"]
# }
#
# ## HTTP client configuration (SSL and proxy)
# # Truststore to use to validate the X.509 certificate of the MISP
# # instance if the default truststore is not sufficient.
# # Proxy can also be used
# ws {
# ssl.trustManager.stores = [ {
# path = /path/to/truststore.jks
# } ]
# proxy {
# host = proxy.mydomain.org
# port = 3128
# }
# }
#
# # MISP purpose defines if this instance can be used to import events (ImportOnly), export cases (ExportOnly) or both (ImportAndExport)
# # Default is ImportAndExport
# purpose = ImportAndExport
#} ## <-- Uncomment to complete the configuration
}
webhooks {
NodeRedWebHook {
url = "http://{{ MANAGERIP }}:1880/thehive"
}
#SOCtopusWebHook {
# url = "http://{{ MANAGERIP }}:7000/enrich"
#}
}

View File

@@ -1,148 +0,0 @@
{%- set MANAGERIP = salt['pillar.get']('global:managerip', '') %}
{%- set CORTEXPLAYSECRET = salt['pillar.get']('global:cortexplaysecret', '') %}
# Secret Key
# The secret key is used to secure cryptographic functions.
# WARNING: If you deploy your application on several servers, make sure to use the same key.
play.http.secret.key="{{ CORTEXPLAYSECRET }}"
play.http.context=/cortex/
pidfile.path = "/dev/null"
search.uri = "http://{{ MANAGERIP }}:9400"
# Elasticsearch
search {
# Name of the index
index = cortex
# Name of the Elasticsearch cluster
cluster = thehive
# Address of the Elasticsearch instance
host = ["{{ MANAGERIP }}:9500"]
# Scroll keepalive
keepalive = 1m
# Size of the page for scroll
pagesize = 50
# Number of shards
nbshards = 5
# Number of replicas
nbreplicas = 0
# Arbitrary settings
settings {
# Maximum number of nested fields
mapping.nested_fields.limit = 100
}
## Authentication configuration
#search.username = ""
#search.password = ""
## SSL configuration
#search.keyStore {
# path = "/path/to/keystore"
# type = "JKS" # or PKCS12
# password = "keystore-password"
#}
#search.trustStore {
# path = "/path/to/trustStore"
# type = "JKS" # or PKCS12
# password = "trustStore-password"
#}
}
## Cache
#
# If an analyzer is executed against the same observable, the previous report can be returned without re-executing the
# analyzer. The cache is used only if the second job occurs within cache.job (the default is 10 minutes).
cache.job = 10 minutes
## Authentication
auth {
# "provider" parameter contains the authentication provider(s). It can be multi-valued, which is useful
# for migration.
# The available auth types are:
# - services.LocalAuthSrv : passwords are stored in the user entity within ElasticSearch). No
# configuration are required.
# - ad : use ActiveDirectory to authenticate users. The associated configuration shall be done in
# the "ad" section below.
# - ldap : use LDAP to authenticate users. The associated configuration shall be done in the
# "ldap" section below.
provider = [local]
ad {
# The Windows domain name in DNS format. This parameter is required if you do not use
# 'serverNames' below.
#domainFQDN = "mydomain.local"
# Optionally you can specify the host names of the domain controllers instead of using 'domainFQDN
# above. If this parameter is not set, TheHive uses 'domainFQDN'.
#serverNames = [ad1.mydomain.local, ad2.mydomain.local]
# The Windows domain name using short format. This parameter is required.
#domainName = "MYDOMAIN"
# If 'true', use SSL to connect to the domain controller.
#useSSL = true
}
ldap {
# The LDAP server name or address. The port can be specified using the 'host:port'
# syntax. This parameter is required if you don't use 'serverNames' below.
#serverName = "ldap.mydomain.local:389"
# If you have multiple LDAP servers, use the multi-valued setting 'serverNames' instead.
#serverNames = [ldap1.mydomain.local, ldap2.mydomain.local]
# Account to use to bind to the LDAP server. This parameter is required.
#bindDN = "cn=thehive,ou=services,dc=mydomain,dc=local"
# Password of the binding account. This parameter is required.
#bindPW = "***secret*password***"
# Base DN to search users. This parameter is required.
#baseDN = "ou=users,dc=mydomain,dc=local"
# Filter to search user in the directory server. Please note that {0} is replaced
# by the actual user name. This parameter is required.
#filter = "(cn={0})"
# If 'true', use SSL to connect to the LDAP directory server.
#useSSL = true
}
}
## ANALYZERS
#
analyzer {
# Absolute path where you have pulled the Cortex-Analyzers repository.
path = ["/Cortex-Analyzers/analyzers"]
# Sane defaults. Do not change unless you know what you are doing.
fork-join-executor {
# Min number of threads available for analysis.
parallelism-min = 2
# Parallelism (threads) ... ceil(available processors * factor).
parallelism-factor = 2.0
# Max number of threads available for analysis.
parallelism-max = 4
}
}
## RESPONDERS
##
responder {
# Directory that holds responders
urls = ["/Cortex-Analyzers/responders", "/custom-responders"]
fork-join-executor {
# Min number of threads available for analyze
parallelism-min = 2
# Parallelism (threads) ... ceil(available processors * factor)
parallelism-factor = 2.0
# Max number of threads available for analyze
parallelism-max = 4
}
}
# It's the end my friend. Happy hunting!

View File

@@ -1,17 +0,0 @@
cluster.name: thehive
network.host: 0.0.0.0
discovery.zen.minimum_master_nodes: 1
# This is a test -- if this is here, then the volume is mounted correctly.
path.logs: /var/log/elasticsearch
action.destructive_requires_name: true
discovery.type: single-node
script.allowed_types: inline
transport.bind_host: 0.0.0.0
transport.publish_host: 0.0.0.0
transport.publish_port: 9500
http.host: 0.0.0.0
http.port: 9400
transport.tcp.port: 9500
transport.host: 0.0.0.0
thread_pool.search.queue_size: 100000
thread_pool.write.queue_size: 100000

View File

@@ -1,20 +0,0 @@
status = error
#appender.console.type = Console
#appender.console.name = console
#appender.console.layout.type = PatternLayout
#appender.console.layout.pattern = [%d{ISO8601}][%-5p][%-25c{1.}] %marker%m%n
#rootLogger.level = info
#rootLogger.appenderRef.console.ref = console
# This is a test -- if this here, then the volume is mounted correctly.
appender.rolling.type = RollingFile
appender.rolling.name = rolling
appender.rolling.fileName = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}.log
appender.rolling.layout.type = PatternLayout
appender.rolling.layout.pattern = [%d{ISO8601}][%-5p][%-25c] %.10000m%n
appender.rolling.filePattern = ${sys:es.logs.base_path}${sys:file.separator}${sys:es.logs.cluster_name}-%d{yyyy-MM-dd}.log
appender.rolling.policies.type = Policies
appender.rolling.policies.time.type = TimeBasedTriggeringPolicy
appender.rolling.policies.time.interval = 1
appender.rolling.policies.time.modulate = true
rootLogger.level = info
rootLogger.appenderRef.rolling.ref = rolling

View File

@@ -1,180 +0,0 @@
{% from 'allowed_states.map.jinja' import allowed_states %}
{% if sls in allowed_states %}
{% set MANAGERIP = salt['pillar.get']('manager:mainip', '') %}
{% set VERSION = salt['pillar.get']('global:soversion', 'HH1.2.2') %}
{% set IMAGEREPO = salt['pillar.get']('global:imagerepo') %}
{% set MANAGER = salt['grains.get']('master') %}
thehiveconfdir:
file.directory:
- name: /opt/so/conf/thehive/etc
- makedirs: True
- user: 939
- group: 939
thehivelogdir:
file.directory:
- name: /opt/so/log/thehive
- makedirs: True
- user: 939
- group: 939
thehiveconf:
file.recurse:
- name: /opt/so/conf/thehive/etc
- source: salt://thehive/etc
- user: 939
- group: 939
- template: jinja
cortexconfdir:
file.directory:
- name: /opt/so/conf/cortex
- makedirs: True
- user: 939
- group: 939
cortexlogdir:
file.directory:
- name: /opt/so/log/cortex
- makedirs: True
- user: 939
- group: 939
cortexconf:
file.recurse:
- name: /opt/so/conf/cortex
- source: salt://thehive/etc
- user: 939
- group: 939
- template: jinja
cortexanalyzers:
file.directory:
- name: /opt/so/conf/cortex/custom-analyzers
- user: 939
- group: 939
- template: jinja
cortexresponders:
file.directory:
- name: /opt/so/conf/cortex/custom-responders
- user: 939
- group: 939
- template: jinja
# Install Elasticsearch
# Made directory for ES data to live in
thehiveesdata:
file.directory:
- name: /nsm/thehive/esdata
- makedirs: True
- user: 939
- group: 939
thehive_elasticsearch_yml:
file.exists:
- name: /opt/so/conf/thehive/etc/es/elasticsearch.yml
log4j2_properties:
file.exists:
- name: /opt/so/conf/thehive/etc/es/log4j2.properties
so-thehive-es:
docker_container.running:
- image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-thehive-es:{{ VERSION }}
- hostname: so-thehive-es
- name: so-thehive-es
- user: 939
- interactive: True
- tty: True
- binds:
- /nsm/thehive/esdata:/usr/share/elasticsearch/data:rw
- /opt/so/conf/thehive/etc/es/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro
- /opt/so/conf/thehive/etc/es/log4j2.properties:/usr/share/elasticsearch/config/log4j2.properties:ro
- /opt/so/log/thehive:/var/log/elasticsearch:rw
- environment:
- ES_JAVA_OPTS=-Xms512m -Xmx512m -Dlog4j2.formatMsgNoLookups=true
- port_bindings:
- 0.0.0.0:9400:9400
- 0.0.0.0:9500:9500
- require:
- file: thehive_elasticsearch_yml
- file: log4j2_properties
append_so-thehive-es_so-status.conf:
file.append:
- name: /opt/so/conf/so-status/so-status.conf
- text: so-thehive-es
cortex_application_conf:
file.exists:
- name: /opt/so/conf/thehive/etc/cortex-application.conf
application_conf:
file.exists:
- name: /opt/so/conf/thehive/etc/application.conf
# Install Cortex
so-cortex:
docker_container.running:
- image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-thehive-cortex:{{ VERSION }}
- hostname: so-cortex
- name: so-cortex
- user: 939
- binds:
- /opt/so/conf/thehive/etc/cortex-application.conf:/opt/cortex/conf/application.conf:ro
- /opt/so/conf/cortex/custom-analyzers:/custom-analyzers:ro
- /opt/so/conf/cortex/custom-responders:/custom-responders:ro
- port_bindings:
- 0.0.0.0:9001:9001
- require:
- file: cortex_application_conf
append_so-cortex_so-status.conf:
file.append:
- name: /opt/so/conf/so-status/so-status.conf
- text: so-cortex
cortexscript:
cmd.script:
- source: salt://thehive/scripts/cortex_init
- cwd: /opt/so
- template: jinja
- hide_output: False
so-thehive:
docker_container.running:
- image: {{ MANAGER }}:5000/{{ IMAGEREPO }}/so-thehive:{{ VERSION }}
- environment:
- ELASTICSEARCH_HOST={{ MANAGERIP }}
- hostname: so-thehive
- name: so-thehive
- user: 939
- binds:
- /opt/so/conf/thehive/etc/application.conf:/opt/thehive/conf/application.conf:ro
- port_bindings:
- 0.0.0.0:9000:9000
- require:
- file: application_conf
append_so-thehive_so-status.conf:
file.append:
- name: /opt/so/conf/so-status/so-status.conf
- text: so-thehive
thehivescript:
cmd.script:
- source: salt://thehive/scripts/hive_init
- cwd: /opt/so
- template: jinja
- hide_output: False
{% else %}
{{sls}}_state_not_allowed:
test.fail_without_changes:
- name: {{sls}}_state_not_allowed
{% endif %}

View File

@@ -1,75 +0,0 @@
#!/bin/bash
# {%- set MANAGERIP = salt['pillar.get']('global:managerip', '') %}
# {%- set CORTEXUSER = salt['pillar.get']('global:cortexuser', 'cortexadmin') %}
# {%- set CORTEXPASSWORD = salt['pillar.get']('global:cortexpassword', 'cortexchangeme') %}
# {%- set CORTEXKEY = salt['pillar.get']('global:cortexkey', '') %}
# {%- set CORTEXORGNAME = salt['pillar.get']('global:cortexorgname', '') %}
# {%- set CORTEXORGUSER = salt['pillar.get']('global:cortexorguser', 'soadmin') %}
# {%- set CORTEXORGUSERKEY = salt['pillar.get']('global:cortexorguserkey', '') %}
. /usr/sbin/so-common
default_salt_dir=/opt/so/saltstack/default
cortex_clean(){
sed -i '/^ cortexuser:/d' /opt/so/saltstack/local/pillar/global.sls
sed -i '/^ cortexpassword:/d' /opt/so/saltstack/local/pillar/global.sls
sed -i '/^ cortexorguser:/d' /opt/so/saltstack/local/pillar/global.sls
}
cortex_init(){
CORTEX_URL="http://{{MANAGERIP}}:9001/cortex/"
CORTEX_API_URL="${CORTEX_URL}api"
CORTEX_USER="{{CORTEXUSER}}"
CORTEX_PASSWORD="{{CORTEXPASSWORD}}"
CORTEX_KEY="{{CORTEXKEY}}"
CORTEX_ORG_NAME="{{CORTEXORGNAME}}"
CORTEX_ORG_DESC="{{CORTEXORGNAME}} organization created by Security Onion setup"
CORTEX_ORG_USER="{{CORTEXORGUSER}}"
CORTEX_ORG_USER_KEY="{{CORTEXORGUSERKEY}}"
SOCTOPUS_CONFIG="$default_salt_dir/salt/soctopus/files/SOCtopus.conf"
if wait_for_web_response $CORTEX_URL "Cortex" 120; then
# Migrate DB
curl -sk -XPOST -L "$CORTEX_API_URL/maintenance/migrate"
# Create intial Cortex superadmin
curl -sk -L "$CORTEX_API_URL/user" -H "Content-Type: application/json" -d "{\"login\" : \"$CORTEX_USER\",\"name\" : \"$CORTEX_USER\",\"roles\" : [\"superadmin\"],\"preferences\" : \"{}\",\"password\" : \"$CORTEX_PASSWORD\", \"key\": \"$CORTEX_KEY\"}"
# Create user-supplied org
curl -sk -XPOST -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "$CORTEX_API_URL/organization" -d "{ \"name\": \"$CORTEX_ORG_NAME\",\"description\": \"$CORTEX_ORG_DESC\",\"status\": \"Active\"}"
# Create user-supplied org user
curl -sk -XPOST -H "Authorization: Bearer $CORTEX_KEY" -H "Content-Type: application/json" -L "$CORTEX_API_URL/user" -d "{\"name\": \"$CORTEX_ORG_USER\",\"roles\": [\"read\",\"analyze\",\"orgadmin\"],\"organization\": \"$CORTEX_ORG_NAME\",\"login\": \"$CORTEX_ORG_USER\",\"key\": \"$CORTEX_ORG_USER_KEY\" }"
# Enable URLScan.io Analyzer
curl -sv -k -XPOST -H "Authorization: Bearer $CORTEX_ORG_USER_KEY" -H "Content-Type: application/json" -L "$CORTEX_API_URL/organization/analyzer/Urlscan_io_Search_0_1_0" -d '{"name":"Urlscan_io_Search_0_1_0","configuration":{"auto_extract_artifacts":false,"check_tlp":true,"max_tlp":2}}'
# Enable Cert PassiveDNS Analyzer
curl -sv -k -XPOST -H "Authorization: Bearer $CORTEX_ORG_USER_KEY" -H "Content-Type: application/json" -L "$CORTEX_API_URL/organization/analyzer/CERTatPassiveDNS_2_0" -d '{"name":"CERTatPassiveDNS_2_0","configuration":{"auto_extract_artifacts":false,"check_tlp":true,"max_tlp":2, "limit": 100}}'
# Revoke $CORTEX_USER key
curl -sk -XDELETE -H "Authorization: Bearer $CORTEX_KEY" -L "$CORTEX_API_URL/user/$CORTEX_USER/key"
# Update SOCtopus config with apikey value
#sed -i "s/cortex_key = .*/cortex_key = $CORTEX_KEY/" $SOCTOPUS_CONFIG
touch /opt/so/state/cortex.txt
else
echo "We experienced an issue connecting to Cortex!"
exit 1
fi
}
if [ -f /opt/so/state/cortex.txt ]; then
cortex_clean
exit 0
else
if wait_for_web_response http://{{MANAGERIP}}:9400/_cluster/health '"status":"green"' 120; then
cortex_init
cortex_clean
else
echo "TheHive Elasticsearch server is not ready; unable to proceed with Cortex init."
exit 1
fi
fi

View File

@@ -1,53 +0,0 @@
#!/bin/bash
# {%- set MANAGERIP = salt['pillar.get']('global:managerip', '') %}
# {%- set THEHIVEUSER = salt['pillar.get']('global:hiveuser', 'hiveadmin') %}
# {%- set THEHIVEPASSWORD = salt['pillar.get']('global:hivepassword', 'hivechangeme') %}
# {%- set THEHIVEKEY = salt['pillar.get']('global:hivekey', '') %}
. /usr/sbin/so-common
thehive_clean(){
sed -i '/^ hiveuser:/d' /opt/so/saltstack/local/pillar/global.sls
sed -i '/^ hivepassword:/d' /opt/so/saltstack/local/pillar/global.sls
}
thehive_init(){
THEHIVE_URL="http://{{MANAGERIP}}:9000/thehive/"
THEHIVE_API_URL="${THEHIVE_URL}api"
THEHIVE_USER="{{THEHIVEUSER}}"
THEHIVE_PASSWORD="{{THEHIVEPASSWORD}}"
THEHIVE_KEY="{{THEHIVEKEY}}"
SOCTOPUS_CONFIG="/opt/so/saltstack/salt/soctopus/files/SOCtopus.conf"
echo -n "Waiting for TheHive..."
if wait_for_web_response $THEHIVE_URL "TheHive" 120; then
# Migrate DB
curl -sk -XPOST -L "$THEHIVE_API_URL/maintenance/migrate"
# Create intial TheHive user
curl -sk -L "$THEHIVE_API_URL/user" -H "Content-Type: application/json" -d "{\"login\" : \"$THEHIVE_USER\",\"name\" : \"$THEHIVE_USER\",\"roles\" : [\"read\",\"alert\",\"write\",\"admin\"],\"preferences\" : \"{}\",\"password\" : \"$THEHIVE_PASSWORD\", \"key\": \"$THEHIVE_KEY\"}"
# Pre-load custom fields
#
# reputation
curl -sk -L "$THEHIVE_API_URL/list/custom_fields" -H "Authorization: Bearer $THEHIVE_KEY" -H "Content-Type: application/json" -d "{\"value\":{\"name\": \"reputation\", \"reference\": \"reputation\", \"description\": \"This field provides an overall reputation status for an address/domain.\", \"type\": \"string\", \"options\": []}}"
touch /opt/so/state/thehive.txt
else
echo "We experienced an issue connecting to TheHive!"
exit 1
fi
}
if [ -f /opt/so/state/thehive.txt ]; then
thehive_clean
exit 0
else
if wait_for_web_response http://{{MANAGERIP}}:9400/_cluster/health '"status":"green"' 120; then
thehive_init
thehive_clean
else
echo "TheHive Elasticsearch server is not ready; unable to proceed with TheHive init."
exit 1
fi
fi

View File

@@ -1,6 +1,5 @@
{% set ZEEKVER = salt['pillar.get']('global:mdengine', '') %} {% set ZEEKVER = salt['pillar.get']('global:mdengine', '') %}
{% set WAZUH = salt['pillar.get']('global:wazuh', '0') %} {% set WAZUH = salt['pillar.get']('global:wazuh', '0') %}
{% set THEHIVE = salt['pillar.get']('manager:thehive', '0') %}
{% set PLAYBOOK = salt['pillar.get']('manager:playbook', '0') %} {% set PLAYBOOK = salt['pillar.get']('manager:playbook', '0') %}
{% set FREQSERVER = salt['pillar.get']('manager:freq', '0') %} {% set FREQSERVER = salt['pillar.get']('manager:freq', '0') %}
{% set DOMAINSTATS = salt['pillar.get']('manager:domainstats', '0') %} {% set DOMAINSTATS = salt['pillar.get']('manager:domainstats', '0') %}
@@ -35,11 +34,14 @@ base:
'* and G@saltversion:{{saltversion}}': '* and G@saltversion:{{saltversion}}':
- match: compound - match: compound
- salt.minion - salt.minion
- common
- patch.os.schedule - patch.os.schedule
- motd - motd
- salt.minion-check - salt.minion-check
- salt.lasthighstate - salt.lasthighstate
'not *_workstation and G@saltversion:{{saltversion}}':
- match: compound
- common
'*_helixsensor and G@saltversion:{{saltversion}}': '*_helixsensor and G@saltversion:{{saltversion}}':
- match: compound - match: compound
@@ -142,9 +144,6 @@ base:
- utility - utility
- schedule - schedule
- soctopus - soctopus
{%- if THEHIVE != 0 %}
- thehive
{%- endif %}
{%- if PLAYBOOK != 0 %} {%- if PLAYBOOK != 0 %}
- playbook - playbook
- redis - redis
@@ -209,9 +208,6 @@ base:
- fleet.install_package - fleet.install_package
{%- endif %} {%- endif %}
- soctopus - soctopus
{%- if THEHIVE != 0 %}
- thehive
{%- endif %}
{%- if PLAYBOOK != 0 %} {%- if PLAYBOOK != 0 %}
- playbook - playbook
{%- endif %} {%- endif %}
@@ -283,9 +279,6 @@ base:
- utility - utility
- schedule - schedule
- soctopus - soctopus
{%- if THEHIVE != 0 %}
- thehive
{%- endif %}
{%- if PLAYBOOK != 0 %} {%- if PLAYBOOK != 0 %}
- playbook - playbook
{%- endif %} {%- endif %}
@@ -375,9 +368,6 @@ base:
- fleet.install_package - fleet.install_package
{%- endif %} {%- endif %}
- soctopus - soctopus
{%- if THEHIVE != 0 %}
- thehive
{%- endif %}
{%- if PLAYBOOK != 0 %} {%- if PLAYBOOK != 0 %}
- playbook - playbook
{%- endif %} {%- endif %}
@@ -519,3 +509,11 @@ base:
- docker_clean - docker_clean
- filebeat - filebeat
- idh - idh
'J@workstation:gui:enabled:^[Tt][Rr][Uu][Ee]$ and ( G@saltversion:{{saltversion}} and G@os:CentOS )':
- match: compound
- workstation
'J@workstation:gui:enabled:^[Ff][Aa][Ll][Ss][Ee]$ and ( G@saltversion:{{saltversion}} and G@os:CentOS )':
- match: compound
- workstation.remove_gui

View File

@@ -0,0 +1,7 @@
include:
- workstation.xwindows
{# If the master is 'salt' then the minion hasn't been configured and isn't connected to the grid. #}
{# We need this since the trusted-ca state uses mine data. #}
{% if grains.master != 'salt' %}
- workstation.trusted-ca
{% endif %}

View File

@@ -0,0 +1,60 @@
{# we only want this state to run it is CentOS #}
{% if grains.os == 'CentOS' %}
xwindows_group:
pkg.group_installed:
- name: X Window System
graphical_extras:
pkg.installed:
- pkgs:
- gnome-classic-session
- gnome-terminal
- gnome-terminal-nautilus
- control-center
- liberation-mono-fonts
- file-roller
workstation_packages:
pkg.installed:
- pkgs:
- wget
- curl
- unzip
- gedit
- mono-core
- mono-basic
- mono-winforms
- expect
- wireshark-gnome
- dsniff
- hping3
- netsed
- ngrep
- python36-scapy
- ssldump
- tcpdump
- tcpflow
- whois
- chromium
- libevent
- sslsplit
- perl-IO-Compress
- perl-Net-DNS
- securityonion-networkminer
- securityonion-chaosreader
- securityonion-analyst-extras
- securityonion-bittwist
- securityonion-tcpstat
- securityonion-tcptrace
- securityonion-foremost
- securityonion-strelka-oneshot
- securityonion-strelka-fileshot
{% else %}
workstation_packages_os_fail:
test.fail_without_changes:
- comment: 'SO Analyst Workstation can only be installed on CentOS'
{% endif %}

View File

@@ -0,0 +1,15 @@
{# we only want this state to run it is CentOS #}
{% if grains.os == 'CentOS' %}
remove_graphical_target:
file.symlink:
- name: /etc/systemd/system/default.target
- target: /lib/systemd/system/multi-user.target
- force: True
{% else %}
workstation_trusted-ca_os_fail:
test.fail_without_changes:
- comment: 'SO Analyst Workstation can only be installed on CentOS'
{% endif %}

View File

@@ -0,0 +1,35 @@
{# we only want this state to run it is CentOS #}
{% if grains.os == 'CentOS' %}
{% set global_ca_text = [] %}
{% set global_ca_server = [] %}
{% set manager = salt['grains.get']('master') %}
{% set x509dict = salt['mine.get'](manager | lower~'*', 'x509.get_pem_entries') %}
{% for host in x509dict %}
{% if host.split('_')|last in ['manager', 'managersearch', 'standalone', 'import', 'eval'] %}
{% do global_ca_text.append(x509dict[host].get('/etc/pki/ca.crt')|replace('\n', '')) %}
{% do global_ca_server.append(host) %}
{% endif %}
{% endfor %}
{% set trusttheca_text = global_ca_text[0] %}
{% set ca_server = global_ca_server[0] %}
trusted_ca:
x509.pem_managed:
- name: /etc/pki/ca-trust/source/anchors/ca.crt
- text: {{ trusttheca_text }}
update_ca_certs:
cmd.run:
- name: update-ca-trust
- onchanges:
- x509: trusted_ca
{% else %}
workstation_trusted-ca_os_fail:
test.fail_without_changes:
- comment: 'SO Analyst Workstation can only be installed on CentOS'
{% endif %}

View File

@@ -0,0 +1,23 @@
{# we only want this state to run it is CentOS #}
{% if grains.os == 'CentOS' %}
include:
- workstation.packages
graphical_target:
file.symlink:
- name: /etc/systemd/system/default.target
- target: /lib/systemd/system/graphical.target
- force: True
- require:
- pkg: X Window System
- pkg: graphical_extras
{% else %}
workstation_xwindows_os_fail:
test.fail_without_changes:
- comment: 'SO Analyst Workstation can only be installed on CentOS'
{% endif %}

View File

@@ -38,12 +38,12 @@ event file_state_remove(f: fa_file)
if ( !f$info?$extracted || FileExtract::prefix == "" ) { if ( !f$info?$extracted || FileExtract::prefix == "" ) {
return; return;
} }
# Check some conditions so we know the file is intact: # Check if any of the following conditions exist:
# Check for MD5 # - missing MD5
# Check for total_bytes # - total_bytes exists (some protocols aren't populating this field) but is 0
# Check for missing bytes # - missing bytes
# Check if timed out # - timed out
if ( !f$info?$md5 || !f?$total_bytes || f$missing_bytes > 0 || f$info$timedout) { if ( !f$info?$md5 || (f?$total_bytes && f$total_bytes == 0) || f$missing_bytes > 0 || f$info$timedout) {
# Delete the file if it didn't pass our requirements check. # Delete the file if it didn't pass our requirements check.
local nuke = fmt("rm %s/%s", FileExtract::prefix, f$info$extracted); local nuke = fmt("rm %s/%s", FileExtract::prefix, f$info$extracted);

View File

@@ -70,7 +70,7 @@ RULESETUP=ETOPEN
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
STRELKA=1 STRELKA=1
THEHIVE=1 THEHIVE=0
WAZUH=1 WAZUH=1
WEBUSER=onionuser@somewhere.invalid WEBUSER=onionuser@somewhere.invalid
WEBPASSWD1=0n10nus3r WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -69,7 +69,7 @@ RULESETUP=ETOPEN
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
STRELKA=1 STRELKA=1
THEHIVE=1 THEHIVE=0
WAZUH=1 WAZUH=1
WEBUSER=onionuser@somewhere.invalid WEBUSER=onionuser@somewhere.invalid
WEBPASSWD1=0n10nus3r WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
#STRELKA=1 #STRELKA=1
#THEHIVE=1 #THEHIVE=0
#WAZUH=1 #WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
#STRELKA=1 #STRELKA=1
#THEHIVE=1 #THEHIVE=0
#WAZUH=1 #WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -69,7 +69,7 @@ RULESETUP=ETOPEN
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
STRELKA=1 STRELKA=1
THEHIVE=1 THEHIVE=0
WAZUH=1 WAZUH=1
WEBUSER=onionuser@somewhere.invalid WEBUSER=onionuser@somewhere.invalid
WEBPASSWD1=0n10nus3r WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -72,7 +72,7 @@ SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
SURIPINS=(2 3) SURIPINS=(2 3)
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -69,7 +69,7 @@ RULESETUP=ETOPEN
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
STRELKA=1 STRELKA=1
THEHIVE=1 THEHIVE=0
WAZUH=1 WAZUH=1
WEBUSER=onionuser@somewhere.invalid WEBUSER=onionuser@somewhere.invalid
WEBPASSWD1=0n10nus3r WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -69,7 +69,7 @@ RULESETUP=ETOPEN
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
STRELKA=1 STRELKA=1
THEHIVE=1 THEHIVE=0
WAZUH=1 WAZUH=1
WEBUSER=onionuser@somewhere.invalid WEBUSER=onionuser@somewhere.invalid
WEBPASSWD1=0n10nus3r WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -69,7 +69,7 @@ RULESETUP=ETOPEN
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
STRELKA=1 STRELKA=1
THEHIVE=1 THEHIVE=0
WAZUH=1 WAZUH=1
WEBUSER=onionuser@somewhere.invalid WEBUSER=onionuser@somewhere.invalid
WEBPASSWD1=0n10nus3r WEBPASSWD1=0n10nus3r

View File

@@ -71,7 +71,7 @@ PATCHSCHEDULENAME=auto
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -72,7 +72,7 @@ SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
# STRELKA=1 # STRELKA=1
SURIPINS=(2 3) SURIPINS=(2 3)
# THEHIVE=1 # THEHIVE=0
# WAZUH=1 # WAZUH=1
# WEBUSER=onionuser@somewhere.invalid # WEBUSER=onionuser@somewhere.invalid
# WEBPASSWD1=0n10nus3r # WEBPASSWD1=0n10nus3r

View File

@@ -70,7 +70,7 @@ RULESETUP=ETOPEN
SOREMOTEPASS1=onionuser SOREMOTEPASS1=onionuser
SOREMOTEPASS2=onionuser SOREMOTEPASS2=onionuser
STRELKA=1 STRELKA=1
THEHIVE=1 THEHIVE=0
WAZUH=1 WAZUH=1
WEBUSER=onionuser@somewhere.invalid WEBUSER=onionuser@somewhere.invalid
WEBPASSWD1=0n10nus3r WEBPASSWD1=0n10nus3r

Some files were not shown because too many files have changed in this diff Show More