diff --git a/.github/DISCUSSION_TEMPLATE/3-0.yml b/.github/DISCUSSION_TEMPLATE/3-0.yml index 8f74145c4..9b7ded081 100644 --- a/.github/DISCUSSION_TEMPLATE/3-0.yml +++ b/.github/DISCUSSION_TEMPLATE/3-0.yml @@ -12,6 +12,7 @@ body: - 3.0.0 - 3.1.0 - 3.2.0 + - 3.3.0 - Other (please provide detail below) validations: required: true diff --git a/DOWNLOAD_AND_VERIFY_ISO.md b/DOWNLOAD_AND_VERIFY_ISO.md index bae49c4ac..f3d496b41 100644 --- a/DOWNLOAD_AND_VERIFY_ISO.md +++ b/DOWNLOAD_AND_VERIFY_ISO.md @@ -1,17 +1,17 @@ -### 3.1.0-20260528 ISO image released on 2026/05/28 +### 3.2.0-20260729 ISO image released on 2026/07/29 ### Download and Verify -3.1.0-20260528 ISO image: -https://download.securityonion.net/file/securityonion/securityonion-3.1.0-20260528.iso +3.2.0-20260729 ISO image: +https://download.securityonion.net/file/securityonion/securityonion-3.2.0-20260729.iso -MD5: 9D6FF58DEEE24089D722C73169765B3E -SHA1: 2B8B816B6CEC3B7F96B3C5E040EBF502DD2C412F -SHA256: 62FAB57E247C843D6A04F0796D8162C732B65D82FC3E4A59D087135B9FD32912 +MD5: B1E10F46DF872B655C29325DF965A4DB +SHA1: 0F3C7ED80F6D326B7A993C2F899B986320C01BF9 +SHA256: 7465163C1D1ADFCDC3935530EAFB312E987C016941ADC11841B214553314D1FF Signature for ISO image: -https://github.com/Security-Onion-Solutions/securityonion/raw/3/main/sigs/securityonion-3.1.0-20260528.iso.sig +https://github.com/Security-Onion-Solutions/securityonion/raw/3/main/sigs/securityonion-3.2.0-20260729.iso.sig Signing key: https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/3/main/KEYS @@ -25,22 +25,22 @@ wget https://raw.githubusercontent.com/Security-Onion-Solutions/securityonion/3/ Download the signature file for the ISO: ``` -wget https://github.com/Security-Onion-Solutions/securityonion/raw/3/main/sigs/securityonion-3.1.0-20260528.iso.sig +wget https://github.com/Security-Onion-Solutions/securityonion/raw/3/main/sigs/securityonion-3.2.0-20260729.iso.sig ``` Download the ISO image: ``` -wget https://download.securityonion.net/file/securityonion/securityonion-3.1.0-20260528.iso +wget https://download.securityonion.net/file/securityonion/securityonion-3.2.0-20260729.iso ``` Verify the downloaded ISO image using the signature file: ``` -gpg --verify securityonion-3.1.0-20260528.iso.sig securityonion-3.1.0-20260528.iso +gpg --verify securityonion-3.2.0-20260729.iso.sig securityonion-3.2.0-20260729.iso ``` The output should show "Good signature" and the Primary key fingerprint should match what's shown below: ``` -gpg: Signature made Wed 27 May 2026 03:03:59 PM EDT using RSA key ID FE507013 +gpg: Signature made Tue 28 Jul 2026 06:17:34 PM EDT using RSA key ID FE507013 gpg: Good signature from "Security Onion Solutions, LLC " gpg: WARNING: This key is not certified with a trusted signature! gpg: There is no indication that the signature belongs to the owner. diff --git a/VERSION b/VERSION index 944880fa1..15a279981 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.0 +3.3.0 diff --git a/salt/common/tools/sbin/so-log-check b/salt/common/tools/sbin/so-log-check index 56c0278da..b1a64770d 100755 --- a/salt/common/tools/sbin/so-log-check +++ b/salt/common/tools/sbin/so-log-check @@ -231,7 +231,7 @@ if [[ $EXCLUDE_KNOWN_ERRORS == 'Y' ]]; then EXCLUDED_ERRORS="$EXCLUDED_ERRORS|from NIC checksum offloading" # zeek reporter.log EXCLUDED_ERRORS="$EXCLUDED_ERRORS|marked for removal" # docker container getting recycled EXCLUDED_ERRORS="$EXCLUDED_ERRORS|tcp 127.0.0.1:6791: bind: address already in use" # so-elastic-fleet agent restarting. Seen starting w/ 8.18.8 https://github.com/elastic/kibana/issues/201459 - EXCLUDED_ERRORS="$EXCLUDED_ERRORS|TransformTask\] \[logs-(tychon|aws_billing|microsoft_defender_endpoint|armis|o365_metrics|microsoft_sentinel|snyk|cyera|island_browser).*user so_kibana lacks the required permissions \[(logs|metrics)-\1" # Known issue with integrations starting transform jobs that are explicitly not allowed to start as a system user. This error should not be seen on fresh ES 9.3.3 installs or after SO 3.1.0 with soups addition of check_transform_health_and_reauthorize() + EXCLUDED_ERRORS="$EXCLUDED_ERRORS|TransformTask\] \[logs-.*user so_kibana lacks the required permissions" # Known issue with integrations starting transform jobs that are explicitly not allowed to start as a system user EXCLUDED_ERRORS="$EXCLUDED_ERRORS|manifest unknown" # appears in so-dockerregistry log for so-tcpreplay following docker upgrade to 29.2.1-1 fi diff --git a/salt/nginx/etc/nginx.conf b/salt/nginx/etc/nginx.conf index 3f74c411c..f384caf94 100644 --- a/salt/nginx/etc/nginx.conf +++ b/salt/nginx/etc/nginx.conf @@ -96,14 +96,14 @@ http { add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options nosniff; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; - add_header referrer-Policy no-referrer; + add_header Referrer-Policy no-referrer; ssl_certificate "/etc/pki/nginx/server.crt"; ssl_certificate_key "/etc/pki/nginx/server.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_CCM:TLS_RSA_WITH_ARIA_256_GCM_SHA384:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_128_CCM:TLS_RSA_WITH_ARIA_128_GCM_SHA256; - ssl_ecdh_curve secp521r1:secp384r1; + ssl_ecdh_curve X25519:secp521r1:secp384r1; ssl_prefer_server_ciphers on; ssl_protocols TLSv1.2 TLSv1.3; } @@ -138,14 +138,14 @@ http { add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options nosniff; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; - add_header referrer-Policy no-referrer; + add_header Referrer-Policy no-referrer; ssl_certificate "/etc/pki/nginx/server.crt"; ssl_certificate_key "/etc/pki/nginx/server.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_CCM:TLS_RSA_WITH_ARIA_256_GCM_SHA384:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_128_CCM:TLS_RSA_WITH_ARIA_128_GCM_SHA256; - ssl_ecdh_curve secp521r1:secp384r1; + ssl_ecdh_curve X25519:secp521r1:secp384r1; ssl_prefer_server_ciphers on; ssl_protocols TLSv1.2 TLSv1.3; location / { @@ -172,14 +172,14 @@ http { add_header X-XSS-Protection "1; mode=block"; add_header X-Content-Type-Options nosniff; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; - add_header referrer-Policy no-referrer; + add_header Referrer-Policy no-referrer; ssl_certificate "/etc/pki/nginx/server.crt"; ssl_certificate_key "/etc/pki/nginx/server.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256:TLS_RSA_WITH_AES_256_GCM_SHA384:TLS_RSA_WITH_AES_256_CCM:TLS_RSA_WITH_ARIA_256_GCM_SHA384:TLS_RSA_WITH_AES_128_GCM_SHA256:TLS_RSA_WITH_AES_128_CCM:TLS_RSA_WITH_ARIA_128_GCM_SHA256; - ssl_ecdh_curve secp521r1:secp384r1; + ssl_ecdh_curve X25519:secp521r1:secp384r1; ssl_prefer_server_ciphers on; ssl_protocols TLSv1.2 TLSv1.3; @@ -198,6 +198,10 @@ http { } location / { + if ($http_authorization ~* "^Bearer .*$") { + return 401; + } + auth_request /auth/sessions/whoami; auth_request_set $userid $upstream_http_x_kratos_authenticated_identity_id; proxy_set_header x-user-id $userid; @@ -218,6 +222,13 @@ http { add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires "0"; + + add_header Content-Security-Policy "default-src 'self' 'unsafe-inline' 'unsafe-eval' https: data: blob: wss:; frame-ancestors 'self'"; + add_header X-Frame-Options SAMEORIGIN; + add_header X-XSS-Protection "1; mode=block"; + add_header X-Content-Type-Options nosniff; + add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; + add_header Referrer-Policy no-referrer; } location ~ ^/auth/.*?(login|oidc/callback) { @@ -383,6 +394,11 @@ http { if ($http_authorization = "") { return 403; } + + if ($http_authorization ~* "^Bearer .*$") { + return 401; + } + proxy_pass http://{{ GLOBALS.manager }}:9822/; proxy_read_timeout 90; proxy_connect_timeout 90; @@ -399,7 +415,7 @@ http { error_page 429 = @error429; location @error401 { - if ($request_uri ~* (^.*/api/.*|^/connect/.*|^/oauth2/.*|^/.*\.map$)) { + if ($request_uri ~* (^.*/api/.*|^.*/login.*|^.*/logout.*|^/connect/.*|^/oauth2/.*|^/.*\.map$)) { return 401; } diff --git a/salt/reactor/pillar_push_map.yaml b/salt/reactor/pillar_push_map.yaml index c77f5e93c..993444bd2 100644 --- a/salt/reactor/pillar_push_map.yaml +++ b/salt/reactor/pillar_push_map.yaml @@ -242,7 +242,7 @@ versionlock: # grain (compound supports nested grain matching via G@::). # pillar/vm/soc_vm.sls write path is referenced at salt/_runners/setup_hypervisor.py:856. vm: - - state: vm + - state: vm.user tgt: 'G@salt-cloud:driver:libvirt' # zeek: sensor_roles + so-import (5 roles). diff --git a/salt/repo/client/oracle.sls b/salt/repo/client/oracle.sls index bf0a02751..bb4316879 100644 --- a/salt/repo/client/oracle.sls +++ b/salt/repo/client/oracle.sls @@ -60,6 +60,9 @@ so_repo: {% endif %} - enabled: 1 - gpgcheck: 1 + {% if not GLOBALS.is_manager %} + - sslverify: 0 + {% endif %} # Only assign the kernel repo once this node's running salt matches the version this # SO release ships. During a soup the grid is mid-salt-upgrade; gating here keeps the @@ -77,6 +80,9 @@ so_kernel_repo: {% endif %} - enabled: 1 - gpgcheck: 1 + {% if not GLOBALS.is_manager %} + - sslverify: 0 + {% endif %} # Supplementary kernel repo: tolerate it being empty/unreachable (e.g. before the # manager has populated /nsm/kernelrepo) so a missing repomd.xml can't make every # dnf/pkg operation on the grid fail. diff --git a/salt/soc/defaults.yaml b/salt/soc/defaults.yaml index c89b39dcf..75fc1a597 100644 --- a/salt/soc/defaults.yaml +++ b/salt/soc/defaults.yaml @@ -1512,6 +1512,10 @@ soc: rulesetName: sos-resources-ag branch: main folder: securityonion-normalized + - repo: file:///nsm/airgap-resources/playbooks/securityonion-resources-playbooks + rulesetName: sos-published-ag + branch: published + folder: sigma assistant: systemPromptAddendum: "" systemPromptAddendumMaxLength: 50000 @@ -1530,9 +1534,9 @@ soc: healthTimeoutSeconds: 5 agentic: false agentMapping: - Orchestrator: Claude Sonnet - Investigator: Claude Sonnet - DetectionEngineer: Claude Sonnet + Orchestrator: sonnet@SOAI + Investigator: gemma@SOAI + DetectionEngineer: gemma@SOAI onionconfig: saltstackDir: /opt/so/saltstack bypassEnabled: false @@ -2714,4 +2718,14 @@ soc: enabled: true adapter: SOAI charsPerTokenEstimate: 4 + - id: gemma + displayName: Gemma + origin: USA + contextLimitSmall: 256000 + contextLimitLarge: 256000 + lowBalanceColorAlert: 500000 + enabled: true + adapter: SOAI + charsPerTokenEstimate: 4 + diff --git a/salt/soc/files/soc/sigma_playbook_pipeline.yaml b/salt/soc/files/soc/sigma_playbook_pipeline.yaml index 04bd2ffaf..a779c4dec 100644 --- a/salt/soc/files/soc/sigma_playbook_pipeline.yaml +++ b/salt/soc/files/soc/sigma_playbook_pipeline.yaml @@ -12,6 +12,30 @@ transformations: process.command_line: process.command_line.caseless process.parent.command_line: process.parent.command_line.caseless file.path: file.path.caseless + # entity_id pivots must also match processes that were already running when the + # agent started: Defend emits already_running (event.type:info), not start. + # Kept out of Playbook sigma query because Sysmon has no equivalent concept. + # contains_field is exact, so child pivots (process.parent.entity_id) stay + # start-only. Drop must precede add; + - id: playbook_process_lifecycle_drop_start_scope + type: drop_detection_item + field_name_conditions: + - type: include_fields + fields: ['event.type'] + rule_conditions: + - type: logsource + category: process_creation + - type: contains_field + field: process.entity_id + - id: playbook_process_lifecycle_add-fields + type: add_condition + conditions: + event.type: ['start', 'info'] + rule_conditions: + - type: logsource + category: process_creation + - type: contains_field + field: process.entity_id # file_activity: playbook-only pseudo-category spanning all file operations. - id: playbook_file_activity_add-fields type: add_condition diff --git a/salt/soc/files/soc/sigma_so_pipeline.yaml b/salt/soc/files/soc/sigma_so_pipeline.yaml index 724740673..64b691d8f 100644 --- a/salt/soc/files/soc/sigma_so_pipeline.yaml +++ b/salt/soc/files/soc/sigma_so_pipeline.yaml @@ -68,13 +68,25 @@ transformations: - type: logsource category: antivirus # OS-agnostic process_creation scoping for product-less (NIDS/host-pivot) rules. + # pySigma: rule_cond_expr requires rule_conditions as a mapping, not a list. - id: process_creation_os_agnostic type: add_condition conditions: event.category: process rule_conditions: - - type: logsource - category: process_creation + pc_cat: + type: logsource + category: process_creation + pc_win: + type: logsource + product: windows + pc_mac: + type: logsource + product: macos + pc_lin: + type: logsource + product: linux + rule_cond_expr: "pc_cat and not (pc_win or pc_mac or pc_lin)" # Transforms the `Hashes` field to ECS fields # ECS fields are used by the hash fields emitted by Elastic Defend # If shipped with Elastic Agent, sysmon logs will also have hashes mapped to ECS fields @@ -630,4 +642,4 @@ transformations: tags: '*file' rule_conditions: - type: logsource - category: file \ No newline at end of file + category: file diff --git a/sigs/securityonion-3.2.0-20260729.iso.sig b/sigs/securityonion-3.2.0-20260729.iso.sig new file mode 100644 index 000000000..f9324a9fd Binary files /dev/null and b/sigs/securityonion-3.2.0-20260729.iso.sig differ