Skip to content

[Security Rules] Update security rules package to v9.4.3-beta.1#18793

Merged
shashank-elastic merged 2 commits intomainfrom
detection-rules/9.4.3-beta.1-ccaf094d0
May 5, 2026
Merged

[Security Rules] Update security rules package to v9.4.3-beta.1#18793
shashank-elastic merged 2 commits intomainfrom
detection-rules/9.4.3-beta.1-ccaf094d0

Conversation

@tradebot-elastic
Copy link
Copy Markdown
Contributor

What does this PR do?

Update the Security Rules package to version 9.4.3-beta.1.
Autogenerated from commit https://github.com/elastic/detection-rules/tree/ccaf094d0ff5f61a53150f9cb0aa7fe07fa7ecff

Checklist

  • I have reviewed tips for building integrations and this pull request is aligned with them.
  • I have verified that all data streams collect metrics or logs.
  • I have added an entry to my package's changelog.yml file.
  • If I'm introducing a new feature, I have modified the Kibana version constraint in my package's manifest.yml file to point to the latest Elastic stack release (e.g. ^7.13.0).

Author's Checklist

  • Install the most recently release security rules in the Detection Engine
  • Install the package
  • Confirm the update is available in Kibana. Click "Update X rules" or "Install X rules"
  • Look at the changes made after the install and confirm they are consistent

How to test this PR locally

  • Perform the above checklist, and use package-storage to build EPR from source

Related issues

None

Screenshots

None

@shashank-elastic shashank-elastic added enhancement New feature or request Integration:security_detection_engine Prebuilt Security Detection Rules labels May 5, 2026
@shashank-elastic shashank-elastic marked this pull request as ready for review May 5, 2026 02:28
@shashank-elastic shashank-elastic requested a review from a team as a code owner May 5, 2026 02:28
@shashank-elastic shashank-elastic enabled auto-merge (squash) May 5, 2026 02:28
changes:
- description: Release security rules update
type: enhancement
link: https://github.com/elastic/integrations/pull/18793
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low security_detection_engine/changelog.yml:7

The changelog entry uses the placeholder URL https://github.com/elastic/integrations/pulls/0000 instead of the actual PR number, so the link will not resolve correctly. It also incorrectly uses pulls (plural) instead of pull (singular) in the path. Replace 0000 with the actual PR number and change pulls to pull to match the format of other entries.

Suggested change
link: https://github.com/elastic/integrations/pull/18793
link: https://github.com/elastic/integrations/pull/0000
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/security_detection_engine/changelog.yml around line 7:

The changelog entry uses the placeholder URL `https://github.com/elastic/integrations/pulls/0000` instead of the actual PR number, so the link will not resolve correctly. It also incorrectly uses `pulls` (plural) instead of `pull` (singular) in the path. Replace `0000` with the actual PR number and change `pulls` to `pull` to match the format of other entries.

"query": "from logs-azure.signinlogs-*\n\n| eval\n Esql.time_window_date_trunc = date_trunc(15 minutes, @timestamp),\n Esql_priv.azure_signinlogs_properties_user_principal_name_lower = to_lower(azure.signinlogs.properties.user_principal_name),\n Esql.azure_signinlogs_properties_incoming_token_type_lower = to_lower(azure.signinlogs.properties.incoming_token_type),\n Esql.azure_signinlogs_properties_app_display_name_lower = to_lower(azure.signinlogs.properties.app_display_name),\n Esql.user_agent_original = user_agent.original\n\n| where data_stream.dataset == \"azure.signinlogs\"\n and event.category == \"authentication\"\n and azure.signinlogs.category in (\"NonInteractiveUserSignInLogs\", \"SignInLogs\")\n and azure.signinlogs.properties.resource_display_name rlike \"(.*)365|SharePoint|Exchange|Teams|Office(.*)\"\n and event.outcome == \"failure\"\n and azure.signinlogs.properties.status.error_code != 50053\n and azure.signinlogs.properties.status.error_code in (\n 50034, // UserAccountNotFound\n 50126, // InvalidUsernameOrPassword\n 50055, // PasswordExpired\n 50056, // InvalidPassword\n 50057, // UserDisabled\n 50064, // CredentialValidationFailure\n 50076, // MFARequiredButNotPassed\n 50079, // MFARegistrationRequired\n 50105, // EntitlementGrantsNotFound\n 70000, // InvalidGrant\n 70008, // ExpiredOrRevokedRefreshToken\n 70043, // BadTokenDueToSignInFrequency\n 80002, // OnPremisePasswordValidatorRequestTimedOut\n 80005, // OnPremisePasswordValidatorUnpredictableWebException\n 50144, // InvalidPasswordExpiredOnPremPassword\n 50135, // PasswordChangeCompromisedPassword\n 50142, // PasswordChangeRequiredConditionalAccess\n 120000, // PasswordChangeIncorrectCurrentPassword\n 120002, // PasswordChangeInvalidNewPasswordWeak\n 120020 // PasswordChangeFailure\n )\n and azure.signinlogs.properties.user_principal_name is not null\n and azure.signinlogs.properties.user_principal_name != \"\"\n and user_agent.original != \"Mozilla/5.0 (compatible; MSAL 1.0) PKeyAuth/1.0\"\n\n| stats\n Esql.azure_signinlogs_properties_authentication_requirement_values = values(azure.signinlogs.properties.authentication_requirement),\n Esql.azure_signinlogs_properties_app_id_values = values(azure.signinlogs.properties.app_id),\n Esql.azure_signinlogs_properties_app_display_name_values = values(azure.signinlogs.properties.app_display_name),\n Esql.azure_signinlogs_properties_resource_id_values = values(azure.signinlogs.properties.resource_id),\n Esql.azure_signinlogs_properties_resource_display_name_values = values(azure.signinlogs.properties.resource_display_name),\n Esql.azure_signinlogs_properties_conditional_access_status_values = values(azure.signinlogs.properties.conditional_access_status),\n Esql.azure_signinlogs_properties_device_detail_browser_values = values(azure.signinlogs.properties.device_detail.browser),\n Esql.azure_signinlogs_properties_device_detail_device_id_values = values(azure.signinlogs.properties.device_detail.device_id),\n Esql.azure_signinlogs_properties_device_detail_operating_system_values = values(azure.signinlogs.properties.device_detail.operating_system),\n Esql.azure_signinlogs_properties_incoming_token_type_values = values(azure.signinlogs.properties.incoming_token_type),\n Esql.azure_signinlogs_properties_risk_state_values = values(azure.signinlogs.properties.risk_state),\n Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id),\n Esql.azure_signinlogs_properties_user_id_values = values(azure.signinlogs.properties.user_id),\n Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name),\n Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description),\n Esql.azure_signinlogs_result_signature_values = values(azure.signinlogs.result_signature),\n Esql.azure_signinlogs_result_type_values = values(azure.signinlogs.result_type),\n\n Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct = count_distinct(Esql_priv.azure_signinlogs_properties_user_principal_name_lower),\n Esql_priv.azure_signinlogs_properties_user_principal_name_lower_values = values(Esql_priv.azure_signinlogs_properties_user_principal_name_lower),\n Esql.azure_signinlogs_result_description_count_distinct = count_distinct(azure.signinlogs.result_description),\n Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description),\n Esql.azure_signinlogs_properties_status_error_code_count_distinct = count_distinct(azure.signinlogs.properties.status.error_code),\n Esql.azure_signinlogs_properties_status_error_code_values = values(azure.signinlogs.properties.status.error_code),\n Esql.azure_signinlogs_properties_incoming_token_type_lower_values = values(Esql.azure_signinlogs_properties_incoming_token_type_lower),\n Esql.azure_signinlogs_properties_app_display_name_lower_values = values(Esql.azure_signinlogs_properties_app_display_name_lower),\n Esql.source_ip_values = values(source.ip),\n Esql.source_ip_count_distinct = count_distinct(source.ip),\n Esql.source_as_organization_name_values = values(source.`as`.organization.name),\n Esql.source_as_organization_name_count_distinct = count_distinct(source.`as`.organization.name),\n Esql.source_geo_country_name_values = values(source.geo.country_name),\n Esql.source_geo_country_name_count_distinct = count_distinct(source.geo.country_name),\n Esql.@timestamp.min = min(@timestamp),\n Esql.@timestamp.max = max(@timestamp),\n Esql.event_count = count()\nby Esql.time_window_date_trunc\n\n| eval\n Esql.event_duration_seconds = date_diff(\"seconds\", Esql.@timestamp.min, Esql.@timestamp.max),\n Esql.event_bf_type = case(\n Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct >= 10\n and Esql.event_count >= 30\n and Esql.azure_signinlogs_result_description_count_distinct <= 3\n and Esql.source_ip_count_distinct >= 5\n and Esql.event_duration_seconds <= 600\n and Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct > Esql.source_ip_count_distinct,\n \"credential_stuffing\",\n\n Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct >= 15\n and Esql.azure_signinlogs_result_description_count_distinct == 1\n and Esql.event_count >= 15\n and Esql.event_duration_seconds <= 1800,\n \"password_spraying\",\n\n (Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct == 1\n and Esql.azure_signinlogs_result_description_count_distinct == 1\n and Esql.event_count >= 30\n and Esql.event_duration_seconds <= 300)\n or (Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct <= 3\n and Esql.source_ip_count_distinct > 30\n and Esql.event_count >= 100),\n \"password_guessing\",\n\n \"other\"\n )\n\n| where Esql.event_bf_type != \"other\"\n\n| keep\n Esql.time_window_date_trunc,\n Esql.event_bf_type,\n Esql.event_duration_seconds,\n Esql.event_count,\n Esql.@timestamp.min,\n Esql.@timestamp.max,\n Esql.azure_signinlogs_properties_user_principal_name_lower_count_distinct,\n Esql_priv.azure_signinlogs_properties_user_principal_name_lower_values,\n Esql.azure_signinlogs_result_description_count_distinct,\n Esql.azure_signinlogs_result_description_values,\n Esql.azure_signinlogs_properties_status_error_code_count_distinct,\n Esql.azure_signinlogs_properties_status_error_code_values,\n Esql.azure_signinlogs_properties_incoming_token_type_lower_values,\n Esql.azure_signinlogs_properties_app_display_name_lower_values,\n Esql.source_ip_values,\n Esql.source_ip_count_distinct,\n Esql.source_as_organization_name_values,\n Esql.source_as_organization_name_count_distinct,\n Esql.source_geo_country_name_values,\n Esql.source_geo_country_name_count_distinct,\n Esql.azure_signinlogs_properties_authentication_requirement_values,\n Esql.azure_signinlogs_properties_app_id_values,\n Esql.azure_signinlogs_properties_app_display_name_values,\n Esql.azure_signinlogs_properties_resource_id_values,\n Esql.azure_signinlogs_properties_resource_display_name_values,\n Esql.azure_signinlogs_properties_conditional_access_status_values,\n Esql.azure_signinlogs_properties_device_detail_browser_values,\n Esql.azure_signinlogs_properties_device_detail_device_id_values,\n Esql.azure_signinlogs_properties_device_detail_operating_system_values,\n Esql.azure_signinlogs_properties_incoming_token_type_values,\n Esql.azure_signinlogs_properties_risk_state_values,\n Esql.azure_signinlogs_properties_session_id_values,\n Esql.azure_signinlogs_properties_user_id_values\n",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Medium security_rule/35ab3cfa-6c67-11ef-ab4d-f661ea17fbcc_111.json:16

The rlike pattern "(.*)365|SharePoint|Exchange|Teams|Office(.*)" is parsed as five separate full-string alternatives due to regex precedence: (.*)365 OR SharePoint OR Exchange OR Teams OR Office(.*). Resources like "SharePoint Online" or "Microsoft Teams" fail to match because SharePoint, Exchange, Teams lack wildcards on both sides. This causes the rule to miss brute-force attacks against major M365 services. Consider using (.*(365|SharePoint|Exchange|Teams|Office).*) to match substrings in all resource display names.

    and azure.signinlogs.properties.resource_display_name rlike "(.*(365|SharePoint|Exchange|Teams|Office).*)"
🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/security_detection_engine/kibana/security_rule/35ab3cfa-6c67-11ef-ab4d-f661ea17fbcc_111.json around line 16:

The `rlike` pattern `"(.*)365|SharePoint|Exchange|Teams|Office(.*)"` is parsed as five separate full-string alternatives due to regex precedence: `(.*)365` OR `SharePoint` OR `Exchange` OR `Teams` OR `Office(.*)`. Resources like "SharePoint Online" or "Microsoft Teams" fail to match because `SharePoint`, `Exchange`, `Teams` lack wildcards on both sides. This causes the rule to miss brute-force attacks against major M365 services. Consider using `(.*(365|SharePoint|Exchange|Teams|Office).*)` to match substrings in all resource display names.

"query": "from logs-nginx.access-*, logs-apache.access-*, logs-apache_tomcat.access-*, logs-iis.access-*, logs-traefik.access-*\n| where\n http.request.method == \"GET\" and\n http.response.status_code in (\n 500, // Internal Server Error\n 502, // Bad Gateway\n 503, // Service Unavailable\n 504 // Gateway Timeout\n )\n\n| eval Esql.url_original_to_lower = to_lower(url.original)\n\n| keep\n @timestamp,\n data_stream.dataset,\n http.request.method,\n http.response.status_code,\n source.ip,\n agent.id,\n agent.name,\n Esql.url_original_to_lower,\n data_stream.namespace\n\n| stats\n Esql.event_count = count(),\n Esql.http_response_status_code_count = count(http.response.status_code),\n Esql.http_response_status_code_values = values(http.response.status_code),\n Esql.agent_name_values = values(agent.name),\n Esql.agent_id_values = values(agent.id),\n Esql.http_request_method_values = values(http.request.method),\n Esql.http_response_status_code_values = values(http.response.status_code),\n Esql.url_path_values = values(Esql.url_original_to_lower),\n Esql.data_stream_dataset_values = values(data_stream.dataset),\n Esql.data_stream_namespace_values = values(data_stream.namespace)\n by source.ip, agent.id\n| where\n Esql.http_response_status_code_count > 10\n",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low security_rule/6fa3abe3-9cd8-41de-951b-51ed8f710523_5.json:13

The stats command defines Esql.http_response_status_code_values twice with the same values(http.response.status_code) aggregation. ES|QL does not permit duplicate column names in a single stats command, so this query will fail to parse or execute. Remove the redundant duplicate line.

-    Esql.http_response_status_code_values = values(http.response.status_code),
     Esql.agent_name_values = values(agent.name),
     Esql.agent_id_values = values(agent.id),
     Esql.http_request_method_values = values(http.request.method),
-    Esql.http_response_status_code_values = values(http.response.status_code),
     Esql.url_path_values = values(Esql.url_original_to_lower),
Also found in 1 other location(s)

packages/security_detection_engine/kibana/security_rule/35ab3cfa-6c67-11ef-ab4d-f661ea17fbcc_111.json:16

The stats block in the ES|QL query defines Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description) twice — once in the first group of aggregations and again later alongside count_distinct. Depending on how ES|QL handles duplicate output column names in stats, this could either cause a parse error (breaking the rule entirely) or silently shadow the first definition. If it causes a parse error, the rule will never fire, completely defeating its purpose of detecting brute-force attacks.

🚀 Reply "fix it for me" or copy this AI Prompt for your agent:
In file packages/security_detection_engine/kibana/security_rule/6fa3abe3-9cd8-41de-951b-51ed8f710523_5.json around line 13:

The `stats` command defines `Esql.http_response_status_code_values` twice with the same `values(http.response.status_code)` aggregation. ES|QL does not permit duplicate column names in a single `stats` command, so this query will fail to parse or execute. Remove the redundant duplicate line.

Also found in 1 other location(s):
- packages/security_detection_engine/kibana/security_rule/35ab3cfa-6c67-11ef-ab4d-f661ea17fbcc_111.json:16 -- The `stats` block in the ES|QL query defines `Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description)` twice — once in the first group of aggregations and again later alongside `count_distinct`. Depending on how ES|QL handles duplicate output column names in `stats`, this could either cause a parse error (breaking the rule entirely) or silently shadow the first definition. If it causes a parse error, the rule will never fire, completely defeating its purpose of detecting brute-force attacks.

@elasticmachine
Copy link
Copy Markdown

elasticmachine commented May 5, 2026

@shashank-elastic shashank-elastic merged commit 642bdbc into main May 5, 2026
12 checks passed
@shashank-elastic shashank-elastic deleted the detection-rules/9.4.3-beta.1-ccaf094d0 branch May 5, 2026 03:39
@elastic-vault-github-plugin-prod
Copy link
Copy Markdown

Package security_detection_engine - 9.4.3-beta.1 containing this change is available at https://epr.elastic.co/package/security_detection_engine/9.4.3-beta.1/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Integration:security_detection_engine Prebuilt Security Detection Rules

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants