[Security Rules] Update security rules package to v9.4.3-beta.1#18793
[Security Rules] Update security rules package to v9.4.3-beta.1#18793shashank-elastic merged 2 commits intomainfrom
Conversation
| changes: | ||
| - description: Release security rules update | ||
| type: enhancement | ||
| link: https://github.com/elastic/integrations/pull/18793 |
There was a problem hiding this comment.
🟢 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.
| 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", |
There was a problem hiding this comment.
🟡 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", |
There was a problem hiding this comment.
🟢 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
statsblock in the ES|QL query definesEsql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description)twice — once in the first group of aggregations and again later alongsidecount_distinct. Depending on how ES|QL handles duplicate output column names instats, 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.
💔 Build Failed
Failed CI StepsHistory |
|
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/ |
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 verified that all data streams collect metrics or logs.changelog.ymlfile.manifest.ymlfile to point to the latest Elastic stack release (e.g.^7.13.0).Author's Checklist
How to test this PR locally
package-storageto build EPR from sourceRelated issues
None
Screenshots
None