From 8c8156e0e2a77d34094a888fead6d9897e7a29c7 Mon Sep 17 00:00:00 2001 From: Mika Ayenson Date: Tue, 23 Jun 2026 16:32:50 -0500 Subject: [PATCH 1/3] [Maintenance] Migrate Phase 1 vendor fields to ECS and trim non-ecs schema Remove ECS duplicate entries from non-ecs-schema.json, add a guard test, and update rule queries to use ECS fields where integrations dual-write. Resolves #1776 --- detection_rules/etc/non-ecs-schema.json | 9 ---- ..._suspicious_get_user_password_request.toml | 2 +- ...tion_attempts_behind_rare_user_agents.toml | 8 +-- ...from_abused_hosting_service_providers.toml | 4 +- ...authentication_from_unusual_principal.toml | 4 +- ...interactive_sfa_sign_ins_across_users.toml | 8 +-- ...incipal_credentials_added_to_rare_app.toml | 6 +-- ...ntra_suspicious_odata_client_requests.toml | 12 ++--- ...nt_app_auth_request_on_behalf_of_user.toml | 8 +-- ...access_mfa_bombing_push_notifications.toml | 4 +- ...password_requests_for_different_users.toml | 10 ++-- ...token_retrieval_via_public_client_app.toml | 12 ++--- ...tion_sso_authentication_repeat_source.toml | 2 +- ...orted_for_oauth_access_tokens_granted.toml | 6 +-- ...h_access_token_granted_by_application.toml | 8 +-- ...er_than_average_failed_authentication.toml | 8 +-- ...tial_access_impossible_travel_sign_on.toml | 10 ++-- ..._password_spraying_from_repeat_source.toml | 10 ++-- ...ulti_factor_push_notification_bombing.toml | 6 +-- ..._rare_domain_with_user_authentication.toml | 6 +-- .../windows_logon_activity_by_source_ip.toml | 2 +- ...al_access_multi_could_secrets_via_api.toml | 6 +-- ...ct_interactive_kubernetes_api_request.toml | 4 +- ...tes_api_activity_by_unusual_utilities.toml | 8 +-- ...cess_aws_getpassword_for_ec2_instance.toml | 6 +-- ...elated_with_elevated_detection_alerts.toml | 6 +-- ...eration_via_update_assume_role_policy.toml | 4 +- ...icy_added_for_external_account_access.toml | 4 +- ..._s3_bucket_enumeration_or_brute_force.toml | 4 +- .../initial_access_console_login_root.toml | 4 +- .../ml_cloudtrail_error_message_spike.toml | 4 +- .../aws/ml_cloudtrail_rare_error_code.toml | 4 +- ...oundation_model_access_denied_attempt.toml | 8 +-- ..._resource_based_policy_denied_attempt.toml | 8 +-- ...oot_from_rare_user_and_member_account.toml | 4 +- ...rivilege_escalation_sts_role_chaining.toml | 6 +-- ...al_signin_then_arc_credential_listing.toml | 6 +-- ...s_azure_storage_account_keys_accessed.toml | 4 +- ...agnostics_retrieved_unusual_principal.toml | 6 +-- ...ess_device_code_signin_aad_graph_enum.toml | 4 +- ..._access_entra_id_brute_force_activity.toml | 12 ++--- ...s_entra_id_excessive_account_lockouts.toml | 4 +- ...a_id_signin_brute_force_microsoft_365.toml | 12 ++--- ...ss_entra_id_totp_brute_force_attempts.toml | 4 +- ..._full_network_packet_capture_detected.toml | 8 +-- ...ccess_storage_account_key_regenerated.toml | 4 +- ...se_evasion_automation_runbook_deleted.toml | 6 +-- .../defense_evasion_event_hub_deletion.toml | 4 +- ...insights_diagnostic_settings_deletion.toml | 6 +-- ...nse_evasion_kubernetes_events_deleted.toml | 6 +-- ...sion_network_firewall_policy_deletion.toml | 4 +- ...rk_frontdoor_firewall_policy_deletion.toml | 4 +- ...ense_evasion_network_watcher_deletion.toml | 4 +- ...curity_alert_suppression_rule_created.toml | 4 +- ...ion_storage_blob_permissions_modified.toml | 8 +-- ...d_teamfiltration_user_agents_detected.toml | 4 +- ...ge_blob_container_access_modification.toml | 4 +- ...utomation_runbook_created_or_modified.toml | 6 +-- ...zure_vm_extension_crud_unusual_source.toml | 6 +-- ..._managed_run_command_unusual_identity.toml | 8 +-- ...execution_compute_vm_command_executed.toml | 6 +-- ...pute_restore_point_collection_deleted.toml | 8 +-- ...ute_restore_point_collections_deleted.toml | 8 +-- ...ct_azure_compute_vm_snapshot_deletion.toml | 12 ++--- ...t_azure_compute_vm_snapshot_deletions.toml | 14 ++--- ...impact_azure_storage_account_deletion.toml | 8 +-- ...ure_storage_account_deletion_multiple.toml | 10 ++-- ...ct_key_vault_modified_by_unusual_user.toml | 10 ++-- .../azure/impact_kubernetes_pod_deleted.toml | 6 +-- ...act_resources_resource_group_deletion.toml | 4 +- ...ster_credential_access_unusual_source.toml | 8 +-- ..._actor_token_user_impersonation_abuse.toml | 10 ++-- ...s_entra_id_external_guest_user_invite.toml | 4 +- ...a_id_first_time_seen_device_code_auth.toml | 6 +-- ...ingle_session_from_multiple_addresses.toml | 8 +-- ...tial_access_entra_id_high_risk_signin.toml | 4 +- ...sent_grant_via_registered_application.toml | 8 +-- ...al_access_entra_id_kali365_user_agent.toml | 4 +- ...ft_auth_broker_nonstandard_user_agent.toml | 8 +-- ...icrosoft_auth_broker_unusual_resource.toml | 6 +-- ..._code_grant_unusual_app_resource_user.toml | 8 +-- ...auth_device_code_phishing_tycoon_aitm.toml | 6 +-- ...via_first_party_microsoft_application.toml | 4 +- ...tra_id_oauth_user_impersonation_scope.toml | 8 +-- ...ial_access_entra_id_powershell_signin.toml | 4 +- ...s_entra_id_protection_alerts_for_user.toml | 4 +- ...ra_id_protection_confirmed_compromise.toml | 6 +-- ...a_id_protection_sign_in_risk_detected.toml | 6 +-- ...ntra_id_protection_user_risk_detected.toml | 6 +-- ...tra_id_rare_app_id_for_principal_auth.toml | 14 ++--- ...cation_requirement_for_principal_user.toml | 12 ++--- ..._id_risky_user_or_compromised_sign_in.toml | 4 +- ...ous_oauth_flow_via_auth_broker_to_drs.toml | 8 +-- ...ntra_id_temporary_access_pass_created.toml | 10 ++-- ...s_entra_id_unusual_ropc_login_attempt.toml | 6 +-- ...al_access_entra_id_user_reported_risk.toml | 8 +-- .../azure/initial_access_tycoon_entra_id.toml | 6 +-- ...ement_azure_vm_serial_console_connect.toml | 8 +-- ...ersistence_automation_account_created.toml | 4 +- ...ersistence_automation_webhook_created.toml | 8 +-- ...ension_deployment_by_interactive_user.toml | 10 ++-- ...d_application_credential_modification.toml | 4 +- ...id_conditional_access_policy_modified.toml | 6 +-- ...id_global_administrator_role_assigned.toml | 4 +- ...a_id_guest_account_promoted_to_member.toml | 6 +-- ...stence_entra_id_mfa_disabled_for_user.toml | 8 +-- ...broker_drs_signin_from_suspicious_asn.toml | 6 +-- ...ra_id_oauth_app_redirect_uri_modified.toml | 4 +- ..._entra_id_pim_user_added_global_admin.toml | 6 +-- ...ged_identity_management_role_modified.toml | 4 +- ...id_register_device_unusual_user_agent.toml | 8 +-- ...roadtools_default_device_registration.toml | 12 ++--- ...rt_to_prt_transition_from_user_device.toml | 8 +-- ...ce_entra_id_service_principal_created.toml | 8 +-- ...d_service_principal_credentials_added.toml | 4 +- ...e_principal_federated_issuer_modified.toml | 4 +- ...ntra_id_suspicious_adrs_token_request.toml | 4 +- ..._suspicious_cloud_device_registration.toml | 12 ++--- ..._added_as_owner_for_azure_application.toml | 6 +-- ..._as_owner_for_azure_service_principal.toml | 4 +- ...id_user_signed_in_from_unusual_device.toml | 10 ++-- ...sistence_event_hub_created_or_updated.toml | 6 +-- ..._protect_alert_followed_by_device_reg.toml | 6 +-- ..._elevate_to_user_administrator_access.toml | 8 +-- ...nant_domain_federation_via_audit_logs.toml | 4 +- ...on_kubernetes_aks_rolebinding_created.toml | 8 +-- ...a_id_custom_domain_added_and_verified.toml | 4 +- ...hub_protected_branch_settings_changed.toml | 6 +-- .../github/execution_github_app_deleted.toml | 4 +- ...thub_private_repository_turned_public.toml | 4 +- ...ration_high_number_of_cloning_by_user.toml | 4 +- ...umber_of_closed_pull_requests_by_user.toml | 6 +-- ...protected_branch_force_pushes_by_user.toml | 4 +- ...protected_branch_force_pushes_by_user.toml | 4 +- ...ub_actions_workflow_injection_blocked.toml | 4 +- ...ss_github_register_self_hosted_runner.toml | 4 +- .../github/persistence_new_pat_created.toml | 4 +- ...ure_arc_proxy_secret_configmap_access.toml | 24 ++++----- .../credential_access_get_secrets_access.toml | 6 +-- ...netes_multiple_secret_retrieval_burst.toml | 14 ++--- ..._secret_access_scripting_http_clients.toml | 8 +-- ...t_read_by_node_or_pod_service_account.toml | 10 ++-- ...list_cluster_and_sensitive_namespaces.toml | 4 +- ...ccount_token_created_via_tokenrequest.toml | 12 ++--- .../defense_evasion_events_deleted.toml | 14 ++--- ...covery_denied_service_account_request.toml | 10 ++-- ...mission_enumeration_by_anonymous_user.toml | 26 ++++----- ...mission_enumeration_by_user_and_srcip.toml | 22 ++++---- ...kubernetes_multi_resource_setup_recon.toml | 18 +++---- ...covery_suspicious_self_subject_review.toml | 16 +++--- ...ymous_create_update_patch_pod_request.toml | 12 ++--- .../execution_forbidden_creation_request.toml | 12 ++--- ...bidden_request_from_unsual_user_agent.toml | 4 +- ...n_kubernetes_pod_exec_curl_wget_https.toml | 4 +- ...etes_pod_exec_potential_reverse_shell.toml | 4 +- ...nusual_request_response_by_user_agent.toml | 8 +-- .../execution_user_exec_to_pod.toml | 20 +++---- ...ns_or_kube_dns_configuration_modified.toml | 10 ++-- ...l_access_anonymous_request_authorized.toml | 8 +-- ...nce_cluster_admin_rolebinding_created.toml | 8 +-- ...ed_service_created_with_type_nodeport.toml | 12 ++--- ...admission_webhook_created_or_modified.toml | 10 ++-- ...e_signing_request_created_or_approved.toml | 8 +-- ...netes_eks_aws_auth_configmap_modified.toml | 10 ++-- ...nsitive_role_creation_or_modification.toml | 12 ++--- ..._service_account_bound_to_clusterrole.toml | 6 +-- ...rivilege_escalation_api_proxy_to_node.toml | 4 +- ...ted_with_excessive_linux_capabilities.toml | 18 +++---- ...est_impersonating_privileged_identity.toml | 14 ++--- ...etes_ephemeral_container_added_to_pod.toml | 8 +-- ...e_escalation_pod_created_with_hostipc.toml | 10 ++-- ...calation_pod_created_with_hostnetwork.toml | 8 +-- ...e_escalation_pod_created_with_hostpid.toml | 12 ++--- ...reated_with_sensitive_hostpath_volume.toml | 10 ++-- ...ege_escalation_privileged_pod_created.toml | 10 ++-- ...tch_wildcard_verbs_resources_response.toml | 14 ++--- ...nge_followed_by_workload_modification.toml | 14 ++--- ...e_workload_modification_by_user_agent.toml | 10 ++-- ..._service_account_rbac_write_operation.toml | 10 ++-- ...ignment_of_controller_service_account.toml | 8 +-- ...xchange_excessive_mail_items_accessed.toml | 4 +- ...ilbox_access_by_unusual_client_app_id.toml | 6 +-- ...id_potential_user_account_brute_force.toml | 4 +- ...access_identity_user_account_lockouts.toml | 8 +-- ...on_entra_id_susp_oauth2_authorization.toml | 12 ++--- ...n_exchange_inbox_rule_obfuscated_name.toml | 8 +-- ...entra_id_portal_login_atypical_travel.toml | 8 +-- ...tra_id_portal_login_impossible_travel.toml | 8 +-- ...sent_grant_via_registered_application.toml | 10 ++-- ..._device_code_grant_unusual_source_asn.toml | 6 +-- ...rant_unusual_user_noncompliant_device.toml | 6 +-- ...via_first_party_microsoft_application.toml | 6 +-- ..._identity_unusual_sso_errors_for_user.toml | 4 +- .../o365/initial_access_tycoon_o365.toml | 6 +-- ...picious_mailbox_permission_delegation.toml | 4 +- ...l_access_attempted_bypass_of_okta_mfa.toml | 12 ++--- ...mpts_to_brute_force_okta_user_account.toml | 8 +-- ...vents_from_single_device_behind_proxy.toml | 20 +++---- ..._token_hashes_for_single_okta_session.toml | 28 +++++----- ...ccess_okta_aitm_session_cookie_replay.toml | 28 +++++----- ...users_with_the_same_device_token_hash.toml | 28 +++++----- ...kta_brute_force_device_token_rotation.toml | 14 ++--- ..._access_okta_brute_force_multi_source.toml | 22 ++++---- ...kta_credential_stuffing_single_source.toml | 22 ++++---- ...ta_mfa_bombing_via_push_notifications.toml | 14 ++--- ...cess_okta_password_spray_multi_source.toml | 24 ++++----- ...ess_okta_password_spray_single_source.toml | 22 ++++---- ...l_okta_bombing_via_push_notifications.toml | 14 ++--- ...cessful_login_after_credential_attack.toml | 18 +++---- ...tial_access_user_impersonation_access.toml | 6 +-- ...tempt_to_deactivate_okta_network_zone.toml | 6 +-- ...n_attempt_to_delete_okta_network_zone.toml | 6 +-- ..._app_client_credential_token_exchange.toml | 26 ++++----- ...kta_attempt_to_deactivate_okta_policy.toml | 12 ++--- ...ttempt_to_deactivate_okta_policy_rule.toml | 12 ++--- ...on_okta_attempt_to_delete_okta_policy.toml | 12 ++--- ...ta_attempt_to_delete_okta_policy_rule.toml | 12 ++--- ...a_attempt_to_modify_okta_network_zone.toml | 12 ++--- ...on_okta_attempt_to_modify_okta_policy.toml | 8 +-- ...ta_attempt_to_modify_okta_policy_rule.toml | 12 ++--- ...ser_password_reset_or_unlock_attempts.toml | 10 ++-- ...pact_attempt_to_revoke_okta_api_token.toml | 8 +-- ...ttempt_to_deactivate_okta_application.toml | 14 ++--- ...rrence_user_session_started_via_proxy.toml | 16 +++--- ...initial_access_okta_fastpass_phishing.toml | 4 +- ...s_started_from_different_geolocations.toml | 22 ++++---- ...ss_sign_in_events_via_third_party_idp.toml | 14 ++--- ...cation_sso_from_unknown_client_device.toml | 4 +- ...ent_multiple_sessions_for_single_user.toml | 10 ++-- ...inistrator_role_assigned_to_okta_user.toml | 6 +-- ...mfa_deactivation_with_no_reactivation.toml | 14 ++--- ...e_new_idp_successfully_added_by_admin.toml | 12 ++--- ...login_to_okta_account_after_mfa_reset.toml | 6 +-- ...picious_launch_agent_or_launch_daemon.toml | 5 +- .../collection_fortigate_config_download.toml | 4 +- ...ate_overly_permissive_firewall_policy.toml | 4 +- ...rtigate_admin_creation_unusual_source.toml | 4 +- ..._sso_login_followed_by_admin_creation.toml | 4 +- ...ortigate_super_admin_account_creation.toml | 4 +- .../credential_access_adidns_wildcard.toml | 8 +-- ...ntial_access_bruteforce_admin_account.toml | 14 ++--- ...ple_logon_failure_followed_by_success.toml | 6 +-- ...rce_multiple_logon_failure_same_srcip.toml | 12 ++--- ...ial_access_dcsync_newterm_subjectuser.toml | 40 +++++++------- ...tial_access_dcsync_replication_rights.toml | 6 +-- .../credential_access_dnsnode_creation.toml | 6 +-- ..._access_dollar_account_relay_kerberos.toml | 38 ++++++------- ...tial_access_dollar_account_relay_ntlm.toml | 28 +++++----- ...ccess_imageload_azureadconnectauthsvc.toml | 4 +- .../credential_access_kerberos_coerce.toml | 18 +++---- .../credential_access_ldap_attributes.toml | 6 +-- ...l_access_lsass_handle_via_malseclogon.toml | 8 +-- ...al_access_lsass_memdump_handle_access.toml | 12 ++--- ...tial_access_machine_account_smb_relay.toml | 20 +++---- ...l_access_mimikatz_memssp_default_logs.toml | 4 +- ...ial_access_mimikatz_powershell_module.toml | 6 +-- ..._access_mod_wdigest_security_provider.toml | 4 +- ...credential_access_posh_request_ticket.toml | 6 +-- ...ntial_access_saved_creds_vault_winlog.toml | 6 +-- ...edelegationprivilege_assigned_to_user.toml | 54 +++++++++---------- .../credential_access_shadow_credentials.toml | 20 +++---- ...cious_winreg_access_via_sebackup_priv.toml | 4 +- ...ess_via_snapshot_lsass_clone_creation.toml | 4 +- ...se_evasion_windows_filtering_platform.toml | 6 +-- .../discovery_high_number_ad_properties.toml | 6 +-- ...very_privileged_localgroup_membership.toml | 8 +-- .../discovery_whoami_command_activity.toml | 4 +- .../execution_posh_hacktool_authors.toml | 4 +- ...redential_access_kerberos_correlation.toml | 14 ++--- ...ement_remote_service_installed_winlog.toml | 6 +-- .../windows/persistence_ad_adminsdholder.toml | 24 ++++----- .../persistence_dontexpirepasswd_account.toml | 4 +- ...sistence_group_modification_by_system.toml | 4 +- ...istence_msds_alloweddelegateto_krbtgt.toml | 34 ++++++------ .../persistence_remote_password_reset.toml | 12 ++--- .../persistence_scheduled_task_updated.toml | 4 +- ...istence_sdprop_exclusion_dsheuristics.toml | 4 +- .../persistence_temp_scheduled_task.toml | 6 +-- ...ge_escalation_badsuccessor_dmsa_abuse.toml | 24 ++++----- ...tion_create_process_as_different_user.toml | 4 +- ...privilege_escalation_credroaming_ldap.toml | 6 +-- ...alation_dmsa_creation_by_unusual_user.toml | 26 ++++----- ...lation_group_policy_privileged_groups.toml | 24 ++++----- ...scalation_krbrelayup_service_creation.toml | 34 ++++++------ ...privilege_escalation_make_token_local.toml | 34 ++++++------ ...scalation_newcreds_logon_rare_process.toml | 4 +- ...lation_samaccountname_spoofing_attack.toml | 40 +++++++------- ...alation_suspicious_dnshostname_update.toml | 28 +++++----- ...escalation_thread_cpu_priority_hijack.toml | 32 +++++------ ...lation_tokenmanip_sedebugpriv_enabled.toml | 10 ++-- ...on_windows_service_via_unusual_client.toml | 20 +++---- ...mmon_debug_or_base_image_pod_creation.toml | 8 +-- ...n_github_repo_interaction_from_new_ip.toml | 6 +-- ...pact_azure_recovery_services_deletion.toml | 6 +-- ..._access_github_new_ip_address_for_pat.toml | 6 +-- ...access_github_new_ip_address_for_user.toml | 6 +-- ..._access_github_new_user_agent_for_pat.toml | 6 +-- ...cess_new_okta_authentication_behavior.toml | 10 ++-- ...cess_okta_admin_console_login_failure.toml | 10 ++-- tests/test_all_rules.py | 36 +++++++++++++ 300 files changed, 1450 insertions(+), 1422 deletions(-) diff --git a/detection_rules/etc/non-ecs-schema.json b/detection_rules/etc/non-ecs-schema.json index 3ff5808a895..f8e059db5f4 100644 --- a/detection_rules/etc/non-ecs-schema.json +++ b/detection_rules/etc/non-ecs-schema.json @@ -93,7 +93,6 @@ "file.Ext.header_bytes": "keyword", "file.Ext.entropy": "long", "file.Ext.windows.zone_identifier": "long", - "file.size": "long", "file.Ext.original.name": "keyword", "dll.Ext.device.product_id": "keyword", "dll.Ext.relative_file_creation_time": "double", @@ -119,7 +118,6 @@ "kubernetes.audit.objectRef.subresource": "keyword", "kubernetes.audit.objectRef.name": "keyword", "kubernetes.audit.verb": "keyword", - "kubernetes.audit.objectRef.name": "keyword", "kubernetes.audit.user.username": "keyword", "kubernetes.audit.impersonatedUser.username": "keyword", "kubernetes.audit.annotations.authorization_k8s_io/decision": "keyword", @@ -292,15 +290,8 @@ "okta.debug_context.debug_data.flattened.privilegeGranted": "keyword" }, "logs-network_traffic.http*": { - "data_stream.dataset": "keyword", - "url.path": "keyword", - "http.request.referrer": "keyword", "http.request.headers.content-type": "keyword", - "network.direction": "keyword", - "http.request.method": "keyword", "request": "keyword", - "http.request.body.bytes": "long", - "http.request.body.content": "keyword", "http.response.headers.server": "keyword" }, "metrics-*": { diff --git a/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml b/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml index aeb0868cadf..990ae328f11 100644 --- a/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml +++ b/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Use the `instance_id` field to identify the EC2 instance for which the `GetPasswordData` requests were made", "Check for `RunInstances` API calls to determine if the instance was recently launched or if the password was reset", -"`aws.cloudtrail.error_code` can provide additional context if the `GetPasswordData` request failed or was denied", +"`error.code` can provide additional context if the `GetPasswordData` request failed or was denied", "Review the `aws.cloudtrail.user_identity*` fields to identify the user making the requests and their role permissions", "If a valid account compromise is suspected, review source.* fields for the IP address and geographical location of the request and compare with the user's typical behavior" ] diff --git a/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml b/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml index 50718cc2224..4c1b289b4f0 100644 --- a/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml +++ b/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml @@ -11,10 +11,10 @@ license = "Elastic License v2" notes = [ "Review `azure.signinlogs.properties.authentication_protocol` to verify the authentication method used. Non-interactive SFA is typically reserved for automated processes or legacy authentication methods.", "Review `azure.signinlogs.properties.error_code` to identify the specific error codes associated with the failed authentication attempts. Common error codes include `50053` for account lockouts, `50126` for invalid credentials, and `50055` for expired passwords.", - "Investigate `azure.signinlogs.properties.user_principal_name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", + "Investigate `user.name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", "Analyze `source.as.organization.name` to determine if the request originated from a known hosting provider, VPN, or anonymization service that is unexpected in your environment.", "Examine `source.address` to check if the IP address is associated with previous suspicious activity, high-risk geolocations, or known threat infrastructure.", - "Pivot on `azure.signinlogs.properties.user_principal_name` to identify any other high-risk activities within the same session.", + "Pivot on `user.name` to identify any other high-risk activities within the same session.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to identify possible legacy protocol usage, token replay, permission scopes or bypass mechanisms.", "Review `user_agent.original` to identify the user agent used in the authentication request. Determine if this user agent is expected in your environment or if it is associated with known malicious activity.", ] @@ -35,7 +35,7 @@ from logs-azure.signinlogs* user_agent.original, azure.signinlogs.category, event.outcome, - azure.signinlogs.properties.user_principal_name, + user.name, source.ip | WHERE event.dataset == "azure.signinlogs" @@ -67,7 +67,7 @@ from logs-azure.signinlogs* // count the number of unique user login attempts | stats unique_user_app_login_count = count(*) by - azure.signinlogs.properties.user_principal_name, + user.name, azure.signinlogs.properties.authentication_requirement, azure.signinlogs.properties.app_id | sort unique_user_app_login_count asc diff --git a/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml b/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml index 7e53fd3d2fd..361b1100e0e 100644 --- a/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml +++ b/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml @@ -13,7 +13,7 @@ notes = [ "Device Code Flow authentication is particularly suspicious for non-kiosk, non-IoT devices.", "Analyze `source.as.organization.name` to identify if the authentication originated from a known hosting provider, VPN, or anonymization service you are not expecting", "Investigate `source.address` to determine if the IP address has been previously flagged for suspicious activity.", - "Pivot on `azure.signinlogs.properties.user_principal_name` to check for additional authentication attempts from different IPs, ASNs, or unusual geolocations.", + "Pivot on `user.name` to check for additional authentication attempts from different IPs, ASNs, or unusual geolocations.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to check if legacy protocols, token replay, or bypass mechanisms were involved.", "Look for associated Conditional Access policy decisions in `azure.signinlogs.properties.applied_conditional_access_policies` to determine if the authentication attempt was blocked or allowed.", "Check `azure.signinlogs.properties.device_detail.browser` to see if the user agent is consistent with expected authentication patterns.", @@ -77,7 +77,7 @@ FROM logs-azure.signinlogs-* // aggregate authentication attempts by tenant, user principal name, authentication protocol, category, ASN organization name, and source address | STATS asn_count = count(*) by azure.tenant_id, - azure.signinlogs.properties.user_principal_name, + user.name, azure.signinlogs.properties.authentication_protocol, azure.signinlogs.category, source.as.organization.name, diff --git a/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml b/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml index 293b2614048..0a7ca088a5f 100644 --- a/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml +++ b/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml @@ -15,7 +15,7 @@ notes = [ "Device code flow IS MFA-capable. Single-factor authentication on a device code grant is meaningful — it indicates either no Conditional Access policy targeted the resource, or the policy excludes device code, or no MFA baseline exists. Treat SFA on these grants as elevated risk, not expected behavior.", "Missing `azure.signinlogs.properties.device_detail.*` fields indicate the authenticating endpoint is not Entra-joined, not Intune-enrolled, and not compliant — consistent with an attacker-controlled host completing the flow on the victim's behalf.", "Pivot on `azure.signinlogs.properties.correlation_id`, `session_id`, and `unique_token_identifier` to correlate with subsequent Microsoft Graph activity (`azure.graphactivitylogs-*`), Azure activity (`azure.activitylogs-*`), and M365 audit events (`o365.audit-*`) to map post-compromise actions on the same identity.", - "Pivot on `azure.signinlogs.properties.user_id` against detection alerts on the same cluster to surface stacked alerts on the identity (rare app ID, rare authentication requirement, OAuth phishing first-party app, high-risk sign-in).", + "Pivot on `user.id` against detection alerts on the same cluster to surface stacked alerts on the identity (rare app ID, rare authentication requirement, OAuth phishing first-party app, high-risk sign-in).", "Investigate `user_agent.original` for forged or anomalous tokens (offensive tooling like python-requests, httpx, fasthttp, kali, axiom, nuclei, msal-python, or deliberately silly forged UAs are high-confidence indicators). Real browsers in standard form are not exonerating but do reduce immediate priority.", "Inspect `source.as.organization.name` and `source.geo.country_iso_code` against the user's normal sign-in pattern. Sudden non-Microsoft hosting providers, residential VPNs, or unexpected geographies on these flows are high-priority.", "Microsoft-owned ASNs (MICROSOFT-CORP-MSN-AS-BLOCK / AS8075) are excluded by default but can be re-enabled for tenants where Azure-hosted infrastructure abuse is in scope.", @@ -103,7 +103,7 @@ FROM logs-azure.signinlogs-* correlation_ids = VALUES(azure.signinlogs.properties.correlation_id), session_ids = VALUES(azure.signinlogs.properties.session_id) BY - azure.signinlogs.properties.user_principal_name, + user.name, azure.signinlogs.properties.app_display_name, azure.signinlogs.properties.resource_display_name, azure.signinlogs.properties.authentication_requirement diff --git a/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml b/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml index 9f017e5ebd9..4787265b208 100644 --- a/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml +++ b/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml @@ -11,10 +11,10 @@ license = "Elastic License v2" notes = [ "Review `azure.signinlogs.properties.authentication_protocol` to verify the authentication method used. Non-interactive SFA is typically reserved for automated processes or legacy authentication methods.", "Review `azure.signinlogs.properties.error_code` to identify the specific error codes associated with the failed authentication attempts. Common error codes include `50053` for account lockouts, `50126` for invalid credentials, and `50055` for expired passwords.", - "Investigate `azure.signinlogs.properties.user_principal_name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", + "Investigate `user.name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", "Analyze `source.as.organization.name` to determine if the request originated from a known hosting provider, VPN, or anonymization service that is unexpected in your environment.", "Examine `source.address` to check if the IP address is associated with previous suspicious activity, high-risk geolocations, or known threat infrastructure.", - "Pivot on `azure.signinlogs.properties.user_principal_name` to identify any other high-risk activities within the same session.", + "Pivot on `user.name` to identify any other high-risk activities within the same session.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to identify possible legacy protocol usage, token replay, permission scopes or bypass mechanisms.", ] mitre = ['T1078.004','T1110.003'] @@ -34,7 +34,7 @@ from logs-azure.signinlogs* source.as.organization.name, azure.signinlogs.category, event.outcome, - azure.signinlogs.properties.user_principal_name, + user.name, source.ip // truncate the timestamp to a 10-minute window | eval target_time_window = DATE_TRUNC(10 minutes, @timestamp) @@ -48,7 +48,7 @@ from logs-azure.signinlogs* and azure.signinlogs.properties.status.error_code in (50053, 50126, 50055, 50056, 50064, 50144) // count the number of unique user login attempts | stats - unique_user_login_count = count_distinct(azure.signinlogs.properties.user_principal_name) by target_time_window, azure.signinlogs.properties.status.error_code + unique_user_login_count = count_distinct(user.name) by target_time_window, azure.signinlogs.properties.status.error_code // filter for >= 30 failed SFA auth attempts with the same error codes | where unique_user_login_count >= 30 ''' diff --git a/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml b/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml index 8124767050e..f59ce291f19 100644 --- a/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml +++ b/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml @@ -31,7 +31,7 @@ FROM logs-azure.auditlogs* | WHERE @timestamp > now() - 60 day | WHERE event.dataset == "azure.auditlogs" - AND azure.auditlogs.operation_name == "Add service principal credentials" + AND event.action == "Add service principal credentials" AND event.outcome == "success" | EVAL // Extract appId from additional_details @@ -45,12 +45,12 @@ FROM logs-azure.auditlogs* // Bucket events by each week timestamp_week_bucket = DATE_TRUNC(7 day, @timestamp) | STATS - operation = VALUES(azure.auditlogs.operation_name), + operation = VALUES(event.action), app_id = VALUES(azure.auditlogs.properties.additional_details.appId), correlation_id = VALUES(azure.auditlogs.properties.correlation_id), identity = VALUES(azure.auditlogs.properties.identity), initiated_by_id = VALUES(azure.auditlogs.properties.initiated_by.user.id), - user_principal_name = VALUES(azure.auditlogs.properties.initiated_by.user.userPrincipalName), + user_principal_name = VALUES(user.name), tenant_id = VALUES(azure.auditlogs.properties.tenantId), modified_properties_new = VALUES(azure.auditlogs.properties.target_resources.`0`.modified_properties.`0`.new_value), modified_properties_old = VALUES(azure.auditlogs.properties.target_resources.`0`.modified_properties.`0`.old_value), diff --git a/hunting/azure/queries/entra_suspicious_odata_client_requests.toml b/hunting/azure/queries/entra_suspicious_odata_client_requests.toml index 4b9aa793210..53854d8f430 100644 --- a/hunting/azure/queries/entra_suspicious_odata_client_requests.toml +++ b/hunting/azure/queries/entra_suspicious_odata_client_requests.toml @@ -12,7 +12,7 @@ notes = [ "Review `azure.auditlogs.properties.additional_details.value` for `Microsoft.OData.Client/*` User-Agent strings. This is uncommon for legitimate first-party Microsoft applications and may indicate use of ROADTools or custom automation to register a device and obtain a PRT.", "Check `azure.auditlogs.properties.initiated_by` for both `user` and `app` fields. The presence of both may suggest an OAuth on-behalf-of (OBO) flow, where the app is acting with delegated permissions from a phished user token.", "Review `azure.auditlogs.properties.activity_display_name` and `operation_name` for device registration operations like `Add device` or `Add registered owner to device`. When combined with suspicious user-agents, this may indicate unauthorized device registration.", - "Review `azure.auditlogs.identity` for operations performed by `Device Registration Service`. This service name is commonly associated with device join flows that, if abused, may enable persistence via PRT acquisition.", + "Review `user.full_name` for operations performed by `Device Registration Service`. This service name is commonly associated with device join flows that, if abused, may enable persistence via PRT acquisition.", "Correlate with `azure.signinlogs` for sign-ins using the same `correlation_id` or `userPrincipalName`. Look for signs of previous OAuth token issuance or multi-geo IP behavior surrounding the device registration.", "Investigate whether the device registered (under `azure.auditlogs.properties.target_resources`) corresponds to known or authorized endpoints. Devices with names like `DESKTOP-ATTACKER1` or unexpected OS versions may indicate rogue joins.", "The source IP is likely to be Microsoft-managed infrastructure as requests are proxied through Azure services. Pivoting into which user principal the request is targeting and events leading up to the request may provide additional context." @@ -34,27 +34,27 @@ FROM logs-azure.auditlogs* METADATA _id, _index // Identify logs with the known suspicious OData user agent AND azure.auditlogs.properties.additional_details.value LIKE "Microsoft.OData.Client/*" - AND azure.auditlogs.identity != "Device Registration Service" + AND user.full_name != "Device Registration Service" // Extract time window for pattern analysis | EVAL time_window = DATE_TRUNC(1d, @timestamp) // Normalize actor: prefer user UPN if available, else fallback to app name | EVAL actor = COALESCE( - azure.auditlogs.properties.initiated_by.user.userPrincipalName, + user.name, azure.auditlogs.properties.initiated_by.app.displayName, "unknown" ) // Keep core fields -| KEEP @timestamp, actor, source.ip, azure.auditlogs.operation_name, azure.auditlogs.properties.activity_display_name, azure.auditlogs.identity, azure.auditlogs.properties.tenantId, azure.auditlogs.properties.initiated_by.app.servicePrincipalId, azure.auditlogs.properties.category, azure.auditlogs.properties.additional_details.value, time_window +| KEEP @timestamp, actor, source.ip, event.action, azure.auditlogs.properties.activity_display_name, user.full_name, azure.auditlogs.properties.tenantId, azure.auditlogs.properties.initiated_by.app.servicePrincipalId, azure.auditlogs.properties.category, azure.auditlogs.properties.additional_details.value, time_window // Group by actor per day | STATS count = COUNT(), unique_ips = COUNT_DISTINCT(source.ip), - operations = VALUES(azure.auditlogs.operation_name), - identities = VALUES(azure.auditlogs.identity), + operations = VALUES(event.action), + identities = VALUES(user.full_name), ips = VALUES(source.ip), categories = VALUES(azure.auditlogs.properties.category), clients = VALUES(azure.auditlogs.properties.additional_details.value) diff --git a/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml b/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml index 0b5c48bc285..20ee0612142 100644 --- a/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml +++ b/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml @@ -11,10 +11,10 @@ license = "Elastic License v2" notes = [ "Review `azure.signinlogs.properties.authentication_protocol` to verify the authentication method used. Non-interactive SFA is typically reserved for automated processes or legacy authentication methods.", "Review `azure.signinlogs.properties.error_code` to identify the specific error codes associated with the failed authentication attempts. Common error codes include `50053` for account lockouts, `50126` for invalid credentials, and `50055` for expired passwords.", - "Investigate `azure.signinlogs.properties.user_principal_name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", + "Investigate `user.name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", "Analyze `source.as.organization.name` to determine if the request originated from a known hosting provider, VPN, or anonymization service that is unexpected in your environment.", "Examine `source.address` to check if the IP address is associated with previous suspicious activity, high-risk geolocations, or known threat infrastructure.", - "Pivot on `azure.signinlogs.properties.user_principal_name` to identify any other high-risk activities within the same session.", + "Pivot on `user.name` to identify any other high-risk activities within the same session.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to identify possible legacy protocol usage, token replay, permission scopes or bypass mechanisms.", ] mitre = ['T1078.004','T1110.003'] @@ -29,7 +29,7 @@ from logs-azure.signinlogs* event.category, azure.signinlogs.properties.app_display_name, azure.signinlogs.properties.app_id, - azure.signinlogs.properties.user_principal_name, + user.name, azure.signinlogs.properties.status.error_code, azure.signinlogs.category, source.as.organization.name, @@ -45,7 +45,7 @@ from logs-azure.signinlogs* // aggregate the number of failed sign-in attempts by user and app ID reported | stats auth_via_app_count = count(*) by - azure.signinlogs.properties.user_principal_name, + user.name, azure.signinlogs.properties.app_display_name, azure.signinlogs.properties.app_id // filter for users with less than or equal to 3 failed sign-in attempts per app diff --git a/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml b/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml index b0c20360235..8bb5159d6b1 100644 --- a/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml +++ b/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml @@ -9,7 +9,7 @@ name = "Rapid MFA Deny Push Notifications (MFA Bombing)" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`okta.actor.alternate_id` is the targeted user account.", + "`user.name` is the targeted user account.", "Pivot and search for `event.action` is `user.authentication.auth_via_mfa` to determine if the target user accepted the MFA push notification.", "If a MFA bombing attack is suspected, both username and password are required prior to MFA push notifications. Thus the credentials are likely compromised.", ] @@ -26,7 +26,7 @@ from logs-okta* | where event.action == "user.mfa.okta_verify.deny_push" // Count the number of MFA deny push notifications for each user in each 10 minute window -| stats deny_push_count = count(*) by target_time_window, okta.actor.alternate_id +| stats deny_push_count = count(*) by target_time_window, user.name // Filter for users with more than 5 MFA deny push notifications | where deny_push_count >= 5 diff --git a/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml b/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml index f74cf1453ac..77f5228dbbd 100644 --- a/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml +++ b/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml @@ -9,9 +9,9 @@ name = "Rapid Reset Password Requests for Different Users" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`okta.actor.alternate_id` is the potentially compromised account", - "An API access token may have been compromised, where okta.actor.alternate_id reflects the owner", - "To identify a list of tokens this user created, search for the `okta.actor.alternate_id` where `event.action` is `system.api_token*` which may require a larger time window" + "`user.name` is the potentially compromised account", + "An API access token may have been compromised, where user.name reflects the owner", + "To identify a list of tokens this user created, search for the `user.name` where `event.action` is `system.api_token*` which may require a larger time window" ] mitre = ['T1098.001'] query = [''' @@ -22,12 +22,12 @@ from logs-okta.system* | where event.dataset == "okta.system" and event.action == "user.account.reset_password" and source.user.full_name != user.target.full_name // Extract relevant fields -| keep @timestamp, okta.actor.alternate_id, okta.debug_context.debug_data.dt_hash, user.target.full_name, okta.outcome.result +| keep @timestamp, user.name, okta.debug_context.debug_data.dt_hash, user.target.full_name, event.outcome // Count the number of reset password attempts for each user | stats user_count = count_distinct(user.target.full_name), - reset_counts = by okta.actor.alternate_id, source.user.full_name, okta.debug_context.debug_data.dt_hash + reset_counts = by user.name, source.user.full_name, okta.debug_context.debug_data.dt_hash // Filter for more than 10 unique users and more than 15 reset password attempts by the source | where user_count > 10 and reset_counts > 15 diff --git a/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml b/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml index ea38cd6c528..9ec60555382 100644 --- a/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml +++ b/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Review `okta.debug_context.debug_data.flattened.grantType` to identify if the grant type is `client_credentials`", "Ignore `okta.debug_context.debug_data.flattened.requestedScopes` values that indicate read-only access", - "Review `okta.actor.display_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", + "Review `user.full_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", "Pivot for successful access token retrieval by the same public client app by searching `event.action` equal to `app.oauth2.as.token.grant.access_token` where the display name is the same." ] mitre = ['T1550.001'] @@ -24,16 +24,16 @@ from logs-okta.system* // filter on failed access token grant requests where source is a public client app and event.action == "app.oauth2.as.token.grant" and okta.actor.type == "PublicClientApp" - and okta.outcome.result == "FAILURE" + and event.outcome == "FAILURE" // filter out known Okta and Datadog actors and not ( - okta.actor.display_name LIKE "Okta%" - or okta.actor.display_name LIKE "Datadog%" + user.full_name LIKE "Okta%" + or user.full_name LIKE "Datadog%" ) // filter for scopes that are not implicitly granted - and okta.outcome.reason == "no_matching_scope" + and event.reason == "no_matching_scope" -| keep @timestamp, event.action, okta.actor.type, okta.outcome.result, okta.outcome.reason, okta.actor.display_name +| keep @timestamp, event.action, okta.actor.type, event.outcome, event.reason, user.full_name '''] \ No newline at end of file diff --git a/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml b/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml index 168413e7d8b..efc050320de 100644 --- a/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml +++ b/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml @@ -33,7 +33,7 @@ from logs-okta* | dissect okta.debug_context.debug_data.request_uri"%{?}/app/%{target_application}/" // count the number of unique applications per source IP and user in a 5-minute window -| stats application_count = count_distinct(target_application), window_count = count(*) by target_time_window, source.ip, okta.actor.alternate_id +| stats application_count = count_distinct(target_application), window_count = count(*) by target_time_window, source.ip, user.name // filter for at least 15 distinct applications authenticated from a single source IP | where application_count > 15 diff --git a/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml b/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml index d1f76770846..0efc7ee494c 100644 --- a/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml +++ b/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Review `okta.debug_context.debug_data.flattened.grantType` to identify if the grant type is `client_credentials`", "Ignore `okta.debug_context.debug_data.flattened.requestedScopes` values that indicate read-only access", - "Review `okta.actor.display_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", + "Review `user.full_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", "Filter on the public client app and aggregate by `event.action` to determine what actions were taken by the public client app after the access token was granted." ] mitre = ['T1550.001'] @@ -32,10 +32,10 @@ from logs-okta.system* and okta.actor.type == "PublicClientApp" // ignore Elastic Okta integration and DataDog actors - and not (okta.actor.display_name LIKE "Okta*" or okta.actor.display_name LIKE "Datadog*") + and not (user.full_name LIKE "Okta*" or user.full_name LIKE "Datadog*") // count the number of access tokens granted by the same public client app in a day -| stats token_granted_count = count(*), unique_client_ip = count_distinct(okta.client.ip) by target_time_window, okta.actor.display_name +| stats token_granted_count = count(*), unique_client_ip = count_distinct(source.ip) by target_time_window, user.full_name // filter where access tokens were granted on the same day but client addresses are different | where unique_client_ip >= 2 and token_granted_count >= 2 diff --git a/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml b/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml index f01aa37cc81..81d4b46d155 100644 --- a/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml +++ b/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Review `okta.debug_context.debug_data.flattened.grantType` to identify if the grant type is `client_credentials`", "Ignore `okta.debug_context.debug_data.flattened.requestedScopes` values that indicate read-only access", - "Review `okta.actor.display_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", + "Review `user.full_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", "False-positives may exist if the public client app is new or has not been used in the last 14 days." ] mitre = ['T1550.001'] @@ -29,11 +29,11 @@ from logs-okta.system* and okta.actor.type == "PublicClientApp" // ignore Elastic Okta integration and DataDog actors - and not okta.client.user_agent.raw_user_agent == "Okta-Integrations" - and not (okta.actor.display_name LIKE "Okta%" or okta.actor.display_name LIKE "Datadog%") + and not user_agent.original == "Okta-Integrations" + and not (user.full_name LIKE "Okta%" or user.full_name LIKE "Datadog%") // count the number of access tokens granted by the same public client app -| stats token_granted_count = count(*) by okta.actor.display_name +| stats token_granted_count = count(*) by user.full_name // filter where the public client app has only been granted an access token once in the last 14 days | where token_granted_count == 1 diff --git a/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml b/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml index 10c16c1aeca..96fe880dded 100644 --- a/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml +++ b/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml @@ -9,7 +9,7 @@ name = "Identify High Average of Failed Daily Authentication Attempts" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "Pivot to users by only keeping the first stats statement where `okta.actor.alternate_id` is the targeted accounts.", + "Pivot to users by only keeping the first stats statement where `user.name` is the targeted accounts.", "Pivot for successful logins from the same source IP by searching for `event.action` equal to `user.session.start` or `user.authentication.verify` where the outcome is `SUCCESS`.", "User agents can be used to identify anomalous behavior, such as a user agent that is not associated with a known application or user.", "Another `WHERE` count can be added to the query if activity has been baseline to filter out known behavior." @@ -25,13 +25,13 @@ from logs-okta* // filter for invalid credential authentication events event.action == "user.session.start" - and okta.outcome.result == "FAILURE" - and okta.outcome.reason == "INVALID_CREDENTIALS" + and event.outcome == "FAILURE" + and event.reason == "INVALID_CREDENTIALS" and okta.actor.type == "User" | stats // count the number of daily failed logins for each day and user - failed_daily_logins = count(*) by target_time_window, okta.actor.alternate_id + failed_daily_logins = count(*) by target_time_window, user.name | stats // calculate the average number of daily failed logins for each day diff --git a/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml b/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml index dee9a1dca7a..ff8f5822f55 100644 --- a/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml +++ b/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml @@ -9,8 +9,8 @@ name = "Successful Impossible Travel Sign-On Events" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`okta.actor.alternate_id` would be target of the threat adversary", - "Pivoting into a potential compromise requires an additional search for `okta.outcome.result` being `SUCCESS` for any `user.authentication*` value for `okta.event_type`", + "`user.name` would be target of the threat adversary", + "Pivoting into a potential compromise requires an additional search for `event.outcome` being `SUCCESS` for any `user.authentication*` value for `event.action`", "Pivot to any additional Okta logs after authentication to determine if activity is still being reported by separate countries." ] mitre = ['T1078.004'] @@ -20,14 +20,14 @@ from logs-okta.system* | where event.dataset == "okta.system" // filter on successful sign-on events only - and okta.event_type == "policy.evaluate_sign_on" - and okta.outcome.result in ("ALLOW", "SUCCESS") + and event.action == "policy.evaluate_sign_on" + and event.outcome in ("ALLOW", "SUCCESS") // Truncate the timestamp to 1 hour intervals | eval time_window = DATE_TRUNC(1 hours, @timestamp) // Count the number of successful sign-on events for each user every 15 minutes -| stats country_count = count_distinct(client.geo.country_name) by okta.actor.alternate_id, time_window +| stats country_count = count_distinct(client.geo.country_name) by user.name, time_window // Filter for users who sign on from more than one country in a 15 minute interval | where country_count >= 2 diff --git a/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml b/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml index 2d1d636410a..424e2d3d201 100644 --- a/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml +++ b/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml @@ -9,7 +9,7 @@ name = "Password Spraying from Repeat Source" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`okta.actor.alternate_id` are the targeted accounts.", + "`user.name` are the targeted accounts.", "Pivot for successful logins from the same source IP by searching for `event.action` equal to `user.session.start` or `user.authentication.verify` where the outcome is `SUCCESS`.", "User agents can be used to identify anomalous behavior, such as a user agent that is not associated with a known application or user.", "The `target_count` can be adjusted depending on the organization's account lockout policy or baselined behavior." @@ -25,14 +25,14 @@ from logs-okta* // filter for invalid credential events event.action == "user.session.start" - and okta.outcome.result == "FAILURE" - and okta.outcome.reason == "INVALID_CREDENTIALS" + and event.outcome == "FAILURE" + and event.reason == "INVALID_CREDENTIALS" | stats // count the distinct number of targeted accounts - target_count = count_distinct(okta.actor.alternate_id), + target_count = count_distinct(user.name), // count the number of invalid credential events for each source IP - source_count = count(*) by target_time_window, okta.client.ip + source_count = count(*) by target_time_window, source.ip // filter for source IPs with more than 5 invalid credential events | where target_count >= 10 diff --git a/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml b/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml index d67152cdd71..18c3072f7f8 100644 --- a/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml +++ b/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml @@ -9,8 +9,8 @@ name = "Multi-Factor Authentication (MFA) Push Notification Bombing" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`okta.actor.alternate_id` would be target of the threat adversary", - "Pivoting into a potential compromise requires an additional search for `okta.outcome.result` being `SUCCESS` for any `user.authentication*` value for `okta.event_type`", + "`user.name` would be target of the threat adversary", + "Pivoting into a potential compromise requires an additional search for `event.outcome` being `SUCCESS` for any `user.authentication*` value for `event.action`", "For a smaller window (rapid denies), reduce from 1 hour to 30 minutes or lower" ] mitre = ['T1556.006'] @@ -25,7 +25,7 @@ from logs-okta.system* | eval hourly_count = date_trunc(1 hour, event.ingested) // Count the number of deny push notifications for each user every hour -| stats hourly_denies = count(*) by okta.actor.alternate_id, hourly_count +| stats hourly_denies = count(*) by user.name, hourly_count // Filter for users who deny more than 5 push notifications in a single hour | where hourly_denies > 5 diff --git a/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml b/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml index 44d595f3575..72a0023f215 100644 --- a/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml +++ b/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml @@ -9,7 +9,7 @@ name = "Rare Occurrence of Domain with User Authentication Events" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "Pivot into potential compromised accounts by searching for the `okta.actor.alternate_id` in `okta.target` where `event.action` is `user.lifecycle.create`. This would identify when the user account was created. The `okta.actor.alternate_id` of this event will also be the potential compromised account.", + "Pivot into potential compromised accounts by searching for the `user.name` in `okta.target` where `event.action` is `user.lifecycle.create`. This would identify when the user account was created. The `user.name` of this event will also be the potential compromised account.", ] mitre = ['T1078.004'] query = [''' @@ -17,11 +17,11 @@ from logs-okta* | where @timestamp > NOW() - 7 day | where // Filter for user authentication events - okta.actor.alternate_id is not null + user.name is not null and event.action LIKE "user.authentication*" // Extract the top-level domain (TLD) from the user's email address -| dissect okta.actor.alternate_id "%{}@%{tld}" +| dissect user.name "%{}@%{tld}" // Count the number of user authentication events for each TLD | stats tld_auth_counts = count(*) by tld diff --git a/hunting/windows/queries/windows_logon_activity_by_source_ip.toml b/hunting/windows/queries/windows_logon_activity_by_source_ip.toml index 3647b68d90b..15eaea87f30 100644 --- a/hunting/windows/queries/windows_logon_activity_by_source_ip.toml +++ b/hunting/windows/queries/windows_logon_activity_by_source_ip.toml @@ -22,7 +22,7 @@ from logs-system.security-* /* noisy failure status codes often associated to authentication misconfiguration */ not (event.action == "logon-failed" and winlog.event_data.Status in ("0xC000015B", "0XC000005E", "0XC0000133", "0XC0000192")) | eval failed = case(event.action == "logon-failed", source.ip, null), success = case(event.action == "logged-in", source.ip, null) -| stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(winlog.event_data.TargetUserName) by source.ip +| stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(user.target.name) by source.ip /* below threshold should be adjusted to your env logon patterns */ | where count_failed >= 100 and count_success <= 10 and count_user >= 20 ''' diff --git a/rules/cross-platform/credential_access_multi_could_secrets_via_api.toml b/rules/cross-platform/credential_access_multi_could_secrets_via_api.toml index 561b9785723..45d9a279b00 100644 --- a/rules/cross-platform/credential_access_multi_could_secrets_via_api.toml +++ b/rules/cross-platform/credential_access_multi_could_secrets_via_api.toml @@ -2,7 +2,7 @@ creation_date = "2025/12/01" integration = ["aws", "gcp", "azure", "kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -136,7 +136,7 @@ FROM logs-azure.platformlogs-*, logs-aws.cloudtrail-*, logs-gcp.audit-*, logs-ku event.action IN ("google.cloud.secretmanager.v1.SecretManagerService.AccessSecretVersion", "google.cloud.secretmanager.v1.SecretManagerService.GetSecretRequest")) OR /* Kubernetes Secrets */ - (data_stream.dataset == "kubernetes.audit_logs" AND kubernetes.audit.objectRef.resource == "secrets" AND kubernetes.audit.verb IN ("get", "list")) + (data_stream.dataset == "kubernetes.audit_logs" AND orchestrator.resource.type == "secrets" AND event.action IN ("get", "list")) ) AND source.ip IS NOT NULL @@ -173,7 +173,7 @@ FROM logs-azure.platformlogs-*, logs-aws.cloudtrail-*, logs-gcp.audit-*, logs-ku Esql.gcp_project_id_values = VALUES(CASE(Esql.cloud_vendor == "gcp", cloud.account.id, "unknown")), // Generic cloud metadata Esql.cloud_region_values = VALUES(cloud.region), - Esql.k8s_namespace_values = VALUES(kubernetes.audit.objectRef.namespace), + Esql.k8s_namespace_values = VALUES(orchestrator.namespace), // Namespace values Esql.data_stream_namespace_values = VALUES(data_stream.namespace), Esql_priv.user_name_values = VALUES(user.name) diff --git a/rules/cross-platform/execution_d4c_k8s_mda_forbidden_direct_interactive_kubernetes_api_request.toml b/rules/cross-platform/execution_d4c_k8s_mda_forbidden_direct_interactive_kubernetes_api_request.toml index c4fee6e516f..ea1af353aeb 100644 --- a/rules/cross-platform/execution_d4c_k8s_mda_forbidden_direct_interactive_kubernetes_api_request.toml +++ b/rules/cross-platform/execution_d4c_k8s_mda_forbidden_direct_interactive_kubernetes_api_request.toml @@ -4,7 +4,7 @@ integration = ["cloud_defend", "kubernetes"] maturity = "production" min_stack_comments = "Defend for Containers integration was re-introduced in 9.3.0" min_stack_version = "9.3.0" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -108,7 +108,7 @@ sequence with maxspan=1s ) and process.interactive == true and container.id like "*" ] by orchestrator.resource.name [any where data_stream.dataset == "kubernetes.audit_logs" and kubernetes.audit.stage in ("ResponseComplete", "ResponseStarted") and - `kubernetes.audit.annotations.authorization_k8s_io/decision` == "forbid" + `event.outcome` == "forbid" ] by `kubernetes.audit.user.extra.authentication.kubernetes.io/pod-name` ''' diff --git a/rules/cross-platform/execution_d4c_k8s_mda_kubernetes_api_activity_by_unusual_utilities.toml b/rules/cross-platform/execution_d4c_k8s_mda_kubernetes_api_activity_by_unusual_utilities.toml index dc3e15d6714..00d13d17b18 100644 --- a/rules/cross-platform/execution_d4c_k8s_mda_kubernetes_api_activity_by_unusual_utilities.toml +++ b/rules/cross-platform/execution_d4c_k8s_mda_kubernetes_api_activity_by_unusual_utilities.toml @@ -4,7 +4,7 @@ integration = ["cloud_defend", "kubernetes"] maturity = "production" min_stack_comments = "Defend for Containers integration was re-introduced in 9.3.0" min_stack_version = "9.3.0" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -115,9 +115,9 @@ sequence with maxspan=1s [any where data_stream.dataset == "kubernetes.audit_logs" and kubernetes.audit.stage in ("ResponseStarted","ResponseComplete") and - kubernetes.audit.verb in ("get", "list", "watch", "create", "patch", "update") and + event.action in ("get", "list", "watch", "create", "patch", "update") and ( - kubernetes.audit.objectRef.resource in ( + orchestrator.resource.type in ( "pods", "secrets", "serviceaccounts", "configmaps", "roles", "rolebindings", "clusterroles", "clusterrolebindings", "deployments", "daemonsets", "statefulsets", "jobs", "cronjobs", @@ -125,7 +125,7 @@ sequence with maxspan=1s "selfsubjectaccessreviews", "selfsubjectrulesreviews", "subjectaccessreviews" ) or ( - kubernetes.audit.objectRef.resource == "pods" and + orchestrator.resource.type == "pods" and kubernetes.audit.objectRef.subresource in ("exec", "attach", "portforward", "log") ) ) diff --git a/rules/integrations/aws/credential_access_aws_getpassword_for_ec2_instance.toml b/rules/integrations/aws/credential_access_aws_getpassword_for_ec2_instance.toml index f11d091d592..e76d7ad767e 100644 --- a/rules/integrations/aws/credential_access_aws_getpassword_for_ec2_instance.toml +++ b/rules/integrations/aws/credential_access_aws_getpassword_for_ec2_instance.toml @@ -2,7 +2,7 @@ creation_date = "2024/04/10" integration = ["aws"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -72,7 +72,7 @@ type = "new_terms" query = ''' data_stream.dataset:"aws.cloudtrail" and event.provider:"ec2.amazonaws.com" and event.action:"GetPasswordData" - and aws.cloudtrail.user_identity.type:"AssumedRole" and aws.cloudtrail.error_code:"Client.UnauthorizedOperation" + and aws.cloudtrail.user_identity.type:"AssumedRole" and error.code:"Client.UnauthorizedOperation" ''' [rule.investigation_fields] @@ -87,7 +87,7 @@ field_names = [ "aws.cloudtrail.user_identity.access_key_id", "event.action", "event.outcome", - "aws.cloudtrail.error_code", + "error.code", "aws.cloudtrail.request_parameters", "cloud.account.id", "cloud.region" diff --git a/rules/integrations/aws/credential_access_iam_long_term_access_key_correlated_with_elevated_detection_alerts.toml b/rules/integrations/aws/credential_access_iam_long_term_access_key_correlated_with_elevated_detection_alerts.toml index 0a1d4e89780..6c35f264a41 100644 --- a/rules/integrations/aws/credential_access_iam_long_term_access_key_correlated_with_elevated_detection_alerts.toml +++ b/rules/integrations/aws/credential_access_iam_long_term_access_key_correlated_with_elevated_detection_alerts.toml @@ -2,8 +2,8 @@ creation_date = "2026/04/06" integration = ["aws"] maturity = "production" -updated_date = "2026/04/06" -min_stack_comments = "New entity classification fields added: user.entity.id" +updated_date = "2026/06/23" +min_stack_comments = "New entity classification fields added: aws.cloudtrail.user_identity.arn" min_stack_version = "9.2.0" [rule] @@ -114,7 +114,7 @@ from .alerts-security.* METADATA _id, _version, _index Esql.kibana_alert_rule_id_values = VALUES(kibana.alert.rule.rule_id), Esql.kibana_alert_risk_score_values = VALUES(kibana.alert.risk_score), Esql.kibana_alert_severity_values = VALUES(kibana.alert.severity), - Esql.user_entity_id_values = VALUES(user.entity.id), + Esql.user_entity_id_values = VALUES(aws.cloudtrail.user_identity.arn), Esql.timestamp_min = MIN(@timestamp), Esql.timestamp_max = MAX(@timestamp) by source.ip diff --git a/rules/integrations/aws/discovery_iam_principal_enumeration_via_update_assume_role_policy.toml b/rules/integrations/aws/discovery_iam_principal_enumeration_via_update_assume_role_policy.toml index 3a0b69bd9f2..2b0df44d7e0 100644 --- a/rules/integrations/aws/discovery_iam_principal_enumeration_via_update_assume_role_policy.toml +++ b/rules/integrations/aws/discovery_iam_principal_enumeration_via_update_assume_role_policy.toml @@ -2,7 +2,7 @@ creation_date = "2020/07/16" integration = ["aws"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -108,7 +108,7 @@ query = ''' data_stream.dataset: "aws.cloudtrail" and event.provider: "iam.amazonaws.com" and event.action: "UpdateAssumeRolePolicy" - and aws.cloudtrail.error_code: "MalformedPolicyDocumentException" + and error.code: "MalformedPolicyDocumentException" and event.outcome: "failure" ''' diff --git a/rules/integrations/aws/exfiltration_s3_bucket_policy_added_for_external_account_access.toml b/rules/integrations/aws/exfiltration_s3_bucket_policy_added_for_external_account_access.toml index 0fb3121a22b..3a2e4228640 100644 --- a/rules/integrations/aws/exfiltration_s3_bucket_policy_added_for_external_account_access.toml +++ b/rules/integrations/aws/exfiltration_s3_bucket_policy_added_for_external_account_access.toml @@ -2,7 +2,7 @@ creation_date = "2024/04/17" integration = ["aws"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -142,7 +142,7 @@ info where data_stream.dataset == "aws.cloudtrail" ) and not stringContains(aws.cloudtrail.request_parameters, "arn:aws:cloudfront::") and not stringContains(aws.cloudtrail.request_parameters, "arn:aws:iam::cloudfront:user") -and not stringContains(aws.cloudtrail.request_parameters, aws.cloudtrail.recipient_account_id) +and not stringContains(aws.cloudtrail.request_parameters, cloud.account.id) ''' diff --git a/rules/integrations/aws/impact_aws_s3_bucket_enumeration_or_brute_force.toml b/rules/integrations/aws/impact_aws_s3_bucket_enumeration_or_brute_force.toml index dae825c1569..02332f525fb 100644 --- a/rules/integrations/aws/impact_aws_s3_bucket_enumeration_or_brute_force.toml +++ b/rules/integrations/aws/impact_aws_s3_bucket_enumeration_or_brute_force.toml @@ -2,7 +2,7 @@ creation_date = "2024/05/01" integration = ["aws"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -97,7 +97,7 @@ type = "threshold" query = ''' data_stream.dataset: "aws.cloudtrail" and event.provider : "s3.amazonaws.com" and - aws.cloudtrail.error_code : "AccessDenied" and + error.code : "AccessDenied" and tls.client.server_name : * ''' diff --git a/rules/integrations/aws/initial_access_console_login_root.toml b/rules/integrations/aws/initial_access_console_login_root.toml index 5c32877a96e..07e4285b56d 100644 --- a/rules/integrations/aws/initial_access_console_login_root.toml +++ b/rules/integrations/aws/initial_access_console_login_root.toml @@ -2,7 +2,7 @@ creation_date = "2020/06/11" integration = ["aws"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -25,7 +25,7 @@ note = """## Triage and analysis The AWS root user is the original identity with unrestricted privileges over every resource in the account. Because it bypasses IAM boundaries and carries irreversible privileges, any successful root console login should be treated as a critical security event. AWS explicitly recommends locking away the root credentials and only using them for a small number of account-level administrative tasks (for example, closing an account, modifying support plans, or restoring MFA). See [Tasks that require the root user](https://docs.aws.amazon.com/general/latest/gr/root-vs-iam.html#aws_tasks-that-require-root). -This rule detects a successful AWS Management Console login by the root user (`ConsoleLogin` events with `userIdentity.type: Root` and `event.outcome: Success`). +This rule detects a successful AWS Management Console login by the root user (`ConsoleLogin` events with `userIdentity.type: Root` and `event.outcome: success`). #### Possible investigation steps diff --git a/rules/integrations/aws/ml_cloudtrail_error_message_spike.toml b/rules/integrations/aws/ml_cloudtrail_error_message_spike.toml index 1fb11e95294..4c554249b53 100644 --- a/rules/integrations/aws/ml_cloudtrail_error_message_spike.toml +++ b/rules/integrations/aws/ml_cloudtrail_error_message_spike.toml @@ -2,7 +2,7 @@ creation_date = "2020/07/13" integration = ["aws"] maturity = "production" -updated_date = "2025/11/18" +updated_date = "2026/06/23" [rule] anomaly_threshold = 50 @@ -54,7 +54,7 @@ This rule uses a machine learning job to detect a significant spike in the rate #### Possible investigation steps -- Examine the history of the error. If the error only manifested recently, it might be related to recent changes in an automation module or script. You can find the error in the `aws.cloudtrail.error_code field` field. +- Examine the history of the error. If the error only manifested recently, it might be related to recent changes in an automation module or script. You can find the error in the `error.code field` field. - Investigate other alerts associated with the user account during the past 48 hours. - Validate the activity is not related to planned patches, updates, or network administrator activity. - Examine the request parameters. These may indicate the source of the program or the nature of the task being performed when the error occurred. diff --git a/rules/integrations/aws/ml_cloudtrail_rare_error_code.toml b/rules/integrations/aws/ml_cloudtrail_rare_error_code.toml index f428b4da9a8..5bd96113820 100644 --- a/rules/integrations/aws/ml_cloudtrail_rare_error_code.toml +++ b/rules/integrations/aws/ml_cloudtrail_rare_error_code.toml @@ -2,7 +2,7 @@ creation_date = "2020/07/13" integration = ["aws"] maturity = "production" -updated_date = "2025/11/18" +updated_date = "2026/06/23" [rule] anomaly_threshold = 50 @@ -56,7 +56,7 @@ Detection alerts from this rule indicate a rare and unusual error code that was #### Possible investigation steps -- Examine the history of the error. If the error only manifested recently, it might be related to recent changes in an automation module or script. You can find the error in the `aws.cloudtrail.error_code field` field. +- Examine the history of the error. If the error only manifested recently, it might be related to recent changes in an automation module or script. You can find the error in the `error.code field` field. - Investigate other alerts associated with the user account during the past 48 hours. - Validate the activity is not related to planned patches, updates, or network administrator activity. - Examine the request parameters. These may indicate the source of the program or the nature of the task being performed when the error occurred. diff --git a/rules/integrations/aws/persistence_bedrock_foundation_model_access_denied_attempt.toml b/rules/integrations/aws/persistence_bedrock_foundation_model_access_denied_attempt.toml index eb054c925dd..6dba2470f41 100644 --- a/rules/integrations/aws/persistence_bedrock_foundation_model_access_denied_attempt.toml +++ b/rules/integrations/aws/persistence_bedrock_foundation_model_access_denied_attempt.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/04" integration = ["aws"] maturity = "production" -updated_date = "2026/06/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -43,7 +43,7 @@ This rule detects Bedrock control-plane calls that enable model access at the ac ### Possible investigation steps - Identify the principal by reviewing `aws.cloudtrail.user_identity.arn` and `aws.cloudtrail.user_identity.access_key_id`, and determine whether the identity has any legitimate reason to manage Bedrock model access. A denial for an identity that should never touch these APIs is more suspicious than one from an admin with a transient permission gap. -- Inspect `aws.cloudtrail.error_code` and `aws.cloudtrail.error_message` to confirm the denial reason, and review `event.action` to determine which model-access action was attempted. +- Inspect `error.code` and `aws.cloudtrail.error_message` to confirm the denial reason, and review `event.action` to determine which model-access action was attempted. - Verify the `source.ip` and `user_agent.original` of the request. An unexpected IP, geolocation, or automation user agent is suspicious. - Confirm the `cloud.account.id` and `cloud.region` are expected for Bedrock usage in your environment. - Correlate with recent activity from the same principal, such as new access key creation, IAM permission changes, or repeated denials across Bedrock/IAM APIs, which can indicate permission enumeration or escalation attempts. @@ -92,7 +92,7 @@ data_stream.dataset: "aws.cloudtrail" "CreateFoundationModelAgreement" ) and event.outcome: "failure" - and aws.cloudtrail.error_code: ( + and error.code: ( "AccessDenied" or "AccessDeniedException" ) @@ -121,7 +121,7 @@ field_names = [ "aws.cloudtrail.user_identity.access_key_id", "event.action", "event.outcome", - "aws.cloudtrail.error_code", + "error.code", "cloud.account.id", "cloud.region", "aws.cloudtrail.request_parameters", diff --git a/rules/integrations/aws/persistence_bedrock_resource_based_policy_denied_attempt.toml b/rules/integrations/aws/persistence_bedrock_resource_based_policy_denied_attempt.toml index 81dc7de222b..6c9ce706463 100644 --- a/rules/integrations/aws/persistence_bedrock_resource_based_policy_denied_attempt.toml +++ b/rules/integrations/aws/persistence_bedrock_resource_based_policy_denied_attempt.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/04" integration = ["aws"] maturity = "production" -updated_date = "2026/06/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -49,7 +49,7 @@ take effect. - Determine whether this identity has any legitimate reason to manage Bedrock resource policies. A denial for an identity that should never touch these APIs is more suspicious than one from an admin with a transient gap. - **Assess the attempt** - - Inspect `aws.cloudtrail.error_code` and `aws.cloudtrail.error_message` to confirm the denial reason. + - Inspect `error.code` and `aws.cloudtrail.error_message` to confirm the denial reason. - For `PutResourcePolicy`, review `aws.cloudtrail.request_parameters` and `aws.cloudtrail.flattened.request_parameters` for the target resource ARN and the attempted policy document. Look for `Principal` values referencing external AWS account IDs, `"*"`, or unfamiliar roles. @@ -101,7 +101,7 @@ data_stream.dataset: "aws.cloudtrail" and event.provider: "bedrock.amazonaws.com" and event.action: ("PutResourcePolicy" or "DeleteResourcePolicy") and event.outcome: "failure" and - aws.cloudtrail.error_code: ( + error.code: ( "AccessDenied" or "AccessDeniedException" ) @@ -132,7 +132,7 @@ field_names = [ "event.action", "event.provider", "event.outcome", - "aws.cloudtrail.error_code", + "error.code", "cloud.account.id", "cloud.region", "aws.cloudtrail.request_parameters", diff --git a/rules/integrations/aws/privilege_escalation_sts_assume_root_from_rare_user_and_member_account.toml b/rules/integrations/aws/privilege_escalation_sts_assume_root_from_rare_user_and_member_account.toml index bd53d8ca7bf..cd9fac28b6b 100644 --- a/rules/integrations/aws/privilege_escalation_sts_assume_root_from_rare_user_and_member_account.toml +++ b/rules/integrations/aws/privilege_escalation_sts_assume_root_from_rare_user_and_member_account.toml @@ -2,7 +2,7 @@ creation_date = "2024/11/24" integration = ["aws"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -41,7 +41,7 @@ This rule is a New Terms rule that detects when a previously unseen combination - Review `aws.cloudtrail.user_identity.arn` and `aws.cloudtrail.user_identity.access_key_id` to determine: - Whether the caller is an IAM user, federated user, or role. - Whether this identity is normally used for organization-level administration or automation. - - Inspect `aws.cloudtrail.resources.account_id` and `aws.cloudtrail.recipient_account_id` to identify the affected member account. + - Inspect `aws.cloudtrail.resources.account_id` and `cloud.account.id` to identify the affected member account. - Check `source.address`, `source.geo.*`, and `user_agent.original` to understand where and how the call was made (console, CLI, SDK, automation runner, VPN, corporate IP, etc.). - **Understand session, policy, and target details** diff --git a/rules/integrations/aws/privilege_escalation_sts_role_chaining.toml b/rules/integrations/aws/privilege_escalation_sts_role_chaining.toml index cfe2841e142..1b234fe05f1 100644 --- a/rules/integrations/aws/privilege_escalation_sts_role_chaining.toml +++ b/rules/integrations/aws/privilege_escalation_sts_role_chaining.toml @@ -2,7 +2,7 @@ creation_date = "2024/10/23" integration = ["aws"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -34,7 +34,7 @@ Role chaining occurs when a role assumed with temporary credentials (`AssumeRole - **Review Alert Context**: Investigate the alert, focusing on `aws.cloudtrail.user_identity.session_context.session_issuer.arn` (the calling role) and `aws.cloudtrail.resources.arn` (the target role). -- **Determine scope and intent.** Check `aws.cloudtrail.recipient_account_id` and `aws.cloudtrail.resources.account_id` fields to identify whether the chaining is Intra-account (within the same AWS account) or Cross-account (from another AWS account). +- **Determine scope and intent.** Check `cloud.account.id` and `aws.cloudtrail.resources.account_id` fields to identify whether the chaining is Intra-account (within the same AWS account) or Cross-account (from another AWS account). - **Check role privileges.** Compare policies of the calling and target roles. Determine if chaining increases permissions (for example, access to S3 data, IAM modifications, or admin privileges). @@ -125,7 +125,7 @@ field_names = [ "aws.cloudtrail.resources.type", "event.action", "event.outcome", - "aws.cloudtrail.recipient_account_id", + "cloud.account.id", "aws.cloudtrail.resources.account_id", "cloud.region", "aws.cloudtrail.request_parameters", diff --git a/rules/integrations/azure/credential_access_azure_service_principal_signin_then_arc_credential_listing.toml b/rules/integrations/azure/credential_access_azure_service_principal_signin_then_arc_credential_listing.toml index d5cfc25407f..6258caa1a3e 100644 --- a/rules/integrations/azure/credential_access_azure_service_principal_signin_then_arc_credential_listing.toml +++ b/rules/integrations/azure/credential_access_azure_service_principal_signin_then_arc_credential_listing.toml @@ -2,7 +2,7 @@ creation_date = "2026/03/10" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -92,7 +92,7 @@ sequence with maxspan=30m and azure.signinlogs.properties.status.error_code == 0 ] by azure.signinlogs.properties.app_id [any where data_stream.dataset == "azure.activitylogs" - and azure.activitylogs.operation_name : "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/LISTCLUSTERUSERCREDENTIAL/ACTION" + and event.action : "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/LISTCLUSTERUSERCREDENTIAL/ACTION" and event.outcome : ("Success", "success") ] by azure.activitylogs.identity.claims.appid ''' @@ -145,7 +145,7 @@ field_names = [ "azure.signinlogs.properties.app_display_name", "azure.signinlogs.properties.service_principal_name", "azure.signinlogs.category", - "azure.activitylogs.operation_name", + "event.action", "azure.activitylogs.identity.claims.appid", "azure.resource.id", "source.ip", diff --git a/rules/integrations/azure/credential_access_azure_storage_account_keys_accessed.toml b/rules/integrations/azure/credential_access_azure_storage_account_keys_accessed.toml index 11731473783..80e7f1d784e 100644 --- a/rules/integrations/azure/credential_access_azure_storage_account_keys_accessed.toml +++ b/rules/integrations/azure/credential_access_azure_storage_account_keys_accessed.toml @@ -2,7 +2,7 @@ creation_date = "2025/09/23" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -76,7 +76,7 @@ type = "new_terms" query = ''' data_stream.dataset: "azure.activitylogs" and -azure.activitylogs.operation_name: "MICROSOFT.STORAGE/STORAGEACCOUNTS/LISTKEYS/ACTION" and +event.action: "MICROSOFT.STORAGE/STORAGEACCOUNTS/LISTKEYS/ACTION" and azure.activitylogs.identity.authorization.evidence.principal_type: "User" and azure.activitylogs.identity.authorization.evidence.role: ( "Owner" or diff --git a/rules/integrations/azure/credential_access_azure_vm_boot_diagnostics_retrieved_unusual_principal.toml b/rules/integrations/azure/credential_access_azure_vm_boot_diagnostics_retrieved_unusual_principal.toml index 35f88cd5729..16186f3a39f 100644 --- a/rules/integrations/azure/credential_access_azure_vm_boot_diagnostics_retrieved_unusual_principal.toml +++ b/rules/integrations/azure/credential_access_azure_vm_boot_diagnostics_retrieved_unusual_principal.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/15" integration = ["azure"] maturity = "production" -updated_date = "2026/06/15" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -84,7 +84,7 @@ type = "query" query = ''' data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.COMPUTE/VIRTUALMACHINES/RETRIEVEBOOTDIAGNOSTICSDATA/ACTION" and - event.outcome:(success or Success) + event.outcome:(success) ''' @@ -105,7 +105,7 @@ reference = "https://attack.mitre.org/tactics/TA0006/" field_names = [ "@timestamp", "event.outcome", - "azure.activitylogs.operation_name", + "event.action", "azure.activitylogs.identity.authorization.evidence.principal_id", "azure.activitylogs.identity.authorization.evidence.principal_type", "azure.activitylogs.identity.claims.appid", diff --git a/rules/integrations/azure/credential_access_device_code_signin_aad_graph_enum.toml b/rules/integrations/azure/credential_access_device_code_signin_aad_graph_enum.toml index 4ff3edb5c8d..9f43d87dc6e 100644 --- a/rules/integrations/azure/credential_access_device_code_signin_aad_graph_enum.toml +++ b/rules/integrations/azure/credential_access_device_code_signin_aad_graph_enum.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/22" integration = ["azure"] maturity = "production" -updated_date = "2026/05/22" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -205,7 +205,7 @@ reference = "https://attack.mitre.org/tactics/TA0007/" field_names = [ "user.id", "azure.tenant_id", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.app_id", "azure.signinlogs.properties.app_display_name", "azure.signinlogs.properties.resource_id", diff --git a/rules/integrations/azure/credential_access_entra_id_brute_force_activity.toml b/rules/integrations/azure/credential_access_entra_id_brute_force_activity.toml index 06764bfd878..1aa2200e419 100644 --- a/rules/integrations/azure/credential_access_entra_id_brute_force_activity.toml +++ b/rules/integrations/azure/credential_access_entra_id_brute_force_activity.toml @@ -2,7 +2,7 @@ creation_date = "2024/09/06" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -121,7 +121,7 @@ from logs-azure.signinlogs-* 120002, // PasswordChangeInvalidNewPasswordWeak 120020 // PasswordChangeFailure ) - and azure.signinlogs.properties.user_principal_name is not null and azure.signinlogs.properties.user_principal_name != "" + and user.name is not null and user.name != "" and user_agent.original != "Mozilla/5.0 (compatible; MSAL 1.0) PKeyAuth/1.0" and source.`as`.organization.name != "MICROSOFT-CORP-MSN-as-BLOCK" @@ -138,14 +138,14 @@ from logs-azure.signinlogs-* Esql.azure_signinlogs_properties_incoming_token_type_values = values(azure.signinlogs.properties.incoming_token_type), Esql.azure_signinlogs_properties_risk_state_values = values(azure.signinlogs.properties.risk_state), Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id), - Esql.azure_signinlogs_properties_user_id_values = values(azure.signinlogs.properties.user_id), - Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name), + Esql.azure_signinlogs_properties_user_id_values = values(user.id), + Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(user.name), Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description), Esql.azure_signinlogs_result_signature_values = values(azure.signinlogs.result_signature), Esql.azure_signinlogs_result_type_values = values(azure.signinlogs.result_type), - Esql.azure_signinlogs_properties_user_id_count_distinct = count_distinct(azure.signinlogs.properties.user_id), - Esql.azure_signinlogs_properties_user_id_list = values(azure.signinlogs.properties.user_id), + Esql.azure_signinlogs_properties_user_id_count_distinct = count_distinct(user.id), + Esql.azure_signinlogs_properties_user_id_list = values(user.id), Esql.azure_signinlogs_result_description_values_all = values(azure.signinlogs.result_description), Esql.azure_signinlogs_result_description_count_distinct = count_distinct(azure.signinlogs.result_description), Esql.azure_signinlogs_properties_status_error_code_values = values(azure.signinlogs.properties.status.error_code), diff --git a/rules/integrations/azure/credential_access_entra_id_excessive_account_lockouts.toml b/rules/integrations/azure/credential_access_entra_id_excessive_account_lockouts.toml index 9ee9d1d0bfe..86ac69853cd 100644 --- a/rules/integrations/azure/credential_access_entra_id_excessive_account_lockouts.toml +++ b/rules/integrations/azure/credential_access_entra_id_excessive_account_lockouts.toml @@ -4,7 +4,7 @@ integration = ["azure"] maturity = "production" min_stack_comments = "Changing min stack to 9.2.0, the latest minimum supported version for 9.X releases." min_stack_version = "9.2.0" -updated_date = "2026/04/22" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -99,7 +99,7 @@ data_stream.dataset: "azure.signinlogs" and event.category: "authentication" and event.outcome: "failure" and azure.signinlogs.properties.authentication_requirement: "singleFactorAuthentication" and azure.signinlogs.properties.status.error_code: 50053 - and azure.signinlogs.properties.user_principal_name: (* and not "") + and user.name: (* and not "") and not source.as.organization.name: "MICROSOFT-CORP-MSN-as-BLOCK" and not source.ip: ("10.0.0.0/8" or "172.16.0.0/12" or "192.168.0.0/16" or "127.0.0.0/8" or "::1/128" or "fd00::/8") ''' diff --git a/rules/integrations/azure/credential_access_entra_id_signin_brute_force_microsoft_365.toml b/rules/integrations/azure/credential_access_entra_id_signin_brute_force_microsoft_365.toml index 6fd7cf9f9d0..ad1d9c304cd 100644 --- a/rules/integrations/azure/credential_access_entra_id_signin_brute_force_microsoft_365.toml +++ b/rules/integrations/azure/credential_access_entra_id_signin_brute_force_microsoft_365.toml @@ -2,7 +2,7 @@ creation_date = "2024/09/06" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -92,7 +92,7 @@ from logs-azure.signinlogs-* | eval Esql.time_window_date_trunc = date_trunc(15 minutes, @timestamp), - Esql_priv.azure_signinlogs_properties_user_principal_name_lower = to_lower(azure.signinlogs.properties.user_principal_name), + Esql_priv.azure_signinlogs_properties_user_principal_name_lower = to_lower(user.name), Esql.azure_signinlogs_properties_incoming_token_type_lower = to_lower(azure.signinlogs.properties.incoming_token_type), Esql.azure_signinlogs_properties_app_display_name_lower = to_lower(azure.signinlogs.properties.app_display_name), Esql.user_agent_original = user_agent.original @@ -125,8 +125,8 @@ from logs-azure.signinlogs-* 120002, // PasswordChangeInvalidNewPasswordWeak 120020 // PasswordChangeFailure ) - and azure.signinlogs.properties.user_principal_name is not null - and azure.signinlogs.properties.user_principal_name != "" + and user.name is not null + and user.name != "" and user_agent.original != "Mozilla/5.0 (compatible; MSAL 1.0) PKeyAuth/1.0" | stats @@ -142,8 +142,8 @@ from logs-azure.signinlogs-* Esql.azure_signinlogs_properties_incoming_token_type_values = values(azure.signinlogs.properties.incoming_token_type), Esql.azure_signinlogs_properties_risk_state_values = values(azure.signinlogs.properties.risk_state), Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id), - Esql.azure_signinlogs_properties_user_id_values = values(azure.signinlogs.properties.user_id), - Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name), + Esql.azure_signinlogs_properties_user_id_values = values(user.id), + Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(user.name), Esql.azure_signinlogs_result_description_values = values(azure.signinlogs.result_description), Esql.azure_signinlogs_result_signature_values = values(azure.signinlogs.result_signature), Esql.azure_signinlogs_result_type_values = values(azure.signinlogs.result_type), diff --git a/rules/integrations/azure/credential_access_entra_id_totp_brute_force_attempts.toml b/rules/integrations/azure/credential_access_entra_id_totp_brute_force_attempts.toml index ee801af25b2..d381cdd42f1 100644 --- a/rules/integrations/azure/credential_access_entra_id_totp_brute_force_attempts.toml +++ b/rules/integrations/azure/credential_access_entra_id_totp_brute_force_attempts.toml @@ -2,7 +2,7 @@ creation_date = "2024/12/11" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -110,7 +110,7 @@ from logs-azure.signinlogs-* metadata _id, _version, _index Esql.source_address_values = values(source.address), Esql.azure_tenant_id_valuues = values(azure.tenant_id), Esql_priv.azure_identity_values = values(azure.signinlogs.identity), - Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name), + Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(user.name), Esql.azure_signinlogs_properties_app_id_values = values(azure.signinlogs.properties.app_id), Esql.azure_signinlogs_properties_app_display_name_values = values(azure.signinlogs.properties.app_display_name), Esql.azure_signinlogs_properties_authentication_requirement_values = values(azure.signinlogs.properties.authentication_requirement), diff --git a/rules/integrations/azure/credential_access_network_full_network_packet_capture_detected.toml b/rules/integrations/azure/credential_access_network_full_network_packet_capture_detected.toml index cdc5cf35990..f6774259d39 100644 --- a/rules/integrations/azure/credential_access_network_full_network_packet_capture_detected.toml +++ b/rules/integrations/azure/credential_access_network_full_network_packet_capture_detected.toml @@ -2,7 +2,7 @@ creation_date = "2021/08/12" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -35,7 +35,7 @@ Azure's Packet Capture is a feature of Network Watcher that allows for the inspe ### Possible investigation steps -- Review the Azure activity logs to identify the specific user or service principal associated with the packet capture operation by examining the `azure.activitylogs.operation_name` and `event.dataset` fields. +- Review the Azure activity logs to identify the specific user or service principal associated with the packet capture operation by examining the `event.action` and `event.dataset` fields. - Check the timestamp of the detected packet capture activity to determine the exact time frame of the event and correlate it with any other suspicious activities or changes in the environment. - Investigate the source and destination IP addresses involved in the packet capture to understand the scope and potential impact, focusing on any unencrypted traffic that might have been captured. - Verify the legitimacy of the packet capture request by contacting the user or team responsible for the operation to confirm if it was authorized and necessary for troubleshooting or other legitimate purposes. @@ -71,13 +71,13 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name: +data_stream.dataset:azure.activitylogs and event.action: ( MICROSOFT.NETWORK/*/STARTPACKETCAPTURE/ACTION or MICROSOFT.NETWORK/*/VPNCONNECTIONS/STARTPACKETCAPTURE/ACTION or MICROSOFT.NETWORK/*/PACKETCAPTURES/WRITE ) and -event.outcome:(Success or success) +event.outcome:(success) ''' diff --git a/rules/integrations/azure/credential_access_storage_account_key_regenerated.toml b/rules/integrations/azure/credential_access_storage_account_key_regenerated.toml index bb546674ed8..464bfa1783e 100644 --- a/rules/integrations/azure/credential_access_storage_account_key_regenerated.toml +++ b/rules/integrations/azure/credential_access_storage_account_key_regenerated.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/19" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -79,7 +79,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.STORAGE/STORAGEACCOUNTS/REGENERATEKEY/ACTION" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.STORAGE/STORAGEACCOUNTS/REGENERATEKEY/ACTION" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_automation_runbook_deleted.toml b/rules/integrations/azure/defense_evasion_automation_runbook_deleted.toml index 491140ad507..9809d4d2c46 100644 --- a/rules/integrations/azure/defense_evasion_automation_runbook_deleted.toml +++ b/rules/integrations/azure/defense_evasion_automation_runbook_deleted.toml @@ -2,7 +2,7 @@ creation_date = "2020/09/01" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -68,8 +68,8 @@ type = "query" query = ''' data_stream.dataset:azure.activitylogs and - azure.activitylogs.operation_name:"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DELETE" and - event.outcome:(Success or success) + event.action:"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DELETE" and + event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_event_hub_deletion.toml b/rules/integrations/azure/defense_evasion_event_hub_deletion.toml index 6a0e32c182f..8caefd101d5 100644 --- a/rules/integrations/azure/defense_evasion_event_hub_deletion.toml +++ b/rules/integrations/azure/defense_evasion_event_hub_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,7 +74,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.EVENTHUB/NAMESPACES/EVENTHUBS/DELETE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.EVENTHUB/NAMESPACES/EVENTHUBS/DELETE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_insights_diagnostic_settings_deletion.toml b/rules/integrations/azure/defense_evasion_insights_diagnostic_settings_deletion.toml index c2a83bd3fc9..4b2ff9d116e 100644 --- a/rules/integrations/azure/defense_evasion_insights_diagnostic_settings_deletion.toml +++ b/rules/integrations/azure/defense_evasion_insights_diagnostic_settings_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/17" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -77,8 +77,8 @@ type = "new_terms" query = ''' data_stream.dataset:azure.activitylogs - and azure.activitylogs.operation_name:"MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE" - and event.outcome:(Success or success) + and event.action:"MICROSOFT.INSIGHTS/DIAGNOSTICSETTINGS/DELETE" + and event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_kubernetes_events_deleted.toml b/rules/integrations/azure/defense_evasion_kubernetes_events_deleted.toml index 1c56f11241a..009953252c1 100644 --- a/rules/integrations/azure/defense_evasion_kubernetes_events_deleted.toml +++ b/rules/integrations/azure/defense_evasion_kubernetes_events_deleted.toml @@ -2,7 +2,7 @@ creation_date = "2021/06/24" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -73,8 +73,8 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/EVENTS.K8S.IO/EVENTS/DELETE" and -event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/EVENTS.K8S.IO/EVENTS/DELETE" and +event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_network_firewall_policy_deletion.toml b/rules/integrations/azure/defense_evasion_network_firewall_policy_deletion.toml index 8b172e0fb22..b540877175e 100644 --- a/rules/integrations/azure/defense_evasion_network_firewall_policy_deletion.toml +++ b/rules/integrations/azure/defense_evasion_network_firewall_policy_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -76,7 +76,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.NETWORK/FIREWALLPOLICIES/DELETE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.NETWORK/FIREWALLPOLICIES/DELETE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_network_frontdoor_firewall_policy_deletion.toml b/rules/integrations/azure/defense_evasion_network_frontdoor_firewall_policy_deletion.toml index a3f501fe860..0d973de08d3 100644 --- a/rules/integrations/azure/defense_evasion_network_frontdoor_firewall_policy_deletion.toml +++ b/rules/integrations/azure/defense_evasion_network_frontdoor_firewall_policy_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2021/08/01" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -79,7 +79,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.NETWORK/FRONTDOORWEBAPPLICATIONFIREWALLPOLICIES/DELETE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.NETWORK/FRONTDOORWEBAPPLICATIONFIREWALLPOLICIES/DELETE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_network_watcher_deletion.toml b/rules/integrations/azure/defense_evasion_network_watcher_deletion.toml index f16bf04dbca..c286c90c744 100644 --- a/rules/integrations/azure/defense_evasion_network_watcher_deletion.toml +++ b/rules/integrations/azure/defense_evasion_network_watcher_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/31" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -75,7 +75,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.NETWORK/NETWORKWATCHERS/DELETE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.NETWORK/NETWORKWATCHERS/DELETE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/defense_evasion_security_alert_suppression_rule_created.toml b/rules/integrations/azure/defense_evasion_security_alert_suppression_rule_created.toml index 1ce24f3433c..34132fa667c 100644 --- a/rules/integrations/azure/defense_evasion_security_alert_suppression_rule_created.toml +++ b/rules/integrations/azure/defense_evasion_security_alert_suppression_rule_created.toml @@ -2,7 +2,7 @@ creation_date = "2021/08/27" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -74,7 +74,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.SECURITY/ALERTSSUPPRESSIONRULES/WRITE" and +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.SECURITY/ALERTSSUPPRESSIONRULES/WRITE" and event.outcome: "success" ''' diff --git a/rules/integrations/azure/defense_evasion_storage_blob_permissions_modified.toml b/rules/integrations/azure/defense_evasion_storage_blob_permissions_modified.toml index 401ddb47c34..00d020c6ef4 100644 --- a/rules/integrations/azure/defense_evasion_storage_blob_permissions_modified.toml +++ b/rules/integrations/azure/defense_evasion_storage_blob_permissions_modified.toml @@ -2,7 +2,7 @@ creation_date = "2021/09/22" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -33,7 +33,7 @@ Azure Blob Storage is a service for storing large amounts of unstructured data. ### Possible investigation steps -- Review the Azure activity logs to identify the user or service principal associated with the permission modification event by examining the relevant fields such as `event.dataset` and `azure.activitylogs.operation_name`. +- Review the Azure activity logs to identify the user or service principal associated with the permission modification event by examining the relevant fields such as `event.dataset` and `event.action`. - Check the `event.outcome` field to confirm the success of the permission modification and gather details on the specific permissions that were altered. - Investigate the context of the modification by reviewing recent activities of the identified user or service principal to determine if the change aligns with their typical behavior or role. - Assess the potential impact of the permission change on the affected Azure Blob by evaluating the sensitivity of the data and the new access levels granted. @@ -75,10 +75,10 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:( +data_stream.dataset:azure.activitylogs and event.action:( "MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/BLOBS/MANAGEOWNERSHIP/ACTION" or "MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/BLOBS/MODIFYPERMISSIONS/ACTION") and - event.outcome:(Success or success) + event.outcome:(success) ''' diff --git a/rules/integrations/azure/discovery_entra_id_teamfiltration_user_agents_detected.toml b/rules/integrations/azure/discovery_entra_id_teamfiltration_user_agents_detected.toml index 054deba18a5..1f694321f40 100644 --- a/rules/integrations/azure/discovery_entra_id_teamfiltration_user_agents_detected.toml +++ b/rules/integrations/azure/discovery_entra_id_teamfiltration_user_agents_detected.toml @@ -2,7 +2,7 @@ creation_date = "2025/07/02" integration = ["azure", "o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -45,7 +45,7 @@ The detection is based on TeamFiltration's hardcoded user agent string and/or th ### Possible investigation steps - Confirm the tool used via `user_agent.original`. -- Identify the `user.id`, `user.name`, or `azure.signinlogs.properties.user_principal_name` fields to determine which identity executed the API requests or sign-in attempts. +- Identify the `user.id`, `user.name`, or `user.name` fields to determine which identity executed the API requests or sign-in attempts. - Review `app_id`, `app_display_name`, or `client_id` to identify the application context (e.g., Azure CLI, Graph Explorer, unauthorized app). TeamFiltration uses a list of FOCI compliant applications to perform enumeration and password spraying. TeamFiltration uses Microsoft Teams client ID `1fec8e78-bce4-4aaf-ab1b-5451cc387264` for enumeration. - Check `http.request.method`, `http.response.status_code`, and `event.action` for enumeration patterns (many successful GETs in a short period) if Graph API activity logs. - Investigate correlated sign-ins (`azure.signinlogs`) by the same user, IP, or app immediately preceding the API calls. Was MFA used? Is the location suspicious? diff --git a/rules/integrations/azure/discovery_storage_blob_container_access_modification.toml b/rules/integrations/azure/discovery_storage_blob_container_access_modification.toml index 8216140ed39..49cc32f6f1c 100644 --- a/rules/integrations/azure/discovery_storage_blob_container_access_modification.toml +++ b/rules/integrations/azure/discovery_storage_blob_container_access_modification.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/20" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,7 +69,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/WRITE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.STORAGE/STORAGEACCOUNTS/BLOBSERVICES/CONTAINERS/WRITE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/execution_automation_runbook_created_or_modified.toml b/rules/integrations/azure/execution_automation_runbook_created_or_modified.toml index 8d97058e227..2c2b26661df 100644 --- a/rules/integrations/azure/execution_automation_runbook_created_or_modified.toml +++ b/rules/integrations/azure/execution_automation_runbook_created_or_modified.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,13 +69,13 @@ type = "query" query = ''' data_stream.dataset:azure.activitylogs and - azure.activitylogs.operation_name: + event.action: ( "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/DRAFT/WRITE" or "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/WRITE" or "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/RUNBOOKS/PUBLISH/ACTION" ) and - event.outcome:(Success or success) + event.outcome:(success) ''' [[rule.threat]] diff --git a/rules/integrations/azure/execution_azure_vm_extension_crud_unusual_source.toml b/rules/integrations/azure/execution_azure_vm_extension_crud_unusual_source.toml index 909317d9ca6..7d6dcddb20f 100644 --- a/rules/integrations/azure/execution_azure_vm_extension_crud_unusual_source.toml +++ b/rules/integrations/azure/execution_azure_vm_extension_crud_unusual_source.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/15" integration = ["azure"] maturity = "production" -updated_date = "2026/06/15" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -100,7 +100,7 @@ data_stream.dataset:azure.activitylogs and "MICROSOFT.COMPUTE/VIRTUALMACHINESCALESETS/EXTENSIONS/DELETE" or "MICROSOFT.COMPUTE/VIRTUALMACHINESCALESETS/EXTENSIONS/READ" or "MICROSOFT.COMPUTE/VIRTUALMACHINESCALESETS/EXTENSIONS/WRITE" - ) and event.outcome:(Success or success) and + ) and event.outcome:(success) and azure.resource.name:* and source.as.number:(* and not (3598 or 8068 or 8069 or 8070 or 8071 or 8072 or 8073 or 8074 or 8075 or 12076)) ''' @@ -135,7 +135,7 @@ reference = "https://attack.mitre.org/tactics/TA0003/" field_names = [ "@timestamp", "event.outcome", - "azure.activitylogs.operation_name", + "event.action", "azure.resource.name", "azure.resource.id", "source.ip", diff --git a/rules/integrations/azure/execution_azure_vm_managed_run_command_unusual_identity.toml b/rules/integrations/azure/execution_azure_vm_managed_run_command_unusual_identity.toml index 8ddf80ea1b2..496735d9146 100644 --- a/rules/integrations/azure/execution_azure_vm_managed_run_command_unusual_identity.toml +++ b/rules/integrations/azure/execution_azure_vm_managed_run_command_unusual_identity.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/16" integration = ["azure"] maturity = "production" -updated_date = "2026/06/16" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -89,7 +89,7 @@ data_stream.dataset:azure.activitylogs and event.action:( "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMANDS/WRITE" or "MICROSOFT.COMPUTE/VIRTUALMACHINESCALESETS/VIRTUALMACHINES/RUNCOMMANDS/WRITE" - ) and event.outcome:(success or Success) and + ) and event.outcome:(success) and azure.activitylogs.identity.authorization.evidence.principal_id: * ''' @@ -97,11 +97,11 @@ data_stream.dataset:azure.activitylogs and field_names = [ "@timestamp", "event.outcome", - "azure.activitylogs.operation_name", + "event.action", "azure.activitylogs.identity.authorization.evidence.principal_id", "azure.activitylogs.identity.authorization.evidence.principal_type", "azure.activitylogs.identity.claims.appid", - "azure.activitylogs.identity.claims_initiated_by_user.name", + "user.name", "azure.resource.id", "azure.resource.name", "source.ip", diff --git a/rules/integrations/azure/execution_compute_vm_command_executed.toml b/rules/integrations/azure/execution_compute_vm_command_executed.toml index 4bc586ad7aa..e65ca449bdf 100644 --- a/rules/integrations/azure/execution_compute_vm_command_executed.toml +++ b/rules/integrations/azure/execution_compute_vm_command_executed.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/17" integration = ["azure"] maturity = "production" -updated_date = "2026/06/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -85,10 +85,10 @@ type = "new_terms" query = ''' data_stream.dataset:azure.activitylogs and - azure.activitylogs.operation_name:( + event.action:( "MICROSOFT.COMPUTE/VIRTUALMACHINES/RUNCOMMAND/ACTION" or "MICROSOFT.COMPUTE/VIRTUALMACHINESCALESETS/VIRTUALMACHINES/RUNCOMMAND/ACTION" - ) and event.outcome:(Success or success) and + ) and event.outcome:(success) and azure.activitylogs.identity.authorization.evidence.principal_id: * and source.as.number: * and azure.resource.name: * diff --git a/rules/integrations/azure/impact_azure_compute_restore_point_collection_deleted.toml b/rules/integrations/azure/impact_azure_compute_restore_point_collection_deleted.toml index 66b264bfd67..164c80556be 100644 --- a/rules/integrations/azure/impact_azure_compute_restore_point_collection_deleted.toml +++ b/rules/integrations/azure/impact_azure_compute_restore_point_collection_deleted.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/13" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -38,7 +38,7 @@ indicate unauthorized activity or a compromised account. ### Possible investigation steps -- Review the `azure.activitylogs.identity.claims_initiated_by_user.name` field to identify the specific user who performed the deletion operation. +- Review the `user.name` field to identify the specific user who performed the deletion operation. - Investigate the `azure.resource.id` or `azure.resource.name` fields to identify which Restore Point Collection was deleted and assess its criticality to business operations. - Review the timeline of the deletion event and correlate it with other security events or user activities to identify any suspicious patterns or related activities. - Verify whether the user account has legitimate access to perform this operation and whether this deletion was authorized through change management processes. @@ -84,7 +84,7 @@ type = "new_terms" query = ''' data_stream.dataset: azure.activitylogs and event.action: "MICROSOFT.COMPUTE/RESTOREPOINTCOLLECTIONS/DELETE" and - event.outcome: (Success or success) + event.outcome: (success) ''' @@ -103,7 +103,7 @@ reference = "https://attack.mitre.org/tactics/TA0040/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.activitylogs.identity.claims_initiated_by_user.name", "azure.resource.group"] +value = ["user.name", "azure.resource.group"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/azure/impact_azure_compute_restore_point_collections_deleted.toml b/rules/integrations/azure/impact_azure_compute_restore_point_collections_deleted.toml index be5456403be..90f59b67569 100644 --- a/rules/integrations/azure/impact_azure_compute_restore_point_collections_deleted.toml +++ b/rules/integrations/azure/impact_azure_compute_restore_point_collections_deleted.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/13" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -42,7 +42,7 @@ unusual in normal operations and highly suspicious when observed. ### Possible investigation steps -- Identify the user account responsible for the deletions by examining the `azure.activitylogs.identity.claims_initiated_by_user.name` or `user.name` field in the alerts. +- Identify the user account responsible for the deletions by examining the `user.name` or `user.name` field in the alerts. - Review all deletion events from this user in the specified time window to determine the scope and scale of the activity. - Check the `azure.resource.id` and `azure.resource.name` fields to identify which Restore Point Collections were deleted and assess their criticality to business operations. - Verify whether the user account has legitimate administrative access and whether these deletions were authorized through change management or documented maintenance activities. @@ -105,7 +105,7 @@ type = "threshold" query = ''' data_stream.dataset: azure.activitylogs and event.action: "MICROSOFT.COMPUTE/RESTOREPOINTCOLLECTIONS/DELETE" and - event.outcome: (Success or success) + event.outcome: (success) ''' @@ -123,7 +123,7 @@ name = "Impact" reference = "https://attack.mitre.org/tactics/TA0040/" [rule.threshold] -field = ["azure.activitylogs.identity.claims_initiated_by_user.name"] +field = ["user.name"] value = 1 [[rule.threshold.cardinality]] field = "azure.activitylogs.resource.id" diff --git a/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletion.toml b/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletion.toml index dbd05834cc2..d471179474d 100644 --- a/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletion.toml +++ b/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/10" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -83,21 +83,21 @@ type = "new_terms" query = ''' data_stream.dataset: azure.activitylogs and - azure.activitylogs.operation_name: "MICROSOFT.COMPUTE/SNAPSHOTS/DELETE" and + event.action: "MICROSOFT.COMPUTE/SNAPSHOTS/DELETE" and azure.activitylogs.properties.status_code: "Accepted" and - azure.activitylogs.identity.claims_initiated_by_user.name: * + user.name: * ''' [rule.investigation_fields] field_names = [ "@timestamp", - "azure.activitylogs.identity.claims_initiated_by_user.name", + "user.name", "azure.activitylogs.identity.authorization.evidence.principal_id", "azure.activitylogs.identity.claims.appid", "azure.activitylogs.identity.claims.sid", "azure.resource.name", "azure.resource.group", - "azure.activitylogs.operation_name", + "event.action", "azure.subscription_id", "azure.activitylogs.tenant_id", "source.ip", @@ -124,7 +124,7 @@ reference = "https://attack.mitre.org/tactics/TA0040/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.activitylogs.identity.claims_initiated_by_user.name", "azure.resource.group"] +value = ["user.name", "azure.resource.group"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletions.toml b/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletions.toml index ac867c9e138..7c67d5ff6fa 100644 --- a/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletions.toml +++ b/rules/integrations/azure/impact_azure_compute_vm_snapshot_deletions.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/10" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -33,7 +33,7 @@ Azure disk snapshots are critical backup and recovery resources that enable orga ### Possible investigation steps -- Review the Azure activity logs to identify the user or service principal that initiated the multiple snapshot deletions by examining the principal ID, UPN and user agent fields in `azure.activitylogs.identity.claims_initiated_by_user.name`. +- Review the Azure activity logs to identify the user or service principal that initiated the multiple snapshot deletions by examining the principal ID, UPN and user agent fields in `user.name`. - Check the specific snapshot names in `azure.resource.name` to understand which backups were deleted and assess the overall impact on recovery capabilities. - Investigate the timing and sequence of deletions to determine if they followed a pattern consistent with automated malicious activity or manual destruction. - Examine the user's recent activity history including authentication events, privilege changes, and other Azure resource modifications to identify signs of account compromise. @@ -87,21 +87,21 @@ type = "threshold" query = ''' data_stream.dataset: azure.activitylogs and - azure.activitylogs.operation_name: "MICROSOFT.COMPUTE/SNAPSHOTS/DELETE" and + event.action: "MICROSOFT.COMPUTE/SNAPSHOTS/DELETE" and azure.activitylogs.properties.status_code: "Accepted" and - azure.activitylogs.identity.claims_initiated_by_user.name: * + user.name: * ''' [rule.investigation_fields] field_names = [ "@timestamp", - "azure.activitylogs.identity.claims_initiated_by_user.name", + "user.name", "azure.activitylogs.identity.authorization.evidence.principal_id", "azure.activitylogs.identity.claims.appid", "azure.activitylogs.identity.claims.sid", "azure.resource.name", "azure.resource.group", - "azure.activitylogs.operation_name", + "event.action", "azure.subscription_id", "azure.activitylogs.tenant_id", "source.ip", @@ -127,7 +127,7 @@ name = "Impact" reference = "https://attack.mitre.org/tactics/TA0040/" [rule.threshold] -field = ["azure.activitylogs.identity.claims_initiated_by_user.name"] +field = ["user.name"] value = 1 [[rule.threshold.cardinality]] field = "azure.resource.name" diff --git a/rules/integrations/azure/impact_azure_storage_account_deletion.toml b/rules/integrations/azure/impact_azure_storage_account_deletion.toml index 4e9b6b0fe3f..72ca391b7d5 100644 --- a/rules/integrations/azure/impact_azure_storage_account_deletion.toml +++ b/rules/integrations/azure/impact_azure_storage_account_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/08" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -79,8 +79,8 @@ type = "new_terms" query = ''' data_stream.dataset: azure.activitylogs and - azure.activitylogs.operation_name: "MICROSOFT.STORAGE/STORAGEACCOUNTS/DELETE" and - azure.activitylogs.identity.claims_initiated_by_user.name: * + event.action: "MICROSOFT.STORAGE/STORAGEACCOUNTS/DELETE" and + user.name: * ''' @@ -104,7 +104,7 @@ reference = "https://attack.mitre.org/tactics/TA0040/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.activitylogs.identity.claims_initiated_by_user.name"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/azure/impact_azure_storage_account_deletion_multiple.toml b/rules/integrations/azure/impact_azure_storage_account_deletion_multiple.toml index 72ae8b2d4b0..e068e94be23 100644 --- a/rules/integrations/azure/impact_azure_storage_account_deletion_multiple.toml +++ b/rules/integrations/azure/impact_azure_storage_account_deletion_multiple.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/08" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -33,7 +33,7 @@ Azure Storage Accounts are critical infrastructure components that store applica ### Possible investigation steps -- Review the Azure activity logs to identify the user or service principal that initiated the multiple storage account deletions by examining the principal ID, UPN and user agent fields in `azure.activitylogs.identity.claims_initiated_by_user.name`. +- Review the Azure activity logs to identify the user or service principal that initiated the multiple storage account deletions by examining the principal ID, UPN and user agent fields in `user.name`. - Check the specific storage account names in `azure.resource.name` to understand which storage resources were deleted and assess the overall business impact. - Investigate the timing and sequence of deletions to determine if they followed a pattern consistent with automated malicious activity or manual destruction. - Examine the user's recent activity history including authentication events, privilege changes, and other Azure resource modifications to identify signs of account compromise. @@ -83,8 +83,8 @@ type = "threshold" query = ''' data_stream.dataset: azure.activitylogs and - azure.activitylogs.operation_name: "MICROSOFT.STORAGE/STORAGEACCOUNTS/DELETE" and - azure.activitylogs.identity.claims_initiated_by_user.name: * + event.action: "MICROSOFT.STORAGE/STORAGEACCOUNTS/DELETE" and + user.name: * ''' @@ -107,7 +107,7 @@ name = "Impact" reference = "https://attack.mitre.org/tactics/TA0040/" [rule.threshold] -field = ["azure.activitylogs.identity.claims_initiated_by_user.name"] +field = ["user.name"] value = 1 [[rule.threshold.cardinality]] diff --git a/rules/integrations/azure/impact_key_vault_modified_by_unusual_user.toml b/rules/integrations/azure/impact_key_vault_modified_by_unusual_user.toml index 5162b13b9e2..e29a4a6f573 100644 --- a/rules/integrations/azure/impact_key_vault_modified_by_unusual_user.toml +++ b/rules/integrations/azure/impact_key_vault_modified_by_unusual_user.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/31" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ note = """## Triage and analysis Azure Key Vault is a cloud service that safeguards encryption keys and secrets like certificates, connection strings, and passwords. It is crucial for managing sensitive data in Azure environments. Unauthorized modifications to Key Vaults can lead to data breaches or service disruptions. This rule detects modifications to Key Vaults, which may indicate potential security incidents or misconfigurations. ### Possible investigation steps -- Review the `azure.activitylogs.operation_name` field to identify the specific operation performed on the Key Vault. Common operations include `Microsoft.KeyVault/vaults/write` for modifications and `Microsoft.KeyVault/vaults/delete` for deletions. +- Review the `event.action` field to identify the specific operation performed on the Key Vault. Common operations include `Microsoft.KeyVault/vaults/write` for modifications and `Microsoft.KeyVault/vaults/delete` for deletions. - Check the `event.outcome` field to confirm the success of the operation. A successful outcome indicates that the modification or deletion was completed. - Investigate the `azure.activitylogs.identity.principal_id` or `azure.activitylogs.identity.principal_name` fields to determine the user or service principal that performed the operation. This can help identify whether the action was authorized or potentially malicious. - Analyze the `azure.activitylogs.resource_id` field to identify the specific Key Vault that was modified. This can help assess the impact of the change and whether it affects critical resources or applications. @@ -73,8 +73,8 @@ type = "new_terms" query = ''' data_stream.dataset: "azure.activitylogs" - and azure.activitylogs.operation_name: MICROSOFT.KEYVAULT/VAULTS/* - and event.outcome:(Success or success) + and event.action: MICROSOFT.KEYVAULT/VAULTS/* + and event.outcome:(success) ''' @@ -105,7 +105,7 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.activitylogs.identity.claims_initiated_by_user.name"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" diff --git a/rules/integrations/azure/impact_kubernetes_pod_deleted.toml b/rules/integrations/azure/impact_kubernetes_pod_deleted.toml index 1a3e54ef842..6b63806effa 100644 --- a/rules/integrations/azure/impact_kubernetes_pod_deleted.toml +++ b/rules/integrations/azure/impact_kubernetes_pod_deleted.toml @@ -2,7 +2,7 @@ creation_date = "2021/06/24" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -71,8 +71,8 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/PODS/DELETE" and -event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/PODS/DELETE" and +event.outcome:(success) ''' diff --git a/rules/integrations/azure/impact_resources_resource_group_deletion.toml b/rules/integrations/azure/impact_resources_resource_group_deletion.toml index e583a83dd9b..83dcbb75afc 100644 --- a/rules/integrations/azure/impact_resources_resource_group_deletion.toml +++ b/rules/integrations/azure/impact_resources_resource_group_deletion.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/17" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,7 +74,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.RESOURCES/SUBSCRIPTIONS/RESOURCEGROUPS/DELETE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.RESOURCES/SUBSCRIPTIONS/RESOURCEGROUPS/DELETE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/initial_access_azure_arc_cluster_credential_access_unusual_source.toml b/rules/integrations/azure/initial_access_azure_arc_cluster_credential_access_unusual_source.toml index 3fa4319630a..cbee247d218 100644 --- a/rules/integrations/azure/initial_access_azure_arc_cluster_credential_access_unusual_source.toml +++ b/rules/integrations/azure/initial_access_azure_arc_cluster_credential_access_unusual_source.toml @@ -2,7 +2,7 @@ creation_date = "2026/03/10" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -82,8 +82,8 @@ type = "new_terms" query = ''' data_stream.dataset: "azure.activitylogs" - and azure.activitylogs.operation_name: "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/LISTCLUSTERUSERCREDENTIAL/ACTION" - and event.outcome: (Success or success) + and event.action: "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/LISTCLUSTERUSERCREDENTIAL/ACTION" + and event.outcome: (success) ''' @@ -143,7 +143,7 @@ reference = "https://attack.mitre.org/tactics/TA0005/" [rule.investigation_fields] field_names = [ "@timestamp", - "azure.activitylogs.operation_name", + "event.action", "azure.activitylogs.identity.claims.appid", "azure.activitylogs.identity.authorization.evidence.role", "azure.activitylogs.identity.authorization.evidence.principalType", diff --git a/rules/integrations/azure/initial_access_entra_id_actor_token_user_impersonation_abuse.toml b/rules/integrations/azure/initial_access_entra_id_actor_token_user_impersonation_abuse.toml index 117f4401963..3321b25a2c9 100644 --- a/rules/integrations/azure/initial_access_entra_id_actor_token_user_impersonation_abuse.toml +++ b/rules/integrations/azure/initial_access_entra_id_actor_token_user_impersonation_abuse.toml @@ -2,7 +2,7 @@ creation_date = "2025/09/18" integration = ["azure"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -33,7 +33,7 @@ This rule detects when Microsoft services use actor tokens to perform operations ### Possible investigation steps -- Review the `azure.auditlogs.properties.initiated_by.user.userPrincipalName` field to identify which service principals are exhibiting this behavior. +- Review the `user.name` field to identify which service principals are exhibiting this behavior. - Check the `azure.auditlogs.properties.initiated_by.user.displayName` to confirm these are legitimate Microsoft services. - Analyze the actions performed by these service principals - look for privilege escalations, permission grants, or unusual administrative operations. - Review the timing and frequency of these events to identify potential attack patterns or automated exploitation. @@ -89,9 +89,9 @@ from logs-azure.auditlogs-* metadata _id, _version, _index "Office 365 SharePoint Online", "Microsoft Dynamics ERP" ) and - not azure.auditlogs.operation_name like "*group*" and - azure.auditlogs.operation_name != "Set directory feature on tenant" - and azure.auditlogs.properties.initiated_by.user.userPrincipalName rlike ".+@[A-Za-z0-9.]+\\.[A-Za-z]{2,}" + not event.action like "*group*" and + event.action != "Set directory feature on tenant" + and user.name rlike ".+@[A-Za-z0-9.]+\\.[A-Za-z]{2,}" | keep @timestamp, azure.*, diff --git a/rules/integrations/azure/initial_access_entra_id_external_guest_user_invite.toml b/rules/integrations/azure/initial_access_entra_id_external_guest_user_invite.toml index 9cb5e978a1d..9778bf66673 100644 --- a/rules/integrations/azure/initial_access_entra_id_external_guest_user_invite.toml +++ b/rules/integrations/azure/initial_access_entra_id_external_guest_user_invite.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/31" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -72,7 +72,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.auditlogs and azure.auditlogs.operation_name:"Invite external user" and azure.auditlogs.properties.target_resources.*.display_name:guest and event.outcome:(Success or success) +data_stream.dataset:azure.auditlogs and event.action:"Invite external user" and azure.auditlogs.properties.target_resources.*.display_name:guest and event.outcome:(success) ''' diff --git a/rules/integrations/azure/initial_access_entra_id_first_time_seen_device_code_auth.toml b/rules/integrations/azure/initial_access_entra_id_first_time_seen_device_code_auth.toml index 8e9d465b4db..d7a4c526199 100644 --- a/rules/integrations/azure/initial_access_entra_id_first_time_seen_device_code_auth.toml +++ b/rules/integrations/azure/initial_access_entra_id_first_time_seen_device_code_auth.toml @@ -2,7 +2,7 @@ creation_date = "2024/10/14" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Matteo Potito Giorgio"] @@ -25,7 +25,7 @@ This rule detects the first instance of a user authenticating via the DeviceCode ### Possible investigation steps -- Review `azure.signinlogs.properties.user_principal_name` and `azure.signinlogs.properties.user_id` to identify the user involved. +- Review `user.name` and `user.id` to identify the user involved. - Confirm that `azure.signinlogs.properties.authentication_protocol` is set to `deviceCode`. - Verify the application through `azure.signinlogs.properties.app_display_name` and `azure.signinlogs.properties.app_id` to determine if it is expected. - Check `source.ip` and compare it with previous authentication logs to determine whether the login originated from a trusted location. @@ -153,7 +153,7 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.signinlogs.properties.user_principal_name"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/azure/initial_access_entra_id_graph_single_session_from_multiple_addresses.toml b/rules/integrations/azure/initial_access_entra_id_graph_single_session_from_multiple_addresses.toml index 1b3f9fd8e60..691cd276478 100644 --- a/rules/integrations/azure/initial_access_entra_id_graph_single_session_from_multiple_addresses.toml +++ b/rules/integrations/azure/initial_access_entra_id_graph_single_session_from_multiple_addresses.toml @@ -2,7 +2,7 @@ creation_date = "2025/05/08" integration = ["azure"] maturity = "production" -updated_date = "2026/05/21" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -103,7 +103,7 @@ from logs-azure.signinlogs-*, logs-azure.graphactivitylogs-* metadata _id, _vers | eval Esql.azure_signinlogs_properties_session_id_coalesce = coalesce(azure.signinlogs.properties.session_id, azure.graphactivitylogs.properties.c_sid), - Esql.azure_signinlogs_properties_user_id_coalesce = coalesce(azure.signinlogs.properties.user_id, azure.graphactivitylogs.properties.user_principal_object_id), + Esql.azure_signinlogs_properties_user_id_coalesce = coalesce(user.id, azure.graphactivitylogs.properties.user_principal_object_id), Esql.azure_signinlogs_properties_app_id_coalesce = coalesce(azure.signinlogs.properties.app_id, azure.graphactivitylogs.properties.app_id), Esql.source_ip = source.ip, Esql.@timestamp = @timestamp, @@ -151,12 +151,12 @@ from logs-azure.signinlogs-*, logs-azure.graphactivitylogs-* metadata _id, _vers user_agent.original, url.original, azure.graphactivitylogs.properties.scopes, - azure.signinlogs.properties.user_principal_name + user.name | stats Esql.azure_signinlogs_properties_user_id_coalesce_values = values(Esql.azure_signinlogs_properties_user_id_coalesce), Esql.azure_signinlogs_properties_session_id_coalesce_values = values(Esql.azure_signinlogs_properties_session_id_coalesce), - Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name), + Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(user.name), Esql.source_ip_values = values(Esql.source_ip), Esql.source_ip_count_distinct = count_distinct(Esql.source_ip), Esql.source_as_organization_name_values = values(source.`as`.organization.name), diff --git a/rules/integrations/azure/initial_access_entra_id_high_risk_signin.toml b/rules/integrations/azure/initial_access_entra_id_high_risk_signin.toml index 36e607d1c99..7f5d4d1bc3e 100644 --- a/rules/integrations/azure/initial_access_entra_id_high_risk_signin.toml +++ b/rules/integrations/azure/initial_access_entra_id_high_risk_signin.toml @@ -2,7 +2,7 @@ creation_date = "2021/01/04" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Willem D'Haese"] @@ -25,7 +25,7 @@ This rule detects high-risk sign-ins in Microsoft Entra ID as identified by Iden ### Possible investigation steps -- Review the `azure.signinlogs.properties.user_id` and associated identity fields to determine the impacted user. +- Review the `user.id` and associated identity fields to determine the impacted user. - Inspect the `risk_level_during_signin` field and confirm it is set to `high`. If `risk_level_aggregated` is also present and high, this suggests sustained risk across multiple sign-ins. - Check `source.ip`, `source.geo.country_name`, and `source.as.organization.name` to evaluate the origin of the sign-in attempt. Flag unexpected geolocations or ASNs (e.g., anonymizers or residential ISPs). - Review the `device_detail` fields such as `operating_system` and `browser` for new or unrecognized devices. diff --git a/rules/integrations/azure/initial_access_entra_id_illicit_consent_grant_via_registered_application.toml b/rules/integrations/azure/initial_access_entra_id_illicit_consent_grant_via_registered_application.toml index 7d1ff22f34c..9607a5f97a9 100644 --- a/rules/integrations/azure/initial_access_entra_id_illicit_consent_grant_via_registered_application.toml +++ b/rules/integrations/azure/initial_access_entra_id_illicit_consent_grant_via_registered_application.toml @@ -2,7 +2,7 @@ creation_date = "2020/09/01" integration = ["azure"] maturity = "production" -updated_date = "2026/03/30" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ This rule uses ES|QL aggregation-based new terms logic with a 7-day history wind #### Possible investigation steps - Review `azure.auditlogs.properties.additional_details.value` to identify the AppId and User-Agent values to determine which application was granted access and how the request was initiated. Pivot on the AppId in the Azure portal under Enterprise Applications to investigate further. -- Review `azure.auditlogs.properties.initiated_by.user.userPrincipalName` to identify the user who approved the application. Investigate their recent activity for signs of phishing, account compromise, or anomalous behavior during the timeframe of the consent. +- Review `user.name` to identify the user who approved the application. Investigate their recent activity for signs of phishing, account compromise, or anomalous behavior during the timeframe of the consent. - Review `azure.auditlogs.properties.initiated_by.user.ipAddress` to assess the geographic source of the consent action. Unexpected locations or IP ranges may indicate adversary-controlled infrastructure. - Review `azure.auditlogs.properties.target_resources.display_name` to evaluate whether the application name is familiar, expected, or potentially spoofing a known service. - Review `azure.auditlogs.properties.target_resources.modified_properties.display_name` to inspect key indicators of elevated privilege or risk, including: @@ -80,7 +80,7 @@ type = "esql" query = ''' FROM logs-azure.auditlogs-* metadata _id, _version, _index -| WHERE (azure.auditlogs.operation_name == "Consent to application" +| WHERE (event.action == "Consent to application" OR event.action == "Consent to application") AND event.outcome == "success" @@ -105,7 +105,7 @@ FROM logs-azure.auditlogs-* metadata _id, _version, _index Esql.tenant_id_values = VALUES(azure.tenant_id), Esql.correlation_id_values = VALUES(azure.auditlogs.properties.correlation_id), Esql.event_count = COUNT(*) - BY azure.auditlogs.properties.initiated_by.user.userPrincipalName, Esql.app_id + BY user.name, Esql.app_id | WHERE Esql.timestamp_first_seen >= NOW() - 9 minutes OR Esql.consent_reason_values LIKE "*Risky application detected*" diff --git a/rules/integrations/azure/initial_access_entra_id_kali365_user_agent.toml b/rules/integrations/azure/initial_access_entra_id_kali365_user_agent.toml index f811600f761..7a09bc393f9 100644 --- a/rules/integrations/azure/initial_access_entra_id_kali365_user_agent.toml +++ b/rules/integrations/azure/initial_access_entra_id_kali365_user_agent.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/26" integration = ["azure", "o365"] maturity = "production" -updated_date = "2026/05/26" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -47,7 +47,7 @@ against the tenant. - Confirm the tool and identify the affected identity. - `user_agent.original` matches `kali365-live/*`. - - Pivot on `user.name`, `azure.signinlogs.properties.user_principal_name`, or the M365 audit `user.id`. + - Pivot on `user.name`, `user.name`, or the M365 audit `user.id`. - Review the origin and compare against the user's normal sign-in behavior. - `source.ip`, `source.geo.*`, and `source.as.organization.name`; flag hosting/VPS ASNs and unexpected geographies. - Cross-reference published Kali365 infrastructure (`216.203.20.95`, `162.243.166.119`, `199.91.220.111`). diff --git a/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_nonstandard_user_agent.toml b/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_nonstandard_user_agent.toml index 8014d98ae58..89c9d3569d7 100644 --- a/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_nonstandard_user_agent.toml +++ b/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_nonstandard_user_agent.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/27" integration = ["azure"] maturity = "production" -updated_date = "2026/05/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ note = """## Triage and analysis ### Investigating Entra ID Microsoft Authentication Broker Sign-In with Non-Standard User Agent -Review `azure.signinlogs.properties.user_principal_name`, `user_agent.original`, +Review `user.name`, `user_agent.original`, `azure.signinlogs.properties.resource_display_name`, `azure.signinlogs.properties.session_id`, `source.ip`, and `source.as.organization.name`. @@ -82,7 +82,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:"azure.signinlogs" and event.action:"Sign-in activity" and event.outcome:(success or Success) and +data_stream.dataset:"azure.signinlogs" and event.action:"Sign-in activity" and event.outcome:(success) and (azure.signinlogs.properties.app_display_name:"Microsoft Authentication Broker" or azure.signinlogs.properties.app_id:"29d9ed98-a469-4536-ade2-f981bc1d605e") and user_agent.original:(* and not (Mozilla* or Dalvik* or *CFNetwork* or Windows-AzureAD-Authentication-Provider* or Java*ThinkPad*)) and azure.signinlogs.properties.resource_display_name:* @@ -98,7 +98,7 @@ field_names = [ "source.as.organization.name", "source.geo.country_name", "event.outcome", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.session_id", "azure.signinlogs.properties.app_display_name", "azure.signinlogs.properties.app_id", diff --git a/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_unusual_resource.toml b/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_unusual_resource.toml index d0d12be17ad..31ff1c4ed0a 100644 --- a/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_unusual_resource.toml +++ b/rules/integrations/azure/initial_access_entra_id_microsoft_auth_broker_unusual_resource.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/15" integration = ["azure"] maturity = "production" -updated_date = "2026/05/15" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ note = """## Triage and analysis ### Investigating Entra ID Microsoft Authentication Broker Sign-In to Unusual Resource -Review `azure.signinlogs.properties.user_principal_name`, `azure.signinlogs.properties.resource_id`, +Review `user.name`, `azure.signinlogs.properties.resource_id`, `azure.signinlogs.properties.resource_display_name`, `azure.signinlogs.properties.session_id`, `source.ip`, and `user_agent.original`. @@ -94,7 +94,7 @@ field_names = [ "source.ip", "source.geo.country_name", "event.outcome", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.session_id", "azure.signinlogs.properties.app_id", "azure.signinlogs.properties.app_display_name", diff --git a/rules/integrations/azure/initial_access_entra_id_oauth_auth_code_grant_unusual_app_resource_user.toml b/rules/integrations/azure/initial_access_entra_id_oauth_auth_code_grant_unusual_app_resource_user.toml index 363a640cd81..6031795207d 100644 --- a/rules/integrations/azure/initial_access_entra_id_oauth_auth_code_grant_unusual_app_resource_user.toml +++ b/rules/integrations/azure/initial_access_entra_id_oauth_auth_code_grant_unusual_app_resource_user.toml @@ -2,7 +2,7 @@ creation_date = "2025/12/17" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ The rule is particularly effective at catching attacks where adversaries use sto ### Possible investigation steps -- Review `azure.signinlogs.properties.user_principal_name` to identify the affected user and determine if they are a developer who would legitimately use these tools. +- Review `user.name` to identify the affected user and determine if they are a developer who would legitimately use these tools. - Check `azure.signinlogs.properties.app_display_name` to confirm which application was used. Azure CLI or PowerShell access by non-technical users is suspicious. - Examine `azure.signinlogs.properties.resource_id` to identify the target resource. Legacy AAD (`00000002-0000-0000-c000-000000000000`) access is unusual for most users. - Analyze `source.ip` and `source.geo.*` for geographic anomalies. ConsentFix attackers exchange codes from different IPs than the victim. @@ -204,7 +204,7 @@ reference = "https://attack.mitre.org/tactics/TA0005/" [rule.investigation_fields] field_names = [ "@timestamp", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.app_id", "azure.signinlogs.properties.app_display_name", "azure.signinlogs.properties.resource_id", @@ -221,7 +221,7 @@ field_names = [ [rule.new_terms] field = "new_terms_fields" value = [ - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.app_id", "azure.signinlogs.properties.resource_id", ] diff --git a/rules/integrations/azure/initial_access_entra_id_oauth_device_code_phishing_tycoon_aitm.toml b/rules/integrations/azure/initial_access_entra_id_oauth_device_code_phishing_tycoon_aitm.toml index 342b9c5c5f1..608135ae573 100644 --- a/rules/integrations/azure/initial_access_entra_id_oauth_device_code_phishing_tycoon_aitm.toml +++ b/rules/integrations/azure/initial_access_entra_id_oauth_device_code_phishing_tycoon_aitm.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/15" integration = ["azure"] maturity = "production" -updated_date = "2026/05/15" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ note = """## Triage and analysis ### Investigating Entra ID OAuth Device Code Phishing via AiTM -Review `azure.signinlogs.properties.user_principal_name`, `azure.signinlogs.properties.session_id`, `source.ip`, +Review `user.name`, `azure.signinlogs.properties.session_id`, `source.ip`, `user_agent.original`, and `azure.signinlogs.properties.resource_display_name` for context around the device code completion. @@ -88,7 +88,7 @@ field_names = [ "source.ip", "source.geo.country_name", "event.outcome", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.session_id", "azure.signinlogs.properties.app_id", "azure.signinlogs.properties.app_display_name", diff --git a/rules/integrations/azure/initial_access_entra_id_oauth_phishing_via_first_party_microsoft_application.toml b/rules/integrations/azure/initial_access_entra_id_oauth_phishing_via_first_party_microsoft_application.toml index 4e3e844f264..2e92c30df4b 100644 --- a/rules/integrations/azure/initial_access_entra_id_oauth_phishing_via_first_party_microsoft_application.toml +++ b/rules/integrations/azure/initial_access_entra_id_oauth_phishing_via_first_party_microsoft_application.toml @@ -2,7 +2,7 @@ creation_date = "2025/04/23" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ The rule uses split detection logic: developer tools (Azure CLI, VSCode, PowerSh ### Possible investigation steps -- Review `azure.signinlogs.properties.user_principal_name` to identify the affected user and determine if they are a high-value target (privileged roles, executives, IT admins). +- Review `user.name` to identify the affected user and determine if they are a high-value target (privileged roles, executives, IT admins). - Analyze `source.ip` and `source.geo.*` for geographic anomalies. ConsentFix attackers exchange codes from different IPs than the victim's location. - Check `azure.signinlogs.properties.app_display_name` to confirm which first-party application was used. Azure CLI or PowerShell access by non-developers is suspicious. - Examine `azure.signinlogs.properties.resource_id` to identify the target resource. Legacy AAD (`00000002-0000-0000-c000-000000000000`) access is unusual for most users. diff --git a/rules/integrations/azure/initial_access_entra_id_oauth_user_impersonation_scope.toml b/rules/integrations/azure/initial_access_entra_id_oauth_user_impersonation_scope.toml index 54ef36acc34..7295b1fd5f0 100644 --- a/rules/integrations/azure/initial_access_entra_id_oauth_user_impersonation_scope.toml +++ b/rules/integrations/azure/initial_access_entra_id_oauth_user_impersonation_scope.toml @@ -2,7 +2,7 @@ creation_date = "2025/07/03" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ unauthorized access attempts, especially when the user type is `Member` and the ### Possible investigation steps -- Review the `azure.signinlogs.properties.user_principal_name` field to identify the user principal involved in the OAuth workflow. +- Review the `user.name` field to identify the user principal involved in the OAuth workflow. - Check the `azure.signinlogs.properties.authentication_processing_details.Oauth Scope Info` field for the presence of `user_impersonation`. This scope is commonly used in OAuth flows to allow applications to access user resources on behalf of the user. - Confirm that the `azure.signinlogs.properties.authentication_requirement` is set to `singleFactorAuthentication`, indicating that the sign-in did not require multi-factor authentication (MFA). This can be a red flag, as MFA is a critical security control that helps prevent unauthorized access. - Review the `azure.signinlogs.properties.app_display_name` or `azure.signinlogs.properties.app_id` to identify the application involved in the OAuth workflow. Check if this application is known and trusted, or if it appears suspicious or unauthorized. FOCI applications are commonly abused by adversaries to evade security controls or conditional access policies. @@ -120,7 +120,7 @@ field_names = [ "azure.signinlogs.properties.device_detail.operating_system", "azure.signinlogs.properties.is_interactive", "azure.signinlogs.properties.session_id", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.user_type", "azure.signinlogs.result_signature", "azure.tenant_id", @@ -171,7 +171,7 @@ reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.signinlogs.properties.user_principal_name", "azure.signinlogs.properties.app_id"] +value = ["user.name", "azure.signinlogs.properties.app_id"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-10d" diff --git a/rules/integrations/azure/initial_access_entra_id_powershell_signin.toml b/rules/integrations/azure/initial_access_entra_id_powershell_signin.toml index 6b1ddde0caf..559918bf46f 100644 --- a/rules/integrations/azure/initial_access_entra_id_powershell_signin.toml +++ b/rules/integrations/azure/initial_access_entra_id_powershell_signin.toml @@ -2,7 +2,7 @@ creation_date = "2020/12/14" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -84,7 +84,7 @@ type = "query" query = ''' data_stream.dataset:azure.signinlogs and azure.signinlogs.properties.app_display_name:"Azure Active Directory PowerShell" and - azure.signinlogs.properties.token_issuer_type:AzureAD and event.outcome:(success or Success) + azure.signinlogs.properties.token_issuer_type:AzureAD and event.outcome:(success) ''' diff --git a/rules/integrations/azure/initial_access_entra_id_protection_alerts_for_user.toml b/rules/integrations/azure/initial_access_entra_id_protection_alerts_for_user.toml index 20416dde179..32eaaf18a50 100644 --- a/rules/integrations/azure/initial_access_entra_id_protection_alerts_for_user.toml +++ b/rules/integrations/azure/initial_access_entra_id_protection_alerts_for_user.toml @@ -2,7 +2,7 @@ creation_date = "2025/04/30" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -73,7 +73,7 @@ timestamp_override = "event.ingested" type = "eql" query = ''' -sequence by azure.identityprotection.properties.user_principal_name with maxspan=10m +sequence by user.name with maxspan=10m [any where event.module == "azure" and data_stream.dataset == "azure.identity_protection"] with runs=2 ''' diff --git a/rules/integrations/azure/initial_access_entra_id_protection_confirmed_compromise.toml b/rules/integrations/azure/initial_access_entra_id_protection_confirmed_compromise.toml index 6fc82e7d242..ffcdfb1b5ae 100644 --- a/rules/integrations/azure/initial_access_entra_id_protection_confirmed_compromise.toml +++ b/rules/integrations/azure/initial_access_entra_id_protection_confirmed_compromise.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/06" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ This rule detects when an administrator has manually confirmed a user or sign-in ### Possible investigation steps - Review the `azure.identityprotection.properties.risk_detail` field to determine if the compromise was confirmed at the sign-in level (`adminConfirmedSigninCompromised`) or user level (`adminConfirmedUserCompromised`). -- Check the `azure.identityprotection.properties.user_principal_name` field to identify the compromised user account. +- Check the `user.name` field to identify the compromised user account. - Review the `azure.identityprotection.properties.user_display_name` field for additional user identification information. - Examine the `azure.identityprotection.properties.risk_level` field to understand the severity level assigned to the risk event. - Check the `azure.identityprotection.properties.risk_state` field to verify the current state of the risk (should be confirmed as compromised). @@ -167,7 +167,7 @@ field_names = [ "azure.identityprotection.properties.risk_state", "azure.identityprotection.properties.risk_event_type", "azure.identityprotection.properties.risk_type", - "azure.identityprotection.properties.user_principal_name", + "user.name", "azure.identityprotection.properties.user_display_name", "azure.identityprotection.properties.user_id", "azure.identityprotection.properties.ip_address", diff --git a/rules/integrations/azure/initial_access_entra_id_protection_sign_in_risk_detected.toml b/rules/integrations/azure/initial_access_entra_id_protection_sign_in_risk_detected.toml index bf6f4e67332..b12ff69f683 100644 --- a/rules/integrations/azure/initial_access_entra_id_protection_sign_in_risk_detected.toml +++ b/rules/integrations/azure/initial_access_entra_id_protection_sign_in_risk_detected.toml @@ -3,7 +3,7 @@ creation_date = "2025/04/29" integration = ["azure"] maturity = "production" promotion = true -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -45,7 +45,7 @@ This rule detects sign-in risk detection events via Microsoft Entra ID Protectio - Review the `azure.correlation_id` field to correlate this event with other related events in your environment. - Review the `azure.identityprotection.properties.additional_info` field for any additional information provided by Entra ID Protection. - Review the `azure.identityprotection.properties.detection_timing_type` field to understand when the risk event was detected. Offline detections may indicate a delayed response to a potential threat while real-time detections indicate immediate risk assessment. -- Check the `azure.identityprotection.properties.user_principal_name` field to identify the user account associated with the risk event. This can help determine if the account is compromised or if the risk event is expected behavior for that user. Triage the user account with other events from Entra ID audit or sign-in logs to identify any suspicious activity or patterns. +- Check the `user.name` field to identify the user account associated with the risk event. This can help determine if the account is compromised or if the risk event is expected behavior for that user. Triage the user account with other events from Entra ID audit or sign-in logs to identify any suspicious activity or patterns. ### False positive analysis @@ -181,7 +181,7 @@ field_names = [ "azure.identityprotection.properties.risk_event_type", "azure.identityprotection.properties.risk_level", "azure.identityprotection.properties.risk_detail", - "azure.identityprotection.properties.user_principal_name", + "user.name", "azure.identityprotection.properties.user_display_name", "azure.identityprotection.properties.risk_state", "azure.identityprotection.properties.risk_type", diff --git a/rules/integrations/azure/initial_access_entra_id_protection_user_risk_detected.toml b/rules/integrations/azure/initial_access_entra_id_protection_user_risk_detected.toml index 3f97a4ee07a..5d78f0bb0c2 100644 --- a/rules/integrations/azure/initial_access_entra_id_protection_user_risk_detected.toml +++ b/rules/integrations/azure/initial_access_entra_id_protection_user_risk_detected.toml @@ -3,7 +3,7 @@ creation_date = "2025/06/02" integration = ["azure"] maturity = "production" promotion = true -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -45,7 +45,7 @@ This rule detects user risk detection events via Microsoft Entra ID Protection. - Review the `azure.correlation_id` field to correlate this event with other related events in your environment. - Review the `azure.identityprotection.properties.additional_info` field for any additional information provided by Entra ID Protection. - Review the `azure.identityprotection.properties.detection_timing_type` field to understand when the risk event was detected. Offline detections may indicate a delayed response to a potential threat while real-time detections indicate immediate risk assessment. -- Check the `azure.identityprotection.properties.user_principal_name` field to identify the user account associated with the risk event. This can help determine if the account is compromised or if the risk event is expected behavior for that user. Triage the user account with other events from Entra ID audit or sign-in logs to identify any suspicious activity or patterns. +- Check the `user.name` field to identify the user account associated with the risk event. This can help determine if the account is compromised or if the risk event is expected behavior for that user. Triage the user account with other events from Entra ID audit or sign-in logs to identify any suspicious activity or patterns. ### False positive analysis @@ -178,7 +178,7 @@ field_names = [ "azure.identityprotection.properties.risk_event_type", "azure.identityprotection.properties.risk_level", "azure.identityprotection.properties.risk_detail", - "azure.identityprotection.properties.user_principal_name", + "user.name", "azure.identityprotection.properties.user_display_name", "azure.identityprotection.properties.risk_state", "azure.identityprotection.properties.risk_type", diff --git a/rules/integrations/azure/initial_access_entra_id_rare_app_id_for_principal_auth.toml b/rules/integrations/azure/initial_access_entra_id_rare_app_id_for_principal_auth.toml index 2ad9e2ee64d..04cfa97b760 100644 --- a/rules/integrations/azure/initial_access_entra_id_rare_app_id_for_principal_auth.toml +++ b/rules/integrations/azure/initial_access_entra_id_rare_app_id_for_principal_auth.toml @@ -2,7 +2,7 @@ creation_date = "2025/03/10" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -31,7 +31,7 @@ This rule identifies rare Azure Entra apps IDs requesting authentication on-beha ### Possible investigation steps - Identify the source IP address from which the failed login attempts originated by reviewing `source.ip`. Determine if the IP is associated with known malicious activity using threat intelligence sources or if it belongs to a corporate VPN, proxy, or automation process. -- Analyze affected user accounts by reviewing `azure.signinlogs.properties.user_principal_name` to determine if they belong to privileged roles or high-value users. Look for patterns indicating multiple failed attempts across different users, which could suggest a password spraying attempt. +- Analyze affected user accounts by reviewing `user.name` to determine if they belong to privileged roles or high-value users. Look for patterns indicating multiple failed attempts across different users, which could suggest a password spraying attempt. - Examine the authentication method used in `azure.signinlogs.properties.authentication_details` to identify which authentication protocols were attempted and why they failed. Legacy authentication methods may be more susceptible to brute-force attacks. - Review the authentication error codes found in `azure.signinlogs.properties.status.error_code` to understand why the login attempts failed. Common errors include `50126` for invalid credentials, `50053` for account lockouts, `50055` for expired passwords, and `50056` for users without a password. - Correlate failed logins with other sign-in activity by looking at `event.outcome`. Identify if there were any successful logins from the same user shortly after multiple failures or if there are different geolocations or device fingerprints associated with the same account. @@ -45,13 +45,13 @@ This rule identifies rare Azure Entra apps IDs requesting authentication on-beha - User account lockouts from forgotten passwords or misconfigured applications may show multiple authentication failures in `azure.signinlogs.properties.status.error_code`. - Exclude known trusted IPs, such as corporate infrastructure, from alerts by filtering `source.ip`. - Exclude known custom applications from `azure.signinlogs.properties.app_id` that are authorized to use non-interactive authentication. -- Ignore principals with a history of failed logins due to legitimate reasons, such as expired passwords or account lockouts, by filtering `azure.signinlogs.properties.user_principal_name`. +- Ignore principals with a history of failed logins due to legitimate reasons, such as expired passwords or account lockouts, by filtering `user.name`. - Correlate sign-in failures with password reset events or normal user behavior before triggering an alert. ## Response and remediation - Block the source IP address in `source.ip` if determined to be malicious. -- Reset passwords for all affected user accounts listed in `azure.signinlogs.properties.user_principal_name` and enforce stronger password policies. +- Reset passwords for all affected user accounts listed in `user.name` and enforce stronger password policies. - Ensure basic authentication is disabled for all applications using legacy authentication protocols listed in `azure.signinlogs.properties.authentication_protocol`. - Enable multi-factor authentication (MFA) for impacted accounts to mitigate credential-based attacks. - Review conditional access policies to ensure they are correctly configured to block unauthorized access attempts recorded in `azure.signinlogs.properties.authentication_requirement`. @@ -171,8 +171,8 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.investigation_fields] field_names = [ - "azure.signinlogs.properties.user_principal_name", - "azure.signinlogs.properties.user_id", + "user.name", + "user.id", "azure.signinlogs.properties.app_id", "azure.signinlogs.properties.app_display_name", "azure.signinlogs.properties.client_app_used", @@ -190,7 +190,7 @@ field_names = [ [rule.new_terms] field = "new_terms_fields" -value = ["azure.signinlogs.properties.user_principal_name", "azure.signinlogs.properties.app_id"] +value = ["user.name", "azure.signinlogs.properties.app_id"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-14d" diff --git a/rules/integrations/azure/initial_access_entra_id_rare_authentication_requirement_for_principal_user.toml b/rules/integrations/azure/initial_access_entra_id_rare_authentication_requirement_for_principal_user.toml index 8542f6ca1fb..c8dbdc55b49 100644 --- a/rules/integrations/azure/initial_access_entra_id_rare_authentication_requirement_for_principal_user.toml +++ b/rules/integrations/azure/initial_access_entra_id_rare_authentication_requirement_for_principal_user.toml @@ -2,7 +2,7 @@ creation_date = "2025/03/10" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -23,12 +23,12 @@ note = """## Triage and analysis Identifies rare instances of authentication requirements for Azure Entra ID principal users. An adversary with stolen credentials may attempt to authenticate with unusual authentication requirements, which is a rare event and may indicate an attempt to bypass conditional access policies (CAP) and multi-factor authentication (MFA) requirements. The authentication requirements specified may not be commonly used by the user based on their historical sign-in activity. -**This is a New Terms rule that focuses on first occurrence of an Entra ID principal user `azure.signinlogs.properties.user_principal_name` and their authentication requirement `azure.signinlogs.properties.authentication_requirement` in the last 14-days.** +**This is a New Terms rule that focuses on first occurrence of an Entra ID principal user `user.name` and their authentication requirement `azure.signinlogs.properties.authentication_requirement` in the last 14-days.** ### Possible investigation steps - Identify the source IP address from which the failed login attempts originated by reviewing `source.ip`. Determine if the IP is associated with known malicious activity using threat intelligence sources or if it belongs to a corporate VPN, proxy, or automation process. -- Analyze affected user accounts by reviewing `azure.signinlogs.properties.user_principal_name` to determine if they belong to privileged roles or high-value users. Look for patterns indicating multiple failed attempts across different users, which could suggest a password spraying attempt. +- Analyze affected user accounts by reviewing `user.name` to determine if they belong to privileged roles or high-value users. Look for patterns indicating multiple failed attempts across different users, which could suggest a password spraying attempt. - Examine the authentication method used in `azure.signinlogs.properties.authentication_details` to identify which authentication protocols were attempted and why they failed. Legacy authentication methods may be more susceptible to brute-force attacks. - Review the authentication error codes found in `azure.signinlogs.properties.status.error_code` to understand why the login attempts failed. Common errors include `50126` for invalid credentials, `50053` for account lockouts, `50055` for expired passwords, and `50056` for users without a password. - Correlate failed logins with other sign-in activity by looking at `event.outcome`. Identify if there were any successful logins from the same user shortly after multiple failures or if there are different geolocations or device fingerprints associated with the same account. @@ -45,14 +45,14 @@ Identifies rare instances of authentication requirements for Azure Entra ID prin ### How to reduce false positives - Exclude known trusted IPs, such as corporate infrastructure, from alerts by filtering `source.ip`. - Exlcude known custom applications from `azure.signinlogs.properties.app_id` that are authorized to use non-interactive authentication. -- Ignore principals with a history of failed logins due to legitimate reasons, such as expired passwords or account lockouts, by filtering `azure.signinlogs.properties.user_principal_name`. +- Ignore principals with a history of failed logins due to legitimate reasons, such as expired passwords or account lockouts, by filtering `user.name`. - Correlate sign-in failures with password reset events or normal user behavior before triggering an alert. ## Response and remediation ### Immediate actions - Block the source IP address in `source.ip` if determined to be malicious. -- Reset passwords for all affected user accounts listed in `azure.signinlogs.properties.user_principal_name` and enforce stronger password policies. +- Reset passwords for all affected user accounts listed in `user.name` and enforce stronger password policies. - Ensure basic authentication is disabled for all applications using legacy authentication protocols listed in `azure.signinlogs.properties.authentication_protocol`. - Enable multi-factor authentication (MFA) for impacted accounts to mitigate credential-based attacks. - Review conditional access policies to ensure they are correctly configured to block unauthorized access attempts recorded in `azure.signinlogs.properties.authentication_requirement`. @@ -153,7 +153,7 @@ reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" value = [ - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.authentication_requirement", ] [[rule.new_terms.history_window_start]] diff --git a/rules/integrations/azure/initial_access_entra_id_risky_user_or_compromised_sign_in.toml b/rules/integrations/azure/initial_access_entra_id_risky_user_or_compromised_sign_in.toml index 15c46a6f4a0..b9133d21e22 100644 --- a/rules/integrations/azure/initial_access_entra_id_risky_user_or_compromised_sign_in.toml +++ b/rules/integrations/azure/initial_access_entra_id_risky_user_or_compromised_sign_in.toml @@ -2,7 +2,7 @@ creation_date = "2021/10/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -79,7 +79,7 @@ type = "query" query = ''' data_stream.dataset:azure.signinlogs and - azure.signinlogs.properties.risk_state:("confirmedCompromised" or "atRisk") and event.outcome:(success or Success) + azure.signinlogs.properties.risk_state:("confirmedCompromised" or "atRisk") and event.outcome:(success) ''' diff --git a/rules/integrations/azure/initial_access_entra_id_suspicious_oauth_flow_via_auth_broker_to_drs.toml b/rules/integrations/azure/initial_access_entra_id_suspicious_oauth_flow_via_auth_broker_to_drs.toml index d16b7a3ca6d..9360c97cb39 100644 --- a/rules/integrations/azure/initial_access_entra_id_suspicious_oauth_flow_via_auth_broker_to_drs.toml +++ b/rules/integrations/azure/initial_access_entra_id_suspicious_oauth_flow_via_auth_broker_to_drs.toml @@ -2,7 +2,7 @@ creation_date = "2025/04/30" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -95,7 +95,7 @@ from logs-azure.signinlogs-* metadata _id, _version, _index event.outcome == "success" and azure.signinlogs.properties.user_type == "Member" and azure.signinlogs.identity is not null and - azure.signinlogs.properties.user_principal_name is not null and + user.name is not null and source.address is not null and azure.signinlogs.properties.app_id == "29d9ed98-a469-4536-ade2-f981bc1d605e" and // MAB azure.signinlogs.properties.resource_id == "01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9" // DRS @@ -109,7 +109,7 @@ from logs-azure.signinlogs-* metadata _id, _version, _index | stats Esql_priv.azure_signinlogs_properties_user_display_name_values = values(azure.signinlogs.properties.user_display_name), - Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(azure.signinlogs.properties.user_principal_name), + Esql_priv.azure_signinlogs_properties_user_principal_name_values = values(user.name), Esql.azure_signinlogs_properties_session_id_values = values(azure.signinlogs.properties.session_id), Esql.azure_signinlogs_properties_unique_token_identifier_values = values(azure.signinlogs.properties.unique_token_identifier), @@ -147,7 +147,7 @@ from logs-azure.signinlogs-* metadata _id, _version, _index Esql.event_count = count(*) by Esql.time_window_date_trunc, - azure.signinlogs.properties.user_principal_name, + user.name, azure.signinlogs.properties.session_id | keep diff --git a/rules/integrations/azure/initial_access_entra_id_temporary_access_pass_created.toml b/rules/integrations/azure/initial_access_entra_id_temporary_access_pass_created.toml index 369264ca2ce..4f13bd49978 100644 --- a/rules/integrations/azure/initial_access_entra_id_temporary_access_pass_created.toml +++ b/rules/integrations/azure/initial_access_entra_id_temporary_access_pass_created.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/20" integration = ["azure"] maturity = "production" -updated_date = "2026/06/05" +updated_date = "2026/06/23" [rule] author = ["Elastic", "descambiado"] @@ -85,12 +85,12 @@ query = ''' data_stream.dataset: "azure.auditlogs" and ( ( - azure.auditlogs.operation_name: "User registered security info" and - azure.auditlogs.properties.result_reason: "User registered temporary access pass method" + event.action: "User registered security info" and + event.reason: "User registered temporary access pass method" ) or ( - azure.auditlogs.operation_name: "Create Temporary Access Pass method for user" + event.action: "Create Temporary Access Pass method for user" ) or ( - azure.auditlogs.operation_name: "Admin registered security info" and + event.action: "Admin registered security info" and azure.auditlogs.properties.target_resources.*.modified_properties.*.display_name: *TemporaryAccessPass* ) ) and diff --git a/rules/integrations/azure/initial_access_entra_id_unusual_ropc_login_attempt.toml b/rules/integrations/azure/initial_access_entra_id_unusual_ropc_login_attempt.toml index 73652de9658..aaac05998b6 100644 --- a/rules/integrations/azure/initial_access_entra_id_unusual_ropc_login_attempt.toml +++ b/rules/integrations/azure/initial_access_entra_id_unusual_ropc_login_attempt.toml @@ -2,7 +2,7 @@ creation_date = "2025/07/02" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -26,7 +26,7 @@ note = """## Triage and analysis This rule detects unusual login attempts using the Resource Owner Password Credentials (ROPC) flow in Microsoft Entra ID. ROPC allows applications to obtain tokens by directly providing user credentials, bypassing multi-factor authentication (MFA). This method is less secure and can be exploited by adversaries to gain access to user accounts, especially during enumeration or password spraying. ### Possible investigation steps -- Review the `azure.signinlogs.properties.user_principal_name` field to identify the user principal involved in the ROPC login attempt. Check if this user is expected to use ROPC or if it is an unusual account for this type of authentication. +- Review the `user.name` field to identify the user principal involved in the ROPC login attempt. Check if this user is expected to use ROPC or if it is an unusual account for this type of authentication. - Analyze the `azure.signinlogs.properties.authentication_protocol` field to confirm that the authentication protocol is indeed ROPC. This protocol is typically used in legacy applications or scripts that do not support modern authentication methods. - Check the `user_agent.original` field to identify potentially abused open-source tools or scripts that may be using ROPC for unauthorized access such as TeamFiltration or other enumeration tools. - Review the `azure.signinlogs.properties.app_display_name` or `azure.signinlogs.properties.app_id` to determine which application is attempting the ROPC login. FOCI applications are commonly used for enumeration and password spraying. @@ -115,7 +115,7 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.signinlogs.properties.user_principal_name"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-10d" diff --git a/rules/integrations/azure/initial_access_entra_id_user_reported_risk.toml b/rules/integrations/azure/initial_access_entra_id_user_reported_risk.toml index 06a6dfea170..177286563a8 100644 --- a/rules/integrations/azure/initial_access_entra_id_user_reported_risk.toml +++ b/rules/integrations/azure/initial_access_entra_id_user_reported_risk.toml @@ -2,7 +2,7 @@ creation_date = "2025/05/21" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Willem D'Haese"] @@ -22,10 +22,10 @@ This rule detects when a user in Microsoft Entra ID reports suspicious activity ### Possible investigation steps -- Review the `azure.auditlogs.identity` field to identify the reporting user. +- Review the `user.full_name` field to identify the reporting user. - Confirm that `event.action` is `"Suspicious activity reported"` and the result was `"success"`. - Check the `azure.auditlogs.properties.additional_details` array for `AuthenticationMethod`, which shows how the login attempt was performed (e.g., `PhoneAppNotification`). -- Look at the `azure.auditlogs.properties.initiated_by.user.userPrincipalName` and `displayName` to confirm which user reported the suspicious activity. +- Look at the `user.name` and `displayName` to confirm which user reported the suspicious activity. - Investigate recent sign-in activity (`signinlogs`) for the same user. Focus on: - IP address geolocation and ASN. - Device, operating system, and browser. @@ -71,7 +71,7 @@ type = "query" query = ''' data_stream.dataset: "azure.auditlogs" - and azure.auditlogs.operation_name: "Suspicious activity reported" + and event.action: "Suspicious activity reported" and azure.auditlogs.properties.additional_details.key: "AuthenticationMethod" and azure.auditlogs.properties.target_resources.*.type: "User" and event.outcome: "success" diff --git a/rules/integrations/azure/initial_access_tycoon_entra_id.toml b/rules/integrations/azure/initial_access_tycoon_entra_id.toml index 51357a022eb..498b4f09a43 100644 --- a/rules/integrations/azure/initial_access_tycoon_entra_id.toml +++ b/rules/integrations/azure/initial_access_tycoon_entra_id.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/14" integration = ["azure"] maturity = "production" -updated_date = "2026/05/14" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ note = """## Triage and analysis ### Investigating Entra ID Potential AiTM Sign-In via OfficeHome (Tycoon2FA) -Review user.name, azure.signinlogs.properties.user_principal_name, azure.signinlogs.properties.app_id, +Review user.name, user.name, azure.signinlogs.properties.app_id, azure.signinlogs.properties.resource_id, user_agent.original, source.ip, source.geo fields, and azure.signinlogs.properties.session_id. @@ -90,7 +90,7 @@ field_names = [ "source.ip", "source.geo.country_name", "event.outcome", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.session_id", "azure.signinlogs.properties.app_display_name", "azure.signinlogs.properties.app_id", diff --git a/rules/integrations/azure/lateral_movement_azure_vm_serial_console_connect.toml b/rules/integrations/azure/lateral_movement_azure_vm_serial_console_connect.toml index c9cb520dcf0..1f1afb100aa 100644 --- a/rules/integrations/azure/lateral_movement_azure_vm_serial_console_connect.toml +++ b/rules/integrations/azure/lateral_movement_azure_vm_serial_console_connect.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/07" integration = ["azure"] maturity = "production" -updated_date = "2026/06/07" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -87,7 +87,7 @@ timestamp_override = "event.ingested" type = "new_terms" query = ''' data_stream.dataset:azure.activitylogs and - azure.activitylogs.operation_name:"MICROSOFT.SERIALCONSOLE/SERIALPORTS/CONNECT/ACTION" and + event.action:"MICROSOFT.SERIALCONSOLE/SERIALPORTS/CONNECT/ACTION" and event.outcome:("success" or "Success") and azure.activitylogs.identity.authorization.evidence.principal_id:* and source.as.number:* @@ -97,10 +97,10 @@ data_stream.dataset:azure.activitylogs and field_names = [ "@timestamp", "event.outcome", - "azure.activitylogs.operation_name", + "event.action", "azure.activitylogs.identity.authorization.evidence.principal_id", "azure.activitylogs.identity.authorization.evidence.principal_type", - "azure.activitylogs.identity.claims_initiated_by_user.name", + "user.name", "azure.resource.id", "azure.resource.name", "source.ip", diff --git a/rules/integrations/azure/persistence_automation_account_created.toml b/rules/integrations/azure/persistence_automation_account_created.toml index 2fa13e71c83..3d6642edcca 100644 --- a/rules/integrations/azure/persistence_automation_account_created.toml +++ b/rules/integrations/azure/persistence_automation_account_created.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -67,7 +67,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WRITE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WRITE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/persistence_automation_webhook_created.toml b/rules/integrations/azure/persistence_automation_webhook_created.toml index cd7496bf4b1..71ef2323037 100644 --- a/rules/integrations/azure/persistence_automation_webhook_created.toml +++ b/rules/integrations/azure/persistence_automation_webhook_created.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,7 +27,7 @@ Azure Automation webhooks enable automated task execution via HTTP requests, int ### Possible investigation steps -- Review the Azure activity logs to identify the user or service principal that initiated the webhook creation by examining the `event.dataset` and `azure.activitylogs.operation_name` fields. +- Review the Azure activity logs to identify the user or service principal that initiated the webhook creation by examining the `event.dataset` and `event.action` fields. - Check the associated runbook linked to the created webhook to determine its purpose and inspect its content for any potentially malicious scripts or commands. - Investigate the source IP address and location from which the webhook creation request originated to identify any unusual or unauthorized access patterns. - Verify the legitimacy of the webhook by contacting the owner of the Azure Automation account or the relevant team to confirm if the webhook creation was expected and authorized. @@ -69,12 +69,12 @@ type = "query" query = ''' data_stream.dataset:azure.activitylogs and - azure.activitylogs.operation_name: + event.action: ( "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WEBHOOKS/ACTION" or "MICROSOFT.AUTOMATION/AUTOMATIONACCOUNTS/WEBHOOKS/WRITE" ) and - event.outcome:(Success or success) + event.outcome:(success) ''' [[rule.threat]] diff --git a/rules/integrations/azure/persistence_azure_vm_extension_deployment_by_interactive_user.toml b/rules/integrations/azure/persistence_azure_vm_extension_deployment_by_interactive_user.toml index 5c1a1bb29e1..2dddd0e7f50 100644 --- a/rules/integrations/azure/persistence_azure_vm_extension_deployment_by_interactive_user.toml +++ b/rules/integrations/azure/persistence_azure_vm_extension_deployment_by_interactive_user.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/20" integration = ["azure"] maturity = "production" -updated_date = "2026/05/20" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -73,9 +73,9 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:azure.activitylogs and -azure.activitylogs.operation_name:"MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE" and +event.action:"MICROSOFT.COMPUTE/VIRTUALMACHINES/EXTENSIONS/WRITE" and azure.activitylogs.identity.authorization.evidence.principal_type:User and -event.outcome:(success or Success) and +event.outcome:(success) and azure.resource.id:( *VMACCESSAGENT* or *CUSTOMSCRIPTEXTENSION* or @@ -90,10 +90,10 @@ azure.resource.id:( field_names = [ "@timestamp", "event.outcome", - "azure.activitylogs.operation_name", + "event.action", "azure.activitylogs.identity.authorization.evidence.principal_id", "azure.activitylogs.identity.authorization.evidence.principal_type", - "azure.activitylogs.identity.claims_initiated_by_user.name", + "user.name", "azure.resource.id", "azure.resource.name", "source.ip", diff --git a/rules/integrations/azure/persistence_entra_id_application_credential_modification.toml b/rules/integrations/azure/persistence_entra_id_application_credential_modification.toml index 26b7d7f044f..8de60df7401 100644 --- a/rules/integrations/azure/persistence_entra_id_application_credential_modification.toml +++ b/rules/integrations/azure/persistence_entra_id_application_credential_modification.toml @@ -2,7 +2,7 @@ creation_date = "2020/12/14" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -81,7 +81,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.auditlogs and azure.auditlogs.operation_name:"Update application - Certificates and secrets management" and event.outcome:(success or Success) +data_stream.dataset:azure.auditlogs and event.action:"Update application - Certificates and secrets management" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/persistence_entra_id_conditional_access_policy_modified.toml b/rules/integrations/azure/persistence_entra_id_conditional_access_policy_modified.toml index 9d1427b1bc1..1676794af94 100644 --- a/rules/integrations/azure/persistence_entra_id_conditional_access_policy_modified.toml +++ b/rules/integrations/azure/persistence_entra_id_conditional_access_policy_modified.toml @@ -2,7 +2,7 @@ creation_date = "2020/09/01" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -25,7 +25,7 @@ This rule detects a successful update to a Conditional Access Policy in Microsof ### Possible Investigation Steps - **Identify the user who modified the policy:** - - Check the value of `azure.auditlogs.properties.initiated_by.user.userPrincipalName` to determine the identity that made the change. + - Check the value of `user.name` to determine the identity that made the change. - Investigate their recent activity to determine if this change was expected or authorized. - **Review the modified policy name:** @@ -127,7 +127,7 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.auditlogs.properties.initiated_by.user.userPrincipalName"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-14d" diff --git a/rules/integrations/azure/persistence_entra_id_global_administrator_role_assigned.toml b/rules/integrations/azure/persistence_entra_id_global_administrator_role_assigned.toml index 862c8d4de6c..624001cec90 100644 --- a/rules/integrations/azure/persistence_entra_id_global_administrator_role_assigned.toml +++ b/rules/integrations/azure/persistence_entra_id_global_administrator_role_assigned.toml @@ -2,7 +2,7 @@ creation_date = "2022/01/06" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -76,7 +76,7 @@ type = "query" query = ''' data_stream.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement and - azure.auditlogs.operation_name:"Add member to role" and + event.action:"Add member to role" and azure.auditlogs.properties.target_resources.*.modified_properties.*.new_value: "\"Global Administrator\"" ''' diff --git a/rules/integrations/azure/persistence_entra_id_guest_account_promoted_to_member.toml b/rules/integrations/azure/persistence_entra_id_guest_account_promoted_to_member.toml index fabb4cc4851..ca59805fadc 100644 --- a/rules/integrations/azure/persistence_entra_id_guest_account_promoted_to_member.toml +++ b/rules/integrations/azure/persistence_entra_id_guest_account_promoted_to_member.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/20" integration = ["azure"] maturity = "production" -updated_date = "2026/05/20" +updated_date = "2026/06/23" [rule] author = ["Elastic", "descambiado"] @@ -75,11 +75,11 @@ type = "query" query = ''' data_stream.dataset: "azure.auditlogs" and -azure.auditlogs.operation_name: "Update user" and +event.action: "Update user" and azure.auditlogs.properties.target_resources.*.modified_properties.*.display_name: "UserType" and azure.auditlogs.properties.target_resources.*.modified_properties.*.old_value: *Guest* and azure.auditlogs.properties.target_resources.*.modified_properties.*.new_value: *Member* and -event.outcome: (Success or success) +event.outcome: (success) ''' [[rule.threat]] diff --git a/rules/integrations/azure/persistence_entra_id_mfa_disabled_for_user.toml b/rules/integrations/azure/persistence_entra_id_mfa_disabled_for_user.toml index 188160ecd6a..9e52723ddf7 100644 --- a/rules/integrations/azure/persistence_entra_id_mfa_disabled_for_user.toml +++ b/rules/integrations/azure/persistence_entra_id_mfa_disabled_for_user.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/20" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -77,11 +77,11 @@ type = "query" query = ''' data_stream.dataset: "azure.auditlogs" and - (azure.auditlogs.operation_name: "Disable Strong Authentication" or + (event.action: "Disable Strong Authentication" or ( - azure.auditlogs.operation_name: "User deleted security info" and + event.action: "User deleted security info" and azure.auditlogs.properties.additional_details.key: "AuthenticationMethod" - )) and event.outcome: (Success or success) + )) and event.outcome: (success) ''' [[rule.threat]] diff --git a/rules/integrations/azure/persistence_entra_id_microsoft_auth_broker_drs_signin_from_suspicious_asn.toml b/rules/integrations/azure/persistence_entra_id_microsoft_auth_broker_drs_signin_from_suspicious_asn.toml index 0c97cc24302..8d30cf5a102 100644 --- a/rules/integrations/azure/persistence_entra_id_microsoft_auth_broker_drs_signin_from_suspicious_asn.toml +++ b/rules/integrations/azure/persistence_entra_id_microsoft_auth_broker_drs_signin_from_suspicious_asn.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/26" integration = ["azure"] maturity = "production" -updated_date = "2026/05/26" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ note = """## Triage and analysis ### Investigating Entra ID Microsoft Authentication Broker DRS Sign-In from Suspicious ASN -Review `azure.signinlogs.properties.user_principal_name`, `azure.signinlogs.properties.app_display_name`, +Review `user.name`, `azure.signinlogs.properties.app_display_name`, `azure.signinlogs.properties.resource_display_name`, `azure.signinlogs.properties.session_id`, `source.ip`, `source.as.number`, `source.as.organization.name`, and `user_agent.original`. @@ -99,7 +99,7 @@ field_names = [ "source.as.organization.name", "source.geo.country_name", "event.outcome", - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.session_id", "azure.signinlogs.properties.app_display_name", "azure.signinlogs.properties.app_id", diff --git a/rules/integrations/azure/persistence_entra_id_oauth_app_redirect_uri_modified.toml b/rules/integrations/azure/persistence_entra_id_oauth_app_redirect_uri_modified.toml index 865beada7c7..fc41e3221b1 100644 --- a/rules/integrations/azure/persistence_entra_id_oauth_app_redirect_uri_modified.toml +++ b/rules/integrations/azure/persistence_entra_id_oauth_app_redirect_uri_modified.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/20" integration = ["azure"] maturity = "production" -updated_date = "2026/05/20" +updated_date = "2026/06/23" [rule] author = ["Elastic", "descambiado"] @@ -82,7 +82,7 @@ type = "query" query = ''' data_stream.dataset: "azure.auditlogs" and -azure.auditlogs.operation_name: "Update application" and +event.action: "Update application" and event.outcome: ("Success" or "success") and azure.auditlogs.properties.target_resources.*.modified_properties.*.display_name: "AppAddress" ''' diff --git a/rules/integrations/azure/persistence_entra_id_pim_user_added_global_admin.toml b/rules/integrations/azure/persistence_entra_id_pim_user_added_global_admin.toml index 7c259484966..fc6223b738a 100644 --- a/rules/integrations/azure/persistence_entra_id_pim_user_added_global_admin.toml +++ b/rules/integrations/azure/persistence_entra_id_pim_user_added_global_admin.toml @@ -2,7 +2,7 @@ creation_date = "2020/09/24" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -75,10 +75,10 @@ type = "query" query = ''' data_stream.dataset:azure.auditlogs and azure.auditlogs.properties.category:RoleManagement and - azure.auditlogs.operation_name:("Add eligible member to role in PIM completed (permanent)" or + event.action:("Add eligible member to role in PIM completed (permanent)" or "Add member to role in PIM completed (timebound)") and azure.auditlogs.properties.target_resources.*.display_name:"Global Administrator" and - event.outcome:(Success or success) + event.outcome:(success) ''' diff --git a/rules/integrations/azure/persistence_entra_id_privileged_identity_management_role_modified.toml b/rules/integrations/azure/persistence_entra_id_privileged_identity_management_role_modified.toml index f0366644a3e..64762ec70b5 100644 --- a/rules/integrations/azure/persistence_entra_id_privileged_identity_management_role_modified.toml +++ b/rules/integrations/azure/persistence_entra_id_privileged_identity_management_role_modified.toml @@ -2,7 +2,7 @@ creation_date = "2020/09/01" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -79,7 +79,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.auditlogs and azure.auditlogs.operation_name:"Update role setting in PIM" and event.outcome:(Success or success) +data_stream.dataset:azure.auditlogs and event.action:"Update role setting in PIM" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/persistence_entra_id_register_device_unusual_user_agent.toml b/rules/integrations/azure/persistence_entra_id_register_device_unusual_user_agent.toml index d5668dadd2c..c12d1aba770 100644 --- a/rules/integrations/azure/persistence_entra_id_register_device_unusual_user_agent.toml +++ b/rules/integrations/azure/persistence_entra_id_register_device_unusual_user_agent.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/15" integration = ["azure"] maturity = "production" -updated_date = "2026/05/15" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,7 +28,7 @@ note = """## Triage and analysis ### Investigating Entra ID Register Device with Unusual User Agent (Azure AD Join) -Review `azure.auditlogs.properties.initiated_by.user.userPrincipalName`, source IP fields on the audit event, +Review `user.name`, source IP fields on the audit event, `azure.auditlogs.properties.target_resources.0.display_name` for the device name, and `azure.correlation_id` for related audit entries. @@ -67,7 +67,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:"azure.auditlogs" and event.action:"Register device" and -event.outcome:(success or Success) and +event.outcome:(success) and azure.auditlogs.properties.userAgent:(* and not (Dsreg* or DeviceRegistrationClient or Dalvik*)) and azure.auditlogs.properties.additional_details.value:"Azure AD join" ''' @@ -79,7 +79,7 @@ field_names = [ "event.outcome", "azure.auditlogs.properties.userAgent", "azure.auditlogs.properties.additional_details.value", - "azure.auditlogs.properties.initiated_by.user.userPrincipalName", + "user.name", "azure.auditlogs.properties.initiated_by.user.ipAddress", "azure.auditlogs.properties.target_resources.0.display_name", "azure.auditlogs.properties.target_resources.0.id", diff --git a/rules/integrations/azure/persistence_entra_id_roadtools_default_device_registration.toml b/rules/integrations/azure/persistence_entra_id_roadtools_default_device_registration.toml index 6384cb82cb5..3dbb9c9ab94 100644 --- a/rules/integrations/azure/persistence_entra_id_roadtools_default_device_registration.toml +++ b/rules/integrations/azure/persistence_entra_id_roadtools_default_device_registration.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/26" integration = ["azure"] maturity = "production" -updated_date = "2026/05/26" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -49,9 +49,9 @@ modified properties record the registered device characteristics: ### Possible investigation steps -- Confirm the registering identity via `azure.auditlogs.properties.initiated_by.user.userPrincipalName` and determine +- Confirm the registering identity via `user.name` and determine whether that user is expected to register a new device. -- Review `azure.auditlogs.identity` to confirm the `Device Registration Service` initiated the request, and use +- Review `user.full_name` to confirm the `Device Registration Service` initiated the request, and use `azure.correlation_id` to pivot across the full registration flow (`Add device`, `Add registered users to device`, `Add registered owner to device`). - Inspect the device name in `azure.auditlogs.properties.target_resources.0.display_name`; default `DESKTOP-` names that @@ -131,12 +131,12 @@ field_names = [ "@timestamp", "event.action", "event.outcome", - "azure.auditlogs.identity", - "azure.auditlogs.operation_name", + "user.full_name", + "event.action", "azure.auditlogs.properties.target_resources.0.display_name", "azure.auditlogs.properties.target_resources.0.modified_properties.3.new_value", "azure.auditlogs.properties.target_resources.0.modified_properties.4.new_value", - "azure.auditlogs.properties.initiated_by.user.userPrincipalName", + "user.name", "azure.auditlogs.properties.initiated_by.user.ipAddress", "azure.correlation_id", ] diff --git a/rules/integrations/azure/persistence_entra_id_rt_to_prt_transition_from_user_device.toml b/rules/integrations/azure/persistence_entra_id_rt_to_prt_transition_from_user_device.toml index 9f90cb117e7..19579bb8ff6 100644 --- a/rules/integrations/azure/persistence_entra_id_rt_to_prt_transition_from_user_device.toml +++ b/rules/integrations/azure/persistence_entra_id_rt_to_prt_transition_from_user_device.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/24" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -26,7 +26,7 @@ note = """## Triage and analysis This rule identifies a sequence where a Microsoft Entra ID authenticates using a refresh token issued to the Microsoft Authentication Broker (MAB), followed by an authentication using a Primary Refresh Token (PRT) from the same unmanaged device. This behavior is uncommon for normal user activity and strongly suggests adversarial behavior, particularly when paired with OAuth phishing and device registration tools like ROADtx. The use of PRT shortly after a refresh token sign-in typically indicates the attacker has registered a virtual device and is now using the PRT to impersonate a registered user+device pair. The device in question is still marked as unmanaged, indicating it is not compliant with organizational policies and managed by Intune or other MDM solutions. ### Possible investigation steps -- Identify the user principal and device from `azure.signinlogs.properties.user_principal_name` and `azure.signinlogs.properties.device_detail.device_id`. +- Identify the user principal and device from `user.name` and `azure.signinlogs.properties.device_detail.device_id`. - Confirm the first sign-in event came from the Microsoft Auth Broker (`app_id`) with `incoming_token_type: refreshToken`. - Ensure the device has a `trust_type` of "Azure AD joined" and that the `sign_in_session_status` is "unbound". - Confirm the second sign-in used `incoming_token_type: primaryRefreshToken` and that the `resource_display_name` is not "Device Registration Service". @@ -67,7 +67,7 @@ timestamp_override = "event.ingested" type = "eql" query = ''' -sequence by azure.signinlogs.properties.user_id, azure.signinlogs.properties.device_detail.device_id with maxspan=1h +sequence by user.id, azure.signinlogs.properties.device_detail.device_id with maxspan=1h [authentication where data_stream.dataset == "azure.signinlogs" and azure.signinlogs.category == "NonInteractiveUserSignInLogs" and @@ -94,7 +94,7 @@ sequence by azure.signinlogs.properties.user_id, azure.signinlogs.properties.dev [rule.investigation_fields] field_names = [ - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.device_detail.device_id", "azure.signinlogs.properties.incoming_token_type", "azure.signinlogs.properties.resource_display_name", diff --git a/rules/integrations/azure/persistence_entra_id_service_principal_created.toml b/rules/integrations/azure/persistence_entra_id_service_principal_created.toml index f938c577022..cef3ba175e4 100644 --- a/rules/integrations/azure/persistence_entra_id_service_principal_created.toml +++ b/rules/integrations/azure/persistence_entra_id_service_principal_created.toml @@ -2,7 +2,7 @@ creation_date = "2020/12/14" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -88,9 +88,9 @@ type = "query" query = ''' data_stream.dataset:azure.auditlogs - and azure.auditlogs.operation_name:"Add service principal" - and event.outcome:(success or Success) - and not azure.auditlogs.identity: ( + and event.action:"Add service principal" + and event.outcome:(success) + and not user.full_name: ( "Managed Service Identity" or "Windows Azure Service Management API" or "Microsoft Azure AD Internal - Jit Provisioning" or diff --git a/rules/integrations/azure/persistence_entra_id_service_principal_credentials_added.toml b/rules/integrations/azure/persistence_entra_id_service_principal_credentials_added.toml index 7703839749a..b40bee22f8e 100644 --- a/rules/integrations/azure/persistence_entra_id_service_principal_credentials_added.toml +++ b/rules/integrations/azure/persistence_entra_id_service_principal_credentials_added.toml @@ -2,7 +2,7 @@ creation_date = "2021/05/05" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Austin Songer"] @@ -74,7 +74,7 @@ type = "new_terms" query = ''' data_stream.dataset: "azure.auditlogs" - and azure.auditlogs.operation_name:"Add service principal credentials" + and event.action:"Add service principal credentials" and event.outcome: "success" ''' diff --git a/rules/integrations/azure/persistence_entra_id_service_principal_federated_issuer_modified.toml b/rules/integrations/azure/persistence_entra_id_service_principal_federated_issuer_modified.toml index 01c3be3815b..d887ab04013 100644 --- a/rules/integrations/azure/persistence_entra_id_service_principal_federated_issuer_modified.toml +++ b/rules/integrations/azure/persistence_entra_id_service_principal_federated_issuer_modified.toml @@ -4,7 +4,7 @@ integration = ["azure"] maturity = "production" min_stack_version = "9.2.0" min_stack_comments = "Changes in ECS added cloud.* fields which are not available prior to ^9.2.0" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,7 +28,7 @@ This technique provides persistent access to Azure resources with the applicatio ### Possible investigation steps -- Review `azure.auditlogs.properties.initiated_by.user.userPrincipalName` and `ipAddress` to identify who made the change and from where. +- Review `user.name` and `ipAddress` to identify who made the change and from where. - Examine the `Esql.external_idp_old_issuer` and `Esql.external_idp_new_issuer` fields to determine if the new issuer is expected or potentially malicious. - Check if the new issuer domain is controlled by the organization or if it's an external/suspicious domain. - Review the application's assigned roles and permissions to understand the scope of access gained. diff --git a/rules/integrations/azure/persistence_entra_id_suspicious_adrs_token_request.toml b/rules/integrations/azure/persistence_entra_id_suspicious_adrs_token_request.toml index f5d66ef0f1f..0120da8f950 100644 --- a/rules/integrations/azure/persistence_entra_id_suspicious_adrs_token_request.toml +++ b/rules/integrations/azure/persistence_entra_id_suspicious_adrs_token_request.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/13" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -26,7 +26,7 @@ note = """## Triage and analysis Detects suspicious OAuth 2.0 token requests where the Microsoft Authentication Broker (29d9ed98-a469-4536-ade2-f981bc1d605e) requests access to the Device Registration Service (01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9) on behalf of a user principal. The presence of the adrs_access scope in the authentication processing details suggests an attempt to access ADRS, which is atypical for standard user sign-ins. This behavior may reflect an effort to abuse device registration for unauthorized persistence, such as acquiring a Primary Refresh Token (PRT) or establishing a trusted session. ### Possible investigation steps -- Identify the user principal associated with the request by checking `azure.signinlogs.properties.user_principal_name` or `azure.signinlogs.properties.user_id`. +- Identify the user principal associated with the request by checking `user.name` or `user.id`. - Review the `azure.signinlogs.properties.app_id` and `azure.signinlogs.properties.resource_id` to confirm the request is made by the Microsoft Authentication Broker and targeting the Device Registration Service. - Examine the `azure.signinlogs.properties.authentication_processing_details.Oauth Scope Info` for the presence of `adrs_access`, indicating an attempt to access ADRS. - Check the `azure.signinlogs.properties.incoming_token_type` to confirm the request is made using a refresh token, which is typical for persistent access scenarios. diff --git a/rules/integrations/azure/persistence_entra_id_suspicious_cloud_device_registration.toml b/rules/integrations/azure/persistence_entra_id_suspicious_cloud_device_registration.toml index 4b5f06f0fba..b79bc6dc831 100644 --- a/rules/integrations/azure/persistence_entra_id_suspicious_cloud_device_registration.toml +++ b/rules/integrations/azure/persistence_entra_id_suspicious_cloud_device_registration.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/13" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -35,7 +35,7 @@ This pattern has been observed in OAuth phishing and PRT abuse campaigns where a ### Possible investigation steps - Identify the user principal associated with the device registration. -- Review the `azure.auditlogs.identity` field to confirm the Device Registration Service initiated the request. +- Review the `user.full_name` field to confirm the Device Registration Service initiated the request. - Check the user-agent in `azure.auditlogs.properties.additional_details.value`. Known attack tooling signatures include: - `Dsreg/10.0 (Windows X.X.X)` - ROADtools Windows device registration - `DeviceRegistrationClient` - ROADtools MacOS/Android device registration @@ -87,8 +87,8 @@ type = "eql" query = ''' sequence by azure.correlation_id with maxspan=5m [any where data_stream.dataset == "azure.auditlogs" and - azure.auditlogs.identity == "Device Registration Service" and - azure.auditlogs.operation_name == "Add device" and + user.full_name == "Device Registration Service" and + event.action == "Add device" and ( azure.auditlogs.properties.additional_details.value like "Microsoft.OData.Client/*" or azure.auditlogs.properties.additional_details.value like "Dsreg/*" or @@ -97,10 +97,10 @@ sequence by azure.correlation_id with maxspan=5m `azure.auditlogs.properties.target_resources.0.modified_properties.1.display_name` == "CloudAccountEnabled" and `azure.auditlogs.properties.target_resources.0.modified_properties.1.new_value` == "[true]"] [any where data_stream.dataset == "azure.auditlogs" and - azure.auditlogs.operation_name == "Add registered users to device" and + event.action == "Add registered users to device" and `azure.auditlogs.properties.target_resources.0.modified_properties.2.new_value` like "*urn:ms-drs:enterpriseregistration.windows.net*"] [any where data_stream.dataset == "azure.auditlogs" and - azure.auditlogs.operation_name == "Add registered owner to device"] + event.action == "Add registered owner to device"] ''' diff --git a/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_application.toml b/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_application.toml index c54c8b4ffa5..e8746340899 100644 --- a/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_application.toml +++ b/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_application.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/20" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,7 +27,7 @@ Azure applications often require specific permissions for functionality, managed ### Possible investigation steps -- Review the Azure audit logs to confirm the operation by filtering for event.dataset:azure.auditlogs and azure.auditlogs.operation_name:"Add owner to application" with a successful outcome. +- Review the Azure audit logs to confirm the operation by filtering for event.dataset:azure.auditlogs and event.action:"Add owner to application" with a successful outcome. - Identify the user account that was added as an owner and the account that performed the operation to determine if they are legitimate or potentially compromised. - Check the history of activities associated with both the added owner and the account that performed the operation to identify any suspicious behavior or patterns. - Verify the application's current configuration and permissions to assess any changes made after the new owner was added. @@ -62,7 +62,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.auditlogs and azure.auditlogs.operation_name:"Add owner to application" and event.outcome:(Success or success) +data_stream.dataset:azure.auditlogs and event.action:"Add owner to application" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_service_principal.toml b/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_service_principal.toml index 1e81b302fe4..6a56862d050 100644 --- a/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_service_principal.toml +++ b/rules/integrations/azure/persistence_entra_id_user_added_as_owner_for_azure_service_principal.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/20" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -67,7 +67,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.auditlogs and azure.auditlogs.operation_name:"Add owner to service principal" and event.outcome:(Success or success) +data_stream.dataset:azure.auditlogs and event.action:"Add owner to service principal" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/persistence_entra_id_user_signed_in_from_unusual_device.toml b/rules/integrations/azure/persistence_entra_id_user_signed_in_from_unusual_device.toml index c69f9447244..745b50ae75a 100644 --- a/rules/integrations/azure/persistence_entra_id_user_signed_in_from_unusual_device.toml +++ b/rules/integrations/azure/persistence_entra_id_user_signed_in_from_unusual_device.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/16" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -24,7 +24,7 @@ note = """## Triage and analysis This rule detects when a Microsoft Entra ID user signs in from a device that is not typically used by the user, which may indicate potential compromise or unauthorized access attempts. This rule detects unusual sign-in activity by comparing the device used for the sign-in against the user's typical device usage patterns. Adversaries may create and register a new device to obtain a Primary Refresh Token (PRT) and maintain persistent access. ### Possible investigation steps -- Review the `azure.signinlogs.properties.user_principal_name` field to identify the user associated with the sign-in. +- Review the `user.name` field to identify the user associated with the sign-in. - Check the `azure.signinlogs.properties.device_detail.device_id` field to identify the device used for the sign-in. - Review `azure.signinlogs.properties.incoming_token_type` to determine what tpe of security token was used for the sign-in, such as a Primary Refresh Token (PRT). - Examine `azure.signinlogs.category` to determine if these were non-interactive or interactive sign-ins. @@ -79,7 +79,7 @@ data_stream.dataset: "azure.signinlogs" and azure.signinlogs.properties.token_protection_status_details.sign_in_session_status: "unbound" and not azure.signinlogs.properties.device_detail.is_managed: true and not azure.signinlogs.properties.device_detail.device_id: "" and - azure.signinlogs.properties.user_principal_name: * + user.name: * ''' @@ -121,7 +121,7 @@ reference = "https://attack.mitre.org/tactics/TA0001/" [rule.investigation_fields] field_names = [ - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.device_detail.device_id", "azure.signinlogs.properties.incoming_token_type", "azure.signinlogs.category", @@ -137,7 +137,7 @@ field_names = [ [rule.new_terms] field = "new_terms_fields" value = [ - "azure.signinlogs.properties.user_principal_name", + "user.name", "azure.signinlogs.properties.device_detail.device_id", ] [[rule.new_terms.history_window_start]] diff --git a/rules/integrations/azure/persistence_event_hub_created_or_updated.toml b/rules/integrations/azure/persistence_event_hub_created_or_updated.toml index bbea4b3eb2a..05e4328b65d 100644 --- a/rules/integrations/azure/persistence_event_hub_created_or_updated.toml +++ b/rules/integrations/azure/persistence_event_hub_created_or_updated.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -36,7 +36,7 @@ Azure Event Hub Authorization Rules manage access to Event Hubs via cryptographi ### Possible investigation steps -- Review the Azure activity logs to identify the user or service principal associated with the operation by examining the `azure.activitylogs.operation_name` and `event.outcome` fields. +- Review the Azure activity logs to identify the user or service principal associated with the operation by examining the `event.action` and `event.outcome` fields. - Check the timestamp of the event to determine when the authorization rule was created or updated, and correlate this with any other suspicious activities around the same time. - Investigate the specific Event Hub namespace affected by the rule change to understand its role and importance within the organization. - Verify if the `RootManageSharedAccessKey` or any other high-privilege authorization rule was involved, as these carry significant risk if misused. @@ -72,7 +72,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name:"MICROSOFT.EVENTHUB/NAMESPACES/AUTHORIZATIONRULES/WRITE" and event.outcome:(Success or success) +data_stream.dataset:azure.activitylogs and event.action:"MICROSOFT.EVENTHUB/NAMESPACES/AUTHORIZATIONRULES/WRITE" and event.outcome:(success) ''' diff --git a/rules/integrations/azure/persistence_identity_protect_alert_followed_by_device_reg.toml b/rules/integrations/azure/persistence_identity_protect_alert_followed_by_device_reg.toml index 28f5f330964..752fb255c3d 100644 --- a/rules/integrations/azure/persistence_identity_protect_alert_followed_by_device_reg.toml +++ b/rules/integrations/azure/persistence_identity_protect_alert_followed_by_device_reg.toml @@ -2,7 +2,7 @@ creation_date = "2025/04/30" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,8 +74,8 @@ type = "eql" query = ''' sequence with maxspan=5m -[any where data_stream.dataset == "azure.identity_protection"] by azure.identityprotection.properties.user_principal_name -[any where data_stream.dataset == "azure.auditlogs" and event.action == "Register device"] by azure.auditlogs.properties.initiated_by.user.userPrincipalName +[any where data_stream.dataset == "azure.identity_protection"] by user.name +[any where data_stream.dataset == "azure.auditlogs" and event.action == "Register device"] by user.name ''' diff --git a/rules/integrations/azure/privilege_escalation_entra_id_elevate_to_user_administrator_access.toml b/rules/integrations/azure/privilege_escalation_entra_id_elevate_to_user_administrator_access.toml index 36adb58d878..077e36335cf 100644 --- a/rules/integrations/azure/privilege_escalation_entra_id_elevate_to_user_administrator_access.toml +++ b/rules/integrations/azure/privilege_escalation_entra_id_elevate_to_user_administrator_access.toml @@ -2,7 +2,7 @@ creation_date = "2025/05/22" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Austin Songer"] @@ -27,7 +27,7 @@ This rule identifies when a user elevates their permissions to the "User Access ### Possible investigation steps -- Review the `azure.auditlogs.properties.initiated_by.user.userPrincipalName` field to identify the user who elevated access. +- Review the `user.name` field to identify the user who elevated access. - Check `source.ip` and associated `source.geo.*` fields to determine the origin of the action. Confirm whether the IP, ASN, and location are expected for this user. - Investigate the application ID from `azure.auditlogs.properties.additional_details.value` to determine which interface or method was used to elevate access. - Pivot to Azure `signinlogs` or Entra `auditlogs` to: @@ -82,7 +82,7 @@ type = "new_terms" query = ''' data_stream.dataset: azure.auditlogs and ( - azure.auditlogs.operation_name: "User has elevated their access to User Access Administrator for their Azure Resources" or + event.action: "User has elevated their access to User Access Administrator for their Azure Resources" or azure.auditlogs.properties.additional_details.value: "Microsoft.Authorization/elevateAccess/action" ) and event.outcome: "success" ''' @@ -125,7 +125,7 @@ name = "Persistence" reference = "https://attack.mitre.org/tactics/TA0003/" [rule.new_terms] field = "new_terms_fields" -value = ["azure.auditlogs.properties.initiated_by.user.userPrincipalName"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/azure/privilege_escalation_entra_id_tenant_domain_federation_via_audit_logs.toml b/rules/integrations/azure/privilege_escalation_entra_id_tenant_domain_federation_via_audit_logs.toml index aab7eeeafa5..53b7fed1683 100644 --- a/rules/integrations/azure/privilege_escalation_entra_id_tenant_domain_federation_via_audit_logs.toml +++ b/rules/integrations/azure/privilege_escalation_entra_id_tenant_domain_federation_via_audit_logs.toml @@ -2,7 +2,7 @@ creation_date = "2026/03/03" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -31,7 +31,7 @@ Both events share the same `correlation_id` but neither includes the federation ### Possible investigation steps -- Review `azure.auditlogs.properties.initiated_by.user.userPrincipalName` and `ipAddress` to identify who made the change and from where. +- Review `user.name` and `ipAddress` to identify who made the change and from where. - For `"Set domain authentication"` events, check `azure.auditlogs.properties.target_resources.0.display_name` to identify which domain was federated. - Use `azure.correlation_id` to correlate the companion `"Set federation settings on domain"` event and establish the full context. - Query the Graph API to retrieve the actual federation configuration details, since they are not logged in the audit event: `Get-MgDomainFederationConfiguration -DomainId ""`. diff --git a/rules/integrations/azure/privilege_escalation_kubernetes_aks_rolebinding_created.toml b/rules/integrations/azure/privilege_escalation_kubernetes_aks_rolebinding_created.toml index 99401890ed5..564d603871b 100644 --- a/rules/integrations/azure/privilege_escalation_kubernetes_aks_rolebinding_created.toml +++ b/rules/integrations/azure/privilege_escalation_kubernetes_aks_rolebinding_created.toml @@ -2,7 +2,7 @@ creation_date = "2021/10/18" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -27,7 +27,7 @@ Azure Kubernetes role bindings are crucial for managing access control within Ku ### Possible investigation steps -- Review the Azure activity logs to identify the user or service account associated with the role binding creation event. Focus on the `event.dataset` and `azure.activitylogs.operation_name` fields to confirm the specific operation. +- Review the Azure activity logs to identify the user or service account associated with the role binding creation event. Focus on the `event.dataset` and `event.action` fields to confirm the specific operation. - Check the `event.outcome` field to ensure the operation was successful and not a failed attempt, which might indicate a misconfiguration or testing. - Investigate the permissions and roles assigned to the identified user or service account to determine if they have legitimate reasons to create role bindings or cluster role bindings. - Examine the context of the role binding creation, such as the time of the event and any related activities, to identify any unusual patterns or correlations with other suspicious activities. @@ -73,10 +73,10 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:azure.activitylogs and azure.activitylogs.operation_name: +data_stream.dataset:azure.activitylogs and event.action: ("MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/ROLEBINDINGS/WRITE" or "MICROSOFT.KUBERNETES/CONNECTEDCLUSTERS/RBAC.AUTHORIZATION.K8S.IO/CLUSTERROLEBINDINGS/WRITE") and -event.outcome:(Success or success) +event.outcome:(success) ''' diff --git a/rules/integrations/azure/resource_development_entra_id_custom_domain_added_and_verified.toml b/rules/integrations/azure/resource_development_entra_id_custom_domain_added_and_verified.toml index c6ff315a89f..1885074c1d7 100644 --- a/rules/integrations/azure/resource_development_entra_id_custom_domain_added_and_verified.toml +++ b/rules/integrations/azure/resource_development_entra_id_custom_domain_added_and_verified.toml @@ -2,7 +2,7 @@ creation_date = "2026/03/03" integration = ["azure"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,7 +27,7 @@ While adding and verifying domains are legitimate administrative activities, the ### Possible investigation steps -- Review `azure.auditlogs.properties.initiated_by.user.userPrincipalName` and `ipAddress` to identify who performed the action and from where. +- Review `user.name` and `ipAddress` to identify who performed the action and from where. - For `"Add unverified domain"` events, check `azure.auditlogs.properties.target_resources.0.display_name` for the domain name that was added. - Determine whether the domain is known to the organization or is potentially adversary-controlled. - Check if a corresponding `"Verify domain"` event follows shortly after and from the same actor. diff --git a/rules/integrations/github/defense_evasion_github_protected_branch_settings_changed.toml b/rules/integrations/github/defense_evasion_github_protected_branch_settings_changed.toml index 5ebec7f4083..1aee8ebda55 100644 --- a/rules/integrations/github/defense_evasion_github_protected_branch_settings_changed.toml +++ b/rules/integrations/github/defense_evasion_github_protected_branch_settings_changed.toml @@ -2,7 +2,7 @@ creation_date = "2023/08/29" integration = ["github"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,7 +28,7 @@ GitHub's protected branch settings are crucial for maintaining code integrity by ### Possible investigation steps -- Review the GitHub audit logs to identify the specific changes made to the protected branch settings, focusing on entries where event.dataset is "github.audit" and github.category is "protected_branch". +- Review the GitHub audit logs to identify the specific changes made to the protected branch settings, focusing on entries where event.dataset is "github.audit" and event.category is "protected_branch". - Determine the user account responsible for the changes by examining the audit log details, and verify if the account has a legitimate reason to modify branch protection settings. - Check the timing of the changes to see if they coincide with any other suspicious activities or known incidents within the organization. - Investigate the context of the change by reviewing recent pull requests or commits to the affected branch to assess if the changes align with ongoing development activities. @@ -66,7 +66,7 @@ type = "eql" query = ''' configuration where data_stream.dataset == "github.audit" - and github.category == "protected_branch" and event.type == "change" + and event.category == "protected_branch" and event.type == "change" ''' diff --git a/rules/integrations/github/execution_github_app_deleted.toml b/rules/integrations/github/execution_github_app_deleted.toml index ea70a81fe2d..083b23aa862 100644 --- a/rules/integrations/github/execution_github_app_deleted.toml +++ b/rules/integrations/github/execution_github_app_deleted.toml @@ -2,7 +2,7 @@ creation_date = "2023/10/11" integration = ["github"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -61,7 +61,7 @@ timestamp_override = "event.ingested" type = "eql" query = ''' -configuration where data_stream.dataset == "github.audit" and github.category == "integration_installation" and event.type == "deletion" +configuration where data_stream.dataset == "github.audit" and event.category == "integration_installation" and event.type == "deletion" ''' diff --git a/rules/integrations/github/exfiltration_github_private_repository_turned_public.toml b/rules/integrations/github/exfiltration_github_private_repository_turned_public.toml index 00a0600e663..f09e446aab7 100644 --- a/rules/integrations/github/exfiltration_github_private_repository_turned_public.toml +++ b/rules/integrations/github/exfiltration_github_private_repository_turned_public.toml @@ -2,7 +2,7 @@ creation_date = "2025/12/16" integration = ["github"] maturity = "production" -updated_date = "2026/05/12" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -61,7 +61,7 @@ tags = [ timestamp_override = "event.ingested" type = "eql" query = ''' -configuration where data_stream.dataset == "github.audit" and github.operation_type == "modify" and github.category == "repo" and +configuration where data_stream.dataset == "github.audit" and github.operation_type == "modify" and event.category == "repo" and event.action == "repo.access" and github.visibility == "public" ''' diff --git a/rules/integrations/github/exfiltration_high_number_of_cloning_by_user.toml b/rules/integrations/github/exfiltration_high_number_of_cloning_by_user.toml index dd1b2d07c2d..fb1d24272ac 100644 --- a/rules/integrations/github/exfiltration_high_number_of_cloning_by_user.toml +++ b/rules/integrations/github/exfiltration_high_number_of_cloning_by_user.toml @@ -2,7 +2,7 @@ creation_date = "2025/12/16" integration = ["github"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -73,7 +73,7 @@ from logs-github.audit-* metadata _id, _index, _version Esql.github_repo_values = values(github.repo), Esql.github_repository_public_values = values(github.repository_public), Esql.github_token_id_values = values(github.token_id), - Esql.github_user_agent_values = values(github.user_agent), + Esql.github_user_agent_values = values(user_agent.original), Esql.user_name_values = values(user.name), Esql.agent_id_values = values(agent.id), Esql.data_stream_dataset_values = values(data_stream.dataset), diff --git a/rules/integrations/github/impact_high_number_of_closed_pull_requests_by_user.toml b/rules/integrations/github/impact_high_number_of_closed_pull_requests_by_user.toml index 13c75a9f702..75065d887e4 100644 --- a/rules/integrations/github/impact_high_number_of_closed_pull_requests_by_user.toml +++ b/rules/integrations/github/impact_high_number_of_closed_pull_requests_by_user.toml @@ -2,7 +2,7 @@ creation_date = "2025/12/16" integration = ["github"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -68,14 +68,14 @@ query = ''' from logs-github.audit-* metadata _id, _index, _version | where data_stream.dataset == "github.audit" and - github.category == "pull_request" and + event.category == "pull_request" and event.type == "change" and event.action == "pull_request.close" | stats Esql.document_count = COUNT(*), Esql.github_org_values = values(github.org), Esql.github_repo_values = values(github.repo), - Esql.github_user_agent_values = values(github.user_agent), + Esql.github_user_agent_values = values(user_agent.original), Esql.github_pull_request_url_values = values(github.pull_request_url), Esql.user_name_values = values(user.name), Esql.agent_id_values = values(agent.id), diff --git a/rules/integrations/github/impact_high_number_of_failed_protected_branch_force_pushes_by_user.toml b/rules/integrations/github/impact_high_number_of_failed_protected_branch_force_pushes_by_user.toml index c6e97c86c17..822d9fbeff9 100644 --- a/rules/integrations/github/impact_high_number_of_failed_protected_branch_force_pushes_by_user.toml +++ b/rules/integrations/github/impact_high_number_of_failed_protected_branch_force_pushes_by_user.toml @@ -2,7 +2,7 @@ creation_date = "2025/12/16" integration = ["github"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,7 +69,7 @@ query = ''' from logs-github.audit-* metadata _id, _index, _version | where data_stream.dataset == "github.audit" and - github.category == "protected_branch" and + event.category == "protected_branch" and event.action == "protected_branch.rejected_ref_update" | stats Esql.document_count = COUNT(*), diff --git a/rules/integrations/github/impact_high_number_of_protected_branch_force_pushes_by_user.toml b/rules/integrations/github/impact_high_number_of_protected_branch_force_pushes_by_user.toml index 6977d7b4398..8cf5b45fee3 100644 --- a/rules/integrations/github/impact_high_number_of_protected_branch_force_pushes_by_user.toml +++ b/rules/integrations/github/impact_high_number_of_protected_branch_force_pushes_by_user.toml @@ -4,7 +4,7 @@ integration = ["github"] maturity = "production" min_stack_comments = "mv_contains ES|QL function only available post 9.2 in tech preview" min_stack_version = "9.2.0" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -73,7 +73,7 @@ from logs-github.audit-* metadata _id, _index, _version data_stream.dataset == "github.audit" and event.type == "change" and event.action == "protected_branch.policy_override" and - github.category == "protected_branch" and + event.category == "protected_branch" and mv_contains(github.reasons.code, "force_push") | stats Esql.event_count = COUNT(*), diff --git a/rules/integrations/github/initial_access_github_actions_workflow_injection_blocked.toml b/rules/integrations/github/initial_access_github_actions_workflow_injection_blocked.toml index 80af6816d13..bf235d7d7e0 100644 --- a/rules/integrations/github/initial_access_github_actions_workflow_injection_blocked.toml +++ b/rules/integrations/github/initial_access_github_actions_workflow_injection_blocked.toml @@ -2,7 +2,7 @@ creation_date = "2025/12/05" integration = ["github"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -75,7 +75,7 @@ from logs-github.audit-* metadata _id, _index, _version | where data_stream.dataset == "github.audit" and event.action == "protected_branch.rejected_ref_update" and - github.category == "protected_branch" and + event.category == "protected_branch" and github.reasons.code == "workflow_updates" and match(github.reasons.message::STRING, "refusing to allow a GitHub App to create or update workflow") | keep * diff --git a/rules/integrations/github/initial_access_github_register_self_hosted_runner.toml b/rules/integrations/github/initial_access_github_register_self_hosted_runner.toml index 67a7bc803d9..103377584f0 100644 --- a/rules/integrations/github/initial_access_github_register_self_hosted_runner.toml +++ b/rules/integrations/github/initial_access_github_register_self_hosted_runner.toml @@ -2,7 +2,7 @@ creation_date = "2025/11/28" integration = ["github"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -95,7 +95,7 @@ name = "Initial Access" reference = "https://attack.mitre.org/tactics/TA0001/" [rule.new_terms] field = "new_terms_fields" -value = ["user.name", "github.actor_ip"] +value = ["user.name", "source.ip"] [[rule.new_terms.history_window_start]] field = "history_window_start" diff --git a/rules/integrations/github/persistence_new_pat_created.toml b/rules/integrations/github/persistence_new_pat_created.toml index 2e10e92a9c4..a4170679d1b 100644 --- a/rules/integrations/github/persistence_new_pat_created.toml +++ b/rules/integrations/github/persistence_new_pat_created.toml @@ -2,7 +2,7 @@ creation_date = "2023/12/16" integration = ["github"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -66,7 +66,7 @@ timestamp_override = "event.ingested" type = "eql" query = ''' configuration where data_stream.dataset == "github.audit" and github.operation_type == "create" and -github.category == "personal_access_token" and event.action == "personal_access_token.access_granted" +event.category == "personal_access_token" and event.action == "personal_access_token.access_granted" ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/credential_access_azure_arc_proxy_secret_configmap_access.toml b/rules/integrations/kubernetes/credential_access_azure_arc_proxy_secret_configmap_access.toml index 5bfd274a247..343ff63764d 100644 --- a/rules/integrations/kubernetes/credential_access_azure_arc_proxy_secret_configmap_access.toml +++ b/rules/integrations/kubernetes/credential_access_azure_arc_proxy_secret_configmap_access.toml @@ -2,7 +2,7 @@ creation_date = "2026/03/10" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -42,7 +42,7 @@ adversary action: exfiltrating secrets without leaving obvious modification trac ### Possible investigation steps -- Check the `kubernetes.audit.impersonatedUser.username` field — this contains the Azure AD object ID of the actual +- Check the `user.target.name` field — this contains the Azure AD object ID of the actual caller. Cross-reference with Azure AD to identify the service principal or user. - Review the `kubernetes.audit.impersonatedUser.extra.oid` field for the Azure AD object ID. - Examine the namespace — operations in `default` or application namespaces are more suspicious than `azure-arc` or @@ -84,25 +84,25 @@ type = "esql" query = ''' FROM logs-kubernetes.audit_logs-* metadata _id, _version, _index -| WHERE STARTS_WITH(kubernetes.audit.user.username, "system:serviceaccount:azure-arc:") - AND kubernetes.audit.objectRef.resource IN ("secrets", "configmaps") - AND kubernetes.audit.verb IN ("get", "list", "create", "update", "patch", "delete") - AND kubernetes.audit.objectRef.namespace NOT IN ("azure-arc", "azure-arc-release", "kube-system") +| WHERE STARTS_WITH(user.name, "system:serviceaccount:azure-arc:") + AND orchestrator.resource.type IN ("secrets", "configmaps") + AND event.action IN ("get", "list", "create", "update", "patch", "delete") + AND orchestrator.namespace NOT IN ("azure-arc", "azure-arc-release", "kube-system") AND NOT STARTS_WITH(kubernetes.audit.objectRef.name, "sh.helm.release.v1") | STATS - Esql.verb_values = VALUES(kubernetes.audit.verb), - Esql.resource_type_values = VALUES(kubernetes.audit.objectRef.resource), + Esql.verb_values = VALUES(event.action), + Esql.resource_type_values = VALUES(orchestrator.resource.type), Esql.resource_name_values = VALUES(kubernetes.audit.objectRef.name), - Esql.namespace_values = VALUES(kubernetes.audit.objectRef.namespace), - Esql.acting_user_values = VALUES(kubernetes.audit.user.username), + Esql.namespace_values = VALUES(orchestrator.namespace), + Esql.acting_user_values = VALUES(user.name), Esql.user_agent_values = VALUES(kubernetes.audit.userAgent), - Esql.source_ips_values = VALUES(kubernetes.audit.sourceIPs), + Esql.source_ips_values = VALUES(source.ip), Esql.response_code_values = VALUES(kubernetes.audit.responseStatus.code), Esql.timestamp_first_seen = MIN(@timestamp), Esql.timestamp_last_seen = MAX(@timestamp), Esql.event_count = COUNT(*) - BY kubernetes.audit.impersonatedUser.username + BY user.target.name | WHERE Esql.timestamp_first_seen >= NOW() - 9 minutes | KEEP * diff --git a/rules/integrations/kubernetes/credential_access_get_secrets_access.toml b/rules/integrations/kubernetes/credential_access_get_secrets_access.toml index a2063e10e84..25d1906b96b 100644 --- a/rules/integrations/kubernetes/credential_access_get_secrets_access.toml +++ b/rules/integrations/kubernetes/credential_access_get_secrets_access.toml @@ -2,7 +2,7 @@ creation_date = "2026/03/26" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -60,8 +60,8 @@ tags = [ timestamp_override = "event.ingested" type = "new_terms" query = ''' -data_stream.dataset:"kubernetes.audit_logs" and kubernetes.audit.objectRef.resource:"secrets" and -kubernetes.audit.verb:("get" or "list") and user_agent.original:(* and not (*kubernetes/$Format)) +data_stream.dataset:"kubernetes.audit_logs" and orchestrator.resource.type:"secrets" and +event.action:("get" or "list") and user_agent.original:(* and not (*kubernetes/$Format)) ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_multiple_secret_retrieval_burst.toml b/rules/integrations/kubernetes/credential_access_kubernetes_multiple_secret_retrieval_burst.toml index 933673591fb..711c44302eb 100644 --- a/rules/integrations/kubernetes/credential_access_kubernetes_multiple_secret_retrieval_burst.toml +++ b/rules/integrations/kubernetes/credential_access_kubernetes_multiple_secret_retrieval_burst.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/22" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/15" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -59,20 +59,20 @@ query = ''' from logs-kubernetes.audit_logs-* metadata _id, _index, _version | where event.dataset == "kubernetes.audit_logs" and event.action == "get" - and kubernetes.audit.objectRef.resource == "secrets" + and orchestrator.resource.type == "secrets" and source.ip is not null and user.name is not null and not to_string(source.ip) in ("127.0.0.1", "::1") and not user.name in ("system:kube-controller-manager", "system:kube-scheduler") and not kubernetes.audit.objectRef.name like "sh.helm.release.*" and - not kubernetes.audit.user.username in ("system:serviceaccount:flux-system:kustomize-controller", "system:serviceaccount:flux-system:helm-controller", "system:serviceaccount:flux-system:source-controller", "system:serviceaccount:security:trivy-operator") + not user.name in ("system:serviceaccount:flux-system:kustomize-controller", "system:serviceaccount:flux-system:helm-controller", "system:serviceaccount:flux-system:source-controller", "system:serviceaccount:security:trivy-operator") | stats Esql.unique_credentials = count_distinct(kubernetes.audit.objectRef.name), Esql.secrets_names = values(kubernetes.audit.objectRef.name), - Esql.namespaces = values(kubernetes.audit.objectRef.namespace), - Esql.outcome = values(`kubernetes.audit.annotations.authorization_k8s_io/decision`) - by user.name, kubernetes.audit.user.username, source.ip, user_agent.original + Esql.namespaces = values(orchestrator.namespace), + Esql.outcome = values(`event.outcome`) + by user.name, user.name, source.ip, user_agent.original | where Esql.unique_credentials >= 3 -| KEEP user.name, kubernetes.audit.user.username, source.ip, user_agent.original, Esql.* +| KEEP user.name, user.name, source.ip, user_agent.original, Esql.* ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml index afcdc57d591..1ece1d0621e 100644 --- a/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml +++ b/rules/integrations/kubernetes/credential_access_kubernetes_secret_access_scripting_http_clients.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/22" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/22" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -39,11 +39,11 @@ like routine kubectl or well-known controller traffic relative to your environme - Tie `user.name` (and `kubernetes.audit.impersonatedUser.*` if present) to a human, service account, or cloud identity and validate whether that principal should use this user-agent profile against the targeted namespaces and secret names. -- Review `kubernetes.audit.objectRef.namespace` and `kubernetes.audit.objectRef.name` for high-value objects (service +- Review `orchestrator.namespace` and `kubernetes.audit.objectRef.name` for high-value objects (service account tokens, cloud IAM bindings, registry pulls, TLS bundles). - Pivot on `source.ip` in VPC flow, VPN, or proxy logs to determine origin (employee laptop, compromised host, cloud instance) and correlate with other API bursts or exec activity. -- Check `kubernetes.audit.annotations.authorization_k8s_io/decision` for successful reads versus failed probing. +- Check `event.outcome` for successful reads versus failed probing. ### False positive analysis @@ -75,7 +75,7 @@ type = "query" query = ''' data_stream.dataset:"kubernetes.audit_logs" and event.action:(get or list) and -kubernetes.audit.objectRef.resource:"secrets" and +orchestrator.resource.type:"secrets" and user_agent.original:(curl* or python* or Python* or wget* or Go-http* or perl* or java* or node* or php* or *distrib#kali* or *kali-amd64 or *kali-arm64*) and source.ip:* ''' diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_secret_read_by_node_or_pod_service_account.toml b/rules/integrations/kubernetes/credential_access_kubernetes_secret_read_by_node_or_pod_service_account.toml index 7314cd663ee..da655efbe76 100644 --- a/rules/integrations/kubernetes/credential_access_kubernetes_secret_read_by_node_or_pod_service_account.toml +++ b/rules/integrations/kubernetes/credential_access_kubernetes_secret_read_by_node_or_pod_service_account.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/22" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/11" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -41,11 +41,11 @@ high-value secret names, and clients that do not match the workload’s normal u ### Possible investigation steps -- Resolve `user.name` (or `kubernetes.audit.user.username` if present) to the node or workload and review RBAC +- Resolve `user.name` (or `user.name` if present) to the node or workload and review RBAC RoleBindings and ClusterRoleBindings for secret `get`/`list` scope. -- Inspect `kubernetes.audit.objectRef.namespace`, `kubernetes.audit.objectRef.name`, source IP, and +- Inspect `orchestrator.namespace`, `kubernetes.audit.objectRef.name`, source IP, and `user_agent.original` for automation you recognize versus anomalous scripts or generic HTTP clients. -- Review `kubernetes.audit.annotations.authorization_k8s_io/decision` for successful reads versus probing denials. +- Review `event.outcome` for successful reads versus probing denials. - Correlate with pod exec, token creation, RoleBinding changes, or secret modification in the same time window. ### False positive analysis @@ -78,7 +78,7 @@ type = "query" query = ''' data_stream.dataset:"kubernetes.audit_logs" and event.action:(get or list) and -kubernetes.audit.objectRef.resource:"secrets" and +orchestrator.resource.type:"secrets" and user.name:(system\:serviceaccount\:* or system\:node\:*) and source.ip:* and not kubernetes.audit.user.groups:( "system:serviceaccounts:flux-system" diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_secrets_list_cluster_and_sensitive_namespaces.toml b/rules/integrations/kubernetes/credential_access_kubernetes_secrets_list_cluster_and_sensitive_namespaces.toml index b59d0a13c68..a86c7468817 100644 --- a/rules/integrations/kubernetes/credential_access_kubernetes_secrets_list_cluster_and_sensitive_namespaces.toml +++ b/rules/integrations/kubernetes/credential_access_kubernetes_secrets_list_cluster_and_sensitive_namespaces.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/22" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/11" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -52,7 +52,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' event.dataset:"kubernetes.audit_logs" and event.action:list and -kubernetes.audit.objectRef.resource:secrets and +orchestrator.resource.type:secrets and kubernetes.audit.requestURI :(/api/v1/secrets or /api/v1/secrets?limit* or /api/v1/namespaces/kube-system/secrets or /api/v1/namespaces/kube-system/secrets?limit* or /api/v1/namespaces/default/secrets or /api/v1/namespaces/default/secrets?limit*) and source.ip:(* and not ("::1" or "127.0.0.1")) and not user.name: (system\:kube-controller-manager or eks\:cloud-controller-manager or eks\:kms-storage-migrator) and diff --git a/rules/integrations/kubernetes/credential_access_kubernetes_service_account_token_created_via_tokenrequest.toml b/rules/integrations/kubernetes/credential_access_kubernetes_service_account_token_created_via_tokenrequest.toml index 6e93281123c..2484236e89a 100644 --- a/rules/integrations/kubernetes/credential_access_kubernetes_service_account_token_created_via_tokenrequest.toml +++ b/rules/integrations/kubernetes/credential_access_kubernetes_service_account_token_created_via_tokenrequest.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/05" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -40,12 +40,12 @@ mint tokens for more privileged service accounts (including IRSA-linked ones) an #### What to review first - Actor and origin: - - `user.name` / `kubernetes.audit.user.username` - - `source.ip` / `kubernetes.audit.sourceIPs` + - `user.name` / `user.name` + - `source.ip` / `source.ip` - `user_agent.original` / `kubernetes.audit.userAgent` - For cloud identity, review `kubernetes.audit.user.extra.*` (e.g., `arn`, `principalId`). - Targeted service account: - - `kubernetes.audit.objectRef.namespace` and `kubernetes.audit.objectRef.name` + - `orchestrator.namespace` and `kubernetes.audit.objectRef.name` - `kubernetes.audit.requestURI` (should resemble `/api/v1/namespaces//serviceaccounts//token`) - Token issuance hints: - `kubernetes.audit.annotations.authentication_kubernetes_io/issued-credential-id` (token JTI/issued credential id) @@ -80,8 +80,8 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:"kubernetes.audit_logs" and -kubernetes.audit.verb:"create" and -kubernetes.audit.objectRef.resource:"serviceaccounts" and +event.action:"create" and +orchestrator.resource.type:"serviceaccounts" and kubernetes.audit.objectRef.subresource:"token" and user.name:(* and not (system\:kube-controller-manager or diff --git a/rules/integrations/kubernetes/defense_evasion_events_deleted.toml b/rules/integrations/kubernetes/defense_evasion_events_deleted.toml index bcf4818785a..063b9e0d1f8 100644 --- a/rules/integrations/kubernetes/defense_evasion_events_deleted.toml +++ b/rules/integrations/kubernetes/defense_evasion_events_deleted.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/27" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -25,10 +25,10 @@ Kubernetes, a container orchestration platform, logs events to track activities ### Possible investigation steps -- Review the audit logs to identify the source of the deletion request by examining the `kubernetes.audit.user.username` field to determine which user or service account initiated the delete action. -- Check the `kubernetes.audit.sourceIPs` field to trace the IP address from which the deletion request originated, which can help identify potential unauthorized access. -- Investigate the `kubernetes.audit.objectRef.namespace` field to understand which namespace the deleted events belonged to, as this can provide context on the affected applications or services. -- Analyze the timeline of events leading up to the deletion by reviewing other audit logs with similar `kubernetes.audit.verb` values to identify any suspicious activities or patterns. +- Review the audit logs to identify the source of the deletion request by examining the `user.name` field to determine which user or service account initiated the delete action. +- Check the `source.ip` field to trace the IP address from which the deletion request originated, which can help identify potential unauthorized access. +- Investigate the `orchestrator.namespace` field to understand which namespace the deleted events belonged to, as this can provide context on the affected applications or services. +- Analyze the timeline of events leading up to the deletion by reviewing other audit logs with similar `event.action` values to identify any suspicious activities or patterns. - Assess the role and permissions of the user or service account involved in the deletion to determine if they had legitimate access or if there was a potential privilege escalation. - Cross-reference the deletion event with other security alerts or logs to identify any correlated activities that might indicate a broader attack or misconfiguration. @@ -62,8 +62,8 @@ tags = [ timestamp_override = "event.ingested" type = "eql" query = ''' -any where data_stream.dataset == "kubernetes.audit_logs" and kubernetes.audit.verb == "delete" and -kubernetes.audit.objectRef.resource == "events" and kubernetes.audit.stage == "ResponseComplete" +any where data_stream.dataset == "kubernetes.audit_logs" and event.action == "delete" and +orchestrator.resource.type == "events" and kubernetes.audit.stage == "ResponseComplete" ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/discovery_denied_service_account_request.toml b/rules/integrations/kubernetes/discovery_denied_service_account_request.toml index 4630a7f8cbc..efe1053d3e6 100644 --- a/rules/integrations/kubernetes/discovery_denied_service_account_request.toml +++ b/rules/integrations/kubernetes/discovery_denied_service_account_request.toml @@ -2,7 +2,7 @@ creation_date = "2022/09/13" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -34,8 +34,8 @@ Kubernetes service accounts are integral for managing pod permissions and access ### Possible investigation steps -- Review the specific service account involved in the unauthorized request by examining the kubernetes.audit.user.username field to determine which service account was used. -- Analyze the kubernetes.audit.annotations.authorization_k8s_io/decision field to confirm the request was indeed forbidden and identify the nature of the denied request. +- Review the specific service account involved in the unauthorized request by examining the user.name field to determine which service account was used. +- Analyze the event.outcome field to confirm the request was indeed forbidden and identify the nature of the denied request. - Investigate the source of the request by checking the originating pod or node to understand where the unauthorized request was initiated. - Examine recent activity logs for the service account to identify any unusual patterns or deviations from its typical behavior. - Check for any recent changes or deployments in the cluster that might have affected service account permissions or configurations. @@ -80,8 +80,8 @@ timestamp_override = "event.ingested" type = "new_terms" query = ''' data_stream.dataset:"kubernetes.audit_logs" and -kubernetes.audit.user.username:system\:serviceaccount\:* and -kubernetes.audit.annotations.authorization_k8s_io/decision:"forbid" and +user.name:system\:serviceaccount\:* and +event.outcome:"failure" and user_agent.original:(* and not (*kubernetes/$Format or karpenter or csi-secrets-store* or OpenAPI-Generator* or Prometheus* or dashboard* or cilium-agent*)) ''' diff --git a/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_anonymous_user.toml b/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_anonymous_user.toml index 78095ce33eb..6032b9a0fd8 100644 --- a/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_anonymous_user.toml +++ b/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_anonymous_user.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/02" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -64,13 +64,13 @@ type = "esql" query = ''' from logs-kubernetes.audit_logs-* metadata _id, _index, _version | where ( - kubernetes.audit.user.username in ("system:anonymous", "system:unauthenticated") or - kubernetes.audit.user.username is null or - kubernetes.audit.user.username == "" + user.name in ("system:anonymous", "system:unauthenticated") or + user.name is null or + user.name == "" ) and kubernetes.audit.level in ("RequestResponse", "ResponseComplete", "Request") -| eval Esql.decision = `kubernetes.audit.annotations.authorization_k8s_io/decision` +| eval Esql.decision = `event.outcome` | eval Esql.code = kubernetes.audit.responseStatus.code | eval Esql.outcome = case( @@ -97,24 +97,24 @@ from logs-kubernetes.audit_logs-* metadata _id, _index, _version Esql.other_error_count = sum(case(Esql.outcome == "other_error", 1, 0)), Esql.unknown_count = sum(case(Esql.outcome == "unknown", 1, 0)), - Esql.kubernetes_audit_verb_count_distinct = count_distinct(kubernetes.audit.verb), + Esql.kubernetes_audit_verb_count_distinct = count_distinct(event.action), Esql.kubernetes_audit_requestURI_count_distinct = count_distinct(kubernetes.audit.requestURI), - Esql.kubernetes_audit_objectRef_resource_count_distinct = count_distinct(kubernetes.audit.objectRef.resource), + Esql.kubernetes_audit_objectRef_resource_count_distinct = count_distinct(orchestrator.resource.type), Esql.kubernetes_audit_outcome_values = values(Esql.outcome), Esql.kubernetes_audit_decision_values = values(Esql.decision), Esql.kubernetes_audit_responseStatus_code_values = values(Esql.code), Esql.kubernetes_audit_responseStatus_message_values = values(kubernetes.audit.responseStatus.message), - Esql.kubernetes_audit_verb_values = values(kubernetes.audit.verb), - Esql.kubernetes_audit_objectRef_resource_values = values(kubernetes.audit.objectRef.resource), - Esql.kubernetes_audit_objectRef_namespace_values = values(kubernetes.audit.objectRef.namespace), - Esql.kubernetes_audit_user_username_values = values(kubernetes.audit.user.username), + Esql.kubernetes_audit_verb_values = values(event.action), + Esql.kubernetes_audit_objectRef_resource_values = values(orchestrator.resource.type), + Esql.kubernetes_audit_objectRef_namespace_values = values(orchestrator.namespace), + Esql.kubernetes_audit_user_username_values = values(user.name), Esql.kubernetes_audit_user_groups_values = values(kubernetes.audit.user.groups), Esql.kubernetes_audit_requestURI_values = values(kubernetes.audit.requestURI), Esql.data_stream_namespace_values = values(data_stream.namespace) - BY kubernetes.audit.sourceIPs, user_agent.original + BY source.ip, user_agent.original | where Esql.kubernetes_audit_requestURI_count_distinct > 5 and @@ -122,7 +122,7 @@ from logs-kubernetes.audit_logs-* metadata _id, _index, _version Esql.document_count < 50 and (Esql.authz_forbid_count >= 1 or Esql.status_fail_count >= 1 or Esql.not_found_count >= 3) -| keep Esql.*, kubernetes.audit.sourceIPs, user_agent.original +| keep Esql.*, source.ip, user_agent.original ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_user_and_srcip.toml b/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_user_and_srcip.toml index 631b768c7af..df3d234ad11 100644 --- a/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_user_and_srcip.toml +++ b/rules/integrations/kubernetes/discovery_endpoint_permission_enumeration_by_user_and_srcip.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/02" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/03/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -61,32 +61,32 @@ timestamp_override = "event.ingested" type = "esql" query = ''' from logs-kubernetes.audit_logs-* metadata _id, _index, _version -| where kubernetes.audit.stage == "ResponseComplete" and kubernetes.audit.verb in ("get", "list", "watch", "create", "update", "patch") +| where kubernetes.audit.stage == "ResponseComplete" and event.action in ("get", "list", "watch", "create", "update", "patch") | stats Esql.document_count = count(), - Esql.kubernetes_audit_annotations_authorization_k8s_io_decision_count_distinct = count_distinct(`kubernetes.audit.annotations.authorization_k8s_io/decision`), - Esql.kubernetes_audit_verb_count_distinct = count_distinct(kubernetes.audit.verb), + Esql.kubernetes_audit_annotations_authorization_k8s_io_decision_count_distinct = count_distinct(`event.outcome`), + Esql.kubernetes_audit_verb_count_distinct = count_distinct(event.action), Esql.kubernetes_audit_requestURI_count_distinct = count_distinct(kubernetes.audit.requestURI), - Esql.kubernetes_audit_objectRef_resource_count_distinct = count_distinct(kubernetes.audit.objectRef.resource), + Esql.kubernetes_audit_objectRef_resource_count_distinct = count_distinct(orchestrator.resource.type), Esql.kubernetes_audit_responseStatus_message_values = values(kubernetes.audit.responseStatus.message), - Esql.kubernetes_audit_verb_values = values(kubernetes.audit.verb), + Esql.kubernetes_audit_verb_values = values(event.action), Esql.kubernetes_audit_responseStatus_code_values = values(kubernetes.audit.responseStatus.code), - Esql.kubernetes_audit_objectRef_resource_values = values(kubernetes.audit.objectRef.resource), - Esql.kubernetes_audit_objectRef_namespace_values = values(kubernetes.audit.objectRef.namespace), - Esql.kubernetes_audit_user_username_values = values(kubernetes.audit.user.username), + Esql.kubernetes_audit_objectRef_resource_values = values(orchestrator.resource.type), + Esql.kubernetes_audit_objectRef_namespace_values = values(orchestrator.namespace), + Esql.kubernetes_audit_user_username_values = values(user.name), Esql.kubernetes_audit_user_groups_values = values(kubernetes.audit.user.groups), Esql.kubernetes_audit_requestURI_values = values(kubernetes.audit.requestURI), Esql.user_agent_original_values = values(user_agent.original), Esql.data_stream_namespace_values = values(data_stream.namespace) - by kubernetes.audit.user.username, kubernetes.audit.sourceIPs + by user.name, source.ip | where Esql.kubernetes_audit_annotations_authorization_k8s_io_decision_count_distinct == 2 and Esql.kubernetes_audit_requestURI_count_distinct > 5 and Esql.kubernetes_audit_objectRef_resource_count_distinct > 3 and Esql.document_count < 75 -| keep Esql.*, kubernetes.audit.user.username, kubernetes.audit.sourceIPs +| keep Esql.*, user.name, source.ip ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/discovery_kubernetes_multi_resource_setup_recon.toml b/rules/integrations/kubernetes/discovery_kubernetes_multi_resource_setup_recon.toml index 1d820b6bb6f..834df5a0555 100644 --- a/rules/integrations/kubernetes/discovery_kubernetes_multi_resource_setup_recon.toml +++ b/rules/integrations/kubernetes/discovery_kubernetes_multi_resource_setup_recon.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/22" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/15" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -73,19 +73,19 @@ from logs-kubernetes.audit_logs-* metadata _id, _index, _version | eval Esql.time_interval = date_trunc(1 minute, @timestamp) | where event.dataset == "kubernetes.audit_logs" and event.action in ("get", "list") - and kubernetes.audit.objectRef.resource in ("namespaces", "nodes", "pods", "roles", "configmaps", "serviceaccounts", "clusterroles", "clusterrolebindings", "rolebindings") + and orchestrator.resource.type in ("namespaces", "nodes", "pods", "roles", "configmaps", "serviceaccounts", "clusterroles", "clusterrolebindings", "rolebindings") and source.ip is not null and user.name IS NOT NULL and not to_string(source.ip) in ("127.0.0.1", "::1") and not user.name rlike """(system:serviceaccount:kube-system:|eks:|system:kube-|arn:aws:sts::.*:assumed-role/AWSServiceRoleForAmazonEKS/|system:serviceaccount:kube-system:azure|system:node:aks-default|aksService).*""" - and not kubernetes.audit.user.username in ("system:serviceaccount:flux-system:kustomize-controller", "system:serviceaccount:flux-system:helm-controller", "system:serviceaccount:flux-system:source-controller", "system:serviceaccount:security:trivy-operator") + and not user.name in ("system:serviceaccount:flux-system:kustomize-controller", "system:serviceaccount:flux-system:helm-controller", "system:serviceaccount:flux-system:source-controller", "system:serviceaccount:security:trivy-operator") | stats - Esql.unique_resources = count_distinct(kubernetes.audit.objectRef.resource), - Esql.enumerated_resources = values(kubernetes.audit.objectRef.resource), - Esql.enumerated_namespaces = values(kubernetes.audit.objectRef.namespace), - Esql.decisions = values(`kubernetes.audit.annotations.authorization_k8s_io/decision`) - by user.name, kubernetes.audit.user.username, source.ip, user_agent.original, Esql.time_interval + Esql.unique_resources = count_distinct(orchestrator.resource.type), + Esql.enumerated_resources = values(orchestrator.resource.type), + Esql.enumerated_namespaces = values(orchestrator.namespace), + Esql.decisions = values(`event.outcome`) + by user.name, user.name, source.ip, user_agent.original, Esql.time_interval | where Esql.unique_resources >= 3 -| keep Esql.*, kubernetes.audit.user.username, user.name, source.ip, user_agent.original +| keep Esql.*, user.name, user.name, source.ip, user_agent.original ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/discovery_suspicious_self_subject_review.toml b/rules/integrations/kubernetes/discovery_suspicious_self_subject_review.toml index c77fe7c0549..76fa052e78d 100644 --- a/rules/integrations/kubernetes/discovery_suspicious_self_subject_review.toml +++ b/rules/integrations/kubernetes/discovery_suspicious_self_subject_review.toml @@ -2,7 +2,7 @@ creation_date = "2022/06/30" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -34,8 +34,8 @@ Kubernetes uses APIs like selfsubjectaccessreview and selfsubjectrulesreview to ### Possible investigation steps -- Review the Kubernetes audit logs to identify the specific service account or node that triggered the alert by examining the kubernetes.audit.user.username or kubernetes.audit.impersonatedUser.username fields. -- Check the context of the API call by analyzing the kubernetes.audit.objectRef.resource field to confirm whether it involved selfsubjectaccessreviews or selfsubjectrulesreviews. +- Review the Kubernetes audit logs to identify the specific service account or node that triggered the alert by examining the user.name or user.target.name fields. +- Check the context of the API call by analyzing the orchestrator.resource.type field to confirm whether it involved selfsubjectaccessreviews or selfsubjectrulesreviews. - Investigate the source of the API request by looking at the IP address and user agent in the audit logs to determine if the request originated from a known or expected source. - Assess the recent activity of the implicated service account or node to identify any unusual patterns or deviations from normal behavior. - Verify if there have been any recent changes to the permissions or roles associated with the service account or node to understand if the access level has been altered. @@ -80,11 +80,11 @@ timestamp_override = "event.ingested" type = "new_terms" query = ''' data_stream.dataset : "kubernetes.audit_logs" and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.verb:"create" and -kubernetes.audit.objectRef.resource:("selfsubjectaccessreviews" or "selfsubjectrulesreviews") and ( - kubernetes.audit.user.username:(system\:serviceaccount\:* or system\:node\:*) or - kubernetes.audit.impersonatedUser.username:(system\:serviceaccount\:* or system\:node\:*) +event.outcome:"success" and +event.action:"create" and +orchestrator.resource.type:("selfsubjectaccessreviews" or "selfsubjectrulesreviews") and ( + user.name:(system\:serviceaccount\:* or system\:node\:*) or + user.target.name:(system\:serviceaccount\:* or system\:node\:*) ) and user_agent.original:(* and not (*kubernetes/$Format)) ''' diff --git a/rules/integrations/kubernetes/execution_anonymous_create_update_patch_pod_request.toml b/rules/integrations/kubernetes/execution_anonymous_create_update_patch_pod_request.toml index f66c19be7bc..1e3b96446bd 100644 --- a/rules/integrations/kubernetes/execution_anonymous_create_update_patch_pod_request.toml +++ b/rules/integrations/kubernetes/execution_anonymous_create_update_patch_pod_request.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/02" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,11 +29,11 @@ timestamp_override = "event.ingested" type = "eql" query = ''' any where data_stream.dataset == "kubernetes.audit_logs" and ( - kubernetes.audit.user.username in ("system:anonymous", "system:unauthenticated") or - kubernetes.audit.user.username == null or - kubernetes.audit.user.username == "" - ) and kubernetes.audit.level in ("RequestResponse", "ResponseComplete", "Request") and kubernetes.audit.verb in ("create", "update", "patch") and -kubernetes.audit.objectRef.resource == "pods" + user.name in ("system:anonymous", "system:unauthenticated") or + user.name == null or + user.name == "" + ) and kubernetes.audit.level in ("RequestResponse", "ResponseComplete", "Request") and event.action in ("create", "update", "patch") and +orchestrator.resource.type == "pods" ''' diff --git a/rules/integrations/kubernetes/execution_forbidden_creation_request.toml b/rules/integrations/kubernetes/execution_forbidden_creation_request.toml index 83ec206a538..d0230f3eade 100644 --- a/rules/integrations/kubernetes/execution_forbidden_creation_request.toml +++ b/rules/integrations/kubernetes/execution_forbidden_creation_request.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/24" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,9 +28,9 @@ Kubernetes, a container orchestration platform, manages applications across clus ### Possible investigation steps -- Review the audit logs to identify the user or service account associated with the forbidden creation request by examining the `kubernetes.audit.user.username` field. -- Check the `kubernetes.audit.objectRef.resource` field to determine which specific resource type the unauthorized creation attempt was targeting. -- Investigate the `kubernetes.audit.sourceIPs` field to trace the source IP address of the request, which may help identify the origin of the unauthorized attempt. +- Review the audit logs to identify the user or service account associated with the forbidden creation request by examining the `user.name` field. +- Check the `orchestrator.resource.type` field to determine which specific resource type the unauthorized creation attempt was targeting. +- Investigate the `source.ip` field to trace the source IP address of the request, which may help identify the origin of the unauthorized attempt. - Analyze the `kubernetes.audit.annotations.authorization_k8s_io/reason` field, if available, to understand why the request was forbidden, providing insights into potential misconfigurations or policy violations. - Cross-reference the user or service account with existing role bindings and cluster role bindings to verify if there are any misconfigurations or missing permissions that could have led to the forbidden request. - Review recent changes in the cluster's authorization policies or role assignments that might have inadvertently affected permissions, leading to the denied request. @@ -67,8 +67,8 @@ tags = [ timestamp_override = "event.ingested" type = "eql" query = ''' -any where data_stream.dataset == "kubernetes.audit_logs" and kubernetes.audit.verb == "create" and -kubernetes.audit.stage == "ResponseComplete" and `kubernetes.audit.annotations.authorization_k8s_io/decision` == "forbid" +any where data_stream.dataset == "kubernetes.audit_logs" and event.action == "create" and +kubernetes.audit.stage == "ResponseComplete" and `event.outcome` == "forbid" ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/execution_forbidden_request_from_unsual_user_agent.toml b/rules/integrations/kubernetes/execution_forbidden_request_from_unsual_user_agent.toml index 4ac7e15cb99..6a007ea3da6 100644 --- a/rules/integrations/kubernetes/execution_forbidden_request_from_unsual_user_agent.toml +++ b/rules/integrations/kubernetes/execution_forbidden_request_from_unsual_user_agent.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/17" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -67,7 +67,7 @@ type = "new_terms" query = ''' data_stream.dataset:"kubernetes.audit_logs" and kubernetes.audit.stage:"ResponseComplete" and -kubernetes.audit.annotations.authorization_k8s_io/decision:"forbid" and +event.outcome:"failure" and user_agent.original:(* and not (*kubernetes/$Format)) ''' diff --git a/rules/integrations/kubernetes/execution_kubernetes_pod_exec_curl_wget_https.toml b/rules/integrations/kubernetes/execution_kubernetes_pod_exec_curl_wget_https.toml index d8eb419a980..8ebb8f6c240 100644 --- a/rules/integrations/kubernetes/execution_kubernetes_pod_exec_curl_wget_https.toml +++ b/rules/integrations/kubernetes/execution_kubernetes_pod_exec_curl_wget_https.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/23" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/23" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ flags curl or wget combined with https, excluding several ommon health, localhos ### Possible investigation steps -- Confirm who may exec into the target namespace: review kubernetes.audit.user.username, groups, impersonation, and +- Confirm who may exec into the target namespace: review user.name, groups, impersonation, and source.ip / user_agent.original (kubectl, CI, webhooks). - Map the pod (kubernetes.audit.objectRef.name) and workload owner; retrieve the exact decoded URI from Esql.decoded_uri and the reconstructed Esql.command in the alert. diff --git a/rules/integrations/kubernetes/execution_kubernetes_pod_exec_potential_reverse_shell.toml b/rules/integrations/kubernetes/execution_kubernetes_pod_exec_potential_reverse_shell.toml index dd9a8db9115..2d723ba5932 100644 --- a/rules/integrations/kubernetes/execution_kubernetes_pod_exec_potential_reverse_shell.toml +++ b/rules/integrations/kubernetes/execution_kubernetes_pod_exec_potential_reverse_shell.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/23" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/23" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -25,7 +25,7 @@ matches high-signal shell and socket idioms often used to obtain a allback shell ### Possible investigation steps -- Identify the actor (kubernetes.audit.user.username, groups, impersonation), source IP, and user agent +- Identify the actor (user.name, groups, impersonation), source IP, and user agent (human kubectl vs automation). - Resolve the target namespace, pod, and container from kubernetes.audit.objectRef.* and correlate with workload ownership and change tickets. diff --git a/rules/integrations/kubernetes/execution_unusual_request_response_by_user_agent.toml b/rules/integrations/kubernetes/execution_unusual_request_response_by_user_agent.toml index 8abe1dc839f..fc347592b76 100644 --- a/rules/integrations/kubernetes/execution_unusual_request_response_by_user_agent.toml +++ b/rules/integrations/kubernetes/execution_unusual_request_response_by_user_agent.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/18" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -71,8 +71,8 @@ data_stream.dataset:"kubernetes.audit_logs" and kubernetes.audit.stage:"Response user_agent.original:(* and not (*kubernetes/$Format)) and not ( user_agent.original:kubelet* and - not kubernetes.audit.objectRef.resource:(pods or nodes or csinodes or csidrivers or configmaps or secrets or events or leases or runtimeclasses) and - kubernetes.audit.verb:(get or list or watch or patch) + not orchestrator.resource.type:(pods or nodes or csinodes or csidrivers or configmaps or secrets or events or leases or runtimeclasses) and + event.action:(get or list or watch or patch) ) ''' @@ -111,7 +111,7 @@ name = "Initial Access" reference = "https://attack.mitre.org/tactics/TA0001/" [rule.new_terms] field = "new_terms_fields" -value = ["kubernetes.audit.annotations.authorization_k8s_io/decision", "kubernetes.audit.user.username", "user_agent.original"] +value = ["event.outcome", "user.name", "user_agent.original"] [[rule.new_terms.history_window_start]] field = "history_window_start" diff --git a/rules/integrations/kubernetes/execution_user_exec_to_pod.toml b/rules/integrations/kubernetes/execution_user_exec_to_pod.toml index b881749ebd0..fd8646b67c0 100644 --- a/rules/integrations/kubernetes/execution_user_exec_to_pod.toml +++ b/rules/integrations/kubernetes/execution_user_exec_to_pod.toml @@ -2,7 +2,7 @@ creation_date = "2022/05/17" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -38,8 +38,8 @@ Kubernetes allows users to execute commands within a pod using the 'exec' comman ### Possible investigation steps - Review the Kubernetes audit logs to identify the user who executed the 'exec' command by examining the event.dataset field for "kubernetes.audit_logs". -- Check the kubernetes.audit.annotations.authorization_k8s_io/decision field to confirm that the action was allowed and determine if the user had legitimate access. -- Investigate the kubernetes.audit.objectRef.resource and kubernetes.audit.objectRef.subresource fields to verify that the action involved a pod and the 'exec' subresource. +- Check the event.outcome field to confirm that the action was allowed and determine if the user had legitimate access. +- Investigate the orchestrator.resource.type and kubernetes.audit.objectRef.subresource fields to verify that the action involved a pod and the 'exec' subresource. - Analyze the context of the pod involved, including its purpose and the data it has access to, to assess the potential impact of the unauthorized access. - Correlate the event with other logs or alerts to identify any suspicious patterns or repeated unauthorized access attempts by the same user or IP address. - Review the user's activity history to determine if there are other instances of unusual or unauthorized access attempts within the Kubernetes environment. @@ -81,22 +81,22 @@ tags = [ timestamp_override = "event.ingested" type = "eql" query = ''' -any where data_stream.dataset == "kubernetes.audit_logs" and kubernetes.audit.verb in ("get", "create") and +any where data_stream.dataset == "kubernetes.audit_logs" and event.action in ("get", "create") and kubernetes.audit.objectRef.subresource == "exec" and kubernetes.audit.stage in ("ResponseComplete", "ResponseStarted") and -kubernetes.audit.level == "Request" and `kubernetes.audit.annotations.authorization_k8s_io/decision` == "allow" and +kubernetes.audit.level == "Request" and `event.outcome` == "allow" and not ( - (kubernetes.audit.objectRef.namespace == "trident" and kubernetes.audit.objectRef.name like "trident-controller-*") or - (kubernetes.audit.objectRef.namespace == "vuls" and kubernetes.audit.requestURI like "/api/v1/namespaces/vuls/pods/vuls-*/exec?command=sh&command=-c&command=*+%2Fvuls%2Fresults*") or - (kubernetes.audit.objectRef.namespace == "git-runners" and kubernetes.audit.requestURI like ( + (orchestrator.namespace == "trident" and kubernetes.audit.objectRef.name like "trident-controller-*") or + (orchestrator.namespace == "vuls" and kubernetes.audit.requestURI like "/api/v1/namespaces/vuls/pods/vuls-*/exec?command=sh&command=-c&command=*+%2Fvuls%2Fresults*") or + (orchestrator.namespace == "git-runners" and kubernetes.audit.requestURI like ( "/api/v1/namespaces/git-runners/pods/runner-*/exec?command=sh&command=-c&command=if+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fbin%2Fbash+%5D%3B+then%0A%09exec+%2Fbin%2Fbash+%0Aelif+%5B+-x+%2Fusr%2Flocal%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Flocal%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fusr%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fusr%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbin%2Fsh+%5D%3B+then%0A%09exec+%2Fbin%2Fsh+%0Aelif+%5B+-x+%2Fbusybox%2Fsh+%5D%3B+then%0A%09exec+%2Fbusybox%2Fsh+%0Aelse%0A%09echo+shell+not+found%0A%09exit+1%0Afi%0A%0A&container=*&container=*&stderr=true&stdin=true&stdout=true", "/api/v1/namespaces/git-runners/pods/runner-*/exec?command=gitlab-runner-helper&command=read-logs&command=--path&command=%2Flogs-*%2Foutput.log&command=--offset&command=0&command=--wait-file-timeout&command=1m0s&container=*&container=*&stderr=true&stdout=true" )) or - (kubernetes.audit.objectRef.namespace == "elasticsearch-cluster" and kubernetes.audit.requestURI like ( + (orchestrator.namespace == "elasticsearch-cluster" and kubernetes.audit.requestURI like ( "/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stdin=true&stdout=true&tty=true", "/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=elasticsearch&stderr=true&stdout=true", "/api/v1/namespaces/elasticsearch-cluster/pods/*/exec?command=df&command=-h&container=kibana&stderr=true&stdout=true" )) or - (kubernetes.audit.objectRef.namespace == "kube-system" and kubernetes.audit.requestURI like ( + (orchestrator.namespace == "kube-system" and kubernetes.audit.requestURI like ( "/api/v1/namespaces/kube-system/pods/*/exec?command=%2Fproxy-agent&command=--help&container=konnectivity-agent&stderr=true&stdout=true", "api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=endpoint&command=list&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true", "/api/v1/namespaces/kube-system/pods/*/exec?command=cilium&command=status&command=-o&command=json&container=cilium-agent&stderr=true&stdout=true", diff --git a/rules/integrations/kubernetes/impact_kubernetes_coredns_or_kube_dns_configuration_modified.toml b/rules/integrations/kubernetes/impact_kubernetes_coredns_or_kube_dns_configuration_modified.toml index 31ab387fa9a..16df566245b 100644 --- a/rules/integrations/kubernetes/impact_kubernetes_coredns_or_kube_dns_configuration_modified.toml +++ b/rules/integrations/kubernetes/impact_kubernetes_coredns_or_kube_dns_configuration_modified.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/07" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/07" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -66,11 +66,11 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:"kubernetes.audit_logs" and -kubernetes.audit.objectRef.resource:"configmaps" and +orchestrator.resource.type:"configmaps" and kubernetes.audit.objectRef.name:("coredns" or "kube-dns" or "coredns-custom") and -kubernetes.audit.objectRef.namespace:"kube-system" and -kubernetes.audit.verb:("update" or "patch" or "delete") and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and +orchestrator.namespace:"kube-system" and +event.action:("update" or "patch" or "delete") and +event.outcome:"success" and not user.name:( system\:serviceaccount\:kube-system\:coredns or system\:serviceaccount\:kube-system\:kube-dns or diff --git a/rules/integrations/kubernetes/initial_access_anonymous_request_authorized.toml b/rules/integrations/kubernetes/initial_access_anonymous_request_authorized.toml index 3686ac21fb6..6617ad247aa 100644 --- a/rules/integrations/kubernetes/initial_access_anonymous_request_authorized.toml +++ b/rules/integrations/kubernetes/initial_access_anonymous_request_authorized.toml @@ -2,7 +2,7 @@ creation_date = "2022/09/13" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -35,7 +35,7 @@ Kubernetes, a container orchestration platform, manages workloads and services. ### Possible investigation steps - Review the audit logs for the specific event.dataset:kubernetes.audit_logs to identify the context and details of the anonymous request. -- Examine the kubernetes.audit.user.username field to confirm if the request was made by "system:anonymous" or "system:unauthenticated" and assess the potential risk associated with these accounts. +- Examine the user.name field to confirm if the request was made by "system:anonymous" or "system:unauthenticated" and assess the potential risk associated with these accounts. - Analyze the kubernetes.audit.requestURI to determine the target of the request and verify if it is outside the excluded endpoints (/healthz, /livez, /readyz), which could indicate suspicious activity. - Investigate the source IP address and other network metadata associated with the request to identify the origin and assess if it aligns with known or expected traffic patterns. - Check for any subsequent or related activities in the audit logs that might indicate further unauthorized actions or attempts to exploit the cluster. @@ -79,8 +79,8 @@ timestamp_override = "event.ingested" type = "new_terms" query = ''' data_stream.dataset:"kubernetes.audit_logs" and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.user.username:("system:anonymous" or "system:unauthenticated" or not *) and +event.outcome:"success" and +user.name:("system:anonymous" or "system:unauthenticated" or not *) and user_agent.original:(* and not (*kubernetes/$Format)) and not kubernetes.audit.requestURI:(/healthz* or /livez* or /readyz* or /version or /.well-known/oauth-authorization-server) ''' diff --git a/rules/integrations/kubernetes/persistence_cluster_admin_rolebinding_created.toml b/rules/integrations/kubernetes/persistence_cluster_admin_rolebinding_created.toml index 29aa441d5f0..6fe52afdd1f 100644 --- a/rules/integrations/kubernetes/persistence_cluster_admin_rolebinding_created.toml +++ b/rules/integrations/kubernetes/persistence_cluster_admin_rolebinding_created.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/04" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -63,9 +63,9 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset: "kubernetes.audit_logs" and kubernetes.audit.objectRef.resource:("clusterrolebindings" or "rolebindings") and -kubernetes.audit.verb:"create" and kubernetes.audit.requestObject.roleRef.name:"cluster-admin" and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and +data_stream.dataset: "kubernetes.audit_logs" and orchestrator.resource.type:("clusterrolebindings" or "rolebindings") and +event.action:"create" and kubernetes.audit.requestObject.roleRef.name:"cluster-admin" and +event.outcome:"success" and kubernetes.audit.level:"RequestResponse" and kubernetes.audit.stage:"ResponseComplete" ''' diff --git a/rules/integrations/kubernetes/persistence_exposed_service_created_with_type_nodeport.toml b/rules/integrations/kubernetes/persistence_exposed_service_created_with_type_nodeport.toml index 9fcbee8b186..1c844794b19 100644 --- a/rules/integrations/kubernetes/persistence_exposed_service_created_with_type_nodeport.toml +++ b/rules/integrations/kubernetes/persistence_exposed_service_created_with_type_nodeport.toml @@ -2,7 +2,7 @@ creation_date = "2022/07/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -40,8 +40,8 @@ Kubernetes NodePort services enable external access to cluster pods by opening a ### Possible investigation steps -- Review the Kubernetes audit logs to identify the specific service that was created or modified with the type NodePort. Focus on entries where kubernetes.audit.objectRef.resource is "services" and kubernetes.audit.verb is "create", "update", or "patch". -- Check the kubernetes.audit.annotations.authorization_k8s_io/decision field to confirm that the action was allowed, ensuring that the service creation or modification was authorized. +- Review the Kubernetes audit logs to identify the specific service that was created or modified with the type NodePort. Focus on entries where orchestrator.resource.type is "services" and event.action is "create", "update", or "patch". +- Check the event.outcome field to confirm that the action was allowed, ensuring that the service creation or modification was authorized. - Identify the user or service account responsible for the action by examining the relevant fields in the audit logs, such as the user identity or service account name. - Investigate the context of the NodePort service by reviewing the associated pods and their labels to understand what applications or services are being exposed externally. - Assess the network security implications by determining if the NodePort service could potentially bypass existing firewalls or security controls, and evaluate the risk of unauthorized access or data interception. @@ -82,9 +82,9 @@ type = "query" query = ''' data_stream.dataset : "kubernetes.audit_logs" - and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" - and kubernetes.audit.objectRef.resource:"services" - and kubernetes.audit.verb:("create" or "update" or "patch") + and event.outcome:"success" + and orchestrator.resource.type:"services" + and event.action:("create" or "update" or "patch") and kubernetes.audit.requestObject.spec.type:"NodePort" ''' diff --git a/rules/integrations/kubernetes/persistence_kubernetes_admission_webhook_created_or_modified.toml b/rules/integrations/kubernetes/persistence_kubernetes_admission_webhook_created_or_modified.toml index 15edbb4f3ee..e730bc86e65 100644 --- a/rules/integrations/kubernetes/persistence_kubernetes_admission_webhook_created_or_modified.toml +++ b/rules/integrations/kubernetes/persistence_kubernetes_admission_webhook_created_or_modified.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/26" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -36,7 +36,7 @@ MutatingWebhookConfiguration and ValidatingWebhookConfiguration objects by ident ### Possible investigation steps - Confirm the webhook resource and operation: - - kubernetes.audit.objectRef.resource and kubernetes.audit.verb + - orchestrator.resource.type and event.action - kubernetes.audit.objectRef.name (the webhook configuration name) - Attribute the actor and access path: - user.name (human vs service account vs node identity) @@ -84,9 +84,9 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -kubernetes.audit.objectRef.resource:("mutatingwebhookconfigurations" or "validatingwebhookconfigurations") and -kubernetes.audit.verb:("create" or "update" or "patch" or "delete") and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and +orchestrator.resource.type:("mutatingwebhookconfigurations" or "validatingwebhookconfigurations") and +event.action:("create" or "update" or "patch" or "delete") and +event.outcome:"success" and user.name:(* and not (system\:kube-controller-manager or system\:kube-scheduler or diff --git a/rules/integrations/kubernetes/persistence_kubernetes_client_certificate_signing_request_created_or_approved.toml b/rules/integrations/kubernetes/persistence_kubernetes_client_certificate_signing_request_created_or_approved.toml index 92ce340849a..714cda64ef5 100644 --- a/rules/integrations/kubernetes/persistence_kubernetes_client_certificate_signing_request_created_or_approved.toml +++ b/rules/integrations/kubernetes/persistence_kubernetes_client_certificate_signing_request_created_or_approved.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/05" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -89,9 +89,9 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:"kubernetes.audit_logs" and -kubernetes.audit.objectRef.resource:"certificatesigningrequests" and -kubernetes.audit.verb:("create" or "update" or "patch") and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and +orchestrator.resource.type:"certificatesigningrequests" and +event.action:("create" or "update" or "patch") and +event.outcome:"success" and not user.name:( system\:kube-controller-manager or system\:kube-scheduler or diff --git a/rules/integrations/kubernetes/persistence_kubernetes_eks_aws_auth_configmap_modified.toml b/rules/integrations/kubernetes/persistence_kubernetes_eks_aws_auth_configmap_modified.toml index 9f01db48f90..95987448f87 100644 --- a/rules/integrations/kubernetes/persistence_kubernetes_eks_aws_auth_configmap_modified.toml +++ b/rules/integrations/kubernetes/persistence_kubernetes_eks_aws_auth_configmap_modified.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/06" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/06" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -68,11 +68,11 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:"kubernetes.audit_logs" and -kubernetes.audit.objectRef.resource:"configmaps" and +orchestrator.resource.type:"configmaps" and kubernetes.audit.objectRef.name:"aws-auth" and -kubernetes.audit.verb:("update" or "patch" or "delete") and -kubernetes.audit.objectRef.namespace:"kube-system" and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and +event.action:("update" or "patch" or "delete") and +orchestrator.namespace:"kube-system" and +event.outcome:"success" and not user.name:"eks:kms-storage-migrator" ''' diff --git a/rules/integrations/kubernetes/persistence_sensitive_role_creation_or_modification.toml b/rules/integrations/kubernetes/persistence_sensitive_role_creation_or_modification.toml index fdfce80111f..5186fb0661e 100644 --- a/rules/integrations/kubernetes/persistence_sensitive_role_creation_or_modification.toml +++ b/rules/integrations/kubernetes/persistence_sensitive_role_creation_or_modification.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/04" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -64,11 +64,11 @@ type = "esql" query = ''' FROM logs-kubernetes.audit_logs-* metadata _id, _index, _version | WHERE - kubernetes.audit.objectRef.resource in ("roles", "clusterroles") and - kubernetes.audit.verb in ("create", "update", "patch") and - `kubernetes.audit.annotations.authorization_k8s_io/decision` == "allow" and + orchestrator.resource.type in ("roles", "clusterroles") and + event.action in ("create", "update", "patch") and + `event.outcome` == "allow" and kubernetes.audit.level == "RequestResponse" and kubernetes.audit.stage == "ResponseComplete" and - not kubernetes.audit.sourceIPs in ("::1", "127.0.0.1") and + not source.ip in ("::1", "127.0.0.1") and not (user.name like "eks:*" and kubernetes.audit.objectRef.name like "eks:*") and not (user.name == "aksService" and event.action == "create" and kubernetes.audit.objectRef.name like "aks:*") and not (user.name == "system:serviceaccount:kube-system:clusterrole-aggregation-controller" and kubernetes.audit.objectRef.name in ("admin", "edit") and event.action == "patch") and @@ -83,7 +83,7 @@ FROM logs-kubernetes.audit_logs-* metadata _id, _index, _version KQL(""" kubernetes.audit.responseObject.rules.verbs: ("*" or "create" or "patch" or "update") and kubernetes.audit.responseObject.rules.resources:("*" or "clusterroles" or "clusterrolebindings" or "roles" or "rolebindings" or "pods/exec" or "serviceaccounts/token" or "nodes/proxy" or "daemonsets") """) or KQL(""" kubernetes.audit.responseObject.rules.verbs: ("*" or "get" or "list") and kubernetes.audit.responseObject.rules.resources:("*" or "secrets") """) ) -| keep user.name, user_agent.original, event.action, source.ip, kubernetes.audit.verb, kubernetes.audit.objectRef.resource, kubernetes.audit.objectRef.name, kubernetes.audit.requestURI, kubernetes.audit.user.username, kubernetes.audit.user.groups, `kubernetes.audit.annotations.authorization_k8s_io/decision`, event.original, _id, _version, _index, data_stream.namespace +| keep user.name, user_agent.original, event.action, source.ip, event.action, orchestrator.resource.type, kubernetes.audit.objectRef.name, kubernetes.audit.requestURI, user.name, kubernetes.audit.user.groups, `event.outcome`, event.original, _id, _version, _index, data_stream.namespace ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/persistence_service_account_bound_to_clusterrole.toml b/rules/integrations/kubernetes/persistence_service_account_bound_to_clusterrole.toml index 91a129e2796..8059c5658be 100644 --- a/rules/integrations/kubernetes/persistence_service_account_bound_to_clusterrole.toml +++ b/rules/integrations/kubernetes/persistence_service_account_bound_to_clusterrole.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/04" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -63,8 +63,8 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset: "kubernetes.audit_logs" and kubernetes.audit.requestObject.spec.serviceAccountName:* and -kubernetes.audit.verb:"create" and kubernetes.audit.objectRef.resource:("rolebindings" or "clusterrolebindings") and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" +event.action:"create" and orchestrator.resource.type:("rolebindings" or "clusterrolebindings") and +event.outcome:"success" ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/privilege_escalation_api_proxy_to_node.toml b/rules/integrations/kubernetes/privilege_escalation_api_proxy_to_node.toml index 7f7dbe2dfb6..12577cf3ba6 100644 --- a/rules/integrations/kubernetes/privilege_escalation_api_proxy_to_node.toml +++ b/rules/integrations/kubernetes/privilege_escalation_api_proxy_to_node.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/05" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -87,7 +87,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' kubernetes.audit.objectRef.subresource:"proxy" and -kubernetes.audit.objectRef.resource:"nodes" and +orchestrator.resource.type:"nodes" and not kubernetes.audit.requestURI:(*metrics* or *healthz* or *stats/summary* or *elastic-agent* or *configz*) and not user.name:( system\:kube-controller-manager or diff --git a/rules/integrations/kubernetes/privilege_escalation_container_created_with_excessive_linux_capabilities.toml b/rules/integrations/kubernetes/privilege_escalation_container_created_with_excessive_linux_capabilities.toml index 1cfc43c6e3b..eb8618d798b 100644 --- a/rules/integrations/kubernetes/privilege_escalation_container_created_with_excessive_linux_capabilities.toml +++ b/rules/integrations/kubernetes/privilege_escalation_container_created_with_excessive_linux_capabilities.toml @@ -2,7 +2,7 @@ creation_date = "2022/09/20" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -67,17 +67,17 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset: kubernetes.audit_logs and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.verb: create and kubernetes.audit.objectRef.resource: pods and +data_stream.dataset: kubernetes.audit_logs and event.outcome:"success" and +event.action: create and orchestrator.resource.type: pods and kubernetes.audit.requestObject.spec.containers.securityContext.capabilities.add: ("BPF" or "DAC_READ_SEARCH" or "NET_ADMIN" or "SYS_ADMIN" or "SYS_BOOT" or "SYS_MODULE" or "SYS_PTRACE" or "SYS_RAWIO" or "SYSLOG") and not ( kubernetes.audit.requestObject.spec.containers.image : (docker.elastic.co/beats/elastic-agent* or rancher/klipper-lb* or "") or - kubernetes.audit.objectRef.namespace:"kube-system" or - (kubernetes.audit.objectRef.namespace:datadog and kubernetes.audit.requestObject.spec.containers.image:*datadog-agent*) or - (kubernetes.audit.objectRef.namespace:kubearmor and kubernetes.audit.requestObject.spec.containers.image:(*kubearmor\:kubearmor* or kubearmor/kubearmor-snitch*)) or - (kubernetes.audit.objectRef.namespace:defender and kubernetes.audit.requestObject.spec.containers.image:*fp-prisma\:defender-defender*) or - (kubernetes.audit.objectRef.namespace:metallb-system and kubernetes.audit.requestObject.spec.containers.image:(quay.io/frrouting* or quay.io/metallb/speaker*)) or - (kubernetes.audit.objectRef.namespace:longhorn-system and kubernetes.audit.requestObject.spec.containers.image:rancher/mirrored-longhornio*) + orchestrator.namespace:"kube-system" or + (orchestrator.namespace:datadog and kubernetes.audit.requestObject.spec.containers.image:*datadog-agent*) or + (orchestrator.namespace:kubearmor and kubernetes.audit.requestObject.spec.containers.image:(*kubearmor\:kubearmor* or kubearmor/kubearmor-snitch*)) or + (orchestrator.namespace:defender and kubernetes.audit.requestObject.spec.containers.image:*fp-prisma\:defender-defender*) or + (orchestrator.namespace:metallb-system and kubernetes.audit.requestObject.spec.containers.image:(quay.io/frrouting* or quay.io/metallb/speaker*)) or + (orchestrator.namespace:longhorn-system and kubernetes.audit.requestObject.spec.containers.image:rancher/mirrored-longhornio*) ) ''' diff --git a/rules/integrations/kubernetes/privilege_escalation_kubernetes_api_request_impersonating_privileged_identity.toml b/rules/integrations/kubernetes/privilege_escalation_kubernetes_api_request_impersonating_privileged_identity.toml index 7055bc56bdb..ef21d474044 100644 --- a/rules/integrations/kubernetes/privilege_escalation_kubernetes_api_request_impersonating_privileged_identity.toml +++ b/rules/integrations/kubernetes/privilege_escalation_kubernetes_api_request_impersonating_privileged_identity.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/05" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -32,12 +32,12 @@ note = """## Triage and analysis ### Investigating Kubernetes API Request Impersonating Privileged Identity Compare the real actor (user.name, groups, source.ip, user_agent.original) with impersonated -fields (kubernetes.audit.impersonatedUser.username, kubernetes.audit.impersonatedUser.groups). Confirm whether +fields (user.target.name, kubernetes.audit.impersonatedUser.groups). Confirm whether impersonation is authorized for that principal and target identity. ### Possible investigation steps -- Review kubernetes.audit.requestURI, kubernetes.audit.verb, and kubernetes.audit.objectRef for the scope of the +- Review kubernetes.audit.requestURI, event.action, and kubernetes.audit.objectRef for the scope of the operation performed while impersonating. - Determine whether the real user or service account should have impersonate rights against the impersonated user or group; inspect RBAC impersonate verb bindings and any recent changes. @@ -69,10 +69,10 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:kubernetes.audit_logs and -kubernetes.audit.impersonatedUser.username:(* and not ("eks-event-service:event-controller" or eks\:*)) and -kubernetes.audit.annotations.authorization_k8s_io/decision:allow and -kubernetes.audit.verb:(create or delete or get or list or patch or update) and -(kubernetes.audit.impersonatedUser.username:(admin or cluster-admin or kubernetes-admin or "system:admin" or "system:anonymous" or "system:apiserver" or "system:kube-controller-manager" or "system:kube-proxy" or "system:kube-scheduler" or "system:volume-scheduler" or system\:node\:* or system\:serviceaccount\:kube-system\:*) or kubernetes.audit.impersonatedUser.groups:(cluster-admin or "system:cluster-admins" or "system:masters")) and +user.target.name:(* and not ("eks-event-service:event-controller" or eks\:*)) and +event.outcome:success and +event.action:(create or delete or get or list or patch or update) and +(user.target.name:(admin or cluster-admin or kubernetes-admin or "system:admin" or "system:anonymous" or "system:apiserver" or "system:kube-controller-manager" or "system:kube-proxy" or "system:kube-scheduler" or "system:volume-scheduler" or system\:node\:* or system\:serviceaccount\:kube-system\:*) or kubernetes.audit.impersonatedUser.groups:(cluster-admin or "system:cluster-admins" or "system:masters")) and not user.name:(acsService or aksService or masterclient or nodeclient or "system:kube-controller-manager" or "system:kube-scheduler" or arn\:aws\:iam\:*\:role/aws-service-role* or arn\:aws\:sts\:*\:assumed-role/AWSServiceRoleForAmazonEKS* or arn\:aws\:sts\:*\:assumed-role/AWSServiceRoleForAmazonEKSNodegroup* or eks\:* or system\:node\:* or system\:serviceaccount\:kube-system\:*) ''' diff --git a/rules/integrations/kubernetes/privilege_escalation_kubernetes_ephemeral_container_added_to_pod.toml b/rules/integrations/kubernetes/privilege_escalation_kubernetes_ephemeral_container_added_to_pod.toml index fee20ebf39a..e566110f87d 100644 --- a/rules/integrations/kubernetes/privilege_escalation_kubernetes_ephemeral_container_added_to_pod.toml +++ b/rules/integrations/kubernetes/privilege_escalation_kubernetes_ephemeral_container_added_to_pod.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/07" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/07" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -63,10 +63,10 @@ timestamp_override = "event.ingested" type = "query" query = ''' data_stream.dataset:"kubernetes.audit_logs" and -kubernetes.audit.objectRef.resource:"pods" and +orchestrator.resource.type:"pods" and kubernetes.audit.objectRef.subresource:"ephemeralcontainers" and -kubernetes.audit.verb:("update" or "patch") and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and +event.action:("update" or "patch") and +event.outcome:"success" and not user.name:( system\:node\:* or system\:serviceaccount\:kube-system\:* diff --git a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostipc.toml b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostipc.toml index bf4a1dc2129..451d16f9967 100644 --- a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostipc.toml +++ b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostipc.toml @@ -2,7 +2,7 @@ creation_date = "2022/07/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -38,8 +38,8 @@ Kubernetes allows pods to share the host's IPC namespace, enabling inter-process ### Possible investigation steps - Review the Kubernetes audit logs to identify the specific pod creation or modification event that triggered the alert, focusing on the event.dataset field with the value "kubernetes.audit_logs". -- Examine the kubernetes.audit.annotations.authorization_k8s_io/decision field to confirm that the action was allowed, and verify the identity of the user or service account that initiated the request. -- Investigate the kubernetes.audit.objectRef.resource field to ensure the resource involved is indeed a pod, and check the kubernetes.audit.verb field to determine if the action was a create, update, or patch operation. +- Examine the event.outcome field to confirm that the action was allowed, and verify the identity of the user or service account that initiated the request. +- Investigate the orchestrator.resource.type field to ensure the resource involved is indeed a pod, and check the event.action field to determine if the action was a create, update, or patch operation. - Analyze the kubernetes.audit.requestObject.spec.hostIPC field to confirm that host IPC was enabled, and cross-reference with the kubernetes.audit.requestObject.spec.containers.image field to ensure the image is not part of the known benign list. - Check for any other pods or processes on the host that might be using the host's IPC namespace, and assess if there is any unauthorized access or data exposure risk. - Look for any suspicious activity or anomalies in the /dev/shm directory or use the ipcs command to identify any IPC facilities that might be exploited. @@ -84,8 +84,8 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset : "kubernetes.audit_logs" and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.objectRef.resource:"pods" and kubernetes.audit.verb:("create" or "update" or "patch") and +data_stream.dataset : "kubernetes.audit_logs" and event.outcome:"success" and +orchestrator.resource.type:"pods" and event.action:("create" or "update" or "patch") and kubernetes.audit.requestObject.spec.hostIPC:true and not kubernetes.audit.requestObject.spec.containers.image: ( docker.elastic.co/beats/elastic-agent* or rancher/system-agent* or registry.crowdstrike.com/falcon-sensor* diff --git a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostnetwork.toml b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostnetwork.toml index 2326aa00ae8..6b4561f1ec1 100644 --- a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostnetwork.toml +++ b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostnetwork.toml @@ -2,7 +2,7 @@ creation_date = "2022/07/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -81,8 +81,8 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:kubernetes.audit_logs and kubernetes.audit.annotations.authorization_k8s_io/decision:allow and -kubernetes.audit.objectRef.resource:pods and kubernetes.audit.verb:(create or patch or update) and +data_stream.dataset:kubernetes.audit_logs and event.outcome:success and +orchestrator.resource.type:pods and event.action:(create or patch or update) and kubernetes.audit.requestObject.spec.hostNetwork:true and not ( kubernetes.audit.requestObject.spec.containers.image:( @@ -91,7 +91,7 @@ not ( quay.io/frrouting/frr* or quay.io/metallb/speaker* or quay.io/prometheus/node-exporter* or rancher/system-agent* or registry.crowdstrike.com/falcon-sensor* or registry.k8s.io/sig-storage/csi-node-driver-registrar* ) or - kubernetes.audit.objectRef.namespace:( + orchestrator.namespace:( calico or calico-system or cilium or elastic or ingress-nginx or kube-system or noname-security-posture or openebs or sysdig-agent ) ) diff --git a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostpid.toml b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostpid.toml index 974e52ca7c2..5bdfe43fd18 100644 --- a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostpid.toml +++ b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_hostpid.toml @@ -2,7 +2,7 @@ creation_date = "2022/07/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -37,10 +37,10 @@ Kubernetes allows pods to share the host's process ID (PID) namespace, enabling ### Possible investigation steps -- Review the Kubernetes audit logs to identify the user or service account responsible for the pod creation or modification attempt. Look for the `kubernetes.audit.user.username` field to determine who initiated the action. +- Review the Kubernetes audit logs to identify the user or service account responsible for the pod creation or modification attempt. Look for the `user.name` field to determine who initiated the action. - Examine the `kubernetes.audit.requestObject.spec.containers.image` field to identify the container images used in the pod. Verify if any unknown or suspicious images are being deployed. -- Check the `kubernetes.audit.annotations.authorization_k8s_io/decision` field to confirm that the action was allowed and investigate the context or reason for this decision. -- Investigate the `kubernetes.audit.objectRef.resource` and `kubernetes.audit.verb` fields to understand the specific action taken (create, update, or patch) and the resource involved. +- Check the `event.outcome` field to confirm that the action was allowed and investigate the context or reason for this decision. +- Investigate the `orchestrator.resource.type` and `event.action` fields to understand the specific action taken (create, update, or patch) and the resource involved. - Assess the necessity and legitimacy of using HostPID in the pod's configuration by consulting with the relevant development or operations teams. Determine if there is a valid use case or if it was potentially misconfigured or maliciously set. - Review any recent changes in the Kubernetes environment or related configurations that might have led to this alert, focusing on changes around the time the alert was triggered. @@ -84,8 +84,8 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset : "kubernetes.audit_logs" and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.objectRef.resource:"pods" and kubernetes.audit.verb:("create" or "update" or "patch") and +data_stream.dataset : "kubernetes.audit_logs" and event.outcome:"success" and +orchestrator.resource.type:"pods" and event.action:("create" or "update" or "patch") and kubernetes.audit.requestObject.spec.hostPID:true and not kubernetes.audit.requestObject.spec.containers.image: ( ghcr.io/aquasecurity/node-collector* or rancher/system-agent* or ghcr.io/kubereboot/kured* or diff --git a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_sensitive_hostpath_volume.toml b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_sensitive_hostpath_volume.toml index 6e9cf8732ab..176129356d5 100644 --- a/rules/integrations/kubernetes/privilege_escalation_pod_created_with_sensitive_hostpath_volume.toml +++ b/rules/integrations/kubernetes/privilege_escalation_pod_created_with_sensitive_hostpath_volume.toml @@ -2,7 +2,7 @@ creation_date = "2022/07/11" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -39,9 +39,9 @@ Kubernetes allows containers to access host filesystems via hostPath volumes, wh - Review the Kubernetes audit logs to identify the specific pod creation or modification event that triggered the alert, focusing on the event.dataset field with the value "kubernetes.audit_logs". - Examine the kubernetes.audit.requestObject.spec.volumes.hostPath.path field to determine which sensitive hostPath was mounted and assess the potential risk associated with that specific path. -- Check the kubernetes.audit.annotations.authorization_k8s_io/decision field to confirm that the action was allowed, and verify the legitimacy of the authorization decision. +- Check the event.outcome field to confirm that the action was allowed, and verify the legitimacy of the authorization decision. - Investigate the kubernetes.audit.requestObject.spec.containers.image field to identify the container image used, ensuring it is not a known or suspected malicious image, and cross-reference with any known vulnerabilities or security advisories. -- Analyze the context of the pod creation or modification by reviewing the kubernetes.audit.verb field to understand whether the action was a create, update, or patch operation, and correlate this with recent changes or deployments in the environment. +- Analyze the context of the pod creation or modification by reviewing the event.action field to understand whether the action was a create, update, or patch operation, and correlate this with recent changes or deployments in the environment. - Assess the potential impact on the cluster by identifying other pods or services that might be affected by the compromised pod, especially those with elevated privileges or access to sensitive data. ### False positive analysis @@ -83,8 +83,8 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset : "kubernetes.audit_logs" and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.objectRef.resource:"pods" and kubernetes.audit.verb:("create" or "update" or "patch") and +data_stream.dataset : "kubernetes.audit_logs" and event.outcome:"success" and +orchestrator.resource.type:"pods" and event.action:("create" or "update" or "patch") and kubernetes.audit.requestObject.spec.volumes.hostPath.path: ( "/" or "/proc" or "/root" or "/var" or "/var/run" or "/var/run/docker.sock" or "/var/run/crio/crio.sock" or "/var/run/cri-dockerd.sock" or "/var/lib/kubelet" or "/var/lib/kubelet/pki" or "/var/lib/docker/overlay2" or diff --git a/rules/integrations/kubernetes/privilege_escalation_privileged_pod_created.toml b/rules/integrations/kubernetes/privilege_escalation_privileged_pod_created.toml index c5f2a43f4e7..9e4725e3170 100644 --- a/rules/integrations/kubernetes/privilege_escalation_privileged_pod_created.toml +++ b/rules/integrations/kubernetes/privilege_escalation_privileged_pod_created.toml @@ -2,7 +2,7 @@ creation_date = "2022/07/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -37,10 +37,10 @@ Kubernetes allows for the creation of privileged pods, which can access the host ### Possible investigation steps -- Review the Kubernetes audit logs to identify the user or service account responsible for creating the privileged pod by examining the `kubernetes.audit.annotations.authorization_k8s_io/decision` and `kubernetes.audit.verb:create` fields. +- Review the Kubernetes audit logs to identify the user or service account responsible for creating the privileged pod by examining the `event.outcome` and `event.action:create` fields. - Investigate the context of the privileged pod creation by checking the `kubernetes.audit.requestObject.spec.containers.image` field to determine if the image used is known or potentially malicious. - Assess the necessity and legitimacy of the privileged pod by consulting with the relevant development or operations teams to understand if there was a valid reason for its creation. -- Examine the `kubernetes.audit.objectRef.resource:pods` field to identify the specific pod and its associated namespace, and verify if it aligns with expected deployment patterns or environments. +- Examine the `orchestrator.resource.type:pods` field to identify the specific pod and its associated namespace, and verify if it aligns with expected deployment patterns or environments. - Check for any subsequent suspicious activities or anomalies in the Kubernetes environment that may indicate further exploitation attempts, such as lateral movement or data exfiltration, following the creation of the privileged pod. ### False positive analysis @@ -81,8 +81,8 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset : "kubernetes.audit_logs" and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.objectRef.resource:pods and kubernetes.audit.verb:create and kubernetes.audit.requestObject.spec.containers.securityContext.privileged:true and +data_stream.dataset : "kubernetes.audit_logs" and event.outcome:"success" and +orchestrator.resource.type:pods and event.action:create and kubernetes.audit.requestObject.spec.containers.securityContext.privileged:true and not kubernetes.audit.requestObject.spec.containers.image: ( *amazonaws.com/betsie/pipeline/pipeline-core* or mirror.gcr.io/aquasec/trivy* or rancher/mirrored-longhornio-longhorn-instance-manager* or quay.io/calico* or rancher/system-agent* or openebs/m-exporter* or openebs/cstor-istgt* or ghcr.io/kubereboot/kured* or registry.k8s.io/sig-storage/csi-node-driver-registrar* or diff --git a/rules/integrations/kubernetes/privilege_escalation_role_patch_wildcard_verbs_resources_response.toml b/rules/integrations/kubernetes/privilege_escalation_role_patch_wildcard_verbs_resources_response.toml index 576b89e1a5b..ef461af961f 100644 --- a/rules/integrations/kubernetes/privilege_escalation_role_patch_wildcard_verbs_resources_response.toml +++ b/rules/integrations/kubernetes/privilege_escalation_role_patch_wildcard_verbs_resources_response.toml @@ -2,7 +2,7 @@ creation_date = "2026/04/27" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -65,15 +65,15 @@ type = "esql" query = ''' from logs-kubernetes.audit_logs-* metadata _id, _index, _version | where - kubernetes.audit.objectRef.resource in ("roles", "clusterroles") and - kubernetes.audit.verb in ("update", "patch") and - `kubernetes.audit.annotations.authorization_k8s_io/decision` == "allow" and + orchestrator.resource.type in ("roles", "clusterroles") and + event.action in ("update", "patch") and + `event.outcome` == "allow" and kubernetes.audit.level == "RequestResponse" and kubernetes.audit.stage == "ResponseComplete" and - kubernetes.audit.sourceIPs is not null and - not kubernetes.audit.sourceIPs in ("::1", "127.0.0.1") and + source.ip is not null and + not source.ip in ("::1", "127.0.0.1") and KQL(""" kubernetes.audit.responseObject.rules.verbs:"*" and kubernetes.audit.responseObject.rules.resources:"*" """) -| keep user.name, user_agent.original, event.action, source.ip, kubernetes.audit.verb, kubernetes.audit.objectRef.resource, kubernetes.audit.objectRef.name, kubernetes.audit.requestURI, kubernetes.audit.user.username, kubernetes.audit.user.groups, `kubernetes.audit.annotations.authorization_k8s_io/decision`, event.original, _id, _version, _index, data_stream.namespace +| keep user.name, user_agent.original, event.action, source.ip, event.action, orchestrator.resource.type, kubernetes.audit.objectRef.name, kubernetes.audit.requestURI, user.name, kubernetes.audit.user.groups, `event.outcome`, event.original, _id, _version, _index, data_stream.namespace ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/privilege_escalation_sensitive_rbac_change_followed_by_workload_modification.toml b/rules/integrations/kubernetes/privilege_escalation_sensitive_rbac_change_followed_by_workload_modification.toml index 1cfca2a99e8..b3ed5b57eef 100644 --- a/rules/integrations/kubernetes/privilege_escalation_sensitive_rbac_change_followed_by_workload_modification.toml +++ b/rules/integrations/kubernetes/privilege_escalation_sensitive_rbac_change_followed_by_workload_modification.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/04" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -67,13 +67,13 @@ type = "eql" query = ''' sequence by user.name with maxspan=5m [any where data_stream.dataset == "kubernetes.audit_logs" and - `kubernetes.audit.annotations.authorization_k8s_io/decision` == "allow" and - kubernetes.audit.objectRef.resource in ("roles", "clusterroles") and - kubernetes.audit.verb in ("create", "update", "patch")] + `event.outcome` == "allow" and + orchestrator.resource.type in ("roles", "clusterroles") and + event.action in ("create", "update", "patch")] [any where data_stream.dataset == "kubernetes.audit_logs" and - `kubernetes.audit.annotations.authorization_k8s_io/decision` == "allow" and - kubernetes.audit.objectRef.resource in ("daemonsets", "deployments", "cronjobs") and - kubernetes.audit.verb in ("create", "patch") and + `event.outcome` == "allow" and + orchestrator.resource.type in ("daemonsets", "deployments", "cronjobs") and + event.action in ("create", "patch") and /* reduce control-plane / bootstrap noise */ not kubernetes.audit.user.groups == "system:masters" ] diff --git a/rules/integrations/kubernetes/privilege_escalation_sensitive_workload_modification_by_user_agent.toml b/rules/integrations/kubernetes/privilege_escalation_sensitive_workload_modification_by_user_agent.toml index 2a8cdfcf25a..253efdcfbea 100644 --- a/rules/integrations/kubernetes/privilege_escalation_sensitive_workload_modification_by_user_agent.toml +++ b/rules/integrations/kubernetes/privilege_escalation_sensitive_workload_modification_by_user_agent.toml @@ -2,7 +2,7 @@ creation_date = "2026/03/05" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -65,9 +65,9 @@ timestamp_override = "event.ingested" type = "new_terms" query = ''' data_stream.dataset:"kubernetes.audit_logs" and user_agent.original:* and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.objectRef.resource:("daemonsets" or "deployments" or "cronjobs") and -kubernetes.audit.verb:("create" or "patch") and +event.outcome:"success" and +orchestrator.resource.type:("daemonsets" or "deployments" or "cronjobs") and +event.action:("create" or "patch") and not kubernetes.audit.user.groups:"system:masters" ''' @@ -109,7 +109,7 @@ reference = "https://attack.mitre.org/tactics/TA0003/" [rule.new_terms] field = "new_terms_fields" -value = ["user_agent.original", "source.ip", "kubernetes.audit.user.username"] +value = ["user_agent.original", "source.ip", "user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" diff --git a/rules/integrations/kubernetes/privilege_escalation_service_account_rbac_write_operation.toml b/rules/integrations/kubernetes/privilege_escalation_service_account_rbac_write_operation.toml index baa39acb592..ea68aae2ef6 100644 --- a/rules/integrations/kubernetes/privilege_escalation_service_account_rbac_write_operation.toml +++ b/rules/integrations/kubernetes/privilege_escalation_service_account_rbac_write_operation.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/04" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -64,15 +64,15 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset:"kubernetes.audit_logs" and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.user.username:( +data_stream.dataset:"kubernetes.audit_logs" and event.outcome:"success" and +user.name:( system\:serviceaccount\:* and not ( "system:serviceaccount:kube-system:clusterrole-aggregation-controller" or "system:serviceaccount:kube-system:generic-garbage-collector" ) ) and -kubernetes.audit.objectRef.resource:("clusterrolebindings" or "clusterroles" or "rolebindings" or "roles") and -kubernetes.audit.verb:("create" or "delete" or "patch" or "update") +orchestrator.resource.type:("clusterrolebindings" or "clusterroles" or "rolebindings" or "roles") and +event.action:("create" or "delete" or "patch" or "update") ''' [[rule.threat]] diff --git a/rules/integrations/kubernetes/privilege_escalation_suspicious_assignment_of_controller_service_account.toml b/rules/integrations/kubernetes/privilege_escalation_suspicious_assignment_of_controller_service_account.toml index 5f2a7646230..701fe05a3b4 100644 --- a/rules/integrations/kubernetes/privilege_escalation_suspicious_assignment_of_controller_service_account.toml +++ b/rules/integrations/kubernetes/privilege_escalation_suspicious_assignment_of_controller_service_account.toml @@ -2,7 +2,7 @@ creation_date = "2022/09/13" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -80,9 +80,9 @@ tags = [ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset : "kubernetes.audit_logs" and kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.verb : "create" and kubernetes.audit.objectRef.resource : "pods" and -kubernetes.audit.objectRef.namespace : "kube-system" and kubernetes.audit.requestObject.spec.serviceAccountName:*controller and +data_stream.dataset : "kubernetes.audit_logs" and event.outcome:"success" and +event.action : "create" and orchestrator.resource.type : "pods" and +orchestrator.namespace : "kube-system" and kubernetes.audit.requestObject.spec.serviceAccountName:*controller and not kubernetes.audit.requestObject.spec.containers.image:( mirror.gcr.io/aquasec/trivy* or *amazonaws.com/eks/snapshot-controller* or rancher/mirrored-sig-storage-snapshot-controller* or public.ecr.aws/eks/aws-load-balancer-controller* or docker.io/bitnami/sealed-secrets-controller* or exoscale/csi-driver* or diff --git a/rules/integrations/o365/collection_exchange_excessive_mail_items_accessed.toml b/rules/integrations/o365/collection_exchange_excessive_mail_items_accessed.toml index a6c70a99753..28fa4889773 100644 --- a/rules/integrations/o365/collection_exchange_excessive_mail_items_accessed.toml +++ b/rules/integrations/o365/collection_exchange_excessive_mail_items_accessed.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/17" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -33,7 +33,7 @@ Identifies an excessive number of Microsoft 365 mailbox items accessed by a user ### Possible investigation steps - Review `host.name` to identify the tenant where the mailbox access occurred. -- Review `o365.audit.UserId` or `o365.audit.MailboxOwnerUPN` to identify the user associated with the mailbox access. +- Review `user.id` or `o365.audit.MailboxOwnerUPN` to identify the user associated with the mailbox access. - Examine `o365.audit.ExternalAccess` to determine if the mailbox access was performed by an external user or application. - Check the geolocation data to identify the location from which the mailbox access occurred. Is this an expected location for the user? - Check `o365.audit.ClientAppId` to identify the application used for mailbox access. Look for any unusual or unexpected applications but be aware that some legitimate applications may also trigger this rule if OAuth phishing was used. diff --git a/rules/integrations/o365/collection_exchange_mailbox_access_by_unusual_client_app_id.toml b/rules/integrations/o365/collection_exchange_mailbox_access_by_unusual_client_app_id.toml index db4fa2faa6f..653681d1850 100644 --- a/rules/integrations/o365/collection_exchange_mailbox_access_by_unusual_client_app_id.toml +++ b/rules/integrations/o365/collection_exchange_mailbox_access_by_unusual_client_app_id.toml @@ -2,7 +2,7 @@ creation_date = "2023/07/18" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -36,11 +36,11 @@ note = """## Triage and Analysis This rule detects when a user accesses their mailbox using a client application that is not typically used by the user, which may indicate potential compromise or unauthorized access attempts. Adversaries may use custom or third-party applications to access mailboxes, bypassing standard security controls. First-party Microsoft applications are also abused after OAuth tokens are compromised, allowing adversaries to access mailboxes without raising suspicion. ### Possible investigation steps -- Review the `o365.audit.UserId` field to identify the user associated with the mailbox access. +- Review the `user.id` field to identify the user associated with the mailbox access. - Check the `o365.audit.ClientAppId` field to determine which client application was used for the mailbox access. Look for unusual or unexpected applications or determine which first-party Microsoft applications are being abused. - Review `o365.audit.ClientInfoString` to gather additional information about the client application used for the mailbox access. - Examine `o365.audit.Folders.Path` to identify the specific mailbox folders accessed by the client application. This can help determine if sensitive information was accessed or if the access was legitimate. -- Ensure that `o365.audit.MailboxOwnerUPN` matches the `o365.audit.UserId` to confirm that the mailbox accessed belongs to the user identified in the `o365.audit.UserId` field. +- Ensure that `o365.audit.MailboxOwnerUPN` matches the `user.id` to confirm that the mailbox accessed belongs to the user identified in the `user.id` field. - Review geolocation information to identify the location from which the mailbox access occurred. Look for any anomalies or unexpected locations that may indicate suspicious activity. - Examine `o365.audit.Folders.FolderItems.Id` to identify the specific items accessed within the mailbox folders. This can help determine if sensitive information was accessed or if the access was legitimate. diff --git a/rules/integrations/o365/credential_access_entra_id_potential_user_account_brute_force.toml b/rules/integrations/o365/credential_access_entra_id_potential_user_account_brute_force.toml index 75d36b4da8f..7fbbc3ee6de 100644 --- a/rules/integrations/o365/credential_access_entra_id_potential_user_account_brute_force.toml +++ b/rules/integrations/o365/credential_access_entra_id_potential_user_account_brute_force.toml @@ -2,7 +2,7 @@ creation_date = "2020/11/30" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Willem D'Haese", "Austin Songer"] @@ -82,7 +82,7 @@ from logs-o365.audit-* | mv_expand event.category | eval Esql.time_window_date_trunc = date_trunc(5 minutes, @timestamp), - Esql_priv.o365_audit_UserId_lower = to_lower(o365.audit.UserId), + Esql_priv.o365_audit_UserId_lower = to_lower(user.id), Esql.o365_audit_LogonError = o365.audit.LogonError, Esql.o365_audit_ExtendedProperties_RequestType_lower = to_lower(o365.audit.ExtendedProperties.RequestType) | where diff --git a/rules/integrations/o365/credential_access_identity_user_account_lockouts.toml b/rules/integrations/o365/credential_access_identity_user_account_lockouts.toml index 86eef137635..bd238c5d398 100644 --- a/rules/integrations/o365/credential_access_identity_user_account_lockouts.toml +++ b/rules/integrations/o365/credential_access_identity_user_account_lockouts.toml @@ -2,7 +2,7 @@ creation_date = "2025/05/10" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -85,12 +85,12 @@ from logs-o365.audit-* event.action in ("UserLoginFailed", "PasswordLogonInitialAuthUsingPassword") and to_lower(o365.audit.ExtendedProperties.RequestType) rlike "(oauth.*||.*login.*)" and o365.audit.LogonError == "IdsLocked" and - to_lower(o365.audit.UserId) != "not available" and + to_lower(user.id) != "not available" and o365.audit.Target.Type in ("0", "2", "6", "10") and source.`as`.organization.name != "MICROSOFT-CORP-MSN-as-BLOCK" | stats - Esql_priv.o365_audit_UserId_count_distinct = count_distinct(to_lower(o365.audit.UserId)), - Esql_priv.o365_audit_UserId_values = values(to_lower(o365.audit.UserId)), + Esql_priv.o365_audit_UserId_count_distinct = count_distinct(to_lower(user.id)), + Esql_priv.o365_audit_UserId_values = values(to_lower(user.id)), Esql.source_ip_values = values(source.ip), Esql.source_ip_count_distinct = count_distinct(source.ip), Esql.source_as_organization_name_values = values(source.`as`.organization.name), diff --git a/rules/integrations/o365/defense_evasion_entra_id_susp_oauth2_authorization.toml b/rules/integrations/o365/defense_evasion_entra_id_susp_oauth2_authorization.toml index a633ddce8fb..8843a832185 100644 --- a/rules/integrations/o365/defense_evasion_entra_id_susp_oauth2_authorization.toml +++ b/rules/integrations/o365/defense_evasion_entra_id_susp_oauth2_authorization.toml @@ -2,7 +2,7 @@ creation_date = "2025/05/01" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ The rule aggregates events by user, application, and resource, requiring both `O ### Possible investigation steps -- Review `o365.audit.UserId` to identify the affected user and determine if they are a high-value target. +- Review `user.id` to identify the affected user and determine if they are a high-value target. - Analyze `Esql.source_ip_values` to see all unique IP addresses used within the 30-minute window. Determine whether these originate from different geographic regions, cloud providers (AWS, Azure, GCP), or anonymizing infrastructure (Tor, VPNs). - Use `Esql.time_window_date_trunc` to pivot into raw events and reconstruct the full sequence of resource access events with exact timestamps. - Check `Esql.source_as_organization_name_values` for unfamiliar ASN organizations that may indicate attacker infrastructure. @@ -88,7 +88,7 @@ from logs-o365.audit-* data_stream.dataset == "o365.audit" and event.action == "UserLoggedIn" and source.ip is not null and - o365.audit.UserId is not null and + user.id is not null and o365.audit.ApplicationId is not null and o365.audit.UserType in ("0", "2", "3", "10") and ( @@ -151,12 +151,12 @@ from logs-o365.audit-* Esql.time_window_date_trunc = date_trunc(30 minutes, @timestamp), Esql.oauth_authorize_user_id_case = case( o365.audit.ExtendedProperties.RequestType == "OAuth2:Authorize" and o365.audit.ExtendedProperties.ResultStatusDetail == "Redirect", - o365.audit.UserId, + user.id, null ), Esql.oauth_token_user_id_case = case( o365.audit.ExtendedProperties.RequestType == "OAuth2:Token", - o365.audit.UserId, + user.id, null ) | stats @@ -167,7 +167,7 @@ from logs-o365.audit-* Esql.oauth_token_count_distinct = count_distinct(Esql.oauth_token_user_id_case), Esql.oauth_authorize_count_distinct = count_distinct(Esql.oauth_authorize_user_id_case) by - o365.audit.UserId, + user.id, Esql.time_window_date_trunc, o365.audit.ApplicationId, o365.audit.ObjectId diff --git a/rules/integrations/o365/defense_evasion_exchange_inbox_rule_obfuscated_name.toml b/rules/integrations/o365/defense_evasion_exchange_inbox_rule_obfuscated_name.toml index e5796a70a7c..59b8e0591ee 100644 --- a/rules/integrations/o365/defense_evasion_exchange_inbox_rule_obfuscated_name.toml +++ b/rules/integrations/o365/defense_evasion_exchange_inbox_rule_obfuscated_name.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/27" integration = ["o365"] maturity = "production" -updated_date = "2026/05/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -36,7 +36,7 @@ Because this rule uses ESQL `grok` and `keep`, review the original `o365.audit` ### Possible investigation steps - Review `Esql.inbox_rule_name` and `o365.audit.ObjectId` to confirm the parsed rule identity and mailbox path. -- Identify the actor using `o365.audit.UserId` and correlate with Entra ID sign-in logs for the same `source.ip`. +- Identify the actor using `user.id` and correlate with Entra ID sign-in logs for the same `source.ip`. - Inspect `event.action` to determine whether the rule was newly created or modified. - Review kept forwarding and redirect parameters (`ForwardTo`, `ForwardAsAttachmentTo`, `ForwardingAddress`, `RedirectTo`, `RedirectToRecipients`) for external destinations outside `user.domain`. @@ -91,7 +91,7 @@ from logs-o365.audit-* metadata _id, _version, _index _index, Esql.inbox_rule_name, o365.audit.ObjectId, - o365.audit.UserId, + user.id, o365.audit.ApplicationId, user.name, user.domain, @@ -109,7 +109,7 @@ field_names = [ "@timestamp", "Esql.inbox_rule_name", "o365.audit.ObjectId", - "o365.audit.UserId", + "user.id", "user.name", "user.domain", "event.action", diff --git a/rules/integrations/o365/initial_access_entra_id_portal_login_atypical_travel.toml b/rules/integrations/o365/initial_access_entra_id_portal_login_atypical_travel.toml index 2039e72aa13..39602630753 100644 --- a/rules/integrations/o365/initial_access_entra_id_portal_login_atypical_travel.toml +++ b/rules/integrations/o365/initial_access_entra_id_portal_login_atypical_travel.toml @@ -2,7 +2,7 @@ creation_date = "2024/09/04" integration = ["o365"] maturity = "production" -updated_date = "2026/05/06" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -76,7 +76,7 @@ data_stream.dataset:o365.audit and event.action:UserLoggedIn and event.outcome:success and o365.audit.Target.Type:(0 or 10 or 2 or 3 or 5 or 6) and - o365.audit.UserId:(* and not "Not Available") and + user.id:(* and not "Not Available") and source.geo.country_name:* and source.geo.region_name:* and not o365.audit.ApplicationId:( @@ -123,7 +123,7 @@ reference = "https://attack.mitre.org/tactics/TA0001/" field_names = [ "@timestamp", "organization.id", - "o365.audit.UserId", + "user.id", "o365.audit.ActorIpAddress", "o365.audit.ApplicationId", "o365.audit.ExtendedProperties.RequestType", @@ -134,7 +134,7 @@ field_names = [ [rule.new_terms] field = "new_terms_fields" -value = ["o365.audit.UserId", "source.geo.country_name", "source.geo.region_name"] +value = ["user.id", "source.geo.country_name", "source.geo.region_name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/o365/initial_access_entra_id_portal_login_impossible_travel.toml b/rules/integrations/o365/initial_access_entra_id_portal_login_impossible_travel.toml index ba67e438bdb..2687f68909c 100644 --- a/rules/integrations/o365/initial_access_entra_id_portal_login_impossible_travel.toml +++ b/rules/integrations/o365/initial_access_entra_id_portal_login_impossible_travel.toml @@ -2,7 +2,7 @@ creation_date = "2024/09/04" integration = ["o365"] maturity = "production" -updated_date = "2026/05/06" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,7 +74,7 @@ data_stream.dataset:o365.audit and event.action:UserLoggedIn and event.outcome:success and o365.audit.Target.Type:(0 or 10 or 2 or 3 or 5 or 6) and - o365.audit.UserId:(* and not "Not Available") and + user.id:(* and not "Not Available") and source.geo.country_name:* and not o365.audit.ApplicationId:( 29d9ed98-a469-4536-ade2-f981bc1d605e or @@ -116,7 +116,7 @@ reference = "https://attack.mitre.org/tactics/TA0001/" field_names = [ "@timestamp", "organization.id", - "o365.audit.UserId", + "user.id", "o365.audit.ActorIpAddress", "o365.audit.ApplicationId", "o365.audit.ExtendedProperties.RequestType", @@ -125,7 +125,7 @@ field_names = [ ] [rule.threshold] -field = ["o365.audit.UserId"] +field = ["user.id"] value = 1 [[rule.threshold.cardinality]] field = "source.geo.country_name" diff --git a/rules/integrations/o365/initial_access_identity_illicit_consent_grant_via_registered_application.toml b/rules/integrations/o365/initial_access_identity_illicit_consent_grant_via_registered_application.toml index 91dda1da022..bf3c2713a23 100644 --- a/rules/integrations/o365/initial_access_identity_illicit_consent_grant_via_registered_application.toml +++ b/rules/integrations/o365/initial_access_identity_illicit_consent_grant_via_registered_application.toml @@ -2,7 +2,7 @@ creation_date = "2025/03/24" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -35,7 +35,7 @@ This rule identifies a new consent grant to an application using Microsoft 365 a - Check the `Publisher` and `Verified` status. - **Assess the user who granted consent**: - - Investigate `o365.audit.UserId` (e.g., `terrance.dejesus@...`) for signs of phishing or account compromise. + - Investigate `user.id` (e.g., `terrance.dejesus@...`) for signs of phishing or account compromise. - Check if the user was targeted in recent phishing simulations or campaigns. - Review the user’s sign-in logs for suspicious geolocation, IP, or device changes. @@ -97,7 +97,7 @@ data_stream.dataset: "o365.audit" and event.action: "Consent to application." and event.outcome: "success" and o365.audit.Target.Type: (0 or 2 or 3 or 9 or 10) - and o365.audit.UserId: * + and user.id: * and o365.audit.ObjectId: * ''' @@ -150,7 +150,7 @@ field_names = [ "@timestamp", "event.action", "event.outcome", - "o365.audit.UserId", + "user.id", "o365.audit.ObjectId", "o365.audit.Actor.Type", "o365.audit.Target.Type", @@ -161,7 +161,7 @@ field_names = [ [rule.new_terms] field = "new_terms_fields" -value = ["o365.audit.UserId", "o365.audit.ObjectId"] +value = ["user.id", "o365.audit.ObjectId"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-14d" diff --git a/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_source_asn.toml b/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_source_asn.toml index 7da91bf6743..f8e7ea5670b 100644 --- a/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_source_asn.toml +++ b/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_source_asn.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/01" integration = ["o365"] maturity = "production" -updated_date = "2026/06/01" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -36,7 +36,7 @@ This rule detects a user completing an OAuth device code grant (`Cmsi:Cmsi`) to ### Possible investigation steps -- Review `o365.audit.UserId` to identify the impacted account and confirm whether the user expected to perform a device code sign-in. +- Review `user.id` to identify the impacted account and confirm whether the user expected to perform a device code sign-in. - Inspect `source.as.number` and `source.as.organization.name` for the source ASN. Hosting, VPN, or datacenter providers (for example Tencent, Alibaba, DigitalOcean) are unusual for interactive user authentication. - Review `source.ip`, `source.geo.country_name`, and `source.geo.city_name` and compare with the user's normal sign-in locations. - Examine `o365.audit.DeviceProperties` and `user_agent.original` for non-managed devices and automation or headless-browser patterns. @@ -145,7 +145,7 @@ reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["o365.audit.UserId", "source.as.number"] +value = ["user.id", "source.as.number"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_user_noncompliant_device.toml b/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_user_noncompliant_device.toml index 01661395ea2..cbe6f6dde40 100644 --- a/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_user_noncompliant_device.toml +++ b/rules/integrations/o365/initial_access_identity_oauth_device_code_grant_unusual_user_noncompliant_device.toml @@ -2,7 +2,7 @@ creation_date = "2026/06/02" integration = ["o365"] maturity = "production" -updated_date = "2026/06/02" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -37,7 +37,7 @@ This rule detects a user completing an OAuth device code grant (`Cmsi:Cmsi`) fro ### Possible investigation steps -- Review `o365.audit.UserId` to identify the impacted account and confirm whether the user expected to perform a device code sign-in. +- Review `user.id` to identify the impacted account and confirm whether the user expected to perform a device code sign-in. - Examine `o365.audit.DeviceProperties` to understand the device posture (compliance, management state, OS, browser) and whether the device is recognized for this user. - Confirm `o365.audit.ApplicationId` and `o365.audit.Target.ID` to identify the application and resource the grant was for. Authentication Broker (`29d9ed98-a469-4536-ade2-f981bc1d605e`) and developer tooling (Azure CLI, PowerShell) are commonly abused. - Inspect `source.as.number`, `source.as.organization.name`, `source.ip`, and `source.geo.*` and compare with the user's normal sign-in origins. Hosting, VPN, or datacenter providers are unusual for interactive user authentication. @@ -144,7 +144,7 @@ reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["o365.audit.UserId"] +value = ["user.id"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/o365/initial_access_identity_oauth_phishing_via_first_party_microsoft_application.toml b/rules/integrations/o365/initial_access_identity_oauth_phishing_via_first_party_microsoft_application.toml index dadeabd9f00..35dd3cb7569 100644 --- a/rules/integrations/o365/initial_access_identity_oauth_phishing_via_first_party_microsoft_application.toml +++ b/rules/integrations/o365/initial_access_identity_oauth_phishing_via_first_party_microsoft_application.toml @@ -2,7 +2,7 @@ creation_date = "2025/04/23" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,12 +30,12 @@ The rule uses split detection logic: developer tools (Azure CLI, VSCode, PowerSh ### Possible investigation steps -- Review `o365.audit.UserId` to identify the impacted account and validate whether the user expected to authorize the application. +- Review `user.id` to identify the impacted account and validate whether the user expected to authorize the application. - Check `o365.audit.ActorIpAddress` for unexpected IPs, especially outside corporate ranges or from proxy/VPN networks. - Examine `user_agent.original` and `o365.audit.DeviceProperties` for suspicious patterns (automation tools, headless browsers, unusual browser/OS combinations). - Confirm `o365.audit.Target.ID` to identify the resource being accessed. Legacy AAD (`00000002-0000-0000-c000-000000000000`) access is unusual for most users. - Review `o365.audit.ExtendedProperties.RequestType` and `ResultStatusDetail` - `OAuth2:Authorize` with `Redirect` indicates the OAuth code was exposed to the user. -- Look for subsequent `OAuth2:Token` events from different IPs using the same `o365.audit.UserId`, which indicates token exchange from attacker infrastructure. +- Look for subsequent `OAuth2:Token` events from different IPs using the same `user.id`, which indicates token exchange from attacker infrastructure. - Pivot to `azure.graphactivitylogs` to check for follow-up Graph API activity (mailbox enumeration, file access) from unfamiliar locations. - Correlate with `azure.signinlogs` for additional sign-in context and device details. diff --git a/rules/integrations/o365/initial_access_identity_unusual_sso_errors_for_user.toml b/rules/integrations/o365/initial_access_identity_unusual_sso_errors_for_user.toml index b2ea9cd96c1..b2db1242e95 100644 --- a/rules/integrations/o365/initial_access_identity_unusual_sso_errors_for_user.toml +++ b/rules/integrations/o365/initial_access_identity_unusual_sso_errors_for_user.toml @@ -2,7 +2,7 @@ creation_date = "2021/05/17" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Austin Songer"] @@ -148,7 +148,7 @@ name = "Credential Access" reference = "https://attack.mitre.org/tactics/TA0006/" [rule.new_terms] field = "new_terms_fields" -value = ["o365.audit.UserId", "o365.audit.ErrorNumber"] +value = ["user.id", "o365.audit.ErrorNumber"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-10d" diff --git a/rules/integrations/o365/initial_access_tycoon_o365.toml b/rules/integrations/o365/initial_access_tycoon_o365.toml index ec5616b961c..e01629a853a 100644 --- a/rules/integrations/o365/initial_access_tycoon_o365.toml +++ b/rules/integrations/o365/initial_access_tycoon_o365.toml @@ -2,7 +2,7 @@ creation_date = "2026/05/14" integration = ["o365"] maturity = "production" -updated_date = "2026/05/14" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ note = """## Triage and analysis ### Investigating M365 Potential AiTM UserLoggedIn via Office App (Tycoon2FA) -Review `o365.audit.UserId`, `user_agent.original`, `source.ip` or `o365.audit.ActorIpAddress`, and related Entra ID +Review `user.id`, `user_agent.original`, `source.ip` or `o365.audit.ActorIpAddress`, and related Entra ID sign-in logs (`azure.signinlogs`) for the same session or time window. Confirm whether the account owner intentionally authenticated and whether Node.js-style user agents (node, axios, undici) @@ -84,7 +84,7 @@ data_stream.dataset:"o365.audit" and event.category:"authentication" and event.a [rule.investigation_fields] field_names = [ "@timestamp", - "o365.audit.UserId", + "user.id", "user_agent.original", "source.ip", "o365.audit.ActorIpAddress", diff --git a/rules/integrations/o365/persistence_exchange_suspicious_mailbox_permission_delegation.toml b/rules/integrations/o365/persistence_exchange_suspicious_mailbox_permission_delegation.toml index ca33fe1ebb5..5a846fa7cae 100644 --- a/rules/integrations/o365/persistence_exchange_suspicious_mailbox_permission_delegation.toml +++ b/rules/integrations/o365/persistence_exchange_suspicious_mailbox_permission_delegation.toml @@ -2,7 +2,7 @@ creation_date = "2021/05/17" integration = ["o365"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Austin Songer"] @@ -151,7 +151,7 @@ name = "Privilege Escalation" reference = "https://attack.mitre.org/tactics/TA0004/" [rule.new_terms] field = "new_terms_fields" -value = ["o365.audit.UserId"] +value = ["user.id"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-14d" diff --git a/rules/integrations/okta/credential_access_attempted_bypass_of_okta_mfa.toml b/rules/integrations/okta/credential_access_attempted_bypass_of_okta_mfa.toml index d5931e08124..951c9c85c6b 100644 --- a/rules/integrations/okta/credential_access_attempted_bypass_of_okta_mfa.toml +++ b/rules/integrations/okta/credential_access_attempted_bypass_of_okta_mfa.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/21" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -24,11 +24,11 @@ This rule detects attempts to bypass Okta MFA. It might indicate a serious attem #### Possible investigation steps -- Identify the actor related to the alert by reviewing `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields in the alert. -- Review the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. -- Examine the `okta.outcome.reason` field for additional context around the bypass attempt. -- Check the `okta.outcome.result` field to confirm the MFA bypass attempt. -- Check if there are multiple unsuccessful MFA attempts from the same actor or IP address (`okta.client.ip`). +- Identify the actor related to the alert by reviewing `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields in the alert. +- Review the `user_agent.original` field to understand the device and software used by the actor. +- Examine the `event.reason` field for additional context around the bypass attempt. +- Check the `event.outcome` field to confirm the MFA bypass attempt. +- Check if there are multiple unsuccessful MFA attempts from the same actor or IP address (`source.ip`). - Check for successful logins immediately following the MFA bypass attempt. - Verify whether the actor's activity aligns with typical behavior or if any unusual activity took place around the time of the bypass attempt. diff --git a/rules/integrations/okta/credential_access_attempts_to_brute_force_okta_user_account.toml b/rules/integrations/okta/credential_access_attempts_to_brute_force_okta_user_account.toml index eca04ac99bb..f370c58c6a9 100644 --- a/rules/integrations/okta/credential_access_attempts_to_brute_force_okta_user_account.toml +++ b/rules/integrations/okta/credential_access_attempts_to_brute_force_okta_user_account.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/19" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "@BenB196", "Austin Songer"] @@ -26,8 +26,8 @@ This rule fires when an Okta user account has been locked out 3 times within a 3 #### Possible investigation steps: -- Identify the actor related to the alert by reviewing `okta.actor.alternate_id` field in the alert. This should give the username of the account being targeted. -- Review the `okta.event_type` field to understand the nature of the events that led to the account lockout. +- Identify the actor related to the alert by reviewing `user.name` field in the alert. This should give the username of the account being targeted. +- Review the `event.action` field to understand the nature of the events that led to the account lockout. - Check the `okta.severity` and `okta.display_message` fields for more context around the lockout events. - Look for correlation of events from the same IP address. Multiple lockouts from the same IP address might indicate a single source for the attack. - If the IP is not familiar, investigate it. The IP could be a proxy, VPN, Tor node, cloud datacenter, or a legitimate IP turned malicious. @@ -100,6 +100,6 @@ id = "TA0006" name = "Credential Access" reference = "https://attack.mitre.org/tactics/TA0006/" [rule.threshold] -field = ["okta.actor.alternate_id"] +field = ["user.name"] value = 3 diff --git a/rules/integrations/okta/credential_access_multiple_auth_events_from_single_device_behind_proxy.toml b/rules/integrations/okta/credential_access_multiple_auth_events_from_single_device_behind_proxy.toml index e93d1bdfd9a..3b6fe193d35 100644 --- a/rules/integrations/okta/credential_access_multiple_auth_events_from_single_device_behind_proxy.toml +++ b/rules/integrations/okta/credential_access_multiple_auth_events_from_single_device_behind_proxy.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/10" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,18 +27,18 @@ note = """## Triage and analysis This rule detects when Okta user authentication events are reported for multiple users with the same device token hash behind a proxy. This may indicate that a shared device between users, or that a user is using a proxy to access multiple accounts for password spraying. #### Possible investigation steps: -- Identify the users involved in this action by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. -- Determine the device client used for these actions by analyzing `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - - Since the device is behind a proxy, the `okta.client.ip` field will not be useful for determining the actual device IP address. +- Identify the users involved in this action by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. +- Determine the device client used for these actions by analyzing `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. + - Since the device is behind a proxy, the `source.ip` field will not be useful for determining the actual device IP address. - Review the `okta.request.ip_chain` field for more information about the geographic location of the proxy. - With Okta end users identified, review the `okta.debug_context.debug_data.dt_hash` field. - Historical analysis should indicate if this device token hash is commonly associated with the user. -- Review the `okta.event_type` field to determine the type of authentication event that occurred. +- Review the `event.action` field to determine the type of authentication event that occurred. - If the event type is `user.authentication.sso`, the user may have legitimately started a session via a proxy for security or privacy reasons. - If the event type is `user.authentication.password`, the user may be using a proxy to access multiple accounts for password spraying. -- Examine the `okta.outcome.result` field to determine if the authentication was successful. +- Examine the `event.outcome` field to determine if the authentication was successful. - Review the past activities of the actor(s) involved in this action by checking their previous actions. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. - This may help determine the authentication and authorization actions that occurred between the user, Okta and application. ### False positive analysis: @@ -85,8 +85,8 @@ type = "threshold" query = ''' data_stream.dataset:okta.system - and not okta.actor.id:okta* and okta.debug_context.debug_data.dt_hash:* - and okta.event_type:user.authentication* and okta.security_context.is_proxy:true + and not client.user.id:okta* and okta.debug_context.debug_data.dt_hash:* + and event.action:user.authentication* and okta.security_context.is_proxy:true ''' @@ -134,7 +134,7 @@ reference = "https://attack.mitre.org/tactics/TA0001/" field = ["okta.debug_context.debug_data.dt_hash"] value = 1 [[rule.threshold.cardinality]] -field = "okta.actor.id" +field = "client.user.id" value = 3 diff --git a/rules/integrations/okta/credential_access_multiple_device_token_hashes_for_single_okta_session.toml b/rules/integrations/okta/credential_access_multiple_device_token_hashes_for_single_okta_session.toml index a3fcc109f1c..e31c314d3b5 100644 --- a/rules/integrations/okta/credential_access_multiple_device_token_hashes_for_single_okta_session.toml +++ b/rules/integrations/okta/credential_access_multiple_device_token_hashes_for_single_okta_session.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/08" integration = ["okta"] maturity = "production" -updated_date = "2026/04/13" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -26,12 +26,12 @@ This rule detects when a specific Okta actor has multiple device token hashes an > **Note**: This is an ES|QL aggregation-based rule. Exceptions can be added on the original ECS or integration-related fields. We recommend using the indicators from the alert document to pivot into the raw events for analysis. #### Possible investigation steps: -- Use `okta.actor.alternate_id` and `okta.authentication_context.external_session_id` from the alert to pivot into the raw Okta system log events for the affected session. -- Review the source IPs (`okta.client.ip`) and ASN information (`source.as.organization.name`) to determine if the session was used from multiple distinct networks. +- Use `user.name` and `okta.authentication_context.external_session_id` from the alert to pivot into the raw Okta system log events for the affected session. +- Review the source IPs (`source.ip`) and ASN information (`source.as.organization.name`) to determine if the session was used from multiple distinct networks. - Multiple ASNs or geolocations (`client.geo.country_name`, `client.geo.city_name`) within the same session strongly suggest session hijacking. - Compare the `okta.debug_context.debug_data.dt_hash` values to identify the device token hashes associated with the session. - A legitimate session should have a consistent device token hash. Multiple distinct hashes indicate the session cookie may have been replayed from a different device. -- Examine `okta.client.user_agent.raw_user_agent` and `okta.client.device` for inconsistencies that suggest different devices or browsers using the same session. +- Examine `user_agent.original` and `okta.client.device` for inconsistencies that suggest different devices or browsers using the same session. - Review `event.action` to understand what actions were performed during the session. - Look for suspicious post-authentication activity such as admin console access, policy changes, or application assignment modifications. - Check `okta.debug_context.debug_data.risk_level`, `okta.debug_context.debug_data.risk_reasons`, and `okta.debug_context.debug_data.behaviors` for Okta's own risk assessment of the session activity. @@ -49,7 +49,7 @@ This rule detects when a specific Okta actor has multiple device token hashes an - Review Okta system logs for any administrative or sensitive actions performed during the suspicious session window. - If the session was used to access downstream applications, review those application logs for unauthorized activity. - Check with the user to confirm whether they were actively using Okta during the alert time window. -- For recurring false positives from known integrations, add exceptions on `okta.actor.alternate_id` for the specific service account or application client ID. +- For recurring false positives from known integrations, add exceptions on `user.name` for the specific service account or application client ID. """ references = [ "https://developer.okta.com/docs/reference/api/system-log/", @@ -83,30 +83,30 @@ from logs-okta.system-* "user.session.start", "user.authentication.sso" ) and - okta.actor.alternate_id != "system@okta.com" and - okta.actor.alternate_id rlike "[^@\\s]+\\@[^@\\s]+" and + user.name != "system@okta.com" and + user.name rlike "[^@\\s]+\\@[^@\\s]+" and okta.authentication_context.external_session_id != "unknown" and ( okta.authentication_context.external_session_id IS NOT NULL and okta.debug_context.debug_data.dt_hash IS NOT NULL and - okta.client.ip IS NOT NULL and - okta.client.user_agent.raw_user_agent IS NOT NULL + source.ip IS NOT NULL and + user_agent.original IS NOT NULL ) and ( okta.authentication_context.external_session_id != "-" and okta.debug_context.debug_data.dt_hash != "-" and - okta.client.user_agent.raw_user_agent != "-" + user_agent.original != "-" ) | stats Esql.dt_hash_count_distinct = count_distinct(okta.debug_context.debug_data.dt_hash), - Esql.client_ip_count_distinct = count_distinct(okta.client.ip), + Esql.client_ip_count_distinct = count_distinct(source.ip), Esql.event_count = count(*), Esql.first_event_time = min(@timestamp), Esql.last_event_time = max(@timestamp), Esql.dt_hash_values = values(okta.debug_context.debug_data.dt_hash), Esql.event_action_values = values(event.action), - Esql.client_ip_values = values(okta.client.ip), - Esql.user_agent_values = values(okta.client.user_agent.raw_user_agent), + Esql.client_ip_values = values(source.ip), + Esql.user_agent_values = values(user_agent.original), Esql.device_values = values(okta.client.device), Esql.is_proxy_values = values(okta.security_context.is_proxy), Esql.geo_country_name_values = values(client.geo.country_name), @@ -121,7 +121,7 @@ from logs-okta.system-* Esql.risk_behaviors_values = values(okta.debug_context.debug_data.risk_behaviors), Esql.request_uri_values = values(okta.debug_context.debug_data.request_uri) by - okta.actor.alternate_id, + user.name, okta.authentication_context.external_session_id | where Esql.dt_hash_count_distinct >= 4 and diff --git a/rules/integrations/okta/credential_access_okta_aitm_session_cookie_replay.toml b/rules/integrations/okta/credential_access_okta_aitm_session_cookie_replay.toml index 52bd075b206..4da7a3801c7 100644 --- a/rules/integrations/okta/credential_access_okta_aitm_session_cookie_replay.toml +++ b/rules/integrations/okta/credential_access_okta_aitm_session_cookie_replay.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/26" integration = ["okta"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -20,7 +20,7 @@ false_positives = [ """, """ Automated integrations or scripts using service accounts with session cookies may trigger user-agent based - detection. Consider excluding known automation accounts by okta.actor.alternate_id. + detection. Consider excluding known automation accounts by user.name. """, """ Mobile users switching between WiFi and cellular may show IP address changes. Correlate with device type and typical @@ -99,14 +99,14 @@ FROM logs-okta.system-* // Filter to relevant event types for AiTM detection | WHERE - okta.event_type IN ("user.session.start", "policy.evaluate_sign_on", "user.authentication.sso") AND + event.action IN ("user.session.start", "policy.evaluate_sign_on", "user.authentication.sso") AND okta.authentication_context.root_session_id IS NOT NULL AND - okta.actor.alternate_id != "system@okta.com" + user.name != "system@okta.com" // Create event type flags -| EVAL Esql.is_session_start = okta.event_type == "user.session.start" -| EVAL Esql.is_policy_eval = okta.event_type == "policy.evaluate_sign_on" -| EVAL Esql.is_sso = okta.event_type == "user.authentication.sso" +| EVAL Esql.is_session_start = event.action == "user.session.start" +| EVAL Esql.is_policy_eval = event.action == "policy.evaluate_sign_on" +| EVAL Esql.is_sso = event.action == "user.authentication.sso" | EVAL Esql.is_replay_event = Esql.is_policy_eval OR Esql.is_sso // Flag suspicious non-browser user agents @@ -127,20 +127,20 @@ FROM logs-okta.system-* Esql.session_start_time = MIN(CASE(Esql.is_session_start, @timestamp, null)), Esql.first_replay_time = MIN(CASE(Esql.is_replay_event, @timestamp, null)), Esql.last_replay_time = MAX(CASE(Esql.is_replay_event, @timestamp, null)), - Esql.session_start_ip = MAX(CASE(Esql.is_session_start, okta.client.ip, null)), + Esql.session_start_ip = MAX(CASE(Esql.is_session_start, source.ip, null)), Esql.session_start_ua = MAX(CASE(Esql.is_session_start, user_agent.original, null)), Esql.suspicious_ua_count = SUM(CASE(Esql.is_suspicious_ua, 1, 0)), - Esql.okta_client_ip_count_distinct = COUNT_DISTINCT(okta.client.ip), + Esql.okta_client_ip_count_distinct = COUNT_DISTINCT(source.ip), Esql.user_agent_count_distinct = COUNT_DISTINCT(user_agent.original), - Esql.okta_client_ip_values = VALUES(okta.client.ip), + Esql.okta_client_ip_values = VALUES(source.ip), Esql.user_agent_values = VALUES(user_agent.original), - Esql.okta_event_type_values = VALUES(okta.event_type), - Esql.okta_outcome_result_values = VALUES(okta.outcome.result), + Esql.okta_event_type_values = VALUES(event.action), + Esql.okta_outcome_result_values = VALUES(event.outcome), Esql.source_geo_country_name_values = VALUES(source.geo.country_name), Esql.source_geo_city_name_values = VALUES(source.geo.city_name), Esql.okta_debug_context_debug_data_risk_level_values = VALUES(okta.debug_context.debug_data.risk_level), Esql.okta_debug_context_debug_data_risk_reasons_values = VALUES(okta.debug_context.debug_data.risk_reasons) - BY okta.authentication_context.root_session_id, okta.actor.alternate_id + BY okta.authentication_context.root_session_id, user.name // Detection conditions | WHERE @@ -154,7 +154,7 @@ FROM logs-okta.system-* ) | SORT Esql.session_start_time DESC -| KEEP Esql.*, okta.authentication_context.root_session_id, okta.actor.alternate_id +| KEEP Esql.*, okta.authentication_context.root_session_id, user.name ''' diff --git a/rules/integrations/okta/credential_access_okta_authentication_for_multiple_users_with_the_same_device_token_hash.toml b/rules/integrations/okta/credential_access_okta_authentication_for_multiple_users_with_the_same_device_token_hash.toml index c3692f94808..44d76137586 100644 --- a/rules/integrations/okta/credential_access_okta_authentication_for_multiple_users_with_the_same_device_token_hash.toml +++ b/rules/integrations/okta/credential_access_okta_authentication_for_multiple_users_with_the_same_device_token_hash.toml @@ -2,7 +2,7 @@ creation_date = "2024/06/17" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -26,21 +26,21 @@ note = """## Triage and analysis This rule detects when a high number of Okta user authentication events are reported for multiple users in a short time frame. Adversaries may attempt to launch a credential stuffing attack from the same device by using a list of known usernames and passwords to gain unauthorized access to user accounts. Note that Okta does not log unrecognized usernames supplied during authentication attempts, so this rule may not detect all credential stuffing attempts or may indicate a targeted attack. #### Possible investigation steps: -- Since this is an ESQL rule, the `okta.actor.alternate_id` and `okta.debug_context.debug_data.dt_hash` values can be used to pivot into the raw authentication events related to this activity. -- Identify the users involved in this action by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. -- Determine the device client used for these actions by analyzing `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Since this is an ESQL rule, the `user.name` and `okta.debug_context.debug_data.dt_hash` values can be used to pivot into the raw authentication events related to this activity. +- Identify the users involved in this action by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. +- Determine the device client used for these actions by analyzing `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - Review the `okta.security_context.is_proxy` field to determine if the device is a proxy. - If the device is a proxy, this may indicate that a user is using a proxy to access multiple accounts for password spraying. -- With the list of `okta.actor.alternate_id` values, review `event.outcome` results to determine if the authentication was successful. +- With the list of `user.name` values, review `event.outcome` results to determine if the authentication was successful. - If the authentication was successful for any user, pivoting to `event.action` values for those users may provide additional context. - With Okta end users identified, review the `okta.debug_context.debug_data.dt_hash` field. - Historical analysis should indicate if this device token hash is commonly associated with the user. -- Review the `okta.event_type` field to determine the type of authentication event that occurred. +- Review the `event.action` field to determine the type of authentication event that occurred. - If the event type is `user.authentication.sso`, the user may have legitimately started a session via a proxy for security or privacy reasons. - If the event type is `user.authentication.password`, the user may be using a proxy to access multiple accounts for password spraying. -- Examine the `okta.outcome.result` field to determine if the authentication was successful. +- Examine the `event.outcome` field to determine if the authentication was successful. - Review the past activities of the actor(s) involved in this action by checking their previous actions. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. - This may help determine the authentication and authorization actions that occurred between the user, Okta and application. ### False positive analysis: @@ -92,18 +92,18 @@ from logs-okta* data_stream.dataset == "okta.system" and (event.action like "user.authentication.*" or event.action == "user.session.start") and okta.debug_context.debug_data.dt_hash != "-" and - okta.outcome.reason == "INVALID_CREDENTIALS" + event.reason == "INVALID_CREDENTIALS" | keep event.action, okta.debug_context.debug_data.dt_hash, - okta.actor.id, - okta.actor.alternate_id, - okta.outcome.reason + client.user.id, + user.name, + event.reason | stats - Esql.okta_actor_id_count_distinct = count_distinct(okta.actor.id) + Esql.okta_actor_id_count_distinct = count_distinct(client.user.id) by okta.debug_context.debug_data.dt_hash, - okta.actor.alternate_id + user.name | where Esql.okta_actor_id_count_distinct > 20 | sort diff --git a/rules/integrations/okta/credential_access_okta_brute_force_device_token_rotation.toml b/rules/integrations/okta/credential_access_okta_brute_force_device_token_rotation.toml index 6f34edb331a..7785232272f 100644 --- a/rules/integrations/okta/credential_access_okta_brute_force_device_token_rotation.toml +++ b/rules/integrations/okta/credential_access_okta_brute_force_device_token_rotation.toml @@ -2,7 +2,7 @@ creation_date = "2024/06/17" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,8 +74,8 @@ FROM logs-okta.system-* METADATA _id, _version, _index | WHERE data_stream.dataset == "okta.system" AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start") - AND okta.outcome.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") - AND okta.actor.alternate_id IS NOT NULL + AND event.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") + AND user.name IS NOT NULL // Primary authn endpoint; sessions API provides additional coverage AND ( okta.debug_context.debug_data.request_uri == "/api/v1/authn" @@ -88,12 +88,12 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.unique_dt_hashes = COUNT_DISTINCT(okta.debug_context.debug_data.dt_hash), Esql.total_attempts = COUNT(*), Esql.attempts_with_dt = SUM(has_dt_hash), - Esql.unique_user_agents = COUNT_DISTINCT(okta.client.user_agent.raw_user_agent), + Esql.unique_user_agents = COUNT_DISTINCT(user_agent.original), Esql.first_seen = MIN(@timestamp), Esql.last_seen = MAX(@timestamp), Esql.dt_hash_values = VALUES(okta.debug_context.debug_data.dt_hash), Esql.event_action_values = VALUES(event.action), - Esql.user_agent_values = VALUES(okta.client.user_agent.raw_user_agent), + Esql.user_agent_values = VALUES(user_agent.original), Esql.device_values = VALUES(okta.client.device), Esql.is_proxy_values = VALUES(okta.security_context.is_proxy), Esql.geo_country_values = VALUES(client.geo.country_name), @@ -103,7 +103,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.threat_suspected_values = VALUES(okta.debug_context.debug_data.threat_suspected), Esql.risk_level_values = VALUES(okta.debug_context.debug_data.risk_level), Esql.risk_reasons_values = VALUES(okta.debug_context.debug_data.risk_reasons) - BY okta.client.ip, okta.actor.alternate_id + BY source.ip, user.name // Calculate automation detection metrics (float-safe division) | EVAL Esql.dt_coverage = Esql.attempts_with_dt * 1.0 / Esql.total_attempts, Esql.dt_per_attempt = Esql.unique_dt_hashes * 1.0 / Esql.total_attempts @@ -116,7 +116,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index OR (Esql.total_attempts >= 12 AND Esql.dt_coverage < 0.15) OR (Esql.total_attempts >= 10 AND Esql.unique_user_agents >= 5) | SORT Esql.total_attempts DESC -| KEEP Esql.*, okta.client.ip, okta.actor.alternate_id +| KEEP Esql.*, source.ip, user.name ''' diff --git a/rules/integrations/okta/credential_access_okta_brute_force_multi_source.toml b/rules/integrations/okta/credential_access_okta_brute_force_multi_source.toml index 3633461fbfb..8d6fbc5d9be 100644 --- a/rules/integrations/okta/credential_access_okta_brute_force_multi_source.toml +++ b/rules/integrations/okta/credential_access_okta_brute_force_multi_source.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/19" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -72,30 +72,30 @@ query = ''' FROM logs-okta.system-* METADATA _id, _version, _index | WHERE data_stream.dataset == "okta.system" AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start") - AND okta.outcome.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") - AND okta.actor.alternate_id IS NOT NULL + AND event.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") + AND user.name IS NOT NULL // Create source mapping for analyst context | EVAL Esql.source_info = CONCAT( - "{\"ip\":\"", COALESCE(okta.client.ip::STRING, "unknown"), + "{\"ip\":\"", COALESCE(source.ip::STRING, "unknown"), "\",\"country\":\"", COALESCE(client.geo.country_name, "unknown"), "\",\"asn\":\"", COALESCE(source.as.organization.name, "unknown"), - "\",\"user_agent\":\"", COALESCE(okta.client.user_agent.raw_user_agent, "unknown"), "\"}" + "\",\"user_agent\":\"", COALESCE(user_agent.original, "unknown"), "\"}" ) | STATS - Esql.unique_source_ips = COUNT_DISTINCT(okta.client.ip), + Esql.unique_source_ips = COUNT_DISTINCT(source.ip), Esql.total_attempts = COUNT(*), - Esql.unique_user_agents = COUNT_DISTINCT(okta.client.user_agent.raw_user_agent), + Esql.unique_user_agents = COUNT_DISTINCT(user_agent.original), Esql.unique_dt_hashes = COUNT_DISTINCT(okta.debug_context.debug_data.dt_hash), Esql.unique_asns = COUNT_DISTINCT(source.as.number), Esql.unique_countries = COUNT_DISTINCT(client.geo.country_name), Esql.first_seen = MIN(@timestamp), Esql.last_seen = MAX(@timestamp), - Esql.source_ip_values = VALUES(okta.client.ip), + Esql.source_ip_values = VALUES(source.ip), Esql.source_mapping = VALUES(Esql.source_info), Esql.event_action_values = VALUES(event.action), - Esql.user_agent_values = VALUES(okta.client.user_agent.raw_user_agent), + Esql.user_agent_values = VALUES(user_agent.original), Esql.device_values = VALUES(okta.client.device), Esql.is_proxy_values = VALUES(okta.security_context.is_proxy), Esql.geo_country_values = VALUES(client.geo.country_name), @@ -105,7 +105,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.threat_suspected_values = VALUES(okta.debug_context.debug_data.threat_suspected), Esql.risk_level_values = VALUES(okta.debug_context.debug_data.risk_level), Esql.risk_reasons_values = VALUES(okta.debug_context.debug_data.risk_reasons) - BY okta.actor.alternate_id + BY user.name | EVAL Esql.attempts_per_ip = Esql.total_attempts * 1.0 / Esql.unique_source_ips, @@ -122,7 +122,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index ) | SORT Esql.unique_source_ips DESC -| KEEP Esql.*, okta.actor.alternate_id +| KEEP Esql.*, user.name ''' diff --git a/rules/integrations/okta/credential_access_okta_credential_stuffing_single_source.toml b/rules/integrations/okta/credential_access_okta_credential_stuffing_single_source.toml index 8995d85e522..5954bc8422a 100644 --- a/rules/integrations/okta/credential_access_okta_credential_stuffing_single_source.toml +++ b/rules/integrations/okta/credential_access_okta_credential_stuffing_single_source.toml @@ -2,7 +2,7 @@ creation_date = "2024/06/17" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -75,13 +75,13 @@ FROM logs-okta.system-* METADATA _id, _version, _index | WHERE data_stream.dataset == "okta.system" AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start") - AND okta.outcome.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") - AND okta.actor.alternate_id IS NOT NULL + AND event.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") + AND user.name IS NOT NULL // Build user-source context as JSON for enrichment | EVAL Esql.user_source_info = CONCAT( - "{\"user\":\"", okta.actor.alternate_id, - "\",\"ip\":\"", COALESCE(okta.client.ip::STRING, "unknown"), - "\",\"user_agent\":\"", COALESCE(okta.client.user_agent.raw_user_agent, "unknown"), "\"}" + "{\"user\":\"", user.name, + "\",\"ip\":\"", COALESCE(source.ip::STRING, "unknown"), + "\",\"user_agent\":\"", COALESCE(user_agent.original, "unknown"), "\"}" ) // FIRST STATS: Aggregate by (IP, user) to get per-user attempt counts // This prevents skew from outlier users with many attempts @@ -89,7 +89,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.user_attempts = COUNT(*), Esql.user_dt_hashes = COUNT_DISTINCT(okta.debug_context.debug_data.dt_hash), Esql.user_source_info = VALUES(Esql.user_source_info), - Esql.user_agents_per_user = VALUES(okta.client.user_agent.raw_user_agent), + Esql.user_agents_per_user = VALUES(user_agent.original), Esql.devices_per_user = VALUES(okta.client.device), Esql.is_proxy = VALUES(okta.security_context.is_proxy), Esql.geo_country = VALUES(client.geo.country_name), @@ -102,7 +102,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.event_actions = VALUES(event.action), Esql.first_seen_user = MIN(@timestamp), Esql.last_seen_user = MAX(@timestamp) - BY okta.client.ip, okta.actor.alternate_id + BY source.ip, user.name // SECOND STATS: Aggregate by IP to detect credential stuffing pattern // Now we can accurately measure the distribution of attempts across users | STATS @@ -115,7 +115,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.users_with_few_attempts = SUM(CASE(Esql.user_attempts <= 2, 1, 0)), Esql.first_seen = MIN(Esql.first_seen_user), Esql.last_seen = MAX(Esql.last_seen_user), - Esql.target_users = VALUES(okta.actor.alternate_id), + Esql.target_users = VALUES(user.name), Esql.user_source_mapping = VALUES(Esql.user_source_info), Esql.event_action_values = VALUES(Esql.event_actions), Esql.user_agent_values = VALUES(Esql.user_agents_per_user), @@ -128,7 +128,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.threat_suspected_values = VALUES(Esql.threat_suspected), Esql.risk_level_values = VALUES(Esql.risk_level), Esql.risk_reasons_values = VALUES(Esql.risk_reasons) - BY okta.client.ip + BY source.ip // Calculate stuffing signature: most users should have very few attempts | EVAL Esql.pct_users_few_attempts = Esql.users_with_few_attempts * 100.0 / Esql.unique_users // Credential stuffing: many users, most with 1-2 attempts each, low max per user @@ -139,7 +139,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index AND Esql.max_attempts_per_user <= 2 AND Esql.pct_users_few_attempts >= 80.0 | SORT Esql.unique_users DESC -| KEEP Esql.*, okta.client.ip +| KEEP Esql.*, source.ip ''' diff --git a/rules/integrations/okta/credential_access_okta_mfa_bombing_via_push_notifications.toml b/rules/integrations/okta/credential_access_okta_mfa_bombing_via_push_notifications.toml index 89e31417873..a9460bc2930 100644 --- a/rules/integrations/okta/credential_access_okta_mfa_bombing_via_push_notifications.toml +++ b/rules/integrations/okta/credential_access_okta_mfa_bombing_via_push_notifications.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/18" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -72,28 +72,28 @@ tags = [ type = "eql" query = ''' -sequence by okta.actor.id with maxspan=10m +sequence by client.user.id with maxspan=10m [ any where data_stream.dataset == "okta.system" and ( - okta.event_type == "user.mfa.okta_verify.deny_push" + event.action == "user.mfa.okta_verify.deny_push" or ( - okta.event_type == "user.authentication.auth_via_mfa" + event.action == "user.authentication.auth_via_mfa" and okta.debug_context.debug_data.factor == "OKTA_VERIFY_PUSH" - and okta.outcome.reason == "INVALID_CREDENTIALS" + and event.reason == "INVALID_CREDENTIALS" ) ) ] with runs=5 until [ any where data_stream.dataset == "okta.system" - and okta.event_type in ( + and event.action in ( "user.authentication.sso", "user.authentication.auth_via_mfa", "user.authentication.verify", "user.session.start" ) - and okta.outcome.result == "SUCCESS" + and event.outcome == "SUCCESS" ] ''' diff --git a/rules/integrations/okta/credential_access_okta_password_spray_multi_source.toml b/rules/integrations/okta/credential_access_okta_password_spray_multi_source.toml index 73880429ec2..6e3fc845e02 100644 --- a/rules/integrations/okta/credential_access_okta_password_spray_multi_source.toml +++ b/rules/integrations/okta/credential_access_okta_password_spray_multi_source.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/19" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,33 +74,33 @@ FROM logs-okta.system-* METADATA _id, _version, _index | WHERE data_stream.dataset == "okta.system" AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start") - AND okta.outcome.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") - AND okta.actor.alternate_id IS NOT NULL + AND event.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") + AND user.name IS NOT NULL // Bucket into 15-minute windows and create user-source mapping for context | EVAL Esql.time_bucket = DATE_TRUNC(15 minutes, @timestamp), Esql.user_source_info = CONCAT( - "{\"user\":\"", okta.actor.alternate_id, - "\",\"ip\":\"", COALESCE(okta.client.ip::STRING, "unknown"), - "\",\"user_agent\":\"", COALESCE(okta.client.user_agent.raw_user_agent, "unknown"), "\"}" + "{\"user\":\"", user.name, + "\",\"ip\":\"", COALESCE(source.ip::STRING, "unknown"), + "\",\"user_agent\":\"", COALESCE(user_agent.original, "unknown"), "\"}" ) // Aggregate across entire tenant per time bucket to detect distributed spray | STATS - Esql.unique_users = COUNT_DISTINCT(okta.actor.alternate_id), - Esql.unique_source_ips = COUNT_DISTINCT(okta.client.ip), + Esql.unique_users = COUNT_DISTINCT(user.name), + Esql.unique_source_ips = COUNT_DISTINCT(source.ip), Esql.total_attempts = COUNT(*), - Esql.unique_user_agents = COUNT_DISTINCT(okta.client.user_agent.raw_user_agent), + Esql.unique_user_agents = COUNT_DISTINCT(user_agent.original), Esql.unique_asns = COUNT_DISTINCT(source.as.number), Esql.unique_countries = COUNT_DISTINCT(client.geo.country_name), Esql.first_seen = MIN(@timestamp), Esql.last_seen = MAX(@timestamp), - Esql.target_users = VALUES(okta.actor.alternate_id), - Esql.source_ip_values = VALUES(okta.client.ip), + Esql.target_users = VALUES(user.name), + Esql.source_ip_values = VALUES(source.ip), Esql.user_source_mapping = VALUES(Esql.user_source_info), Esql.event_action_values = VALUES(event.action), - Esql.user_agent_values = VALUES(okta.client.user_agent.raw_user_agent), + Esql.user_agent_values = VALUES(user_agent.original), Esql.device_values = VALUES(okta.client.device), Esql.is_proxy_values = VALUES(okta.security_context.is_proxy), Esql.geo_country_values = VALUES(client.geo.country_name), diff --git a/rules/integrations/okta/credential_access_okta_password_spray_single_source.toml b/rules/integrations/okta/credential_access_okta_password_spray_single_source.toml index e5bf7837ebd..c5cd5225627 100644 --- a/rules/integrations/okta/credential_access_okta_password_spray_single_source.toml +++ b/rules/integrations/okta/credential_access_okta_password_spray_single_source.toml @@ -2,7 +2,7 @@ creation_date = "2020/07/16" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -73,20 +73,20 @@ FROM logs-okta.system-* METADATA _id, _version, _index | WHERE data_stream.dataset == "okta.system" AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start") - AND okta.outcome.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") - AND okta.actor.alternate_id IS NOT NULL + AND event.reason IN ("INVALID_CREDENTIALS", "LOCKED_OUT") + AND user.name IS NOT NULL // Build user-source context as JSON for enrichment | EVAL Esql.user_source_info = CONCAT( - "{\"user\":\"", okta.actor.alternate_id, - "\",\"ip\":\"", COALESCE(okta.client.ip::STRING, "unknown"), - "\",\"user_agent\":\"", COALESCE(okta.client.user_agent.raw_user_agent, "unknown"), "\"}" + "{\"user\":\"", user.name, + "\",\"ip\":\"", COALESCE(source.ip::STRING, "unknown"), + "\",\"user_agent\":\"", COALESCE(user_agent.original, "unknown"), "\"}" ) // FIRST STATS: Aggregate by (IP, user) to get per-user attempt counts // This prevents skew from outlier users with many attempts | STATS Esql.user_attempts = COUNT(*), Esql.user_source_info = VALUES(Esql.user_source_info), - Esql.user_agents_per_user = VALUES(okta.client.user_agent.raw_user_agent), + Esql.user_agents_per_user = VALUES(user_agent.original), Esql.devices_per_user = VALUES(okta.client.device), Esql.is_proxy = VALUES(okta.security_context.is_proxy), Esql.geo_country = VALUES(client.geo.country_name), @@ -98,7 +98,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.event_actions = VALUES(event.action), Esql.first_seen_user = MIN(@timestamp), Esql.last_seen_user = MAX(@timestamp) - BY okta.client.ip, okta.actor.alternate_id + BY source.ip, user.name // SECOND STATS: Aggregate by IP to detect password spray pattern // Now we can accurately measure the distribution of attempts across users | STATS @@ -113,7 +113,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.users_with_single_attempt = SUM(CASE(Esql.user_attempts == 1, 1, 0)), Esql.first_seen = MIN(Esql.first_seen_user), Esql.last_seen = MAX(Esql.last_seen_user), - Esql.target_users = VALUES(okta.actor.alternate_id), + Esql.target_users = VALUES(user.name), Esql.user_source_mapping = VALUES(Esql.user_source_info), Esql.event_action_values = VALUES(Esql.event_actions), Esql.user_agent_values = VALUES(Esql.user_agents_per_user), @@ -125,7 +125,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index Esql.source_asn_org_values = VALUES(Esql.asn_org), Esql.threat_suspected_values = VALUES(Esql.threat_suspected), Esql.risk_level_values = VALUES(Esql.risk_level) - BY okta.client.ip + BY source.ip // Calculate spray signature metrics | EVAL // Percentage of users in the spray band (2-6 attempts) @@ -147,7 +147,7 @@ FROM logs-okta.system-* METADATA _id, _version, _index AND Esql.pct_users_in_spray_band >= 60.0 AND Esql.attack_duration_minutes >= 5 | SORT Esql.total_attempts DESC -| KEEP Esql.*, okta.client.ip +| KEEP Esql.*, source.ip ''' diff --git a/rules/integrations/okta/credential_access_okta_potentially_successful_okta_bombing_via_push_notifications.toml b/rules/integrations/okta/credential_access_okta_potentially_successful_okta_bombing_via_push_notifications.toml index 60b9cae2db1..27c8edcf11e 100644 --- a/rules/integrations/okta/credential_access_okta_potentially_successful_okta_bombing_via_push_notifications.toml +++ b/rules/integrations/okta/credential_access_okta_potentially_successful_okta_bombing_via_push_notifications.toml @@ -2,7 +2,7 @@ creation_date = "2022/01/05" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -75,27 +75,27 @@ tags = [ type = "eql" query = ''' -sequence by okta.actor.id with maxspan=10m +sequence by client.user.id with maxspan=10m [ any where data_stream.dataset == "okta.system" and ( - okta.event_type == "user.mfa.okta_verify.deny_push" + event.action == "user.mfa.okta_verify.deny_push" or ( - okta.event_type == "user.authentication.auth_via_mfa" + event.action == "user.authentication.auth_via_mfa" and okta.debug_context.debug_data.factor == "OKTA_VERIFY_PUSH" - and okta.outcome.reason == "INVALID_CREDENTIALS" + and event.reason == "INVALID_CREDENTIALS" ) ) ] with runs=5 [ any where data_stream.dataset == "okta.system" - and okta.event_type in ( + and event.action in ( "user.authentication.sso", "user.authentication.auth_via_mfa", "user.authentication.verify", "user.session.start" ) - and okta.outcome.result == "SUCCESS" + and event.outcome == "SUCCESS" ] ''' diff --git a/rules/integrations/okta/credential_access_okta_successful_login_after_credential_attack.toml b/rules/integrations/okta/credential_access_okta_successful_login_after_credential_attack.toml index a150f462178..332e883c116 100644 --- a/rules/integrations/okta/credential_access_okta_successful_login_after_credential_attack.toml +++ b/rules/integrations/okta/credential_access_okta_successful_login_after_credential_attack.toml @@ -2,7 +2,7 @@ creation_date = "2026/02/12" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -102,13 +102,13 @@ FROM .alerts-security.*, logs-okta.system-* METADATA _id, _version, _index // Successful Okta authentication events data_stream.dataset == "okta.system" AND (event.action LIKE "user.authentication.*" OR event.action == "user.session.start") - AND okta.outcome.result == "SUCCESS" - AND okta.actor.alternate_id IS NOT NULL + AND event.outcome == "SUCCESS" + AND user.name IS NOT NULL ) // correlation - alerts may store user/IP in different fields than raw logs | EVAL - Esql.user = COALESCE(okta.actor.alternate_id, user.name, user.email), - Esql.source_ip = COALESCE(okta.client.ip, client.ip, source.ip) + Esql.user = COALESCE(user.name, user.name, user.email), + Esql.source_ip = COALESCE(source.ip, client.ip, source.ip) // Must have user identity to correlate | WHERE Esql.user IS NOT NULL // Classify events and capture timestamps/IPs by event type @@ -124,7 +124,7 @@ FROM .alerts-security.*, logs-okta.system-* METADATA _id, _version, _index ), Esql.is_success_login = CASE( data_stream.dataset == "okta.system" - AND okta.outcome.result == "SUCCESS", 1, 0 + AND event.outcome == "SUCCESS", 1, 0 ), Esql.attack_ip = CASE( kibana.alert.rule.rule_id IN ( @@ -137,7 +137,7 @@ FROM .alerts-security.*, logs-okta.system-* METADATA _id, _version, _index ), Esql.login_ip = CASE( data_stream.dataset == "okta.system" - AND okta.outcome.result == "SUCCESS", Esql.source_ip, null + AND event.outcome == "SUCCESS", Esql.source_ip, null ), Esql.attack_ts = CASE( kibana.alert.rule.rule_id IN ( @@ -150,7 +150,7 @@ FROM .alerts-security.*, logs-okta.system-* METADATA _id, _version, _index ), Esql.login_ts = CASE( data_stream.dataset == "okta.system" - AND okta.outcome.result == "SUCCESS", @timestamp, null + AND event.outcome == "SUCCESS", @timestamp, null ) // Aggregate by user (catches IP rotation: spray from IP A, login from IP B) | STATS @@ -170,7 +170,7 @@ FROM .alerts-security.*, logs-okta.system-* METADATA _id, _version, _index Esql.geo_city_values = VALUES(client.geo.city_name), Esql.source_asn_values = VALUES(source.as.number), Esql.source_asn_org_values = VALUES(source.as.organization.name), - Esql.user_agent_values = VALUES(okta.client.user_agent.raw_user_agent), + Esql.user_agent_values = VALUES(user_agent.original), Esql.device_values = VALUES(okta.client.device), Esql.is_proxy_values = VALUES(okta.security_context.is_proxy) BY Esql.user diff --git a/rules/integrations/okta/credential_access_user_impersonation_access.toml b/rules/integrations/okta/credential_access_user_impersonation_access.toml index 500b6a4def9..94e1ab8c619 100644 --- a/rules/integrations/okta/credential_access_user_impersonation_access.toml +++ b/rules/integrations/okta/credential_access_user_impersonation_access.toml @@ -2,7 +2,7 @@ creation_date = "2022/03/22" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -25,7 +25,7 @@ The detection of an Okta User Session Impersonation indicates that a user has in #### Possible investigation steps -- Identify the actor associated with the impersonation event by checking the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields. +- Identify the actor associated with the impersonation event by checking the `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields. - Review the `event.action` field to confirm the initiation of the impersonation event. - Check the `event.time` field to understand the timing of the event. - Check the `okta.target.id`, `okta.target.type`, `okta.target.alternate_id`, or `okta.target.display_name` to identify the user who was impersonated. @@ -34,7 +34,7 @@ The detection of an Okta User Session Impersonation indicates that a user has in ### False positive analysis - Verify if the session impersonation was part of an approved activity. Check if it was associated with any documented administrative tasks or troubleshooting efforts. -- Ensure that the impersonation session was initiated by an authorized individual. You can check this by verifying the `okta.actor.id` or `okta.actor.display_name` against the list of approved administrators. +- Ensure that the impersonation session was initiated by an authorized individual. You can check this by verifying the `client.user.id` or `user.full_name` against the list of approved administrators. ### Response and remediation diff --git a/rules/integrations/okta/defense_evasion_attempt_to_deactivate_okta_network_zone.toml b/rules/integrations/okta/defense_evasion_attempt_to_deactivate_okta_network_zone.toml index 40f723c7861..9eb86ac3a5e 100644 --- a/rules/integrations/okta/defense_evasion_attempt_to_deactivate_okta_network_zone.toml +++ b/rules/integrations/okta/defense_evasion_attempt_to_deactivate_okta_network_zone.toml @@ -2,7 +2,7 @@ creation_date = "2020/11/06" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ The Okta network zones can be configured to restrict or limit access to a networ #### Possible investigation steps -- Identify the actor related to the alert by reviewing the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields. +- Identify the actor related to the alert by reviewing the `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields. - Examine the `event.action` field to confirm the deactivation of a network zone. - Check the `okta.target.id`, `okta.target.type`, `okta.target.alternate_id`, or `okta.target.display_name` to identify the network zone that was deactivated. - Investigate the `event.time` field to understand when the event happened. @@ -37,7 +37,7 @@ The Okta network zones can be configured to restrict or limit access to a networ ### False positive analysis -- Check the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. If these match the actor's normal behavior, it might be a false positive. +- Check the `user_agent.original` field to understand the device and software used by the actor. If these match the actor's normal behavior, it might be a false positive. - Check if the actor is a known administrator or part of the IT team who might have a legitimate reason to deactivate a network zone. - Verify the actor's actions with any known planned changes or maintenance activities. diff --git a/rules/integrations/okta/defense_evasion_attempt_to_delete_okta_network_zone.toml b/rules/integrations/okta/defense_evasion_attempt_to_delete_okta_network_zone.toml index 8bcddf85d1e..5b32943a8b0 100644 --- a/rules/integrations/okta/defense_evasion_attempt_to_delete_okta_network_zone.toml +++ b/rules/integrations/okta/defense_evasion_attempt_to_delete_okta_network_zone.toml @@ -2,7 +2,7 @@ creation_date = "2020/11/06" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ Okta network zones can be configured to limit or restrict access to a network ba #### Possible investigation steps: -- Identify the actor associated with the alert by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields. +- Identify the actor associated with the alert by examining the `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields. - Examine the `event.action` field to confirm the deletion of a network zone. - Investigate the `okta.target.id`, `okta.target.type`, `okta.target.alternate_id`, or `okta.target.display_name` fields to identify the network zone that was deleted. - Review the `event.time` field to understand when the event happened. @@ -37,7 +37,7 @@ Okta network zones can be configured to limit or restrict access to a network ba ### False positive analysis: -- Verify the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. If these match the actor's typical behavior, it might be a false positive. +- Verify the `user_agent.original` field to understand the device and software used by the actor. If these match the actor's typical behavior, it might be a false positive. - Check if the actor is a known administrator or a member of the IT team who might have a legitimate reason to delete a network zone. - Cross-verify the actor's actions with any known planned changes or maintenance activities. diff --git a/rules/integrations/okta/defense_evasion_first_occurence_public_app_client_credential_token_exchange.toml b/rules/integrations/okta/defense_evasion_first_occurence_public_app_client_credential_token_exchange.toml index f76d4706c03..9c7254fe3ba 100644 --- a/rules/integrations/okta/defense_evasion_first_occurence_public_app_client_credential_token_exchange.toml +++ b/rules/integrations/okta/defense_evasion_first_occurence_public_app_client_credential_token_exchange.toml @@ -2,7 +2,7 @@ creation_date = "2024/09/11" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -12,7 +12,7 @@ generated when a public client app attempts to exchange a client credentials gra the request is denied due to the lack of required scopes. This could indicate compromised client credentials in which an adversary is attempting to obtain an access token for unauthorized scopes. This is a [New Terms](https://www.elastic.co/guide/en/security/current/rules-ui-create.html#create-new-terms-rule) rule where the -`okta.actor.display_name` field value has not been seen in the last 14 days regarding this event. +`user.full_name` field value has not been seen in the last 14 days regarding this event. """ from = "now-9m" index = ["filebeat-*", "logs-okta*"] @@ -30,18 +30,18 @@ OAuth 2.0 is a protocol for authorization, allowing apps to access resources on ### Possible investigation steps -- Review the `okta.actor.display_name` field to identify the public client app involved in the failed token grant attempt and determine if it is a known or expected application. +- Review the `user.full_name` field to identify the public client app involved in the failed token grant attempt and determine if it is a known or expected application. - Examine the `okta.debug_context.debug_data.flattened.requestedScopes` field to understand which unauthorized scopes were requested and assess their potential impact if accessed. - Investigate the `okta.actor.type` field to confirm that the actor is indeed a public client app, which lacks secure storage, and evaluate the risk of compromised credentials. -- Check the `okta.outcome.reason` field for "no_matching_scope" to verify that the failure was due to a scope mismatch, indicating an attempt to access unauthorized resources. -- Analyze the `okta.client.user_agent.raw_user_agent` field to ensure the request did not originate from known Okta integrations, which are excluded from the rule, to rule out false positives. +- Check the `event.reason` field for "no_matching_scope" to verify that the failure was due to a scope mismatch, indicating an attempt to access unauthorized resources. +- Analyze the `user_agent.original` field to ensure the request did not originate from known Okta integrations, which are excluded from the rule, to rule out false positives. - Correlate the event with other security logs or alerts to identify any patterns or additional suspicious activities related to the same client credentials or IP address. ### False positive analysis -- Frequent legitimate access attempts by known public client apps may trigger false positives. To manage this, consider creating exceptions for specific `okta.actor.display_name` values that are known to frequently request scopes without malicious intent. -- Automated processes or integrations that use client credentials might occasionally request scopes not typically associated with their function. Review these processes and, if deemed non-threatening, exclude their `okta.client.user_agent.raw_user_agent` from triggering the rule. -- Development or testing environments often simulate various OAuth 2.0 token grant scenarios, which can result in false positives. Identify and exclude these environments by their `okta.actor.display_name` or other distinguishing attributes. +- Frequent legitimate access attempts by known public client apps may trigger false positives. To manage this, consider creating exceptions for specific `user.full_name` values that are known to frequently request scopes without malicious intent. +- Automated processes or integrations that use client credentials might occasionally request scopes not typically associated with their function. Review these processes and, if deemed non-threatening, exclude their `user_agent.original` from triggering the rule. +- Development or testing environments often simulate various OAuth 2.0 token grant scenarios, which can result in false positives. Identify and exclude these environments by their `user.full_name` or other distinguishing attributes. - Regularly review and update the list of non-threatening scopes in `okta.debug_context.debug_data.flattened.requestedScopes` to ensure that legitimate scope requests are not flagged as unauthorized. ### Response and remediation @@ -78,11 +78,11 @@ data_stream.dataset: okta.system and event.action: "app.oauth2.as.token.grant" and okta.actor.type: "PublicClientApp" and okta.debug_context.debug_data.flattened.grantType: "client_credentials" - and okta.outcome.result: "FAILURE" - and not okta.client.user_agent.raw_user_agent: "Okta-Integrations" - and not okta.actor.display_name: (Okta* or Datadog) + and event.outcome: "failure" + and not user_agent.original: "Okta-Integrations" + and not user.full_name: (Okta* or Datadog) and not okta.debug_context.debug_data.flattened.requestedScopes: ("okta.logs.read" or "okta.eventHooks.read" or "okta.inlineHooks.read") - and okta.outcome.reason: "no_matching_scope" + and event.reason: "no_matching_scope" ''' @@ -115,7 +115,7 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["okta.actor.display_name"] +value = ["user.full_name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-14d" diff --git a/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy.toml b/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy.toml index 2254ada1c60..5a0f023ac67 100644 --- a/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy.toml +++ b/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/21" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -31,11 +31,11 @@ This rule is designed to detect attempts to deactivate an Okta policy, which cou #### Possible investigation steps: -- Identify the actor related to the alert by reviewing `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields in the alert. -- Review the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. -- Examine the `okta.outcome.reason` field for additional context around the deactivation attempt. -- Check the `okta.outcome.result` field to confirm the policy deactivation attempt. -- Check if there are multiple policy deactivation attempts from the same actor or IP address (`okta.client.ip`). +- Identify the actor related to the alert by reviewing `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields in the alert. +- Review the `user_agent.original` field to understand the device and software used by the actor. +- Examine the `event.reason` field for additional context around the deactivation attempt. +- Check the `event.outcome` field to confirm the policy deactivation attempt. +- Check if there are multiple policy deactivation attempts from the same actor or IP address (`source.ip`). - Check for successful logins immediately following the policy deactivation attempt. - Verify whether the actor's activity aligns with typical behavior or if any unusual activity took place around the time of the deactivation attempt. diff --git a/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy_rule.toml b/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy_rule.toml index 665dcdaf66f..a0f4478a3dd 100644 --- a/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy_rule.toml +++ b/rules/integrations/okta/defense_evasion_okta_attempt_to_deactivate_okta_policy_rule.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/21" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,11 +30,11 @@ This rule detects attempts to deactivate a rule within an Okta policy, which cou #### Possible investigation steps: -- Identify the actor related to the alert by reviewing `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields in the alert. -- Review the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. -- Examine the `okta.outcome.reason` field for additional context around the deactivation attempt. -- Check the `okta.outcome.result` field to confirm the policy rule deactivation attempt. -- Check if there are multiple policy rule deactivation attempts from the same actor or IP address (`okta.client.ip`). +- Identify the actor related to the alert by reviewing `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields in the alert. +- Review the `user_agent.original` field to understand the device and software used by the actor. +- Examine the `event.reason` field for additional context around the deactivation attempt. +- Check the `event.outcome` field to confirm the policy rule deactivation attempt. +- Check if there are multiple policy rule deactivation attempts from the same actor or IP address (`source.ip`). - Check for successful logins immediately following the policy rule deactivation attempt. - Verify whether the actor's activity aligns with typical behavior or if any unusual activity took place around the time of the deactivation attempt. diff --git a/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy.toml b/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy.toml index 7cfd831ebf8..9156cc66e1d 100644 --- a/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy.toml +++ b/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/28" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -31,11 +31,11 @@ This rule detects attempts to delete an Okta policy, which could be indicative o #### Possible investigation steps: -- Identify the actor related to the alert by reviewing `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields in the alert. -- Review the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. -- Examine the `okta.outcome.reason` field for additional context around the deletion attempt. -- Check the `okta.outcome.result` field to confirm the policy deletion attempt. -- Check if there are multiple policy deletion attempts from the same actor or IP address (`okta.client.ip`). +- Identify the actor related to the alert by reviewing `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields in the alert. +- Review the `user_agent.original` field to understand the device and software used by the actor. +- Examine the `event.reason` field for additional context around the deletion attempt. +- Check the `event.outcome` field to confirm the policy deletion attempt. +- Check if there are multiple policy deletion attempts from the same actor or IP address (`source.ip`). - Check for successful logins immediately following the policy deletion attempt. - Verify whether the actor's activity aligns with typical behavior or if any unusual activity took place around the time of the deletion attempt. diff --git a/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy_rule.toml b/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy_rule.toml index 1a47f8ff81c..89d36b777db 100644 --- a/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy_rule.toml +++ b/rules/integrations/okta/defense_evasion_okta_attempt_to_delete_okta_policy_rule.toml @@ -2,7 +2,7 @@ creation_date = "2020/11/06" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,11 +30,11 @@ This rule detects attempts to delete an Okta policy rule, which could indicate a #### Possible investigation steps: -- Identify the actor related to the alert by reviewing `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields in the alert. -- Review the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. -- Examine the `okta.outcome.reason` field for additional context around the deletion attempt. -- Check the `okta.outcome.result` field to confirm the policy rule deletion attempt. -- Check if there are multiple policy rule deletion attempts from the same actor or IP address (`okta.client.ip`). +- Identify the actor related to the alert by reviewing `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields in the alert. +- Review the `user_agent.original` field to understand the device and software used by the actor. +- Examine the `event.reason` field for additional context around the deletion attempt. +- Check the `event.outcome` field to confirm the policy rule deletion attempt. +- Check if there are multiple policy rule deletion attempts from the same actor or IP address (`source.ip`). - Check for successful logins immediately following the policy rule deletion attempt. - Verify whether the actor's activity aligns with typical behavior or if any unusual activity took place around the time of the deletion attempt. diff --git a/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_network_zone.toml b/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_network_zone.toml index 377888bbc4d..91233e86c77 100644 --- a/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_network_zone.toml +++ b/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_network_zone.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/21" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,11 +29,11 @@ The modification of an Okta network zone is a critical event as it could potenti #### Possible investigation steps: -- Identify the actor related to the alert by reviewing `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields in the alert. -- Review the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. -- Examine the `okta.outcome.reason` field for additional context around the modification attempt. -- Check the `okta.outcome.result` field to confirm the network zone modification attempt. -- Check if there are multiple network zone modification attempts from the same actor or IP address (`okta.client.ip`). +- Identify the actor related to the alert by reviewing `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields in the alert. +- Review the `user_agent.original` field to understand the device and software used by the actor. +- Examine the `event.reason` field for additional context around the modification attempt. +- Check the `event.outcome` field to confirm the network zone modification attempt. +- Check if there are multiple network zone modification attempts from the same actor or IP address (`source.ip`). - Check for successful logins immediately following the modification attempt. - Verify whether the actor's activity aligns with typical behavior or if any unusual activity took place around the time of the modification attempt. diff --git a/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy.toml b/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy.toml index 11747ff06ab..28fff3c3bcd 100644 --- a/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy.toml +++ b/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/21" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,10 +28,10 @@ note = """## Triage and analysis Modifications to Okta policies may indicate attempts to weaken an organization's security controls. If such an attempt is detected, consider the following steps for investigation. #### Possible investigation steps: -- Identify the actor associated with the event. Check the fields `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name`. -- Determine the client used by the actor. You can look at `okta.client.device`, `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.ip_chain.ip`, and `okta.client.geographical_context`. +- Identify the actor associated with the event. Check the fields `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name`. +- Determine the client used by the actor. You can look at `okta.client.device`, `source.ip`, `user_agent.original`, `source.ip_chain.ip`, and `okta.client.geographical_context`. - Check the nature of the policy modification. You can review the `okta.target` field, especially `okta.target.display_name` and `okta.target.id`. -- Examine the `okta.outcome.result` and `okta.outcome.reason` fields to understand the outcome of the modification attempt. +- Examine the `event.outcome` and `event.reason` fields to understand the outcome of the modification attempt. - Check if there have been other similar modification attempts in a short time span from the same actor or IP address. ### False positive analysis: diff --git a/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy_rule.toml b/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy_rule.toml index 1c442309906..4e78348d3ae 100644 --- a/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy_rule.toml +++ b/rules/integrations/okta/defense_evasion_okta_attempt_to_modify_okta_policy_rule.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/21" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,11 +28,11 @@ The modification of an Okta policy rule can be an indication of malicious activi #### Possible investigation steps: -- Identify the actor related to the alert by reviewing `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, or `okta.actor.display_name` fields in the alert. -- Review the `okta.client.user_agent.raw_user_agent` field to understand the device and software used by the actor. -- Examine the `okta.outcome.reason` field for additional context around the modification attempt. -- Check the `okta.outcome.result` field to confirm the rule modification attempt. -- Check if there are multiple rule modification attempts from the same actor or IP address (`okta.client.ip`). +- Identify the actor related to the alert by reviewing `client.user.id`, `okta.actor.type`, `user.name`, or `user.full_name` fields in the alert. +- Review the `user_agent.original` field to understand the device and software used by the actor. +- Examine the `event.reason` field for additional context around the modification attempt. +- Check the `event.outcome` field to confirm the rule modification attempt. +- Check if there are multiple rule modification attempts from the same actor or IP address (`source.ip`). - Check for successful logins immediately following the modification attempt. - Verify whether the actor's activity aligns with typical behavior or if any unusual activity took place around the time of the modification attempt. diff --git a/rules/integrations/okta/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.toml b/rules/integrations/okta/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.toml index c23e889e0d4..bd3044737b1 100644 --- a/rules/integrations/okta/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.toml +++ b/rules/integrations/okta/defense_evasion_suspicious_okta_user_password_reset_or_unlock_attempts.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/19" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic", "@BenB196", "Austin Songer"] @@ -30,9 +30,9 @@ note = """## Triage and analysis This rule is designed to detect a suspiciously high number of password reset or account unlock attempts in Okta. Excessive password resets or account unlocks can be indicative of an attacker's attempt to gain unauthorized access to an account. #### Possible investigation steps: -- Identify the actor associated with the excessive attempts. The `okta.actor.alternate_id` field can be used for this purpose. -- Determine the client used by the actor. You can look at `okta.client.device`, `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.ip_chain.ip`, and `okta.client.geographical_context`. -- Review the `okta.outcome.result` and `okta.outcome.reason` fields to understand the outcome of the password reset or unlock attempts. +- Identify the actor associated with the excessive attempts. The `user.name` field can be used for this purpose. +- Determine the client used by the actor. You can look at `okta.client.device`, `source.ip`, `user_agent.original`, `source.ip_chain.ip`, and `okta.client.geographical_context`. +- Review the `event.outcome` and `event.reason` fields to understand the outcome of the password reset or unlock attempts. - Review the event actions associated with these attempts. Look at the `event.action` field and filter for actions related to password reset and account unlock attempts. - Check for other similar patterns of behavior from the same actor or IP address. If there is a high number of failed login attempts before the password reset or unlock attempts, this may suggest a brute force attack. - Also, look at the times when these attempts were made. If these were made during off-hours, it could further suggest an adversary's activity. @@ -134,6 +134,6 @@ id = "TA0001" name = "Initial Access" reference = "https://attack.mitre.org/tactics/TA0001/" [rule.threshold] -field = ["okta.actor.alternate_id"] +field = ["user.name"] value = 5 diff --git a/rules/integrations/okta/impact_attempt_to_revoke_okta_api_token.toml b/rules/integrations/okta/impact_attempt_to_revoke_okta_api_token.toml index b3222e1595e..547203824d0 100644 --- a/rules/integrations/okta/impact_attempt_to_revoke_okta_api_token.toml +++ b/rules/integrations/okta/impact_attempt_to_revoke_okta_api_token.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/21" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,10 +27,10 @@ note = """## Triage and analysis The rule alerts when attempts are made to revoke an Okta API token. The API tokens are critical for integration services, and revoking them may lead to disruption in services. Therefore, it's important to validate these activities. #### Possible investigation steps: -- Identify the actor associated with the API token revocation attempt. You can use the `okta.actor.alternate_id` field for this purpose. -- Determine the client used by the actor. Review the `okta.client.device`, `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.ip_chain.ip`, and `okta.client.geographical_context` fields. +- Identify the actor associated with the API token revocation attempt. You can use the `user.name` field for this purpose. +- Determine the client used by the actor. Review the `okta.client.device`, `source.ip`, `user_agent.original`, `source.ip_chain.ip`, and `okta.client.geographical_context` fields. - Verify if the API token revocation was authorized or part of some planned activity. -- Check the `okta.outcome.result` and `okta.outcome.reason` fields to see if the attempt was successful or failed. +- Check the `event.outcome` and `event.reason` fields to see if the attempt was successful or failed. - Analyze the past activities of the actor involved in this action. An actor who usually performs such activities may indicate a legitimate reason. - Evaluate the actions that happened just before and after this event. It can help understand the full context of the activity. diff --git a/rules/integrations/okta/impact_okta_attempt_to_deactivate_okta_application.toml b/rules/integrations/okta/impact_okta_attempt_to_deactivate_okta_application.toml index d01c8df7816..98628a417b2 100644 --- a/rules/integrations/okta/impact_okta_attempt_to_deactivate_okta_application.toml +++ b/rules/integrations/okta/impact_okta_attempt_to_deactivate_okta_application.toml @@ -2,7 +2,7 @@ creation_date = "2020/11/06" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,22 +27,22 @@ note = """## Triage and analysis This rule detects attempts to deactivate an Okta application. Unauthorized deactivation could lead to disruption of services and pose a significant risk to the organization. #### Possible investigation steps: -- Identify the actor associated with the deactivation attempt by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. -- Determine the client used by the actor. Review the `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Identify the actor associated with the deactivation attempt by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. +- Determine the client used by the actor. Review the `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - If the client is a device, check the `okta.device.id`, `okta.device.name`, `okta.device.os_platform`, `okta.device.os_version`, and `okta.device.managed` fields. - Understand the context of the event from the `okta.debug_context.debug_data` and `okta.authentication_context` fields. -- Check the `okta.outcome.result` and `okta.outcome.reason` fields to see if the attempt was successful or failed. +- Check the `event.outcome` and `event.reason` fields to see if the attempt was successful or failed. - Review the past activities of the actor involved in this action by checking their previous actions logged in the `okta.target` field. - Analyze the `okta.transaction.id` and `okta.transaction.type` fields to understand the context of the transaction. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. ### False positive analysis: -- It might be a false positive if the action was part of a planned activity, performed by an authorized person, or if the `okta.outcome.result` field shows a failure. +- It might be a false positive if the action was part of a planned activity, performed by an authorized person, or if the `event.outcome` field shows a failure. - An unsuccessful attempt might also indicate an authorized user having trouble rather than a malicious activity. ### Response and remediation: - If unauthorized deactivation attempts are confirmed, initiate the incident response process. -- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `okta.client.ip` and `okta.device.id` fields. +- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `source.ip` and `okta.device.id` fields. - Reset the user's password and enforce MFA re-enrollment, if applicable. - Conduct a review of Okta policies and ensure they are in accordance with security best practices. - If the deactivated application was crucial for business operations, coordinate with the relevant team to reactivate it and minimize the impact. diff --git a/rules/integrations/okta/initial_access_first_occurrence_user_session_started_via_proxy.toml b/rules/integrations/okta/initial_access_first_occurrence_user_session_started_via_proxy.toml index 146e61eed23..4b63b934573 100644 --- a/rules/integrations/okta/initial_access_first_occurrence_user_session_started_via_proxy.toml +++ b/rules/integrations/okta/initial_access_first_occurrence_user_session_started_via_proxy.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/07" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -15,15 +15,15 @@ note = """## Triage and analysis ### Investigating First Occurrence of Okta User Session Started via Proxy -This rule detects the first occurrence of an Okta user session started via a proxy. This rule is designed to help identify suspicious authentication behavior that may be indicative of an attacker attempting to gain access to an Okta account while remaining anonymous. This rule leverages the New Terms rule type feature where the `okta.actor.id` value is checked against the previous 7 days of data to determine if the value has been seen before for this activity. +This rule detects the first occurrence of an Okta user session started via a proxy. This rule is designed to help identify suspicious authentication behavior that may be indicative of an attacker attempting to gain access to an Okta account while remaining anonymous. This rule leverages the New Terms rule type feature where the `client.user.id` value is checked against the previous 7 days of data to determine if the value has been seen before for this activity. #### Possible investigation steps: -- Identify the user involved in this action by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. -- Determine the client used by the actor. Review the `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Identify the user involved in this action by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. +- Determine the client used by the actor. Review the `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - Examine the `okta.debug_context.debug_data.flattened` field for more information about the proxy used. - Review the `okta.request.ip_chain` field for more information about the geographic location of the proxy. - Review the past activities of the actor involved in this action by checking their previous actions. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. ### False positive analysis: - A user may have legitimately started a session via a proxy for security or privacy reasons. @@ -62,14 +62,14 @@ type = "new_terms" query = ''' data_stream.dataset:okta.system and - okta.event_type: ( + event.action: ( user.session.start or user.authentication.verify or user.authentication.sso or user.authentication.auth_via_mfa ) and okta.security_context.is_proxy:true and - not okta.actor.id: okta* + not client.user.id: okta* ''' @@ -98,7 +98,7 @@ reference = "https://attack.mitre.org/tactics/TA0001/" [rule.new_terms] field = "new_terms_fields" -value = ["okta.actor.id", "cloud.account.id"] +value = ["client.user.id", "cloud.account.id"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/integrations/okta/initial_access_okta_fastpass_phishing.toml b/rules/integrations/okta/initial_access_okta_fastpass_phishing.toml index 4890343347d..b26747b9bdb 100644 --- a/rules/integrations/okta/initial_access_okta_fastpass_phishing.toml +++ b/rules/integrations/okta/initial_access_okta_fastpass_phishing.toml @@ -2,7 +2,7 @@ creation_date = "2023/05/07" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Austin Songer"] @@ -76,7 +76,7 @@ type = "query" query = ''' data_stream.dataset:okta.system and event.category:authentication and - okta.event_type:user.authentication.auth_via_mfa and event.outcome:failure and okta.outcome.reason:"FastPass declined phishing attempt" + event.action:user.authentication.auth_via_mfa and event.outcome:failure and event.reason:"FastPass declined phishing attempt" ''' diff --git a/rules/integrations/okta/initial_access_okta_user_sessions_started_from_different_geolocations.toml b/rules/integrations/okta/initial_access_okta_user_sessions_started_from_different_geolocations.toml index 5dbebfd5cc8..730b04a33fa 100644 --- a/rules/integrations/okta/initial_access_okta_user_sessions_started_from_different_geolocations.toml +++ b/rules/integrations/okta/initial_access_okta_user_sessions_started_from_different_geolocations.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/18" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -23,17 +23,17 @@ note = """## Triage and analysis This rule detects when a specific Okta actor has multiple sessions started from different geolocations. Adversaries may attempt to launch an attack by using a list of known usernames and passwords to gain unauthorized access to user accounts from different locations. #### Possible investigation steps: -- Since this is an ESQL rule, the `okta.actor.alternate_id` and `okta.client.id` values can be used to pivot into the raw authentication events related to this alert. -- Identify the users involved in this action by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. -- Determine the device client used for these actions by analyzing `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Since this is an ESQL rule, the `user.name` and `okta.client.id` values can be used to pivot into the raw authentication events related to this alert. +- Identify the users involved in this action by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. +- Determine the device client used for these actions by analyzing `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - With Okta end users identified, review the `okta.debug_context.debug_data.dt_hash` field. - Historical analysis should indicate if this device token hash is commonly associated with the user. -- Review the `okta.event_type` field to determine the type of authentication event that occurred. +- Review the `event.action` field to determine the type of authentication event that occurred. - If the event type is `user.authentication.sso`, the user may have legitimately started a session via a proxy for security or privacy reasons. - If the event type is `user.authentication.password`, the user may be using a proxy to access multiple accounts for password spraying. - If the event type is `user.session.start`, the source may have attempted to establish a session via the Okta authentication API. - Review the past activities of the actor(s) involved in this action by checking their previous actions. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. - This may help determine the authentication and authorization actions that occurred between the user, Okta and application. ### False positive analysis: @@ -51,7 +51,7 @@ This rule detects when a specific Okta actor has multiple sessions started from - Reset passwords and reset MFA for the user. - If this is a false positive, consider adding the `okta.debug_context.debug_data.dt_hash` field to the `exceptions` list in the rule. - This will prevent future occurrences of this event for this device from triggering the rule. - - Alternatively adding `okta.client.ip` or a CIDR range to the `exceptions` list can prevent future occurrences of this event from triggering the rule. + - Alternatively adding `source.ip` or a CIDR range to the `exceptions` list can prevent future occurrences of this event from triggering the rule. - This should be done with caution as it may prevent legitimate alerts from being generated. """ references = [ @@ -82,18 +82,18 @@ from logs-okta* data_stream.dataset == "okta.system" and (event.action like "user.authentication.*" or event.action == "user.session.start") and okta.security_context.is_proxy != true and - okta.actor.id != "unknown" and + client.user.id != "unknown" and event.outcome == "success" | keep event.action, okta.security_context.is_proxy, - okta.actor.id, - okta.actor.alternate_id, + client.user.id, + user.name, event.outcome, client.geo.country_name | stats Esql.client_geo_country_name_count_distinct = count_distinct(client.geo.country_name) - by okta.actor.id, okta.actor.alternate_id + by client.user.id, user.name | where Esql.client_geo_country_name_count_distinct >= 2 | sort diff --git a/rules/integrations/okta/initial_access_sign_in_events_via_third_party_idp.toml b/rules/integrations/okta/initial_access_sign_in_events_via_third_party_idp.toml index 0ab167873f2..70dbd9dd8ac 100644 --- a/rules/integrations/okta/initial_access_sign_in_events_via_third_party_idp.toml +++ b/rules/integrations/okta/initial_access_sign_in_events_via_third_party_idp.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/06" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,13 +29,13 @@ Adversaries may attempt to add an unauthorized IdP to an Okta tenant to gain acc - Identify the third-party IdP by examining the `okta.authentication_context.issuer.id` field. - Once the third-party IdP is identified, determine if this IdP is authorized to be used by the tenant. - If the IdP is unauthorized, deactivate it immediately via the Okta console. -- Identify the actor associated with the IdP creation by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields in historical data. +- Identify the actor associated with the IdP creation by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields in historical data. - The `New Okta Identity Provider (IdP) Added by Admin` rule may be helpful in identifying the actor and the IdP creation event. -- Determine the client used by the actor. Review the `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Determine the client used by the actor. Review the `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - If the client is a device, check the `okta.device.id`, `okta.device.name`, `okta.device.os_platform`, `okta.device.os_version`, and `okta.device.managed` fields. - Review the past activities of the actor involved in this action by checking their previous actions logged in the `okta.target` field. - Examine the `okta.request.ip_chain` field to potentially determine if the actor used a proxy or VPN to perform this action. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. ### False positive analysis: - It might be a false positive if this IdP is authorized to be used by the tenant. @@ -49,7 +49,7 @@ Adversaries may attempt to add an unauthorized IdP to an Okta tenant to gain acc - If the actor is unauthorized, deactivate their account via the Okta console. - If the actor is authorized, ensure that the actor's account is not compromised. -- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `okta.client.ip` and `okta.device.id` fields. +- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `source.ip` and `okta.device.id` fields. - Conduct a review of Okta policies and ensure they are in accordance with security best practices. - If the deactivated IdP was crucial to the organization, consider adding a new IdP and removing the unauthorized IdP. @@ -90,8 +90,8 @@ data_stream.dataset: "okta.system" ) or ( event.action: "user.authentication.auth_via_IDP" - and okta.outcome.result: "FAILURE" - and okta.outcome.reason: ( + and event.outcome: "failure" + and event.reason: ( "A SAML assert with the same ID has already been processed by Okta for a previous request" or "Unable to match transformed username" or "Unable to resolve IdP endpoint" diff --git a/rules/integrations/okta/initial_access_successful_application_sso_from_unknown_client_device.toml b/rules/integrations/okta/initial_access_successful_application_sso_from_unknown_client_device.toml index 6fd29ea9fa6..e9151a46d76 100644 --- a/rules/integrations/okta/initial_access_successful_application_sso_from_unknown_client_device.toml +++ b/rules/integrations/okta/initial_access_successful_application_sso_from_unknown_client_device.toml @@ -2,7 +2,7 @@ creation_date = "2024/10/07" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -96,7 +96,7 @@ reference = "https://attack.mitre.org/tactics/TA0001/" [rule.new_terms] field = "new_terms_fields" -value = ["client.user.name", "okta.client.user_agent.raw_user_agent"] +value = ["client.user.name", "user_agent.original"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-14d" diff --git a/rules/integrations/okta/lateral_movement_multiple_sessions_for_single_user.toml b/rules/integrations/okta/lateral_movement_multiple_sessions_for_single_user.toml index 6c4d266d2f2..9a556d422d7 100644 --- a/rules/integrations/okta/lateral_movement_multiple_sessions_for_single_user.toml +++ b/rules/integrations/okta/lateral_movement_multiple_sessions_for_single_user.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/07" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -32,7 +32,7 @@ Okta is a widely used identity management service that facilitates secure user a - Review the Okta logs to identify the specific user account associated with the multiple session initiations and note the distinct session IDs. - Check the geographic locations and IP addresses associated with each session initiation to determine if there are any unusual or unexpected locations. - Investigate the timestamps of the session initiations to see if they align with the user's typical login patterns or if they suggest simultaneous logins from different locations. -- Examine the okta.actor.id and okta.actor.display_name fields to ensure that the sessions were not initiated by legitimate Okta system actors. +- Examine the client.user.id and user.full_name fields to ensure that the sessions were not initiated by legitimate Okta system actors. - Contact the user to verify if they recognize the session activity and if they have recently logged in from multiple devices or locations. - Assess if there are any other related security alerts or incidents involving the same user account that could indicate a broader compromise. @@ -79,9 +79,9 @@ type = "threshold" query = ''' data_stream.dataset:okta.system - and okta.event_type:user.session.start + and event.action:user.session.start and okta.authentication_context.external_session_id:* - and not (okta.actor.id: okta* or okta.actor.display_name: okta*) + and not (client.user.id: okta* or user.full_name: okta*) ''' @@ -104,7 +104,7 @@ name = "Lateral Movement" reference = "https://attack.mitre.org/tactics/TA0008/" [rule.threshold] -field = ["okta.actor.id"] +field = ["client.user.id"] value = 1 [[rule.threshold.cardinality]] field = "okta.authentication_context.external_session_id" diff --git a/rules/integrations/okta/persistence_administrator_role_assigned_to_okta_user.toml b/rules/integrations/okta/persistence_administrator_role_assigned_to_okta_user.toml index 70d74fa3240..64b40e45d2b 100644 --- a/rules/integrations/okta/persistence_administrator_role_assigned_to_okta_user.toml +++ b/rules/integrations/okta/persistence_administrator_role_assigned_to_okta_user.toml @@ -2,7 +2,7 @@ creation_date = "2020/11/06" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -31,10 +31,10 @@ note = """## Triage and analysis Okta administrator roles provide elevated permissions to manage users, applications, policies, and security settings within the Okta environment. Adversaries who compromise Okta accounts may assign administrator privileges to establish persistence and maintain control over the identity infrastructure. This rule detects when administrator roles are granted to users or groups, which can indicate privilege escalation or persistence techniques. #### Possible investigation steps: -- Identify the actor who performed the privilege grant by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. +- Identify the actor who performed the privilege grant by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. - Determine the target user or group that received administrator privileges by reviewing the `okta.target` fields. - Review the specific administrator role granted by examining the `okta.debug_context.debug_data.flattened.privilegeGranted` field. -- Determine the client used by the actor. Review the `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Determine the client used by the actor. Review the `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - Check if the source IP is associated with known malicious activity, VPN/proxy services, or unusual geolocations. - Examine the `okta.request.ip_chain` field to determine if the actor used a proxy or VPN. - Review the actor's recent authentication history and session activity for suspicious patterns. diff --git a/rules/integrations/okta/persistence_mfa_deactivation_with_no_reactivation.toml b/rules/integrations/okta/persistence_mfa_deactivation_with_no_reactivation.toml index fc43c7282dc..9a245ba6df2 100644 --- a/rules/integrations/okta/persistence_mfa_deactivation_with_no_reactivation.toml +++ b/rules/integrations/okta/persistence_mfa_deactivation_with_no_reactivation.toml @@ -2,7 +2,7 @@ creation_date = "2020/05/20" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -34,9 +34,9 @@ This rule fires when an Okta user account has MFA deactivated and no subsequent #### Possible investigation steps: - Identify the entity related to the alert by reviewing `okta.target.alternate_id`, `okta.target.id` or `user.target.full_name` fields. This should give the username of the account being targeted. Verify if MFA is deactivated for the target entity. -- Using the `okta.target.alternate_id` field, search for MFA re-activation events where `okta.event_type` is `user.mfa.factor.activate`. Note if MFA re-activation attempts were made against the target. -- Identify the actor performing the deactivation by reviewing `okta.actor.alternate_id`, `okta.actor.id` or `user.full_name` fields. This should give the username of the account performing the action. Determine if deactivation was performed by a separate user. -- Review events where `okta.event_type` is `user.authenticate*` to determine if the actor or target accounts had suspicious login activity. +- Using the `okta.target.alternate_id` field, search for MFA re-activation events where `event.action` is `user.mfa.factor.activate`. Note if MFA re-activation attempts were made against the target. +- Identify the actor performing the deactivation by reviewing `user.name`, `client.user.id` or `user.full_name` fields. This should give the username of the account performing the action. Determine if deactivation was performed by a separate user. +- Review events where `event.action` is `user.authenticate*` to determine if the actor or target accounts had suspicious login activity. - Geolocation details found in `client.geo*` related fields may be useful in determining if the login activity was suspicious for this user. - Examine related administrative activity by the actor for privilege misuse or suspicious changes. @@ -77,9 +77,9 @@ type = "eql" query = ''' sequence by okta.target.id with maxspan=12h - [any where data_stream.dataset == "okta.system" and okta.event_type in ("user.mfa.factor.deactivate", "user.mfa.factor.reset_all") - and okta.outcome.reason != "User reset SECURITY_QUESTION factor" and okta.outcome.result == "SUCCESS"] - ![any where data_stream.dataset == "okta.system" and okta.event_type == "user.mfa.factor.activate"] + [any where data_stream.dataset == "okta.system" and event.action in ("user.mfa.factor.deactivate", "user.mfa.factor.reset_all") + and event.reason != "User reset SECURITY_QUESTION factor" and event.outcome == "SUCCESS"] + ![any where data_stream.dataset == "okta.system" and event.action == "user.mfa.factor.activate"] ''' diff --git a/rules/integrations/okta/persistence_new_idp_successfully_added_by_admin.toml b/rules/integrations/okta/persistence_new_idp_successfully_added_by_admin.toml index 3c6561b0236..89d0ceda31f 100644 --- a/rules/integrations/okta/persistence_new_idp_successfully_added_by_admin.toml +++ b/rules/integrations/okta/persistence_new_idp_successfully_added_by_admin.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/06" integration = ["okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -23,13 +23,13 @@ note = """## Triage and analysis This rule detects the creation of a new Identity Provider (IdP) by a Super Administrator or Organization Administrator within Okta. #### Possible investigation steps: -- Identify the actor associated with the IdP creation by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. +- Identify the actor associated with the IdP creation by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. - Identify the IdP added by reviewing the `okta.target` field and determing if this IdP is authorized. -- Determine the client used by the actor. Review the `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Determine the client used by the actor. Review the `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - If the client is a device, check the `okta.device.id`, `okta.device.name`, `okta.device.os_platform`, `okta.device.os_version`, and `okta.device.managed` fields. - Review the past activities of the actor involved in this action by checking their previous actions logged in the `okta.target` field. - Examine the `okta.request.ip_chain` field to potentially determine if the actor used a proxy or VPN to perform this action. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. ### False positive analysis: - It might be a false positive if the action was part of a planned activity or performed by an authorized person. @@ -41,7 +41,7 @@ This rule detects the creation of a new Identity Provider (IdP) by a Super Admin - If the actor is unauthorized, deactivate their account via the Okta console. - If the actor is authorized, ensure that the actor's account is not compromised. - Reset the user's password and enforce MFA re-enrollment, if applicable. -- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `okta.client.ip` and `okta.device.id` fields. +- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `source.ip` and `okta.device.id` fields. - Conduct a review of Okta policies and ensure they are in accordance with security best practices. - If the deactivated IdP was crucial to the organization, consider adding a new IdP and removing the unauthorized IdP. @@ -70,7 +70,7 @@ timestamp_override = "event.ingested" type = "query" query = ''' -data_stream.dataset: "okta.system" and event.action: "system.idp.lifecycle.create" and okta.outcome.result: "SUCCESS" +data_stream.dataset: "okta.system" and event.action: "system.idp.lifecycle.create" and event.outcome: "success" ''' diff --git a/rules/integrations/okta/persistence_stolen_credentials_used_to_login_to_okta_account_after_mfa_reset.toml b/rules/integrations/okta/persistence_stolen_credentials_used_to_login_to_okta_account_after_mfa_reset.toml index c98257da52b..2e4c9feceb3 100644 --- a/rules/integrations/okta/persistence_stolen_credentials_used_to_login_to_okta_account_after_mfa_reset.toml +++ b/rules/integrations/okta/persistence_stolen_credentials_used_to_login_to_okta_account_after_mfa_reset.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/09" integration = ["endpoint", "okta"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -80,8 +80,8 @@ type = "eql" query = ''' sequence by user.name with maxspan=12h [any where host.os.type == "windows" and signal.rule.threat.tactic.name == "Credential Access"] - [any where data_stream.dataset == "okta.system" and okta.event_type == "user.mfa.factor.update"] - [any where data_stream.dataset == "okta.system" and okta.event_type: ("user.session.start", "user.authentication*")] + [any where data_stream.dataset == "okta.system" and event.action == "user.mfa.factor.update"] + [any where data_stream.dataset == "okta.system" and event.action: ("user.session.start", "user.authentication*")] ''' diff --git a/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml b/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml index 9a480e1b7f1..018214cea84 100644 --- a/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml +++ b/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/30" integration = ["endpoint"] maturity = "production" -updated_date = "2026/01/30" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -86,7 +86,8 @@ file where host.os.type == "macos" and event.type != "deletion" and not process.executable like ("/System/*", "/Library/PrivilegedHelperTools/*") and not (process.code_signature.signing_id in ("com.apple.vim", "com.apple.cat", "com.apple.cfprefsd", "com.jetbrains.toolbox", "com.apple.pico", "com.apple.shove", - "com.sublimetext.4", "com.apple.ditto") and process.code_signature.trusted == true) + "com.sublimetext.4", "com.apple.ditto") and process.code_signature.trusted == true) and + not process.Ext.effective_parent.executable : "/opt/jc/bin/jumpcloud-agent" ''' [[rule.threat]] diff --git a/rules/network/collection_fortigate_config_download.toml b/rules/network/collection_fortigate_config_download.toml index 99e4fe06fee..63190ab0b5a 100644 --- a/rules/network/collection_fortigate_config_download.toml +++ b/rules/network/collection_fortigate_config_download.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/28" integration = ["fortinet_fortigate"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,7 +69,7 @@ type = "eql" query = ''' any where data_stream.dataset == "fortinet_fortigate.log" and event.code == "0100032095" and - fortinet.firewall.action == "download" + event.action == "download" ''' diff --git a/rules/network/defense_evasion_fortigate_overly_permissive_firewall_policy.toml b/rules/network/defense_evasion_fortigate_overly_permissive_firewall_policy.toml index 26343b6babd..3191053242f 100644 --- a/rules/network/defense_evasion_fortigate_overly_permissive_firewall_policy.toml +++ b/rules/network/defense_evasion_fortigate_overly_permissive_firewall_policy.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/28" integration = ["fortinet_fortigate"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,7 +69,7 @@ query = ''' any where data_stream.dataset == "fortinet_fortigate.log" and event.code == "0100044547" and fortinet.firewall.cfgpath == "firewall.policy" and - fortinet.firewall.action in ("Add", "Edit") and + event.action in ("Add", "Edit") and fortinet.firewall.cfgattr like~ "*srcaddr[all]*" and fortinet.firewall.cfgattr like~ "*dstaddr[all]*" and fortinet.firewall.cfgattr like~ "*service[all]*" diff --git a/rules/network/persistence_fortigate_admin_creation_unusual_source.toml b/rules/network/persistence_fortigate_admin_creation_unusual_source.toml index 64cede40f1c..26d9fb852e9 100644 --- a/rules/network/persistence_fortigate_admin_creation_unusual_source.toml +++ b/rules/network/persistence_fortigate_admin_creation_unusual_source.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/28" integration = ["fortinet_fortigate"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,7 +69,7 @@ query = ''' data_stream.dataset: "fortinet_fortigate.log" and event.code: "0100044547" and fortinet.firewall.cfgpath: "system.admin" and - fortinet.firewall.action: "Add" and + event.action: "Add" and fortinet.firewall.ui: (* and not "") ''' diff --git a/rules/network/persistence_fortigate_sso_login_followed_by_admin_creation.toml b/rules/network/persistence_fortigate_sso_login_followed_by_admin_creation.toml index 7e3be29b4a1..07a0c9559f9 100644 --- a/rules/network/persistence_fortigate_sso_login_followed_by_admin_creation.toml +++ b/rules/network/persistence_fortigate_sso_login_followed_by_admin_creation.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/28" integration = ["fortinet_fortigate"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,7 +74,7 @@ sequence by observer.name with maxspan=15m [any where data_stream.dataset == "fortinet_fortigate.log" and event.code == "0100044547" and fortinet.firewall.cfgpath == "system.admin" and - fortinet.firewall.action == "Add"] + event.action == "Add"] ''' diff --git a/rules/network/persistence_fortigate_super_admin_account_creation.toml b/rules/network/persistence_fortigate_super_admin_account_creation.toml index 54e18c3c37c..c9296c3107a 100644 --- a/rules/network/persistence_fortigate_super_admin_account_creation.toml +++ b/rules/network/persistence_fortigate_super_admin_account_creation.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/28" integration = ["fortinet_fortigate"] maturity = "production" -updated_date = "2026/04/10" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,7 +69,7 @@ query = ''' any where data_stream.dataset == "fortinet_fortigate.log" and event.code == "0100044547" and fortinet.firewall.cfgpath == "system.admin" and - fortinet.firewall.action == "Add" and + event.action == "Add" and fortinet.firewall.cfgattr like~ "*accprofile[super_admin]*" ''' diff --git a/rules/windows/credential_access_adidns_wildcard.toml b/rules/windows/credential_access_adidns_wildcard.toml index 90a53a6f376..0440ad6a425 100644 --- a/rules/windows/credential_access_adidns_wildcard.toml +++ b/rules/windows/credential_access_adidns_wildcard.toml @@ -2,7 +2,7 @@ creation_date = "2024/03/26" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/04/22" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -52,7 +52,7 @@ note = """## Triage and analysis - What wildcard object did the alert create, and which ADIDNS scope can it affect? - Why: a leading `DC=*` object can answer otherwise unresolved names across that ADIDNS zone, so the zone and partition define the first impact boundary. - - Focus: `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, and `winlog.computer_name`. + - Focus: `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, and `host.name`. - Hint: parse `winlog.event_data.ObjectDN` from left to right. In `DC=*,DC=example.com,CN=MicrosoftDNS,DC=DomainDnsZones,DC=example,DC=com`, `DC=*` is the wildcard node, `DC=example.com` is the DNS zone, and `DC=DomainDnsZones,...` identifies the AD DNS partition. - Implication: escalate faster when the object is a wildcard dnsNode in a production domain or forest DNS partition; lower concern only when the same object, zone, and domain controller align with a defensive sinkhole or contained test candidate, then continue to session and change evidence before closure. @@ -91,7 +91,7 @@ note = """## Triage and analysis ### Response and remediation -- If confirmed as an authorized defensive sinkhole or test, reverse any temporary containment, verify the wildcard is removed or retained according to that scope, and document `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, creating `user.id`, `winlog.event_data.SubjectLogonId`, `winlog.computer_name`, and the confirming scope. +- If confirmed as an authorized defensive sinkhole or test, reverse any temporary containment, verify the wildcard is removed or retained according to that scope, and document `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, creating `user.id`, `winlog.event_data.SubjectLogonId`, `host.name`, and the confirming scope. - If suspicious but unconfirmed, export the AD object state, replication context, and related 5136/5137 Windows Security events before modifying the record or account. Then apply reversible containment tied to the evidence, such as restricting the creating account's ADIDNS write path or temporarily limiting that account while scope is clarified. - If confirmed malicious, preserve the exported AD object, 5136 attribute evidence, session-origin evidence, and related alerts before deletion. Remove the wildcard and any unauthorized ADIDNS objects from the same session, then verify removal replicated to all domain controllers. - Disable or restrict the creating account after evidence preservation to prevent re-poisoning. Use `winlog.event_data.SubjectLogonId` and recovered `source.ip` to hand off the source system for endpoint investigation of ADIDNS tooling, credential capture, or follow-on authentication. @@ -115,7 +115,7 @@ field_names = [ "winlog.event_data.ObjectDN", "winlog.event_data.ObjectGUID", "winlog.event_data.DSName", - "winlog.computer_name", + "host.name", "host.id" ] diff --git a/rules/windows/credential_access_bruteforce_admin_account.toml b/rules/windows/credential_access_bruteforce_admin_account.toml index fb4cee42650..f00d48a55c0 100644 --- a/rules/windows/credential_access_bruteforce_admin_account.toml +++ b/rules/windows/credential_access_bruteforce_admin_account.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/29" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [transform] [[transform.osquery]] @@ -114,9 +114,9 @@ type = "esql" query = ''' from logs-system.security*, logs-windows.forwarded*, winlogbeat-* metadata _id, _version, _index | where event.category == "authentication" and host.os.type == "windows" and event.action == "logon-failed" and - winlog.logon.type == "Network" and source.ip is not null and winlog.computer_name is not null and + winlog.logon.type == "Network" and source.ip is not null and host.name is not null and not cidr_match(TO_IP(source.ip), "127.0.0.0/8", "::1") and - to_lower(winlog.event_data.TargetUserName) like "*admin*" and + to_lower(user.target.name) like "*admin*" and /* noisy failure status codes often associated to authentication misconfiguration 0xC000015B - The user has not been granted the requested logon type (also called the logon right) at this machine. @@ -129,14 +129,14 @@ from logs-system.security*, logs-windows.forwarded*, winlogbeat-* metadata _id, // truncate the timestamp to a 60-second window | eval Esql.time_window = date_trunc(60 seconds, @timestamp) | stats Esql.failed_auth_count = COUNT(*), - Esql.target_user_name_values = VALUES(winlog.event_data.TargetUserName), - Esql.count_distinct_user_name = count_distinct(winlog.event_data.TargetUserName), + Esql.target_user_name_values = VALUES(user.target.name), + Esql.count_distinct_user_name = count_distinct(user.target.name), Esql.user_domain_values = VALUES(user.domain), Esql.error_codes = VALUES(winlog.event_data.Status), - Esql.data_stream_namespace.values = VALUES(data_stream.namespace) by winlog.computer_name, source.ip, Esql.time_window, winlog.logon.type + Esql.data_stream_namespace.values = VALUES(data_stream.namespace) by host.name, source.ip, Esql.time_window, winlog.logon.type | where Esql.failed_auth_count >= 50 and Esql.count_distinct_user_name >= 2 | eval user.name = mv_first(Esql.target_user_name_values) -| KEEP winlog.computer_name, source.ip, user.name, Esql.time_window, winlog.logon.type, Esql.* +| KEEP host.name, source.ip, user.name, Esql.time_window, winlog.logon.type, Esql.* ''' diff --git a/rules/windows/credential_access_bruteforce_multiple_logon_failure_followed_by_success.toml b/rules/windows/credential_access_bruteforce_multiple_logon_failure_followed_by_success.toml index a8eefd69e55..faa60962f49 100644 --- a/rules/windows/credential_access_bruteforce_multiple_logon_failure_followed_by_success.toml +++ b/rules/windows/credential_access_bruteforce_multiple_logon_failure_followed_by_success.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/29" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [transform] [[transform.osquery]] @@ -117,12 +117,12 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name, source.ip with maxspan=5s +sequence by host.name, source.ip with maxspan=5s [authentication where host.os.type == "windows" and event.action == "logon-failed" and /* event 4625 need to be logged */ winlog.logon.type : "Network" and user.id != null and source.ip != null and source.ip != "127.0.0.1" and source.ip != "::1" and - not winlog.event_data.TargetUserSid : "S-1-0-0" and not user.id : "S-1-0-0" and + not user.target.id : "S-1-0-0" and not user.id : "S-1-0-0" and not user.name : ("ANONYMOUS LOGON", "-", "*$") and not user.domain == "NT AUTHORITY" and /* noisy failure status codes often associated to authentication misconfiguration */ diff --git a/rules/windows/credential_access_bruteforce_multiple_logon_failure_same_srcip.toml b/rules/windows/credential_access_bruteforce_multiple_logon_failure_same_srcip.toml index 3d4b9760f24..dc72445331f 100644 --- a/rules/windows/credential_access_bruteforce_multiple_logon_failure_same_srcip.toml +++ b/rules/windows/credential_access_bruteforce_multiple_logon_failure_same_srcip.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/29" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [transform] [[transform.osquery]] @@ -123,7 +123,7 @@ type = "esql" query = ''' from logs-system.security*, logs-windows.forwarded*, winlogbeat-* metadata _id, _version, _index | where event.category == "authentication" and host.os.type == "windows" and event.action == "logon-failed" and - winlog.logon.type == "Network" and source.ip is not null and winlog.computer_name is not null and + winlog.logon.type == "Network" and source.ip is not null and host.name is not null and not cidr_match(TO_IP(source.ip), "127.0.0.0/8", "::1") and not user.name in ("ANONYMOUS LOGON", "-") and not user.name like "*$" and user.domain != "NT AUTHORITY" and /* @@ -138,14 +138,14 @@ from logs-system.security*, logs-windows.forwarded*, winlogbeat-* metadata _id, // truncate the timestamp to a 60-second window | eval Esql.time_window = date_trunc(60 seconds, @timestamp) | stats Esql.failed_auth_count = COUNT(*), - Esql.count_distinct_target_user_name = count_distinct(winlog.event_data.TargetUserName), - Esql.target_user_name_values = VALUES(winlog.event_data.TargetUserName), + Esql.count_distinct_target_user_name = count_distinct(user.target.name), + Esql.target_user_name_values = VALUES(user.target.name), Esql.user_domain_values = VALUES(user.domain), Esql.error_codes = VALUES(winlog.event_data.Status), - Esql.data_stream_namespace.values = VALUES(data_stream.namespace) by winlog.computer_name, source.ip, Esql.time_window, winlog.logon.type + Esql.data_stream_namespace.values = VALUES(data_stream.namespace) by host.name, source.ip, Esql.time_window, winlog.logon.type | where Esql.failed_auth_count >= 100 and Esql.count_distinct_target_user_name >= 2 | eval user.name = MV_FIRST(Esql.target_user_name_values) -| KEEP winlog.computer_name, source.ip, user.name, Esql.time_window, winlog.logon.type, Esql.* +| KEEP host.name, source.ip, user.name, Esql.time_window, winlog.logon.type, Esql.* ''' diff --git a/rules/windows/credential_access_dcsync_newterm_subjectuser.toml b/rules/windows/credential_access_dcsync_newterm_subjectuser.toml index 90f311ea7be..83319195c8e 100644 --- a/rules/windows/credential_access_dcsync_newterm_subjectuser.toml +++ b/rules/windows/credential_access_dcsync_newterm_subjectuser.toml @@ -2,7 +2,7 @@ creation_date = "2022/12/19" integration = ["windows", "system"] maturity = "production" -updated_date = "2026/04/22" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -47,7 +47,7 @@ event.code:"4662" and host.os.type:"windows" and *DS-Replication-Get-Changes* or *DS-Replication-Get-Changes-All* or *DS-Replication-Get-Changes-In-Filtered-Set* or *1131f6ad-9c07-11d1-f79f-00c04fc2dcd2* or *1131f6aa-9c07-11d1-f79f-00c04fc2dcd2* or *89e95b76-444d-4c62-991a-0facbeda640c*) and - not winlog.event_data.SubjectUserName:(*$ or MSOL_*) + not user.name:(*$ or MSOL_*) ''' note = """## Triage and analysis @@ -57,7 +57,7 @@ note = """## Triage and analysis #### Possible investigation steps - What did the alerted 4662 prove about the subject and replication request? - - Focus: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.Properties`, `winlog.event_data.AccessMask`, and `winlog.computer_name`. + - Focus: `user.id`, `user.name`, `winlog.event_data.Properties`, `winlog.event_data.AccessMask`, and `host.name`. - Hint: replication-right GUIDs map to `DS-Replication-Get-Changes` (`1131f6aa-9c07-11d1-f79f-00c04fc2dcd2`), `DS-Replication-Get-Changes-All` (`1131f6ad-9c07-11d1-f79f-00c04fc2dcd2`), and `DS-Replication-Get-Changes-In-Filtered-Set` (`89e95b76-444d-4c62-991a-0facbeda640c`). - Implication: escalate faster when a human admin, new service account, or other non-machine principal used Control Access with DS-Replication-Get-Changes rights; lower suspicion only when the same stable SID and controller match one recognized directory-replication connector or AD backup/recovery job. @@ -70,7 +70,7 @@ note = """## Triage and analysis - Does the subject logon session resolve to another domain controller or an unexpected source system? - Focus: match `winlog.event_data.SubjectLogonId` to 4624 `winlog.event_data.TargetLogonId` on the same `host.id`, then read `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`. $investigate_0 - Range: search backward from `@timestamp` on the same `host.id` because the session-creating 4624 can predate the 4662 by minutes or hours. - - Hint: if the linked 4624 is missing or `source.ip` is absent, preserve `winlog.event_data.SubjectLogonId`, `winlog.computer_name`, and `@timestamp`. Missing authentication telemetry is unresolved, not benign. + - Hint: if the linked 4624 is missing or `source.ip` is absent, preserve `winlog.event_data.SubjectLogonId`, `host.name`, and `@timestamp`. Missing authentication telemetry is unresolved, not benign. - Implication: escalate when the session originates from a workstation, member server, rare admin host, or a DC interactive / remote-interactive logon; lower suspicion when the 4624 source, logon type, and auth package match recognized replication infrastructure. - Do surrounding authentication events show explicit-credential use or a session pattern that does not fit routine replication? @@ -80,12 +80,12 @@ note = """## Triage and analysis - Implication: escalate when the subject shows new remote-interactive or network sessions from unusual origins, explicit credentials for the alerted account or controller, or NTLM where the workflow normally uses Kerberos. - Did surrounding directory-object changes or related 4662 activity show how the account obtained or expanded replication rights? - - Focus: surrounding 4662 activity for `winlog.event_data.SubjectUserSid`, plus 5136 changes using `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, `winlog.event_data.AttributeValue`, and `winlog.event_data.OpCorrelationID`. $investigate_1 + - Focus: surrounding 4662 activity for `user.id`, plus 5136 changes using `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, `winlog.event_data.AttributeValue`, and `winlog.event_data.OpCorrelationID`. $investigate_1 - Hint: group related 5136 records by `winlog.event_data.OpCorrelationID`; if 5136 visibility is absent, preserve the gap and answer from surrounding 4662 activity. - Implication: escalate when 5136 shows recent ACL or delegation changes granting DS-Replication-Get-Changes rights to the subject or its groups, when another grantor touched sensitive delegation or domain-level objects, or when privileged 4662 access appears on multiple controllers. - If local evidence is still suspicious, did the same subject or replication-right scope touch other controllers? - - Focus: Windows Security 4662 and 5136 records for `winlog.event_data.SubjectUserSid` and `winlog.event_data.Properties`, grouped by `winlog.computer_name` and `winlog.event_data.ObjectName`. + - Focus: Windows Security 4662 and 5136 records for `user.id` and `winlog.event_data.Properties`, grouped by `host.name` and `winlog.event_data.ObjectName`. - Range: start with the surrounding window, then expand only if the local subject, source, or rights scope remains suspicious. - Implication: escalate domain-wide when the same subject or rights scope appears on multiple controllers or directory objects; keep scope local when only this controller shows activity, but do not close unresolved DCSync evidence from absence alone. @@ -95,8 +95,8 @@ note = """## Triage and analysis ### False positive analysis -- Directory-replication connectors and AD backup/recovery jobs can legitimately trigger this rule. Confirm only when `winlog.event_data.SubjectUserSid`, `winlog.event_data.Properties`, `winlog.event_data.ObjectName`, recovered 4624 `source.ip`, and `winlog.computer_name` align to one exact connector or job run. For backup/recovery tooling, require 5136 or owner/product evidence that the activity was tool-driven rather than hands-on operator behavior. If telemetry cannot prove the workflow, require outside confirmation for that exact run; do not close from prior-alert recurrence alone. -- Build exceptions from the minimum confirmed workflow: stable `winlog.event_data.SubjectUserSid`, recovered 4624 `source.ip`, `winlog.event_data.Properties`, `winlog.event_data.ObjectName`, and `winlog.computer_name`, plus the specific product or connector identity that explains the access. Avoid exceptions on `winlog.event_data.SubjectUserName` alone, broad replication-right strings, or "first benign occurrence" claims without exact workflow confirmation. +- Directory-replication connectors and AD backup/recovery jobs can legitimately trigger this rule. Confirm only when `user.id`, `winlog.event_data.Properties`, `winlog.event_data.ObjectName`, recovered 4624 `source.ip`, and `host.name` align to one exact connector or job run. For backup/recovery tooling, require 5136 or owner/product evidence that the activity was tool-driven rather than hands-on operator behavior. If telemetry cannot prove the workflow, require outside confirmation for that exact run; do not close from prior-alert recurrence alone. +- Build exceptions from the minimum confirmed workflow: stable `user.id`, recovered 4624 `source.ip`, `winlog.event_data.Properties`, `winlog.event_data.ObjectName`, and `host.name`, plus the specific product or connector identity that explains the access. Avoid exceptions on `user.name` alone, broad replication-right strings, or "first benign occurrence" claims without exact workflow confirmation. ### Response and remediation @@ -104,7 +104,7 @@ note = """## Triage and analysis - If suspicious but unconfirmed, preserve a case export containing the triggering 4662 event, linked 4624/4648 authentication records, recovered `source.ip`, replication rights/object fields, and any 5136 delegation-change records before containment. Apply reversible containment first, such as temporarily blocking the recovered `source.ip` from reaching domain controllers or isolating the unexpected non-domain-controller source host when its role tolerates isolation. Escalate to broader account disablement or host isolation only if credential-theft, relay, or privilege-change evidence appears. - If confirmed malicious, use endpoint or identity-response tooling to isolate the unexpected source host and disable or reset the implicated account. If direct response is unavailable, escalate with the same artifact set to the AD or incident-response team. Record all preserved evidence before terminating processes, revoking access, or removing delegated rights. - If confirmed malicious activity included broad domain scope in `winlog.event_data.ObjectName` or `winlog.event_data.ObjectType`, hand off to the AD incident-response team with the preserved evidence before privileged-account resets or delegated-rights cleanup. -- Review other controllers and sync hosts for the same `winlog.event_data.SubjectUserSid`, `source.ip`, and `winlog.event_data.Properties` before removing delegated rights or cleaning up changes. +- Review other controllers and sync hosts for the same `user.id`, `source.ip`, and `winlog.event_data.Properties` before removing delegated rights or cleaning up changes. - Eradicate only the unauthorized replication-right delegation or directory changes identified during the investigation: remove "DS-Replication-Get-Changes*" grants, restore modified directory objects or ACLs, and remediate the path that let the subject obtain replication capability. - Post-incident hardening: restrict replication rights to authorized service accounts and sync hosts, retain Security 4662, 4624, 4648, and 5136 coverage on controllers, and document any uncovered variant or logging gap in the incident record for follow-up ownership. """ @@ -119,9 +119,9 @@ Setup instructions: https://ela.st/audit-directory-service-access field_names = [ "@timestamp", "host.id", - "winlog.computer_name", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "host.name", + "user.name", + "user.id", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectName", @@ -155,37 +155,37 @@ description = "" providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "4662", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.Properties", queryType = "phrase", value = "DS-Replication-Get-Changes", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4662", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.Properties", queryType = "phrase", value = "DS-Replication-Get-Changes-All", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4662", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.Properties", queryType = "phrase", value = "DS-Replication-Get-Changes-In-Filtered-Set", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4662", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.Properties", queryType = "phrase", value = "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4662", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.Properties", queryType = "phrase", value = "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4662", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.Properties", queryType = "phrase", value = "89e95b76-444d-4c62-991a-0facbeda640c", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-24h" @@ -193,7 +193,7 @@ relativeTo = "now" [rule.new_terms] field = "new_terms_fields" -value = ["winlog.event_data.SubjectUserName"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-15d" diff --git a/rules/windows/credential_access_dcsync_replication_rights.toml b/rules/windows/credential_access_dcsync_replication_rights.toml index 1eefe72a121..3179eefe6e4 100644 --- a/rules/windows/credential_access_dcsync_replication_rights.toml +++ b/rules/windows/credential_access_dcsync_replication_rights.toml @@ -2,7 +2,7 @@ creation_date = "2022/02/08" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -97,7 +97,7 @@ host.os.type:"windows" and event.code:"4662" and *DS-Replication-Get-Changes-In-Filtered-Set* or *1131f6ad-9c07-11d1-f79f-00c04fc2dcd2* or *1131f6aa-9c07-11d1-f79f-00c04fc2dcd2* or *89e95b76-444d-4c62-991a-0facbeda640c* ) and winlog.event_data.AccessMask : "0x100" and - not winlog.event_data.SubjectUserName:(*$ or MSOL_*) + not user.name:(*$ or MSOL_*) ''' @@ -138,7 +138,7 @@ reference = "https://attack.mitre.org/tactics/TA0004/" [rule.new_terms] field = "new_terms_fields" -value = ["winlog.event_data.SubjectUserSid", "winlog.event_data.ObjectName"] +value = ["user.id", "winlog.event_data.ObjectName"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-12h" diff --git a/rules/windows/credential_access_dnsnode_creation.toml b/rules/windows/credential_access_dnsnode_creation.toml index e1fa292ac82..8d0f4df4ddc 100644 --- a/rules/windows/credential_access_dnsnode_creation.toml +++ b/rules/windows/credential_access_dnsnode_creation.toml @@ -2,7 +2,7 @@ creation_date = "2024/03/26" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -31,7 +31,7 @@ Active Directory Integrated DNS (ADIDNS) is crucial for maintaining domain consi ### Possible investigation steps - Review the event logs for event code 5137 to identify the specific DNS-named record that was created and the associated timestamp. -- Examine the winlog.event_data.SubjectUserName field to determine the user account that initiated the DNS record creation, ensuring it is not a system account. +- Examine the user.name field to determine the user account that initiated the DNS record creation, ensuring it is not a system account. - Investigate the context around the winlog.event_data.ObjectClass field to confirm the object class is "dnsNode" and assess if the DNS record creation aligns with expected administrative activities. - Check for any recent LLMNR/NBT-NS requests or network traffic that might indicate an attempt to exploit the newly created DNS record for spoofing purposes. - Correlate the alert with other security events or logs to identify any patterns or anomalies that might suggest malicious intent or unauthorized access attempts. @@ -81,7 +81,7 @@ type = "eql" query = ''' any where host.os.type == "windows" and event.code == "5137" and winlog.event_data.ObjectClass == "dnsNode" and - not winlog.event_data.SubjectUserName : "*$" + not user.name : "*$" ''' diff --git a/rules/windows/credential_access_dollar_account_relay_kerberos.toml b/rules/windows/credential_access_dollar_account_relay_kerberos.toml index afd60b6f67d..54a49073689 100644 --- a/rules/windows/credential_access_dollar_account_relay_kerberos.toml +++ b/rules/windows/credential_access_dollar_account_relay_kerberos.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/18" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/04/22" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -43,11 +43,11 @@ timestamp_override = "event.ingested" type = "eql" query = ''' -sequence by winlog.computer_name, source.ip with maxspan=5s +sequence by host.name, source.ip with maxspan=5s /* Filter for an event that indicates coercion against known abused named pipes using an account that is not the host */ [file where host.os.type == "windows" and event.code : "5145" and - not startswith~(winlog.computer_name, substring(user.name, 0, -1)) and + not startswith~(host.name, substring(user.name, 0, -1)) and file.name : ( "Spoolss", "netdfs", "lsarpc", "lsass", "netlogon", "samr", "efsrpc", "FssagentRpc", "eventlog", "winreg", "srvsvc", "dnsserver", "dhcpserver", "WinsPipe" @@ -59,7 +59,7 @@ sequence by winlog.computer_name, source.ip with maxspan=5s winlog.event_data.AuthenticationPackageName : "Kerberos" and /* Filter for a machine account that matches the hostname */ - startswith~(winlog.computer_name, substring(user.name, 0, -1)) and + startswith~(host.name, substring(user.name, 0, -1)) and /* Verify if the Source IP belongs to the host */ not endswith(string(source.ip), string(host.ip)) and @@ -74,12 +74,12 @@ note = """## Triage and analysis - What do the recovered source events prove about the relay sequence? - Why: Kerberos relay can reuse a coerced machine-account ticket when SPN selection or service protections allow it; reflective variants keep the same triage anchors: recovered pipe, `source.ip`, target dollar account, and Kerberos network auth. - - Hint: Open Investigate in Timeline before interpreting the grouped alert; filter the alert window to `event.code` 5145 and 4624/4625 with the same `winlog.computer_name` and `source.ip`. In this step, read `file.name` from the recovered 5145 source event. If endpoint file telemetry is available for this host and time window, recover the matching `file.*` evidence before using it for interpretation or remediation. Treat it as optional corroboration, not the alert source. - - Focus: recovered 5145 and 4624/4625 source events scoped by `winlog.computer_name`, `source.ip`, and `@timestamp`; in the 5145 event read `file.name` as the named-pipe value, then in the auth event read `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, and `host.ip`. + - Hint: Open Investigate in Timeline before interpreting the grouped alert; filter the alert window to `event.code` 5145 and 4624/4625 with the same `host.name` and `source.ip`. In this step, read `file.name` from the recovered 5145 source event. If endpoint file telemetry is available for this host and time window, recover the matching `file.*` evidence before using it for interpretation or remediation. Treat it as optional corroboration, not the alert source. + - Focus: recovered 5145 and 4624/4625 source events scoped by `host.name`, `source.ip`, and `@timestamp`; in the 5145 event read `file.name` as the named-pipe value, then in the auth event read `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, and `host.ip`. - Implication: escalate when a known coercion pipe such as Spoolss, netdfs, lsarpc, efsrpc, netlogon, srvsvc, or winreg is followed within seconds by a Kerberos network logon from the same non-target `source.ip`; lower suspicion only when the recovered pipe/auth outcome recurs for the same source, server, and machine account and outside topology or owner evidence verifies that exact infrastructure role. - Does the authenticated machine account belong to the target server? - - Focus: `winlog.event_data.TargetUserName` dollar-account prefix and `winlog.event_data.TargetDomainName` from the auth source event compared with `winlog.computer_name`. + - Focus: `user.target.name` dollar-account prefix and `winlog.event_data.TargetDomainName` from the auth source event compared with `host.name`. - Implication: escalate when the target account is the target server's dollar account and the source is not the server itself; if the account does not map to the target server, resolve whether the sequence paired unrelated events before using the alert for closure or escalation. - Did the Kerberos authentication create a usable session or only a failed attempt? @@ -87,14 +87,14 @@ note = """## Triage and analysis - Implication: prioritize confirmed compromise review when a 4624 produces a `winlog.event_data.TargetLogonId`; keep failed-only 4625 sequences suspicious when the source or pipe is unexplained, but lower urgency when the status pattern is a recurring, bounded failure from recognized infrastructure. - Does the source IP fit recognized infrastructure or relay-characteristic behavior? - - Focus: surrounding Windows Security authentication events for `source.ip` and `winlog.computer_name`, reading `winlog.event_data.TargetUserName`, `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, `winlog.event_data.Status`, and `winlog.event_data.SubStatus`. + - Focus: surrounding Windows Security authentication events for `source.ip` and `host.name`, reading `user.target.name`, `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, `winlog.event_data.Status`, and `winlog.event_data.SubStatus`. - Hint: use same-source authentication events to see whether the source targets multiple machine accounts or alternates Kerberos successes and failures around the alert. $investigate_2 - Implication: escalate when the source is rare for this server, targets multiple machine accounts, or alternates Kerberos successes and failures outside a verified infrastructure role; missing surrounding authentication telemetry is unresolved, not benign. Lower suspicion only when the same bounded source/server/account/outcome pattern recurs and outside topology or owner evidence verifies the exact role. - If local evidence is suspicious or unresolved, is this part of broader relay activity? - Focus: related alerts for `source.ip` that show additional coercion or machine-account Kerberos relay. $investigate_0 - Hint: pivot target-server related alerts for service creation, persistence, or remote execution only when the source pivot is suspicious; missing related alerts narrows existing-alert scope only, not host activity. $investigate_1 - - Hint: for raw Windows Security scoping after a 4624, review follow-on Windows Security events on the same `winlog.computer_name` where `winlog.event_data.SubjectLogonId` matches the recovered `winlog.event_data.TargetLogonId`; filter within results for service creation, task creation, share access, or persistence if the result set is large. Missing follow-on events is unresolved unless that event coverage is confirmed. $investigate_3 + - Hint: for raw Windows Security scoping after a 4624, review follow-on Windows Security events on the same `host.name` where `winlog.event_data.SubjectLogonId` matches the recovered `winlog.event_data.TargetLogonId`; filter within results for service creation, task creation, share access, or persistence if the result set is large. Missing follow-on events is unresolved unless that event coverage is confirmed. $investigate_3 - Implication: expand scope when source history shows other coercion or machine-account Kerberos relay, or when target history shows follow-on service, persistence, or remote-execution alerts; keep containment local only when related alerts stay limited to the same explained infrastructure tuple. - Based on the recovered evidence, what disposition is supported? @@ -103,14 +103,14 @@ note = """## Triage and analysis ### False positive analysis -- Validated infrastructure peers or authorized relay/coercion testing are the narrow benign paths. Confirm by verifying the recovered source events align on the same `source.ip`, `winlog.computer_name`, target machine account in `winlog.event_data.TargetUserName`, Kerberos `winlog.event_data.AuthenticationPackageName`, network `winlog.logon.type`, bounded `winlog.event_data.Status`/`winlog.event_data.SubStatus`, and recovered pipe evidence for the same server/account/pipe/outcome tuple. If telemetry cannot explain the specific pipe, account, and outcome, do not close as benign. -- Use topology, owner, or test-plan confirmation only to verify the exact recovered tuple after source-event recovery. Before creating an exception, validate recurrence across prior alerts from this rule for the same source/server/account/pipe/outcome pattern. If this is the first confirmed benign occurrence, document it as a candidate exception and monitor before suppressing. Build exceptions from the full confirmed workflow pattern; avoid exceptions on `source.ip`, `winlog.computer_name`, or machine-account name alone. +- Validated infrastructure peers or authorized relay/coercion testing are the narrow benign paths. Confirm by verifying the recovered source events align on the same `source.ip`, `host.name`, target machine account in `user.target.name`, Kerberos `winlog.event_data.AuthenticationPackageName`, network `winlog.logon.type`, bounded `winlog.event_data.Status`/`winlog.event_data.SubStatus`, and recovered pipe evidence for the same server/account/pipe/outcome tuple. If telemetry cannot explain the specific pipe, account, and outcome, do not close as benign. +- Use topology, owner, or test-plan confirmation only to verify the exact recovered tuple after source-event recovery. Before creating an exception, validate recurrence across prior alerts from this rule for the same source/server/account/pipe/outcome pattern. If this is the first confirmed benign occurrence, document it as a candidate exception and monitor before suppressing. Build exceptions from the full confirmed workflow pattern; avoid exceptions on `source.ip`, `host.name`, or machine-account name alone. ### Response and remediation -- If confirmed benign, reverse any temporary containment and document the evidence that proved the workflow: `source.ip`, `winlog.computer_name`, target machine account, Kerberos network auth, bounded `winlog.event_data.Status`/`winlog.event_data.SubStatus`, and recovered pipe evidence. Create an exception only after the same full pattern recurs across prior alerts from this rule. +- If confirmed benign, reverse any temporary containment and document the evidence that proved the workflow: `source.ip`, `host.name`, target machine account, Kerberos network auth, bounded `winlog.event_data.Status`/`winlog.event_data.SubStatus`, and recovered pipe evidence. Create an exception only after the same full pattern recurs across prior alerts from this rule. - If suspicious but unconfirmed, preserve the alert export, Timeline source events, recovered pipe evidence, target machine-account identity, auth outcome, session identifier when present, and related-alert results before containment. Use reversible containment first: temporarily restrict SMB/RPC between `source.ip` and the affected server, or isolate the source host when its role tolerates isolation. Escalate to broader host or account action only if follow-on service, persistence, execution, or wider relay evidence appears. -- If confirmed malicious, preserve the same alert export, Timeline source events, recovered pipe evidence, target machine-account identity, auth outcome, session identifier when present, and related-alert results before action. Then contain the source host and restrict access to the affected `winlog.computer_name`; if direct containment is unavailable, hand off the preserved evidence set to the team that can act. Remove the coercion route, block the offending source path, and eradicate only services, scheduled tasks, dropped tools, or configuration changes confirmed during response. +- If confirmed malicious, preserve the same alert export, Timeline source events, recovered pipe evidence, target machine-account identity, auth outcome, session identifier when present, and related-alert results before action. Then contain the source host and restrict access to the affected `host.name`; if direct containment is unavailable, hand off the preserved evidence set to the team that can act. Remove the coercion route, block the offending source path, and eradicate only services, scheduled tasks, dropped tools, or configuration changes confirmed during response. - Rotate the affected computer-account secret and review adjacent delegated, service, or administrative credentials that could have been exposed through the relay path. Coordinate disruptive credential or host actions with identity and infrastructure owners when the target is a domain controller, cluster node, or other critical service. - After containment, audit other servers reached from the same `source.ip` and retain Windows Security source events needed to reconstruct each source/server/account/pipe sequence. - Post-incident hardening: before releasing containment for a reflective Kerberos relay path, validate the relevant CVE-2025-33073 fixes and SMB signing or service-specific signing/sealing/channel binding on the affected service tier. Restrict coercion-prone RPC and named-pipe exposure, then document the confirmed source/server/account/pipe pattern for future analysts and control owners. @@ -127,12 +127,12 @@ The following Windows audit policies must be enabled to generate the events used field_names = [ "@timestamp", "event.code", - "winlog.computer_name", + "host.name", "source.ip", "host.ip", "user.name", "file.name", - "winlog.event_data.TargetUserName", + "user.target.name", "winlog.event_data.TargetDomainName", "winlog.event_data.AuthenticationPackageName", "winlog.logon.type", @@ -160,7 +160,7 @@ description = "" providers = [ [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" } + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" @@ -171,13 +171,13 @@ label = "Authentication events from this source to this target" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "source.ip", queryType = "phrase", value = "{{source.ip}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }, { excluded = false, field = "winlog.event_data.AuthenticationPackageName", queryType = "phrase", value = "Kerberos", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "source.ip", queryType = "phrase", value = "{{source.ip}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4625", valueType = "string" }, { excluded = false, field = "winlog.event_data.AuthenticationPackageName", queryType = "phrase", value = "Kerberos", valueType = "string" } @@ -191,7 +191,7 @@ label = "Follow-on Windows Security events for the Kerberos logon session" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.TargetLogonId}}", valueType = "string" } ] ] diff --git a/rules/windows/credential_access_dollar_account_relay_ntlm.toml b/rules/windows/credential_access_dollar_account_relay_ntlm.toml index 6cebfdbc20f..ef262bd5f85 100644 --- a/rules/windows/credential_access_dollar_account_relay_ntlm.toml +++ b/rules/windows/credential_access_dollar_account_relay_ntlm.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/18" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/04/22" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -39,11 +39,11 @@ timestamp_override = "event.ingested" type = "eql" query = ''' -sequence by winlog.computer_name, source.ip with maxspan=5s +sequence by host.name, source.ip with maxspan=5s /* Filter for an event that indicates coercion against known abused named pipes using an account that is not the host */ [file where host.os.type == "windows" and event.code : "5145" and - not startswith~(winlog.computer_name, substring(user.name, 0, -1)) and + not startswith~(host.name, substring(user.name, 0, -1)) and file.name : ( "Spoolss", "netdfs", "lsarpc", "lsass", "netlogon", "samr", "efsrpc", "FssagentRpc", "eventlog", "winreg", "srvsvc", "dnsserver", "dhcpserver", "WinsPipe" @@ -55,7 +55,7 @@ sequence by winlog.computer_name, source.ip with maxspan=5s winlog.event_data.AuthenticationPackageName : "NTLM" and /* Filter for a machine account that matches the hostname */ - startswith~(winlog.computer_name, substring(user.name, 0, -1)) and + startswith~(host.name, substring(user.name, 0, -1)) and /* Verify if the Source IP belongs to the host */ not endswith(string(source.ip), string(host.ip)) and @@ -69,7 +69,7 @@ note = """## Triage and analysis #### Possible investigation steps - What source events make up the sequence, and do they support a coercion-to-NTLM path? - - Focus: open Timeline from the sequence alert and recover member events for the alert `host.id` or `host.name` plus `source.ip`; compare source-event `winlog.computer_name`, 5145 `file.name`, `winlog.event_data.TargetUserName`, `winlog.event_data.AuthenticationPackageName`, and `winlog.logon.type`. + - Focus: open Timeline from the sequence alert and recover member events for the alert `host.id` or `host.name` plus `source.ip`; compare source-event `host.name`, 5145 `file.name`, `user.target.name`, `winlog.event_data.AuthenticationPackageName`, and `winlog.logon.type`. - Hint: use the recovered 5145 Windows Security source event as the primary pipe evidence. If endpoint file telemetry is available for this host and time window, recover the matching `file.*` evidence before using it for interpretation or remediation. - Implication: escalate when a coercion-style pipe such as Spoolss, netdfs, efsrpc, FssagentRpc, lsarpc, netlogon, samr, srvsvc, winreg, dnsserver, or WinsPipe is followed within seconds by a type 3 NTLM machine-account logon from the same source; lower concern when the recovered pair matches a recurring proxy, cluster, backup, or management path with the same pipe and auth pattern; close as a non-hit only when source events break the sequence or do not share the same source and target. @@ -78,16 +78,16 @@ note = """## Triage and analysis - Implication: urgent escalation is warranted for a 4624 success, success-after-failure pattern, or NTLMv1/weak `winlog.event_data.LmPackageName`; failure-only 4625 activity still supports attempted coercion when the recovered pipe event and source path hold. - Does the authenticated machine account belong to the target server? - - Focus: auth-stage `winlog.event_data.TargetUserName` and `winlog.event_data.TargetDomainName` compared with `winlog.computer_name`, `host.name`, and `host.id`. + - Focus: auth-stage `user.target.name` and `winlog.event_data.TargetDomainName` compared with `host.name`, `host.name`, and `host.id`. - Implication: target-name alignment plus a dollar-suffixed machine account supports relayed or reflected computer-account use; a different host, alias, or cluster identity is an identity mismatch to resolve before disposition, not a benign conclusion by itself. - Does the source fit a recognized SMB/RPC infrastructure path for this server? - - Focus: surrounding Windows Security events for the same target, source, and machine account, checking `winlog.event_data.TargetUserName`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.LmPackageName`, `winlog.event_data.Status`, and `winlog.event_data.SubStatus`. + - Focus: surrounding Windows Security events for the same target, source, and machine account, checking `user.target.name`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.LmPackageName`, `winlog.event_data.Status`, and `winlog.event_data.SubStatus`. - Hint: use same-source NTLM authentication events to review repeated machine-account logons, success-after-failure patterns, and weak `LmPackageName` values around the alert. $investigate_2 - Implication: escalate when the source is rare for this server, targets multiple machine accounts, or drives burst failures followed by success; lower concern only when the same source/server/account/auth pattern recurs as a recognized proxy, load-balancer, cluster, backup, or management path. Missing Windows Security history leaves source fit unresolved, not benign. - Did the same source perform follow-on Windows Security activity after the relay pair? - - Focus: post-sequence Windows Security events on the same target and source, especially `event.code` 5145, 4624, or 4625 plus `winlog.event_data.TargetUserName`, `winlog.event_data.Status`, and `winlog.event_data.SubStatus`. + - Focus: post-sequence Windows Security events on the same target and source, especially `event.code` 5145, 4624, or 4625 plus `user.target.name`, `winlog.event_data.Status`, and `winlog.event_data.SubStatus`. - Hint: review same-source follow-on Windows Security events for repeated share or pipe access and repeated machine-account logons after the sequence. $investigate_3 - Implication: escalate when the source keeps accessing shares or pipes or repeats machine-account logons after the relay window; absence of follow-on Windows Security events reduces observed scope but does not prove benign execution did not occur. @@ -102,14 +102,14 @@ note = """## Triage and analysis ### False positive analysis -- Clustered file services, SMB/RPC proxies, backup controllers, or management tiers can legitimately front machine-account NTLM traffic through bounded SMB/RPC paths. Confirm by verifying the same `source.ip`, `winlog.computer_name`, `winlog.event_data.TargetUserName`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.LmPackageName`, status pattern, 5145 named-pipe/share object, and lack of suspicious follow-on `event.code` activity all converge on the same workflow. If workflow records are unavailable, require historical recurrence of that exact telemetry pattern before closing. -- Before creating an exception, validate recurrence across prior alerts from this rule for the same `source.ip`, `winlog.computer_name`, machine account, NTLM package/version, and 5145 object family. Build the exception from the minimum confirmed workflow pattern; avoid exceptions on source IP alone, target server alone, or dollar-suffixed machine-account names alone. +- Clustered file services, SMB/RPC proxies, backup controllers, or management tiers can legitimately front machine-account NTLM traffic through bounded SMB/RPC paths. Confirm by verifying the same `source.ip`, `host.name`, `user.target.name`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.LmPackageName`, status pattern, 5145 named-pipe/share object, and lack of suspicious follow-on `event.code` activity all converge on the same workflow. If workflow records are unavailable, require historical recurrence of that exact telemetry pattern before closing. +- Before creating an exception, validate recurrence across prior alerts from this rule for the same `source.ip`, `host.name`, machine account, NTLM package/version, and 5145 object family. Build the exception from the minimum confirmed workflow pattern; avoid exceptions on source IP alone, target server alone, or dollar-suffixed machine-account names alone. ### Response and remediation -- If confirmed benign, reverse temporary containment and document the exact `source.ip`, `winlog.computer_name`, `winlog.event_data.TargetUserName`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.LmPackageName`, `winlog.event_data.Status` or `winlog.event_data.SubStatus`, and 5145 object pattern that proved the workflow. Create a narrow exception only after recurrence proves the same telemetry pattern. +- If confirmed benign, reverse temporary containment and document the exact `source.ip`, `host.name`, `user.target.name`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.LmPackageName`, `winlog.event_data.Status` or `winlog.event_data.SubStatus`, and 5145 object pattern that proved the workflow. Create a narrow exception only after recurrence proves the same telemetry pattern. - If suspicious but unconfirmed, preserve the alert document, Timeline member events, recovered 5145 object, authentication result, NTLM package/version, source and target identifiers, status values, and any follow-on Windows Security records before containment. Use reversible containment first, such as temporarily blocking the recovered source from SMB/RPC access to the affected server or isolating the unexpected source host when its role tolerates isolation. -- If confirmed malicious, keep the preserved evidence set attached to the case, then isolate or block the source host and restrict its SMB/RPC access to the affected `winlog.computer_name`. Eradicate only confirmed follow-on services, tasks, shares, or relay tooling identified during investigation; coordinate disruptive actions on domain controllers, cluster nodes, and production servers with identity and infrastructure owners. +- If confirmed malicious, keep the preserved evidence set attached to the case, then isolate or block the source host and restrict its SMB/RPC access to the affected `host.name`. Eradicate only confirmed follow-on services, tasks, shares, or relay tooling identified during investigation; coordinate disruptive actions on domain controllers, cluster nodes, and production servers with identity and infrastructure owners. - Rotate the affected computer-account secret only after evidence preservation and service-impact review, then review delegated or administrative credentials that could have been exposed or reused through the relayed session. Reduce NTLM exposure, enforce SMB signing and Extended Protection for Authentication where applicable, and disable unneeded coercion-prone RPC services on the affected tier. - After containment, audit other servers reached from the same `source.ip` and retain the Windows Security telemetry needed to reconstruct the 5145-to-4624/4625 sequence. Document any reflection-style or marshaled-target variant indicators for future case comparison. """ @@ -129,9 +129,9 @@ field_names = [ "host.name", "host.ip", "source.ip", - "winlog.computer_name", + "host.name", "file.name", - "winlog.event_data.TargetUserName", + "user.target.name", "winlog.event_data.TargetDomainName", "winlog.event_data.AuthenticationPackageName", "winlog.event_data.LmPackageName", diff --git a/rules/windows/credential_access_imageload_azureadconnectauthsvc.toml b/rules/windows/credential_access_imageload_azureadconnectauthsvc.toml index 48fc8a03404..1e0937a00ce 100644 --- a/rules/windows/credential_access_imageload_azureadconnectauthsvc.toml +++ b/rules/windows/credential_access_imageload_azureadconnectauthsvc.toml @@ -2,7 +2,7 @@ creation_date = "2024/10/14" integration = ["endpoint", "windows"] maturity = "production" -updated_date = "2026/04/24" +updated_date = "2026/06/23" [rule] author = ["Elastic", "Matteo Potito Giorgio"] @@ -72,7 +72,7 @@ note = """## Triage and analysis - Was the service handling sign-ins around the load, and which identities may have been exposed? - Focus: if Windows Security authentication telemetry is collected, recover the service session from `process.Ext.authentication_id`, then query events on `host.id` where `winlog.event_data.TargetLogonId` matches it. - - Hint: this exposure pivot depends on an additional data source that may not be collected on every PTA host; read `winlog.event_data.TargetUserName`, `source.ip`, `event.outcome`, and `winlog.event_data.AuthenticationPackageName`. Missing authentication telemetry is unresolved, not benign. + - Hint: this exposure pivot depends on an additional data source that may not be collected on every PTA host; read `user.target.name`, `source.ip`, `event.outcome`, and `winlog.event_data.AuthenticationPackageName`. Missing authentication telemetry is unresolved, not benign. - Implication: escalate credential exposure when successful sign-ins or repeated attempts overlap the load because a malicious module could access PTA credentials handled by the service; bound exposure as lower only when authentication records show the service was idle and the module, provenance, and lineage evidence also fit benign activity. - If earlier findings remain suspicious, do additional module loads or related alerts show broader service or host compromise? diff --git a/rules/windows/credential_access_kerberos_coerce.toml b/rules/windows/credential_access_kerberos_coerce.toml index 09d13e7fe9d..10f2b3e5425 100644 --- a/rules/windows/credential_access_kerberos_coerce.toml +++ b/rules/windows/credential_access_kerberos_coerce.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/14" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/04/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -56,11 +56,11 @@ note = """## Triage and analysis #### Possible investigation steps - Which ADIDNS record or access event matched the coercion blob? - - Focus: `event.code`, `winlog.event_data.AdditionalInfo`, `winlog.event_data.ObjectDN`, `winlog.event_data.DSName`, and `winlog.computer_name` to place the marshaled CREDENTIAL_TARGET_INFORMATION blob in its MicrosoftDNS partition. + - Focus: `event.code`, `winlog.event_data.AdditionalInfo`, `winlog.event_data.ObjectDN`, `winlog.event_data.DSName`, and `host.name` to place the marshaled CREDENTIAL_TARGET_INFORMATION blob in its MicrosoftDNS partition. - Implication: a namespace used by real clients makes the alert high priority; a lab-only namespace reduces urgency only when later telemetry stays bounded. - Which account and logon session touched the record? - - Focus: `user.id`, `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectDomainName`, and `winlog.event_data.SubjectLogonId`. + - Focus: `user.id`, `user.id`, `user.name`, `winlog.event_data.SubjectDomainName`, and `winlog.event_data.SubjectLogonId`. - Hint: match `winlog.event_data.SubjectLogonId` on the same domain controller to authentication events where `winlog.event_data.TargetLogonId` matches, then read `source.ip` and `winlog.logon.type`. $investigate_2 Missing authentication telemetry is unresolved, not benign. - Implication: an actor, source, or logon type outside the DNS or directory-administration tier raises concern; a lab-scoped account, source, and session lowers suspicion only when the change set and authentication evidence also stay bounded. @@ -76,7 +76,7 @@ note = """## Triage and analysis - Do Windows Security authentication events show the coercion progressed? - Focus: after the directory-service event, review Windows Security logon or explicit-credential events with `event.code`, `winlog.event_data.TargetServerName`, `winlog.event_data.TargetInfo`, and `winlog.event_data.AuthenticationPackageName` tied to the spoofed hostname or expected target service. - - Hint: use `source.ip`, `winlog.event_data.TargetUserName`, and `winlog.computer_name` to identify victim systems and relay targets. Missing authentication telemetry is unresolved, not benign. + - Hint: use `source.ip`, `user.target.name`, and `host.name` to identify victim systems and relay targets. Missing authentication telemetry is unresolved, not benign. - Implication: escalate as progressed coercion when Kerberos or service access follows the record creation, especially from machine accounts or management systems; treat it as attempted-only when authentication evidence remains absent and the local record evidence is otherwise bounded. - Is the suspicious pattern isolated to this actor and domain controller? @@ -90,8 +90,8 @@ note = """## Triage and analysis ### False positive analysis -- Authorized security testing or lab validation can create CredMarshalTargetInfo-style ADIDNS records. Confirm by verifying that `winlog.event_data.ObjectDN` is in the test namespace named by the validation record, `user.id` or `winlog.event_data.SubjectUserSid` matches the named operator, the MicrosoftDNS change set stays bounded, and Windows Security authentication events stay inside the stated victim and target scope. If validation records are unavailable and telemetry cannot prove that exact workflow, keep the alert unresolved instead of closing on recurrence alone. -- Build exceptions from the minimum confirmed pattern: stable `user.id` or `winlog.event_data.SubjectUserSid`, the specific zone path in `winlog.event_data.ObjectDN`, and the logging `host.id`. Avoid exceptions on event codes 4662 or 5137, all MicrosoftDNS changes, or the blob pattern alone. +- Authorized security testing or lab validation can create CredMarshalTargetInfo-style ADIDNS records. Confirm by verifying that `winlog.event_data.ObjectDN` is in the test namespace named by the validation record, `user.id` or `user.id` matches the named operator, the MicrosoftDNS change set stays bounded, and Windows Security authentication events stay inside the stated victim and target scope. If validation records are unavailable and telemetry cannot prove that exact workflow, keep the alert unresolved instead of closing on recurrence alone. +- Build exceptions from the minimum confirmed pattern: stable `user.id` or `user.id`, the specific zone path in `winlog.event_data.ObjectDN`, and the logging `host.id`. Avoid exceptions on event codes 4662 or 5137, all MicrosoftDNS changes, or the blob pattern alone. ### Response and remediation @@ -115,9 +115,9 @@ field_names = [ "@timestamp", "event.code", "host.id", - "winlog.computer_name", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "host.name", + "user.name", + "user.id", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectDN", diff --git a/rules/windows/credential_access_ldap_attributes.toml b/rules/windows/credential_access_ldap_attributes.toml index b8ead0416e8..96471e5a30c 100644 --- a/rules/windows/credential_access_ldap_attributes.toml +++ b/rules/windows/credential_access_ldap_attributes.toml @@ -2,7 +2,7 @@ creation_date = "2022/11/09" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,7 +27,7 @@ LDAP (Lightweight Directory Access Protocol) is crucial for accessing and managi ### Possible investigation steps - Review the event logs for event code 4662 to identify the specific user or process attempting to access the sensitive LDAP attributes. -- Check the winlog.event_data.SubjectUserSid to determine the identity of the user or service account involved in the access attempt, excluding the well-known SID S-1-5-18 (Local System). +- Check the user.id to determine the identity of the user or service account involved in the access attempt, excluding the well-known SID S-1-5-18 (Local System). - Analyze the winlog.event_data.Properties field to confirm which sensitive attribute was accessed, such as unixUserPassword, ms-PKI-AccountCredentials, or msPKI-CredentialRoamingTokens. - Investigate the context of the access attempt by correlating the event with other logs or alerts around the same timestamp to identify any suspicious patterns or activities. - Verify the legitimacy of the access by checking if the user or process has a valid reason or permission to access the sensitive attributes, considering the organization's access control policies. @@ -80,7 +80,7 @@ type = "eql" query = ''' any where host.os.type == "windows" and event.code == "4662" and - not winlog.event_data.SubjectUserSid : "S-1-5-18" and + not user.id : "S-1-5-18" and winlog.event_data.Properties : ( /* unixUserPassword */ diff --git a/rules/windows/credential_access_lsass_handle_via_malseclogon.toml b/rules/windows/credential_access_lsass_handle_via_malseclogon.toml index 092b94746c2..fcaa4bcf92a 100644 --- a/rules/windows/credential_access_lsass_handle_via_malseclogon.toml +++ b/rules/windows/credential_access_lsass_handle_via_malseclogon.toml @@ -2,7 +2,7 @@ creation_date = "2022/06/29" integration = ["windows"] maturity = "production" -updated_date = "2026/04/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -75,7 +75,7 @@ note = """## Triage and analysis - Do follow-on authentication events suggest the leaked handle was used to pivot? - Why: MalSecLogon handle leakage is usually a precursor to dumping or token abuse, so later credential use can be more decisive than the access event alone. - Focus: Windows Security events for the same `host.id` and initial `user.id` pivot, especially `winlog.event_id`, `winlog.logon.type`, `winlog.event_data.TargetLogonId`, `winlog.event_data.SubjectLogonId`, and `source.ip`. $investigate_4 - - Hint: if `process.Ext.authentication_id` is available, match it to `winlog.event_data.TargetLogonId` for 4624 session creation and search `winlog.event_data.SubjectLogonId` separately for 4648 explicit-credential use; read `winlog.event_data.TargetUserSid` as the authenticated account and `winlog.event_data.SubjectUserSid` as the initiator when they differ. Missing authentication telemetry is unresolved, not benign. + - Hint: if `process.Ext.authentication_id` is available, match it to `winlog.event_data.TargetLogonId` for 4624 session creation and search `winlog.event_data.SubjectLogonId` separately for 4648 explicit-credential use; read `user.target.id` as the authenticated account and `user.id` as the initiator when they differ. Missing authentication telemetry is unresolved, not benign. - Implication: escalate when later events show NewCredentials logon type 9, explicit-credential use, or unexpected remote logons after the LSASS access; do not close solely because no follow-on authentication telemetry was ingested. - If the local evidence remains suspicious or unresolved, do related alerts for this user or host show broader credential abuse? @@ -188,12 +188,12 @@ providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }, { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetUserSid", queryType = "phrase", value = "{{user.id}}", valueType = "string" } + { excluded = false, field = "user.target.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4648", valueType = "string" }, { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{user.id}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-24h" diff --git a/rules/windows/credential_access_lsass_memdump_handle_access.toml b/rules/windows/credential_access_lsass_memdump_handle_access.toml index 8c78cf694c4..eb17f356e89 100644 --- a/rules/windows/credential_access_lsass_memdump_handle_access.toml +++ b/rules/windows/credential_access_lsass_memdump_handle_access.toml @@ -2,7 +2,7 @@ creation_date = "2022/02/16" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/12" +updated_date = "2026/06/23" [transform] [[transform.osquery]] @@ -130,7 +130,7 @@ host.os.type:"windows" and event.code:"4656" and ) and winlog.event_data.ObjectType : "Process" and winlog.event_data.ObjectName : *\\Windows\\System32\\lsass.exe and - not winlog.event_data.ProcessName : ( + not process.executable : ( "C:\Windows\System32\wbem\WmiPrvSE.exe" or "C:\Windows\SysWOW64\wbem\WmiPrvSE.exe" or "C:\Windows\System32\dllhost.exe" or @@ -149,21 +149,21 @@ host.os.type:"windows" and event.code:"4656" and [[rule.filters]] [rule.filters.meta] negate = true -[rule.filters.query.wildcard."winlog.event_data.ProcessName"] +[rule.filters.query.wildcard."process.executable"] case_insensitive = true value = "C:\\\\Program Files (x86)\\\\*.exe" [[rule.filters]] [rule.filters.meta] negate = true -[rule.filters.query.wildcard."winlog.event_data.ProcessName"] +[rule.filters.query.wildcard."process.executable"] case_insensitive = true value = "C:\\\\Program Files\\\\*.exe" [[rule.filters]] [rule.filters.meta] negate = true -[rule.filters.query.wildcard."winlog.event_data.ProcessName"] +[rule.filters.query.wildcard."process.executable"] case_insensitive = true value = "?:\\\\ProgramData\\\\Microsoft\\\\Windows Defender\\\\*.exe" @@ -188,7 +188,7 @@ reference = "https://attack.mitre.org/tactics/TA0006/" [rule.new_terms] field = "new_terms_fields" -value = ["winlog.event_data.ProcessName", "winlog.event_data.SubjectUserName"] +value = ["process.executable", "user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-1d" diff --git a/rules/windows/credential_access_machine_account_smb_relay.toml b/rules/windows/credential_access_machine_account_smb_relay.toml index 93873dba3fe..a9c77bcb0d5 100644 --- a/rules/windows/credential_access_machine_account_smb_relay.toml +++ b/rules/windows/credential_access_machine_account_smb_relay.toml @@ -2,7 +2,7 @@ creation_date = "2025/06/16" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/04/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -40,7 +40,7 @@ query = ''' file where host.os.type == "windows" and event.code == "5145" and endswith(user.name, "$") and /* compare computername with user.name and make sure they match (dot-boundary prevents prefix-only matches) */ - startswith~(concat(winlog.computer_name, "."), concat(substring(user.name, 0, -1), ".")) and + startswith~(concat(host.name, "."), concat(substring(user.name, 0, -1), ".")) and /* exclude local access */ not endswith(string(source.ip), string(host.ip)) and @@ -54,17 +54,17 @@ note = """## Triage and analysis #### Possible investigation steps - What does the alert-local 5145 event show about the remote source, target server, machine account, and exact share or pipe path? - - Focus: `source.ip`, `winlog.computer_name`, `user.name`, `winlog.event_data.ShareName`, and `winlog.event_data.RelativeTargetName`, noting "IPC$", "ADMIN$", and coercion-related named pipes in the relative target path. + - Focus: `source.ip`, `host.name`, `user.name`, `winlog.event_data.ShareName`, and `winlog.event_data.RelativeTargetName`, noting "IPC$", "ADMIN$", and coercion-related named pipes in the relative target path. - Implication: escalate when a remote source reaches relayable pipes or admin shares while `user.name` matches the target server machine account; lower suspicion only when the same source, target, and path are already tied to a known relay-safe infrastructure tier. - Does the apparent machine-account access really resolve to one target-server identity and one stable infrastructure path? - - Focus: `user.name`, `winlog.computer_name`, `host.name`, `host.ip`, and `source.ip`. + - Focus: `user.name`, `host.name`, `host.name`, `host.ip`, and `source.ip`. - Implication: relay remains likely when the target server account appears from a `source.ip` that is not one of the target server's `host.ip` values; if hostname aliases or clustering explain the address mismatch, keep validating the share path and auth evidence before closure. - Do surrounding authentication events show the same source creating machine-account network logons or NTLM fallback on the target? - Why: 5145 proves share access; 4624 and 4625 show whether the source authenticated with the target machine account and which protocol path was used, while 4648 only adds explicit-credential context. - - Focus: Windows Security events on the target server from the alert source: `winlog.event_data.TargetUserName`, `winlog.logon.type`, `winlog.event_data.AuthenticationPackageName`, and `winlog.event_data.LmPackageName`. - - Hint: pivot on 4624 and 4625 for the alert `source.ip`, target server, and `user.name` to `winlog.event_data.TargetUserName` match; use 4648 only for explicit-credential context. Missing authentication telemetry is unresolved, not benign. $investigate_2 + - Focus: Windows Security events on the target server from the alert source: `user.target.name`, `winlog.logon.type`, `winlog.event_data.AuthenticationPackageName`, and `winlog.event_data.LmPackageName`. + - Hint: pivot on 4624 and 4625 for the alert `source.ip`, target server, and `user.name` to `user.target.name` match; use 4648 only for explicit-credential context. Missing authentication telemetry is unresolved, not benign. $investigate_2 - Implication: escalate when the same source produces machine-account type 3 logons, failures followed by success, NTLM where Kerberos is expected, or weak LM details; lower suspicion only when auth fields match the same stable infrastructure path seen in the 5145 evidence. - Do surrounding 5145 events show the source revisiting relayable pipes, alternate shares, or more servers with the same machine-account pattern? @@ -84,7 +84,7 @@ note = """## Triage and analysis ### False positive analysis - Load balancers, cluster nodes, proxies, management gateways, backup, or orchestration tooling can make a machine account appear to access a share from a different source. Confirm only when the source-target-account tuple, share or pipe path, access mask, and auth method all align with the same stable infrastructure role, with no broader relayable paths or extra machine-account auth. Use topology records only to corroborate that exact telemetry pattern; if unavailable, require the same field pattern across prior alerts. -- Build exceptions from the minimum confirmed workflow: `source.ip`, `winlog.computer_name`, `user.name`, `winlog.event_data.ShareName`, and `winlog.event_data.RelativeTargetName`, plus the stable auth pattern when available. Avoid exceptions on `user.name`, `winlog.event_data.ShareName`, or `source.ip` alone. +- Build exceptions from the minimum confirmed workflow: `source.ip`, `host.name`, `user.name`, `winlog.event_data.ShareName`, and `winlog.event_data.RelativeTargetName`, plus the stable auth pattern when available. Avoid exceptions on `user.name`, `winlog.event_data.ShareName`, or `source.ip` alone. ### Response and remediation @@ -111,7 +111,7 @@ field_names = [ "host.name", "host.id", "host.ip", - "winlog.computer_name", + "host.name", "event.code", "winlog.event_data.SubjectLogonId", "winlog.event_data.IpAddress", @@ -152,13 +152,13 @@ providers = [ { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }, { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }, { excluded = false, field = "source.ip", queryType = "phrase", value = "{{source.ip}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetUserName", queryType = "phrase", value = "{{user.name}}", valueType = "string" } + { excluded = false, field = "user.target.name", queryType = "phrase", value = "{{user.name}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4625", valueType = "string" }, { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }, { excluded = false, field = "source.ip", queryType = "phrase", value = "{{source.ip}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetUserName", queryType = "phrase", value = "{{user.name}}", valueType = "string" } + { excluded = false, field = "user.target.name", queryType = "phrase", value = "{{user.name}}", valueType = "string" } ] ] relativeFrom = "now-1h" diff --git a/rules/windows/credential_access_mimikatz_memssp_default_logs.toml b/rules/windows/credential_access_mimikatz_memssp_default_logs.toml index a0c0893257f..69ad49a4a5d 100644 --- a/rules/windows/credential_access_mimikatz_memssp_default_logs.toml +++ b/rules/windows/credential_access_mimikatz_memssp_default_logs.toml @@ -2,7 +2,7 @@ creation_date = "2020/08/31" integration = ["endpoint", "windows", "sentinel_one_cloud_funnel", "m365_defender", "crowdstrike"] maturity = "production" -updated_date = "2026/05/06" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -70,7 +70,7 @@ note = """## Triage and analysis - Which accounts may have been exposed after the log appeared? - Why: MemSSP records credentials from successful authentications after injection, so exposure depends on who logged on or unlocked the host after the write. - - Focus: if Windows Security authentication logs are available, correlate same-`host.id` events after `@timestamp` with `winlog.event_id`, `winlog.event_data.TargetUserName`, `winlog.logon.type`, `source.ip`, and `winlog.event_data.AuthenticationPackageName`. $investigate_3 + - Focus: if Windows Security authentication logs are available, correlate same-`host.id` events after `@timestamp` with `winlog.event_id`, `user.target.name`, `winlog.logon.type`, `source.ip`, and `winlog.event_data.AuthenticationPackageName`. $investigate_3 - Implication: escalate when privileged, service, machine, remote, or unexpected NTLM logons appear after creation; if policy permits secure collection, accounts visible in "mimilsa.log" are direct exposure evidence. Missing Windows Security telemetry or uncollected log content is unresolved, not benign. - Does the host show default in-memory MemSSP only, or a persistent SSP setup? diff --git a/rules/windows/credential_access_mimikatz_powershell_module.toml b/rules/windows/credential_access_mimikatz_powershell_module.toml index c6654707867..2ff85ddd386 100644 --- a/rules/windows/credential_access_mimikatz_powershell_module.toml +++ b/rules/windows/credential_access_mimikatz_powershell_module.toml @@ -2,7 +2,7 @@ creation_date = "2020/12/07" integration = ["windows"] maturity = "production" -updated_date = "2026/04/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -86,7 +86,7 @@ note = """## Triage and analysis - Implication: escalate when files appear in writable, external, or collection paths, especially certificate exports or archives matching the reconstructed command. Missing file telemetry is unresolved, not benign. - Do authentication records show post-alert credential use? - - Focus: Windows Security events after `@timestamp`, separating `event.code` 4624/4648/4625 and reading `winlog.event_data.TargetUserName`, `source.ip`, and `winlog.event_data.TargetServerName`. $investigate_3 + - Focus: Windows Security events after `@timestamp`, separating `event.code` 4624/4648/4625 and reading `user.target.name`, `source.ip`, and `winlog.event_data.TargetServerName`. $investigate_3 - Hint: If endpoint process telemetry is available for this host, recover the matching process via `host.id + process.pid` before using `process.*` or `process.parent.*` for interpretation; bridge recovered `process.Ext.authentication_id` to `winlog.event_data.TargetLogonId`, and search `winlog.event_data.SubjectLogonId` separately for 4648 explicit-credential events. - Implication: escalate when new privileged logons, explicit-credential use, remote source IPs, or unusual authentication-package patterns follow the script. Missing authentication telemetry is unresolved, not benign. @@ -109,7 +109,7 @@ note = """## Triage and analysis - If confirmed benign, document the reconstructed script, source path, host-user scope, recovered launcher context if available, authentication evidence, and exercise evidence that confirmed the bounded test before reversing temporary containment. Create an exception only when that stable evidence set is confirmed, not from one unconfirmed event. - If suspicious but unconfirmed, preserve the reconstructed script-block events, source script path, recovered process record if available, dump, password-store, ticket/hash, or certificate-export artifacts, and relevant Windows Security records before containment. Then apply reversible controls tied to the evidence, such as temporary session restriction, heightened monitoring, or limiting access for the affected `user.id` on `host.id`. - If confirmed malicious, record evidence before destructive action, then isolate the endpoint or restrict the account based on the artifact and authentication findings. Terminate PowerShell only after evidence capture, then block or quarantine confirmed malicious scripts, artifact hashes, domains, or destinations only when those indicators were recovered during scoping. -- If credential dumping is confirmed, treat the involved `user.id` and any additional `winlog.event_data.TargetUserName` accounts as exposed only when reconstruction, artifacts, or authentication records support that exposure. Prioritize resets for privileged, service, and lateral-movement-relevant accounts, and review related hosts and users for the same authentication or alert pattern before artifact removal. +- If credential dumping is confirmed, treat the involved `user.id` and any additional `user.target.name` accounts as exposed only when reconstruction, artifacts, or authentication records support that exposure. Prioritize resets for privileged, service, and lateral-movement-relevant accounts, and review related hosts and users for the same authentication or alert pattern before artifact removal. - If certificate, DPAPI, vault, ticket, or hash material is confirmed, preserve the affected `file.path` locations and references in `powershell.file.script_block_text`, then coordinate revocation, re-issuance, reset, or downstream trust updates for the confirmed material. - After containment and credential, certificate, or alternate-authentication actions, remove staged scripts, dumps, archives, or exported key material only after scoping related hosts and users for the same source path, account, and authentication evidence. """ diff --git a/rules/windows/credential_access_mod_wdigest_security_provider.toml b/rules/windows/credential_access_mod_wdigest_security_provider.toml index e091a428fb0..26dcda3dc7f 100644 --- a/rules/windows/credential_access_mod_wdigest_security_provider.toml +++ b/rules/windows/credential_access_mod_wdigest_security_provider.toml @@ -2,7 +2,7 @@ creation_date = "2021/01/19" integration = ["endpoint", "windows", "m365_defender"] maturity = "production" -updated_date = "2026/04/29" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -82,7 +82,7 @@ note = """## Triage and analysis - Implication: escalate when children show Mimikatz/sekurlsa, ProcDump or comsvcs.dll LSASS dumping, CrackMapExec, PowerShell remote execution, archives, or cleanup; absent follow-on evidence narrows extraction proof but does not clear enablement. - Did any accounts authenticate while WDigest was enabled? - - Focus: logon events after `@timestamp`: `event.code` 4624, `winlog.event_data.TargetUserName`, `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, and `source.ip`. $investigate_3 + - Focus: logon events after `@timestamp`: `event.code` 4624, `user.target.name`, `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, and `source.ip`. $investigate_3 - Hint: expand until WDigest is disabled or the host is contained; for domain NTLM, search domain-controller 4776 records for the alert host as source workstation. - Implication: escalate credential exposure when successful WDigest or privileged logons occur after enablement. Missing authentication telemetry is unresolved, not benign. diff --git a/rules/windows/credential_access_posh_request_ticket.toml b/rules/windows/credential_access_posh_request_ticket.toml index 25d5429101b..624b0a4f621 100644 --- a/rules/windows/credential_access_posh_request_ticket.toml +++ b/rules/windows/credential_access_posh_request_ticket.toml @@ -2,7 +2,7 @@ creation_date = "2022/01/24" integration = ["windows"] maturity = "production" -updated_date = "2026/04/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -68,7 +68,7 @@ note = """## Triage and analysis - Implication: escalate when writes show SPN lists, ".kirbi" tickets, "$krb5tgs$" or John/Hashcat text, "TicketByteHexStream", base64 blobs, archives, or temp/share/user-writable staging; no file output does not clear direct hash output or memory-only ticket export, and missing file telemetry is unresolved, not benign. - Do domain-controller ticket events confirm active Kerberoasting behavior? - - Focus: DC-side Windows Security `event.code` 4769 near alert time, starting with `winlog.event_data.TargetUserName` = alert `user.name` for domain requesters; review `winlog.event_data.TargetDomainName`, `source.ip`, `winlog.event_data.ServiceName`, `winlog.event_data.TicketEncryptionType`, and target SPN volume. $investigate_5 + - Focus: DC-side Windows Security `event.code` 4769 near alert time, starting with `user.target.name` = alert `user.name` for domain requesters; review `winlog.event_data.TargetDomainName`, `source.ip`, `winlog.event_data.ServiceName`, `winlog.event_data.TicketEncryptionType`, and target SPN volume. $investigate_5 - Hint: if the alert user is local, SYSTEM, or the transform is quiet, retry DC 4769 with UPN/domain variants from `user.name` + `user.domain`, then pivot by source host/address and candidate requester from reconstruction or launch context. - Implication: escalate when 4769 events show broad SPN enumeration, RC4 or weak encryption, service-account-heavy targeting, or client addresses inconsistent with the expected workflow. Missing authentication telemetry is unresolved, not benign. @@ -189,7 +189,7 @@ label = "Kerberos service ticket events for the alert user name" description = "" providers = [ [ - { excluded = false, field = "winlog.event_data.TargetUserName", queryType = "phrase", value = "{{user.name}}", valueType = "string" }, + { excluded = false, field = "user.target.name", queryType = "phrase", value = "{{user.name}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4769", valueType = "string" } ] ] diff --git a/rules/windows/credential_access_saved_creds_vault_winlog.toml b/rules/windows/credential_access_saved_creds_vault_winlog.toml index 2b62541ede2..4138976a957 100644 --- a/rules/windows/credential_access_saved_creds_vault_winlog.toml +++ b/rules/windows/credential_access_saved_creds_vault_winlog.toml @@ -2,7 +2,7 @@ creation_date = "2022/08/30" integration = ["system", "windows"] maturity = "production" -updated_date = "2025/11/14" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ Windows Credential Manager stores credentials for web logins, apps, and networks - Review the process associated with the flagged PID to determine if it is a legitimate application or potentially malicious. Check for known software or unusual executables. - Investigate the source and destination of the web credentials read by examining the winlog.event_data.Resource field to identify any suspicious or unexpected URLs. -- Check the winlog.computer_name to identify the affected system and assess whether it is a high-value target or has been involved in previous suspicious activities. +- Check the host.name to identify the affected system and assess whether it is a high-value target or has been involved in previous suspicious activities. - Analyze the timeline of events around the alert to identify any preceding or subsequent suspicious activities that may indicate a broader attack pattern. - Verify the user context by examining the winlog.event_data.SubjectLogonId to ensure the activity was not performed by a privileged or administrative account without proper authorization. - Cross-reference the event with other security logs or alerts to identify any correlated activities that might suggest a coordinated attack or compromise. @@ -69,7 +69,7 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name, winlog.process.pid with maxspan=1s +sequence by host.name, winlog.process.pid with maxspan=1s /* 2 consecutive vault reads from same pid for web creds */ diff --git a/rules/windows/credential_access_seenabledelegationprivilege_assigned_to_user.toml b/rules/windows/credential_access_seenabledelegationprivilege_assigned_to_user.toml index fe34873a967..c7fe1793538 100644 --- a/rules/windows/credential_access_seenabledelegationprivilege_assigned_to_user.toml +++ b/rules/windows/credential_access_seenabledelegationprivilege_assigned_to_user.toml @@ -2,7 +2,7 @@ creation_date = "2022/01/27" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/04/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -51,12 +51,12 @@ note = """## Triage and analysis #### Possible investigation steps - Which principal received SeEnableDelegationPrivilege, and is it narrow enough for delegation administration? - - Focus: the "4704" grant's `winlog.event_data.PrivilegeList`, `winlog.event_data.TargetSid`, and `winlog.computer_name`; resolve `winlog.event_data.TargetSid` when the account name is absent. + - Focus: the "4704" grant's `winlog.event_data.PrivilegeList`, `user.target.id`, and `host.name`; resolve `user.target.id` when the account name is absent. - Implication: escalate when the target is a human user, broad admin cohort, stale account, or identity not dedicated to delegation administration; lower concern only for a narrow delegation-admin or service-management principal with controlled source, rollback, and no follow-on abuse. - Did a direct actor assign the right, or is the event local policy application? - Why: "4704" often shows "SYSTEM" or the machine account applying policy, which is not the same as identifying the upstream policy editor. - - Focus: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectLogonId`, and `winlog.computer_name` to separate a human or service actor from "S-1-5-18" or a machine account. + - Focus: `user.id`, `user.name`, `winlog.event_data.SubjectLogonId`, and `host.name` to separate a human or service actor from "S-1-5-18" or a machine account. - Implication: escalate when a user-backed or unexpected service account directly assigned the right; when the subject is "SYSTEM" or the machine account, treat it as policy application and keep the upstream policy source unresolved until evidence outside "4704" explains it. - If the grant came from a user-backed session, does the linked logon fit the admin tier? @@ -65,27 +65,27 @@ note = """## Triage and analysis - Implication: escalate for an unusual admin source, remote-interactive or NewCredentials logon, unexpected NTLM, or explicit-credential use; lower concern when Kerberos and the source host fit the controlled delegation-admin workflow. - Did authorization-policy activity stay bounded and roll back? - - Focus: surrounding grant/removal events on `winlog.computer_name` for the same `winlog.event_data.SubjectUserSid` and `winlog.event_data.SubjectLogonId`, including other `winlog.event_data.PrivilegeList` or `winlog.event_data.TargetSid` values. $investigate_1 - - Hint: check paired removals for the same `winlog.event_data.TargetSid`, `winlog.event_data.PrivilegeList`, and `winlog.computer_name`. $investigate_2 + - Focus: surrounding grant/removal events on `host.name` for the same `user.id` and `winlog.event_data.SubjectLogonId`, including other `winlog.event_data.PrivilegeList` or `user.target.id` values. $investigate_1 + - Hint: check paired removals for the same `user.target.id`, `winlog.event_data.PrivilegeList`, and `host.name`. $investigate_2 - Implication: escalate when the same context grants other rights, removes guardrails, touches multiple principals, repeats the grant, or lacks rollback; lower urgency when activity stays bounded to one controlled grant-plus-rollback cycle for the same target. - Did the actor or newly empowered account modify delegation attributes after the grant? - Why: this right is most dangerous when followed by delegation changes on user or computer objects. - - Focus: later "5136" events where `winlog.event_data.SubjectUserSid` matches the assigning or granted principal; review `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue` for "userAccountControl" trusted-for-delegation flags or "msDS-AllowedToDelegateTo" updates. $investigate_3 - - Hint: if "5136" coverage is unavailable, preserve `winlog.event_data.TargetSid`, `winlog.event_data.SubjectUserSid`, and `winlog.computer_name` for AD follow-up instead of treating absent evidence as benign. + - Focus: later "5136" events where `user.id` matches the assigning or granted principal; review `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue` for "userAccountControl" trusted-for-delegation flags or "msDS-AllowedToDelegateTo" updates. $investigate_3 + - Hint: if "5136" coverage is unavailable, preserve `user.target.id`, `user.id`, and `host.name` for AD follow-up instead of treating absent evidence as benign. - Implication: escalate when either principal soon changes delegation flags or constrained-delegation targets because these values can enable Kerberos S4U abuse against named services; absence of follow-on changes lowers urgency only when target, source, and rollback also align. - If local evidence remains suspicious or unresolved, do detection alerts for either SID widen scope? - - Focus: recent alert-window results for the assigning account SID, `winlog.event_data.SubjectUserSid`. $investigate_4 - - Hint: compare the same recent window with alerts for the granted account SID, `winlog.event_data.TargetSid`. $investigate_5 + - Focus: recent alert-window results for the assigning account SID, `user.id`. $investigate_4 + - Hint: compare the same recent window with alerts for the granted account SID, `user.target.id`. $investigate_5 - Implication: escalate scope when either account has privilege, directory, ticket, or lateral-movement alerts; keep the case local when histories are quiet and local evidence supports a controlled workflow. - Escalate for unexpected target/source, abnormal session, absent rollback, follow-on delegation changes, or related alerts; close only when target, source, session, rollback, delegation attributes, and scope bind one controlled workflow; preserve and escalate mixed or incomplete evidence. ### False positive analysis -- Controlled delegation administration can legitimately trigger this rule when a dedicated delegation-admin or service-management principal is temporarily granted this right. Confirm only when `winlog.event_data.TargetSid`, `winlog.event_data.SubjectUserSid` or SYSTEM/machine policy path, `winlog.computer_name`, direct-session `source.ip`, `winlog.logon.type`, `winlog.event_data.AuthenticationPackageName`, rollback, and bounded `winlog.event_data.AttributeLDAPDisplayName` or `winlog.event_data.ObjectDN` changes all fit the same change; use change records or AD owner confirmation when telemetry cannot prove intent, and do not close if any dimension diverges. -- Before creating an exception, validate recurrence for the same source, `winlog.event_data.TargetSid`, `winlog.computer_name`, direct-session source when applicable, and bounded delegation-attribute pattern. Build the exception from that minimum workflow, never from "SeEnableDelegationPrivilege" or the rule name alone. +- Controlled delegation administration can legitimately trigger this rule when a dedicated delegation-admin or service-management principal is temporarily granted this right. Confirm only when `user.target.id`, `user.id` or SYSTEM/machine policy path, `host.name`, direct-session `source.ip`, `winlog.logon.type`, `winlog.event_data.AuthenticationPackageName`, rollback, and bounded `winlog.event_data.AttributeLDAPDisplayName` or `winlog.event_data.ObjectDN` changes all fit the same change; use change records or AD owner confirmation when telemetry cannot prove intent, and do not close if any dimension diverges. +- Before creating an exception, validate recurrence for the same source, `user.target.id`, `host.name`, direct-session source when applicable, and bounded delegation-attribute pattern. Build the exception from that minimum workflow, never from "SeEnableDelegationPrivilege" or the rule name alone. ### Response and remediation @@ -108,12 +108,12 @@ field_names = [ "event.code", "host.name", "host.id", - "winlog.computer_name", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "host.name", + "user.name", + "user.id", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", - "winlog.event_data.TargetSid", + "user.target.id", "winlog.event_data.PrivilegeList", "winlog.activity_id", ] @@ -143,14 +143,14 @@ label = "User-right changes by the same source session" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4704", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4705", valueType = "string" } ] @@ -163,8 +163,8 @@ label = "User-right removals for the granted principal" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetSid", queryType = "phrase", value = "{{winlog.event_data.TargetSid}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, + { excluded = false, field = "user.target.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.PrivilegeList", queryType = "phrase", value = "{{winlog.event_data.PrivilegeList}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4705", valueType = "string" } ] @@ -178,22 +178,22 @@ description = "" providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.AttributeLDAPDisplayName", queryType = "phrase", value = "userAccountControl", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.AttributeLDAPDisplayName", queryType = "phrase", value = "msDS-AllowedToDelegateTo", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.TargetSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.AttributeLDAPDisplayName", queryType = "phrase", value = "userAccountControl", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.TargetSid}}", valueType = "string" }, + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.AttributeLDAPDisplayName", queryType = "phrase", value = "msDS-AllowedToDelegateTo", valueType = "string" } ] ] @@ -206,7 +206,7 @@ description = "" providers = [ [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" @@ -218,7 +218,7 @@ description = "" providers = [ [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetSid", queryType = "phrase", value = "{{winlog.event_data.TargetSid}}", valueType = "string" } + { excluded = false, field = "user.target.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" diff --git a/rules/windows/credential_access_shadow_credentials.toml b/rules/windows/credential_access_shadow_credentials.toml index d7213705b24..86c1945aa5d 100644 --- a/rules/windows/credential_access_shadow_credentials.toml +++ b/rules/windows/credential_access_shadow_credentials.toml @@ -2,7 +2,7 @@ creation_date = "2022/01/26" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/04/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -47,7 +47,7 @@ type = "query" query = ''' event.code:"5136" and host.os.type:"windows" and winlog.event_data.AttributeLDAPDisplayName:"msDS-KeyCredentialLink" and winlog.event_data.AttributeValue :B\:828* and - not winlog.event_data.SubjectUserName: MSOL_* and + not user.name: MSOL_* and not winlog.event_data.ObjectClass: "msDS-Device" ''' @@ -62,13 +62,13 @@ note = """## Triage and analysis - Implication: escalate when a sensitive user or computer receives an added or replaced key-trust value outside recognized enrollment; lower suspicion only when the object class, DN, and operation fit the same identity-registration workflow. - Which account and logon session wrote the value? - - Focus: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectLogonId`, recovered `source.ip`, and `winlog.logon.type`. $investigate_0 + - Focus: `user.id`, `user.name`, `winlog.event_data.SubjectLogonId`, recovered `source.ip`, and `winlog.logon.type`. $investigate_0 - Hint: match alert `winlog.event_data.SubjectLogonId` to same `host.id` authentication events with `winlog.event_data.TargetLogonId`; if no 4624 matches, keep the session unresolved. - Implication: escalate for an unexpected user, admin, service, or machine writer, or source/logon type outside the object's enrollment path; lower suspicion when writer and session match recognized provisioning or device registration. - Does the writer/object pair fit a recognized ADFS or Azure AD Connect-style path? - Why: the abuse path writes authentication material, so service-looking writers still need source and change-set validation. - - Focus: compare `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.ObjectClass`, `winlog.event_data.ObjectDN`, and `source.ip` to the expected service account, object type, and enrollment source. + - Focus: compare `user.id`, `user.name`, `winlog.event_data.ObjectClass`, `winlog.event_data.ObjectDN`, and `source.ip` to the expected service account, object type, and enrollment source. - Implication: lower suspicion when recognized provisioning updates the expected object from the expected source; escalate when the writer is ad hoc, interactive, non-provisioning, object-class mismatched, or unexplained by source. - Was the logical change limited to this key credential? @@ -77,12 +77,12 @@ note = """## Triage and analysis - Did the modified identity authenticate after the change? - Why: post-change authentication shows whether the new key material may already be in use. - - Focus: derive the principal from `winlog.event_data.ObjectDN`; review authentication events for `winlog.event_data.TargetUserName`, `winlog.event_data.TargetDomainName`, `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`. + - Focus: derive the principal from `winlog.event_data.ObjectDN`; review authentication events for `user.target.name`, `winlog.event_data.TargetDomainName`, `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`. - Hint: search after `@timestamp` for Target-side fields matching the derived principal; if `source.ip` is empty, lower origin confidence instead of treating absence as benign. - Implication: escalate when the identity authenticates from a new source, unexpected logon type, or authentication path after the change; absence of follow-on use reduces urgency only when earlier evidence proves recognized provisioning. - Do related alerts change the scope beyond this object? - - Focus: recent alerts for the modifying account using `user.id` or `winlog.event_data.SubjectUserSid`. $investigate_2 + - Focus: recent alerts for the modifying account using `user.id` or `user.id`. $investigate_2 - Hint: compare with alerts scoped to the modified object's `winlog.event_data.ObjectGUID`. $investigate_3 - Implication: broaden response when either scope shows privilege abuse, directory tampering, relay activity, or lateral movement; keep local when related alerts are quiet and local evidence resolves to one recognized workflow. @@ -90,8 +90,8 @@ note = """## Triage and analysis ### False positive analysis -- AutoPilot or WHfB device enrollment can cause a computer to write its own key credential. Confirm `winlog.event_data.SubjectUserName` matches the CN in `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectClass` is "computer", `winlog.event_data.OpCorrelationID` is bounded, and no unexpected follow-on authentication occurs. -- ADFS or Azure AD Connect provisioning can update key credentials on user or computer objects. Confirm `winlog.event_data.SubjectUserSid`, `winlog.event_data.ObjectDN`, recovered `source.ip`, bounded `winlog.event_data.OpCorrelationID`, and post-change authentication align with one named workflow. Keep open when ownership is unresolved. +- AutoPilot or WHfB device enrollment can cause a computer to write its own key credential. Confirm `user.name` matches the CN in `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectClass` is "computer", `winlog.event_data.OpCorrelationID` is bounded, and no unexpected follow-on authentication occurs. +- ADFS or Azure AD Connect provisioning can update key credentials on user or computer objects. Confirm `user.id`, `winlog.event_data.ObjectDN`, recovered `source.ip`, bounded `winlog.event_data.OpCorrelationID`, and post-change authentication align with one named workflow. Keep open when ownership is unresolved. - Build exceptions from stable writer SID, object class or GUID, `host.id`, recovered source, and enrollment path across prior alerts. Avoid exceptions on "msDS-KeyCredentialLink", `user.name`, or host alone. ### Response and remediation @@ -114,8 +114,8 @@ Setup instructions: https://ela.st/audit-directory-service-changes field_names = [ "@timestamp", "user.id", - "winlog.event_data.SubjectUserSid", - "winlog.event_data.SubjectUserName", + "user.id", + "user.name", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectDN", diff --git a/rules/windows/credential_access_suspicious_winreg_access_via_sebackup_priv.toml b/rules/windows/credential_access_suspicious_winreg_access_via_sebackup_priv.toml index 6d5302a2217..be7d6f78b4c 100644 --- a/rules/windows/credential_access_suspicious_winreg_access_via_sebackup_priv.toml +++ b/rules/windows/credential_access_suspicious_winreg_access_via_sebackup_priv.toml @@ -2,7 +2,7 @@ creation_date = "2022/02/16" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -74,7 +74,7 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name, winlog.event_data.SubjectLogonId with maxspan=1m +sequence by host.name, winlog.event_data.SubjectLogonId with maxspan=1m [iam where host.os.type == "windows" and event.action == "logged-in-special" and winlog.event_data.PrivilegeList : "SeBackupPrivilege" and diff --git a/rules/windows/credential_access_via_snapshot_lsass_clone_creation.toml b/rules/windows/credential_access_via_snapshot_lsass_clone_creation.toml index 2b0a587e1de..237d59f41e7 100644 --- a/rules/windows/credential_access_via_snapshot_lsass_clone_creation.toml +++ b/rules/windows/credential_access_via_snapshot_lsass_clone_creation.toml @@ -2,7 +2,7 @@ creation_date = "2021/11/27" integration = ["windows", "system"] maturity = "production" -updated_date = "2026/04/27" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -60,7 +60,7 @@ note = """## Triage and analysis - Do authentication events show follow-on remote use, explicit credentials, or unusual logons? - Why: clone creation often precedes credential use; later auth can show post-dump pivoting. - - Focus: same-host 4624, 4648, and 4625 around `@timestamp`, using `winlog.event_data.TargetUserName`, `winlog.logon.type`, and `source.ip`. $investigate_2 + - Focus: same-host 4624, 4648, and 4625 around `@timestamp`, using `user.target.name`, `winlog.logon.type`, and `source.ip`. $investigate_2 - Implication: escalate when the host or user quickly shows new remote-interactive, service, or explicit-credential logons from unusual sources. If auth telemetry is missing, record the gap and keep the finding unresolved. - Does same-user or same-host activity repeat the evidence pattern? diff --git a/rules/windows/defense_evasion_windows_filtering_platform.toml b/rules/windows/defense_evasion_windows_filtering_platform.toml index 3e8db0bccc5..ee32250cffc 100644 --- a/rules/windows/defense_evasion_windows_filtering_platform.toml +++ b/rules/windows/defense_evasion_windows_filtering_platform.toml @@ -2,7 +2,7 @@ creation_date = "2023/12/15" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,7 +28,7 @@ The Windows Filtering Platform (WFP) is a set of API and system services that pr - Review the specific network events that triggered the alert, focusing on the event.action values "windows-firewall-packet-block" and "windows-firewall-packet-drop" to understand which processes were blocked. - Identify the process names involved in the alert from the process.name field and verify if they are related to known endpoint security software, as listed in the query. -- Check the winlog.computer_name field to determine which systems are affected and assess if multiple systems are involved, indicating a broader issue. +- Check the host.name field to determine which systems are affected and assess if multiple systems are involved, indicating a broader issue. - Investigate the recent changes to the Windows Filtering Platform rules on the affected systems to identify any unauthorized or suspicious modifications. - Correlate the blocked events with any recent security incidents or alerts to determine if there is a pattern or ongoing attack. - Consult system logs and security software logs on the affected systems for additional context or anomalies around the time of the alert. @@ -78,7 +78,7 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name with maxspan=1m +sequence by host.name with maxspan=1m [network where host.os.type == "windows" and event.action : ("windows-firewall-packet-block", "windows-firewall-packet-drop") and process.name : ( diff --git a/rules/windows/discovery_high_number_ad_properties.toml b/rules/windows/discovery_high_number_ad_properties.toml index 516d4e7174c..419120c1ed6 100644 --- a/rules/windows/discovery_high_number_ad_properties.toml +++ b/rules/windows/discovery_high_number_ad_properties.toml @@ -2,7 +2,7 @@ creation_date = "2023/01/29" integration = ["windows", "system"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,7 +27,7 @@ LDAP (Lightweight Directory Access Protocol) is crucial for querying and modifyi ### Possible investigation steps - Review the event logs for the specific event code 4662 to gather details about the suspicious read access, focusing on the winlog.event_data.Properties field to understand which attributes were accessed. -- Identify the user associated with the suspicious activity by examining the winlog.event_data.SubjectUserSid field, and determine if this user has a legitimate reason to access a high number of Active Directory object attributes. +- Identify the user associated with the suspicious activity by examining the user.id field, and determine if this user has a legitimate reason to access a high number of Active Directory object attributes. - Check the user's recent activity and login history to identify any unusual patterns or anomalies that could indicate compromised credentials or unauthorized access. - Investigate the source machine from which the LDAP queries originated to determine if it is a known and trusted device or if it shows signs of compromise or unauthorized use. - Correlate this event with other security alerts or logs to identify if this activity is part of a larger pattern of reconnaissance or privilege escalation attempts within the network. @@ -71,7 +71,7 @@ timestamp_override = "event.ingested" type = "eql" query = ''' -any where host.os.type == "windows" and event.code == "4662" and not winlog.event_data.SubjectUserSid : "S-1-5-18" and +any where host.os.type == "windows" and event.code == "4662" and not user.id : "S-1-5-18" and winlog.event_data.AccessMaskDescription == "Read Property" and length(winlog.event_data.Properties) >= 2000 ''' diff --git a/rules/windows/discovery_privileged_localgroup_membership.toml b/rules/windows/discovery_privileged_localgroup_membership.toml index 4e7da33d4d8..3e311a38881 100644 --- a/rules/windows/discovery_privileged_localgroup_membership.toml +++ b/rules/windows/discovery_privileged_localgroup_membership.toml @@ -2,7 +2,7 @@ creation_date = "2020/10/15" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [transform] [[transform.osquery]] @@ -110,11 +110,11 @@ query = ''' host.os.type:windows and event.category:iam and event.action:user-member-enumerated and ( group.name:(*Admin* or "RemoteDesktopUsers") or - winlog.event_data.TargetSid:("S-1-5-32-544" or "S-1-5-32-555") + user.target.id:("S-1-5-32-544" or "S-1-5-32-555") ) and not ( - winlog.event_data.SubjectUserName: *$ or - winlog.event_data.SubjectUserSid: ("S-1-5-19" or "S-1-5-20") or + user.name: *$ or + user.id: ("S-1-5-19" or "S-1-5-20") or winlog.event_data.CallerProcessName:("-" or C\:\\Windows\\System32\\VSSVC.exe or C\:\\Windows\\System32\\SearchIndexer.exe or diff --git a/rules/windows/discovery_whoami_command_activity.toml b/rules/windows/discovery_whoami_command_activity.toml index 95a897d3883..e99c8c394e6 100644 --- a/rules/windows/discovery_whoami_command_activity.toml +++ b/rules/windows/discovery_whoami_command_activity.toml @@ -2,7 +2,7 @@ creation_date = "2020/02/18" integration = ["endpoint", "system", "windows", "m365_defender"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -104,7 +104,7 @@ process where host.os.type == "windows" and event.type == "start" and process.na ( user.domain : ("NT *", "* NT", "IIS APPPOOL") and user.id : ("S-1-5-18", "S-1-5-19", "S-1-5-20", "S-1-5-82-*") and - not ?winlog.event_data.SubjectUserName : "*$" and + not ?user.name : "*$" and /* Sysmon will always populate user.id as S-1-5-18, leading to FPs */ not data_stream.dataset : ("windows.sysmon_operational", "windows.sysmon") diff --git a/rules/windows/execution_posh_hacktool_authors.toml b/rules/windows/execution_posh_hacktool_authors.toml index 9b3ed637c65..131b84e6051 100644 --- a/rules/windows/execution_posh_hacktool_authors.toml +++ b/rules/windows/execution_posh_hacktool_authors.toml @@ -2,7 +2,7 @@ creation_date = "2024/05/08" integration = ["windows"] maturity = "production" -updated_date = "2026/05/01" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -96,7 +96,7 @@ note = """## Triage and analysis - Implication: escalate when extracted payload paths are created or executed, or registry targets indicate persistence or security changes; missing artifact or configuration telemetry is unresolved, not benign. - Did extracted network or identity observables confirm active offensive use? - - Focus: With network telemetry, search same-PID DNS and connection events for extracted domains in `dns.question.name` or `dns.resolved_ip` and IPs in `destination.ip`. $investigate_5 Review Windows 4624 or 4648 with `winlog.event_data.TargetUserName` and `winlog.event_data.SubjectUserName` for extracted accounts. + - Focus: With network telemetry, search same-PID DNS and connection events for extracted domains in `dns.question.name` or `dns.resolved_ip` and IPs in `destination.ip`. $investigate_5 Review Windows 4624 or 4648 with `user.target.name` and `user.name` for extracted accounts. - Implication: escalate when the host contacts extracted infrastructure, downloads content, or shows remote, credential, or lateral-use evidence. Missing network or authentication telemetry is unresolved, not benign. - If the script content or launch chain remains suspicious or unresolved, does recurrence change scope? diff --git a/rules/windows/lateral_movement_credential_access_kerberos_correlation.toml b/rules/windows/lateral_movement_credential_access_kerberos_correlation.toml index 7b0bd64d4dc..f7815cca13e 100644 --- a/rules/windows/lateral_movement_credential_access_kerberos_correlation.toml +++ b/rules/windows/lateral_movement_credential_access_kerberos_correlation.toml @@ -2,7 +2,7 @@ creation_date = "2025/10/28" integration = ["endpoint", "windows", "system"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -75,7 +75,7 @@ note = """## Triage and analysis - Which Timeline member events define this Kerberos sequence? - Focus: Timeline members keyed by alert `source.ip` and `source.port`; recover source `process.executable`, Kerberos `destination.ip`, and auth `event.code`. - - Hint: record `host.id` and `process.entity_id`; verify auth `winlog.computer_name` is the DC. + - Hint: record `host.id` and `process.entity_id`; verify auth `host.name` is the DC. - Implication: escalate when one non-"lsass.exe" source process maps to a DC "4768" or "4769" event in the sequence window; lower concern for socket reuse, a different process, or non-DC destination. - Is the recovered source process a recognized Kerberos-capable client? @@ -88,25 +88,25 @@ note = """## Triage and analysis - Implication: escalate on Bifrost-like verbs or flags such as asktgt, asktgs, s4u, ptt, kerberoast, service/SPN targets, hashes, keytabs, RC4, or base64 tickets, especially from shell or script parents; bounded diagnostics from a recognized admin tool reduce but do not clear concern. - Which ticket path and target account did the DC member event show? - - Focus: recovered auth `event.code`, `winlog.event_data.TargetUserName`, and `winlog.event_data.TargetDomainName`. + - Focus: recovered auth `event.code`, `user.target.name`, and `winlog.event_data.TargetDomainName`. - Implication: escalate when "4769" shows service-ticket activity or "4768" shows TGT handling for privileged, service, machine, or delegation-sensitive targets from the unusual process; fan-out increases concern. - Does the source user and session context fit one bounded admin or audit source? - - Focus: recovered `user.id`, `user.name`, `user.domain`, and `winlog.event_data.TargetUserName`. + - Focus: recovered `user.id`, `user.name`, `user.domain`, and `user.target.name`. - Implication: escalate when privileged, service, or user-account tickets originate from a workstation, user session, or non-management tool; lower concern only when source host, user, process identity, command/parent, and target account recur as one bounded Kerberos diagnostic or audit pattern. - Do surrounding Kerberos events show repetition or account fan-out? - - Focus: same-source Kerberos network and authentication events, checking additional "4768"/"4769" events and `winlog.event_data.TargetUserName`. + - Focus: same-source Kerberos network and authentication events, checking additional "4768"/"4769" events and `user.target.name`. - $investigate_0 - $investigate_1 - Implication: escalate when requests repeat or fan out across accounts; a single bounded request narrows scope but does not close if process identity or command intent remains suspicious. Missing network or authentication telemetry is unresolved, not benign. - Do later logon or explicit-credential events suggest ticket use? - - Focus: same-source authentication results, checking later `event.code` "4624"/"4648", `winlog.event_data.TargetUserName`, and 4648 `winlog.event_data.TargetServerName`. + - Focus: same-source authentication results, checking later `event.code` "4624"/"4648", `user.target.name`, and 4648 `winlog.event_data.TargetServerName`. - Implication: escalate when post-ticket logon or explicit-credential activity reaches sensitive accounts or servers from the same source; absence narrows impact but does not close if the ticket request remains suspicious. Missing same-source authentication telemetry leaves ticket use unresolved, not benign. - If local evidence remains suspicious or unresolved, does the same source show related alerts? - - Focus: related alerts for `source.ip`; manually pivot on recovered `process.hash.sha256` or `winlog.event_data.TargetUserName` when locally suspicious. $investigate_2 + - Focus: related alerts for `source.ip`; manually pivot on recovered `process.hash.sha256` or `user.target.name` when locally suspicious. $investigate_2 - Implication: broaden scope when credential-access, Kerberoasting, relay, or lateral-movement alerts share the source, process, or target account; keep local only when related alerts are absent and recovered evidence resolves cleanly. - Escalate when sequence recovery, source-process identity, command intent, DC ticket target, account context, or surrounding ticket/logon activity show unauthorized direct Kerberos; close only when telemetry binds one recognized tool, source host, user, and target account and outside confirmation verifies exact activity when telemetry cannot; preserve and escalate when visibility is incomplete or evidence conflicts. diff --git a/rules/windows/lateral_movement_remote_service_installed_winlog.toml b/rules/windows/lateral_movement_remote_service_installed_winlog.toml index 9c6c388a807..9414322495d 100644 --- a/rules/windows/lateral_movement_remote_service_installed_winlog.toml +++ b/rules/windows/lateral_movement_remote_service_installed_winlog.toml @@ -2,7 +2,7 @@ creation_date = "2022/08/30" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ Windows services are crucial for running background processes. Adversaries explo - Check the winlog.logon.id to correlate the logon session with the service installation event, ensuring they are part of the same session. - Investigate the user account associated with the logon session to determine if the activity aligns with their typical behavior or role within the organization. - Examine the service file path from the service-installed event to identify if it is a known or legitimate application. Pay special attention to any paths not excluded in the query. -- Look into the history of the computer where the service was installed (winlog.computer_name) for any previous suspicious activities or alerts. +- Look into the history of the computer where the service was installed (host.name) for any previous suspicious activities or alerts. - Assess the timing and frequency of similar events to determine if this is an isolated incident or part of a broader pattern of suspicious behavior. ### False positive analysis @@ -65,7 +65,7 @@ tags = [ type = "eql" query = ''' -sequence by winlog.logon.id, winlog.computer_name with maxspan=1m +sequence by winlog.logon.id, host.name with maxspan=1m [authentication where host.os.type == "windows" and event.action == "logged-in" and winlog.logon.type : "Network" and event.outcome == "success" and source.ip != null and source.ip != "127.0.0.1" and source.ip != "::1"] [iam where host.os.type == "windows" and event.action == "service-installed" and diff --git a/rules/windows/persistence_ad_adminsdholder.toml b/rules/windows/persistence_ad_adminsdholder.toml index 823dd515c10..b8a68347832 100644 --- a/rules/windows/persistence_ad_adminsdholder.toml +++ b/rules/windows/persistence_ad_adminsdholder.toml @@ -2,7 +2,7 @@ creation_date = "2022/01/31" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -54,7 +54,7 @@ note = """## Triage and analysis - What did the correlated 5136 operation contain? - Why: one alert document may show only part of a logical directory change; `winlog.event_data.OpCorrelationID` reconstructs the rest of the operation. - - Focus: review same-controller `5136` events for the same `host.id`, `winlog.computer_name`, and `winlog.event_data.OpCorrelationID`; compare attribute, value, and operation type. $investigate_0 + - Focus: review same-controller `5136` events for the same `host.id`, `host.name`, and `winlog.event_data.OpCorrelationID`; compare attribute, value, and operation type. $investigate_0 - Implication: escalate when the operation adds multiple ACL changes, touches unrelated sensitive attributes, or suggests a staged AdminSDHolder template rewrite; lower concern only when bounded to one expected non-security update on the same object. - Does the recovered value grant or preserve access that SDProp can stamp onto protected identities? @@ -63,15 +63,15 @@ note = """## Triage and analysis - Implication: escalate when the value adds a SID, DN, ACE, owner path, Full Control, Modify, WriteDacl, WriteOwner, or GenericAll outside the expected tier-0 admin set; truncated or opaque values keep permission impact unresolved and require preserving raw change data. - Who initiated the modification, and where did the session originate? - - Focus: identify the writer and controller with `user.id`, `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectLogonId`, and `winlog.computer_name`. - - Hint: on the same `winlog.computer_name`, match `5136` `winlog.event_data.SubjectLogonId` to `4624` `winlog.event_data.TargetLogonId`; search `4648` for the same `winlog.event_data.SubjectLogonId` when explicit credentials matter, then read `source.ip` and `winlog.event_data.AuthenticationPackageName`. Missing linked authentication records or `source.ip` leaves origin unresolved, not benign. + - Focus: identify the writer and controller with `user.id`, `user.id`, `winlog.event_data.SubjectLogonId`, and `host.name`. + - Hint: on the same `host.name`, match `5136` `winlog.event_data.SubjectLogonId` to `4624` `winlog.event_data.TargetLogonId`; search `4648` for the same `winlog.event_data.SubjectLogonId` when explicit credentials matter, then read `source.ip` and `winlog.event_data.AuthenticationPackageName`. Missing linked authentication records or `source.ip` leaves origin unresolved, not benign. - $investigate_1 - $investigate_2 - Implication: escalate when the writer is unexpected, source or auth method does not fit tier-0 administration, or origin remains unresolved with a security-relevant change; do not wait on auth pivots when the attribute/value and change set already prove unauthorized rights. - Did the template change propagate or get forced onto protected objects? - Why: SDProp can apply the AdminSDHolder template to protected accounts and groups, so impact may appear after the initial directory-change event. - - Focus: on the same `winlog.event_data.DSName` or `winlog.computer_name`, review later `5136` events for object, attribute, writer, and time on protected users or groups. + - Focus: on the same `winlog.event_data.DSName` or `host.name`, review later `5136` events for object, attribute, writer, and time on protected users or groups. - Hint: if the logging controller has no follow-on records, search the same `winlog.event_data.DSName` across domain controllers; absence on one controller does not clear propagation. $investigate_3 - Implication: escalate when later events show security-descriptor, owner, or trustee changes on protected identities after the AdminSDHolder edit; no follow-on `5136` visibility leaves propagation unresolved, not benign. @@ -82,7 +82,7 @@ note = """## Triage and analysis ### False positive analysis - AdminSDHolder ACL hardening, delegated-directory cleanup, security-baseline tooling, or migration automation are narrow tier-0 exceptions, not routine administration. Confirm the exact attribute/value/operation for `winlog.event_data.ObjectDN`, expected admin or service-account session, bounded `winlog.event_data.OpCorrelationID`, matching controller/template rollout, and no unrelated actor or controller alerts. If change records, automation inventory, or deployment records exist, require alignment; otherwise prove the current actor/action or service-account/template fit from telemetry first, then use prior recurrence only to support exception stability. -- Before creating an exception, validate recurrence of the same `user.id` or `winlog.event_data.SubjectUserSid`, specific attribute, object, `winlog.event_data.DSName`, bounded operation shape, and controller pattern across prior alerts from this rule. Build the exception from that minimum confirmed workflow only after the current event is fully explained, and avoid exceptions on AdminSDHolder changes, Windows Security event "5136", or the rule name alone. +- Before creating an exception, validate recurrence of the same `user.id` or `user.id`, specific attribute, object, `winlog.event_data.DSName`, bounded operation shape, and controller pattern across prior alerts from this rule. Build the exception from that minimum confirmed workflow only after the current event is fully explained, and avoid exceptions on AdminSDHolder changes, Windows Security event "5136", or the rule name alone. ### Response and remediation @@ -103,8 +103,8 @@ Setup instructions: https://ela.st/audit-directory-service-changes field_names = [ "@timestamp", "user.id", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "user.name", + "user.id", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectDN", "winlog.event_data.ObjectClass", @@ -114,7 +114,7 @@ field_names = [ "winlog.event_data.OpCorrelationID", "winlog.event_data.DSName", "host.id", - "winlog.computer_name", + "host.name", ] [transform] @@ -137,7 +137,7 @@ label = "Linked logon for the modifying session" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.TargetLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" } ] @@ -150,7 +150,7 @@ label = "Explicit credential events for the modifying session" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4648", valueType = "string" } ] @@ -167,7 +167,7 @@ providers = [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" } ] ] diff --git a/rules/windows/persistence_dontexpirepasswd_account.toml b/rules/windows/persistence_dontexpirepasswd_account.toml index ce03f9e1265..2352bdcb12f 100644 --- a/rules/windows/persistence_dontexpirepasswd_account.toml +++ b/rules/windows/persistence_dontexpirepasswd_account.toml @@ -2,7 +2,7 @@ creation_date = "2022/02/22" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -93,7 +93,7 @@ any where host.os.type == "windows" and event.code == "5136" and winlog.event_data.AttributeLDAPDisplayName == "userAccountControl" and winlog.event_data.AttributeValue in ("66048", "66080") and winlog.event_data.OperationType == "%%14674" and not ( - winlog.event_data.SubjectUserName : "*svc*" or + user.name : "*svc*" or winlog.event_data.ObjectDN : "*Service*" ) ) diff --git a/rules/windows/persistence_group_modification_by_system.toml b/rules/windows/persistence_group_modification_by_system.toml index 2d06e7c9646..7ea8efca8aa 100644 --- a/rules/windows/persistence_group_modification_by_system.toml +++ b/rules/windows/persistence_group_modification_by_system.toml @@ -2,7 +2,7 @@ creation_date = "2024/06/26" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -70,7 +70,7 @@ type = "eql" query = ''' iam where host.os.type == "windows" and event.code == "4728" and -winlog.event_data.SubjectUserSid : "S-1-5-18" and +user.id : "S-1-5-18" and /* DOMAIN_USERS and local groups */ not group.id : "S-1-5-21-*-513" diff --git a/rules/windows/persistence_msds_alloweddelegateto_krbtgt.toml b/rules/windows/persistence_msds_alloweddelegateto_krbtgt.toml index 1734c8d2255..3963a0a9518 100644 --- a/rules/windows/persistence_msds_alloweddelegateto_krbtgt.toml +++ b/rules/windows/persistence_msds_alloweddelegateto_krbtgt.toml @@ -2,7 +2,7 @@ creation_date = "2022/01/27" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -46,11 +46,11 @@ note = """## Triage and analysis #### Possible investigation steps - What account was changed, and what krbtgt delegation value did the alert preserve? - - Focus: alert 4738 evidence in `winlog.event_data.TargetSid`, `winlog.event_data.TargetUserName`, `winlog.event_data.TargetDomainName`, `winlog.event_data.AllowedToDelegateTo`, and `winlog.computer_name`. + - Focus: alert 4738 evidence in `user.target.id`, `user.target.name`, `winlog.event_data.TargetDomainName`, `winlog.event_data.AllowedToDelegateTo`, and `host.name`. - Implication: Escalate when the target now lists a krbtgt service target such as "krbtgt/DOMAIN"; lower suspicion only when the target, value, and controller match a time-boxed security validation or emergency delegation repair explicitly naming krbtgt, which is not routine delegation. - Who initiated the account change? - - Focus: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectDomainName`, and `winlog.event_data.SubjectLogonId`. + - Focus: `user.id`, `user.name`, `winlog.event_data.SubjectDomainName`, and `winlog.event_data.SubjectLogonId`. - Implication: Escalate when a human admin, newly introduced service identity, or unexpected controller-local context made the change; lower suspicion only when the same stable tier-0 identity owns this exact delegation-maintenance path. - What source and authentication method created the modifying session? @@ -59,23 +59,23 @@ note = """## Triage and analysis - Implication: Escalate for an unusual source, remote-interactive access, unexpected NTLM, or explicit credentials; lower suspicion when the session maps to the expected tier-0 admin path for this controller. - Did surrounding directory changes prepare, repeat, or roll back the krbtgt delegation? - - Focus: surrounding 4738 records for the same `winlog.event_data.TargetSid`, plus 5136 records on the same `winlog.computer_name` and modifying subject/session; use `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue` to identify the affected object and value. + - Focus: surrounding 4738 records for the same `user.target.id`, plus 5136 records on the same `host.name` and modifying subject/session; use `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue` to identify the affected object and value. - Hint: reconstruct the burst from same-target 4738 and same-controller directory-service changes; if 5136 grouping is thin, use `winlog.record_id` order on the same controller plus subject/session and object DN. Absent 5136 evidence leaves prerequisite and rollback context unresolved, not benign. - $investigate_2 - $investigate_3 - Implication: Escalate when `winlog.event_data.AttributeLDAPDisplayName` and `winlog.event_data.AttributeValue` show delegation-enabling changes, repeated msDS-AllowedToDelegateTo writes, or no rollback; prompt removal narrows the persistence window but does not clear actor or session intent. - Does the same actor or target touch other delegation-relevant accounts in the case window? - - Focus: run this only if earlier answers are suspicious or unresolved; search 4738 and 5136 records for the same modifying subject/session or `winlog.event_data.TargetSid`, then compare `winlog.event_data.TargetUserName`, `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue`. + - Focus: run this only if earlier answers are suspicious or unresolved; search 4738 and 5136 records for the same modifying subject/session or `user.target.id`, then compare `user.target.name`, `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue`. - Implication: Broaden scope when the same actor or target appears in additional delegation writes across objects or controllers; keep it narrow when changes stay confined to one exact target and resolved maintenance path. $investigate_4 - Escalate when a non-routine actor/session adds krbtgt delegation, supporting directory changes show setup, the value remains, or same-actor/target scope expands; close only when the modified account, krbtgt value, actor/session, source/authentication context, surrounding changes, rollback, and scope all align with one tightly controlled authorized workflow; preserve raw 4738, authentication, and directory-change evidence and escalate when findings stay mixed or incomplete. ### False positive analysis -- Authorized security validation or emergency delegation repair can trigger this rule only when krbtgt delegation is the explicit planned action. Confirm the target (`winlog.event_data.TargetSid` plus `winlog.event_data.AllowedToDelegateTo`), actor/session (`winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectLogonId`, and recovered authentication context), controller, and surrounding attribute evidence all align. If change records are unavailable, telemetry-only closure must still bind one exact workflow with no contradictions; prior benign recurrence strengthens confidence but is not required. +- Authorized security validation or emergency delegation repair can trigger this rule only when krbtgt delegation is the explicit planned action. Confirm the target (`user.target.id` plus `winlog.event_data.AllowedToDelegateTo`), actor/session (`user.id`, `winlog.event_data.SubjectLogonId`, and recovered authentication context), controller, and surrounding attribute evidence all align. If change records are unavailable, telemetry-only closure must still bind one exact workflow with no contradictions; prior benign recurrence strengthens confidence but is not required. - Do not close generic service onboarding, migration, or constrained-delegation cutover as benign unless outside confirmation explicitly names krbtgt delegation and telemetry matches that exact target, actor, session, and controller path. A normal service-delegation explanation that does not account for the krbtgt value is incomplete. -- Before creating an exception, validate that the same `winlog.event_data.SubjectUserSid`, `winlog.event_data.TargetSid`, exact `winlog.event_data.AllowedToDelegateTo`, `winlog.computer_name`, and recovered session pattern identify the authorized workflow across prior benign cases or a tightly controlled test plan. Build the exception from that minimum confirmed pattern, and avoid exceptions on "krbtgt", event 4738, or "msDS-AllowedToDelegateTo" alone. +- Before creating an exception, validate that the same `user.id`, `user.target.id`, exact `winlog.event_data.AllowedToDelegateTo`, `host.name`, and recovered session pattern identify the authorized workflow across prior benign cases or a tightly controlled test plan. Build the exception from that minimum confirmed pattern, and avoid exceptions on "krbtgt", event 4738, or "msDS-AllowedToDelegateTo" alone. ### Response and remediation @@ -98,18 +98,18 @@ field_names = [ "@timestamp", "user.name", "user.id", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "user.name", + "user.id", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.logon.id", - "winlog.event_data.TargetUserName", - "winlog.event_data.TargetSid", + "user.target.name", + "user.target.id", "winlog.event_data.TargetDomainName", "winlog.event_data.AllowedToDelegateTo", "host.name", "host.id", - "winlog.computer_name", + "host.name", ] [transform] @@ -146,7 +146,7 @@ description = "" providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "4738", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetSid", queryType = "phrase", value = "{{winlog.event_data.TargetSid}}", valueType = "string" } + { excluded = false, field = "user.target.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4738", valueType = "string" }, @@ -162,13 +162,13 @@ description = "" providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-24h/h" @@ -180,11 +180,11 @@ description = "" providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "4738", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" diff --git a/rules/windows/persistence_remote_password_reset.toml b/rules/windows/persistence_remote_password_reset.toml index 90ff0865df1..5fde99d98fc 100644 --- a/rules/windows/persistence_remote_password_reset.toml +++ b/rules/windows/persistence_remote_password_reset.toml @@ -2,7 +2,7 @@ creation_date = "2021/10/18" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,7 +28,7 @@ Remote password resets are crucial for managing user accounts, especially for pr ### Possible investigation steps - Review the source IP address from the authentication event to determine if it is from a known or trusted network. Investigate any unfamiliar or suspicious IP addresses. -- Check the winlog.event_data.TargetUserName from the password reset event to confirm if it belongs to a privileged account and verify if the reset was authorized. +- Check the user.target.name from the password reset event to confirm if it belongs to a privileged account and verify if the reset was authorized. - Correlate the winlog.event_data.SubjectLogonId from both the authentication and password reset events to ensure they are linked and identify the user or process responsible for the actions. - Investigate the timing and frequency of similar events to identify patterns or anomalies that may indicate malicious activity. - Examine any recent changes or activities associated with the account in question to assess if there are other signs of compromise or unauthorized access. @@ -83,12 +83,12 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name with maxspan=1m +sequence by host.name with maxspan=1m [authentication where host.os.type == "windows" and event.action == "logged-in" and /* event 4624 need to be logged */ winlog.logon.type : "Network" and event.outcome == "success" and source.ip != null and source.ip != "127.0.0.1" and source.ip != "::1" and - not winlog.event_data.TargetUserName : ("svc*", "PIM_*", "_*_", "*-*-*", "*$")] by winlog.event_data.TargetLogonId + not user.target.name : ("svc*", "PIM_*", "_*_", "*-*-*", "*$")] by winlog.event_data.TargetLogonId /* event 4724 need to be logged */ [iam where host.os.type == "windows" and event.action == "reset-password" and ( @@ -96,8 +96,8 @@ sequence by winlog.computer_name with maxspan=1m This rule is very noisy if not scoped to privileged accounts, duplicate the rule and add your own naming convention and accounts of interest here. */ - winlog.event_data.TargetUserName: ("*Admin*", "*super*", "*SVC*", "*DC0*", "*service*", "*DMZ*", "*ADM*") or - winlog.event_data.TargetSid : ("S-1-5-21-*-500", "S-1-12-1-*-500") + user.target.name: ("*Admin*", "*super*", "*SVC*", "*DC0*", "*service*", "*DMZ*", "*ADM*") or + user.target.id : ("S-1-5-21-*-500", "S-1-12-1-*-500") ) ] by winlog.event_data.SubjectLogonId ''' diff --git a/rules/windows/persistence_scheduled_task_updated.toml b/rules/windows/persistence_scheduled_task_updated.toml index d529ec92c0c..693d18eafd3 100644 --- a/rules/windows/persistence_scheduled_task_updated.toml +++ b/rules/windows/persistence_scheduled_task_updated.toml @@ -2,7 +2,7 @@ creation_date = "2022/08/29" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -73,7 +73,7 @@ type = "new_terms" query = ''' event.category: "iam" and host.os.type:"windows" and event.code: "4702" and - not winlog.event_data.SubjectUserSid : ("S-1-5-18" or "S-1-5-19" or "S-1-5-20") and + not user.id : ("S-1-5-18" or "S-1-5-19" or "S-1-5-20") and not user.name : *$ ''' diff --git a/rules/windows/persistence_sdprop_exclusion_dsheuristics.toml b/rules/windows/persistence_sdprop_exclusion_dsheuristics.toml index e50d3ba9fcb..df94f529810 100644 --- a/rules/windows/persistence_sdprop_exclusion_dsheuristics.toml +++ b/rules/windows/persistence_sdprop_exclusion_dsheuristics.toml @@ -2,7 +2,7 @@ creation_date = "2022/02/24" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -112,7 +112,7 @@ field_names = [ "host.name", "host.id", "user.id", - "winlog.event_data.SubjectUserSid", + "user.id", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectDN", "winlog.event_data.ObjectGUID", diff --git a/rules/windows/persistence_temp_scheduled_task.toml b/rules/windows/persistence_temp_scheduled_task.toml index 874384fa21c..80500740c7a 100644 --- a/rules/windows/persistence_temp_scheduled_task.toml +++ b/rules/windows/persistence_temp_scheduled_task.toml @@ -2,7 +2,7 @@ creation_date = "2022/08/29" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -27,7 +27,7 @@ Scheduled tasks in Windows environments automate routine tasks, but adversaries ### Possible investigation steps -- Review the winlog.computer_name field to identify the affected system and determine if it is a critical asset or part of a sensitive network segment. +- Review the host.name field to identify the affected system and determine if it is a critical asset or part of a sensitive network segment. - Examine the winlog.event_data.TaskName to understand the nature of the task created and deleted, and assess if it aligns with known legitimate tasks or appears suspicious. - Investigate the user.name associated with the task creation and deletion events to determine if the activity was performed by a legitimate user or potentially compromised account. - Check for any related events or logs around the same timeframe on the affected system to identify any additional suspicious activities or anomalies. @@ -66,7 +66,7 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name, winlog.event_data.TaskName with maxspan=5m +sequence by host.name, winlog.event_data.TaskName with maxspan=5m [iam where host.os.type == "windows" and event.action == "scheduled-task-created" and not user.name : "*$"] [iam where host.os.type == "windows" and event.action == "scheduled-task-deleted" and not user.name : "*$"] ''' diff --git a/rules/windows/privilege_escalation_badsuccessor_dmsa_abuse.toml b/rules/windows/privilege_escalation_badsuccessor_dmsa_abuse.toml index f339003e6ac..c747ec0131b 100644 --- a/rules/windows/privilege_escalation_badsuccessor_dmsa_abuse.toml +++ b/rules/windows/privilege_escalation_badsuccessor_dmsa_abuse.toml @@ -2,7 +2,7 @@ creation_date = "2025/05/23" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -52,7 +52,7 @@ note = """## Triage and analysis - Hint: if the operation ID is incomplete, query 5136 on `host.id` plus `winlog.event_data.SubjectLogonId` for same-session dMSA or privileged-object changes. - Implication: escalate on standalone link write, unexpected value replacement, or unrelated ACL, delegation, SPN, or service-account changes; lower suspicion when same-operation or same-session changes stay bounded to one expected migration pair. - Who wrote the link, and does the identity fit dMSA management? - - Focus: use `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectDomainName`, `winlog.event_data.SubjectLogonId`, and `winlog.computer_name` to identify writer, controller session, and service vs human. + - Focus: use `user.id`, `user.name`, `winlog.event_data.SubjectDomainName`, `winlog.event_data.SubjectLogonId`, and `host.name` to identify writer, controller session, and service vs human. - Implication: escalate when the writer is an unfamiliar human, helpdesk account, or low-privilege service identity for dMSA management; keep unresolved when a recognized writer is not tied to the exact dMSA pair. - Did the writer session originate from an expected source and logon type? - Focus: pivot from `winlog.event_data.SubjectLogonId` and `host.id` to authentication where `winlog.event_data.TargetLogonId` matches; review `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`. $investigate_1 @@ -60,7 +60,7 @@ note = """## Triage and analysis - Implication: escalate when the session starts from an unexpected host, uses unusual interactive/RDP logon, or shows explicit-credential behavior outside the writer's role; expected source and logon type support closure only after link target and operation cohere. - Did the linked dMSA or superseded account authenticate from unexpected systems after the change? - Why: risk peaks when the new dMSA relationship is exercised from hosts that should not use the inherited service account. - - Focus: derive dMSA and superseded account names from `winlog.event_data.ObjectDN` and `winlog.event_data.AttributeValue`, then review authentication by `winlog.event_data.TargetUserName`, `source.ip`, and `winlog.logon.type`. + - Focus: derive dMSA and superseded account names from `winlog.event_data.ObjectDN` and `winlog.event_data.AttributeValue`, then review authentication by `user.target.name`, `source.ip`, and `winlog.logon.type`. - Hint: missing authentication telemetry is unresolved, not benign; an unused link still needs disposition from link target, writer, and sequence. - Implication: escalate when either account authenticates from a new host, admin workstation, or service path after the change; unchanged or absent use does not clear suspicion. - If still suspicious or unresolved, do recent writer or dMSA alerts show broader abuse? @@ -72,15 +72,15 @@ note = """## Triage and analysis ### False positive analysis -- Planned dMSA migration by identity/service-account admins may set "msDS-ManagedAccountPrecededByLink". Confirm `winlog.event_data.ObjectDN`, planned `winlog.event_data.AttributeValue`, paired `winlog.event_data.OpCorrelationID`, `winlog.event_data.SubjectUserSid`, recovered `source.ip`, and `winlog.logon.type` match migration account/host path. Telemetry-only closure requires anchors proving one bounded migration; otherwise require records, tickets, or identity-admin confirmation for the exact dMSA pair and writer. Do not close from recurrence or role assumptions. -- Lab validation or staged service-account modernization may trigger. Confirm `winlog.event_data.ObjectDN` and `winlog.event_data.AttributeValue` stay in the authorized test/staging OU, session avoids unrelated privileged objects, and follow-on `winlog.event_data.TargetUserName` or `source.ip` is limited to test hosts. Telemetry-only closure requires test OU, writer, bounded change set, and follow-on hosts proving lab scope; otherwise require test records or lab owner confirmation. -- Before exception, confirm the exact workflow: `winlog.event_data.SubjectUserSid`, `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeValue`, bounded `winlog.event_data.OpCorrelationID`, and recovered controller or source path. Use exceptions only when that verified workflow should repeat; avoid exceptions on the attribute, 5136, or all dMSA changes. +- Planned dMSA migration by identity/service-account admins may set "msDS-ManagedAccountPrecededByLink". Confirm `winlog.event_data.ObjectDN`, planned `winlog.event_data.AttributeValue`, paired `winlog.event_data.OpCorrelationID`, `user.id`, recovered `source.ip`, and `winlog.logon.type` match migration account/host path. Telemetry-only closure requires anchors proving one bounded migration; otherwise require records, tickets, or identity-admin confirmation for the exact dMSA pair and writer. Do not close from recurrence or role assumptions. +- Lab validation or staged service-account modernization may trigger. Confirm `winlog.event_data.ObjectDN` and `winlog.event_data.AttributeValue` stay in the authorized test/staging OU, session avoids unrelated privileged objects, and follow-on `user.target.name` or `source.ip` is limited to test hosts. Telemetry-only closure requires test OU, writer, bounded change set, and follow-on hosts proving lab scope; otherwise require test records or lab owner confirmation. +- Before exception, confirm the exact workflow: `user.id`, `winlog.event_data.ObjectDN`, `winlog.event_data.AttributeValue`, bounded `winlog.event_data.OpCorrelationID`, and recovered controller or source path. Use exceptions only when that verified workflow should repeat; avoid exceptions on the attribute, 5136, or all dMSA changes. ### Response and remediation - If confirmed benign, reverse containment and record: writer SID, dMSA DN, superseded account DN, bounded sequence, recovered source path, and external confirmation for the change. Create an exception only when that workflow should repeat. - If suspicious but unconfirmed, export the triggering 5136 record, same-operation change sequence, writer-session auth records, explicit-credential evidence, and related alerts before destructive changes. Apply reversible containment first: restrict the recovered source host from domain controllers or monitor the writer, modified dMSA, and superseded account. Disable the writer or isolate the source host only if additional privileged changes, unexpected follow-on authentication, or related alerts appear. -- If confirmed malicious, preserve directory-change and session evidence first, then use endpoint response to isolate the recovered source host and disable/reset the malicious dMSA, compromised writer, and affected superseded service account. If endpoint response is unavailable on the source system, escalate with preserved `source.ip`, `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectLogonId`, `winlog.event_data.ObjectGUID`, and related 5136, 4624, or 4648 evidence to responders. Review hosts/services that used the same superseded account or new dMSA before cleanup, verify rollback replication across domain controllers, and only then remove the unauthorized `winlog.event_data.AttributeValue` link, roll back related migration/SPN/delegation changes in the same `winlog.event_data.OpCorrelationID` sequence, and rotate affected secrets or restore service bindings. +- If confirmed malicious, preserve directory-change and session evidence first, then use endpoint response to isolate the recovered source host and disable/reset the malicious dMSA, compromised writer, and affected superseded service account. If endpoint response is unavailable on the source system, escalate with preserved `source.ip`, `user.id`, `winlog.event_data.SubjectLogonId`, `winlog.event_data.ObjectGUID`, and related 5136, 4624, or 4648 evidence to responders. Review hosts/services that used the same superseded account or new dMSA before cleanup, verify rollback replication across domain controllers, and only then remove the unauthorized `winlog.event_data.AttributeValue` link, roll back related migration/SPN/delegation changes in the same `winlog.event_data.OpCorrelationID` sequence, and rotate affected secrets or restore service bindings. - Post-incident hardening: restrict dMSA creation/migration rights, verify domain-controller retention for 5136, 4624, and 4648, and record the migration workflow or BadSuccessor evidence for reuse. """ @@ -94,8 +94,8 @@ Setup instructions: https://ela.st/audit-directory-service-changes field_names = [ "@timestamp", "event.code", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "user.name", + "user.id", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectDN", @@ -106,7 +106,7 @@ field_names = [ "winlog.event_data.OperationType", "winlog.event_data.OpCorrelationID", "host.id", - "winlog.computer_name", + "host.name", ] [transform] @@ -146,7 +146,7 @@ providers = [ ], [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" @@ -166,7 +166,7 @@ relativeTo = "now" [rule.new_terms] field = "new_terms_fields" -value = ["winlog.event_data.SubjectUserName"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/windows/privilege_escalation_create_process_as_different_user.toml b/rules/windows/privilege_escalation_create_process_as_different_user.toml index 059a9e2fd57..10999b7365f 100644 --- a/rules/windows/privilege_escalation_create_process_as_different_user.toml +++ b/rules/windows/privilege_escalation_create_process_as_different_user.toml @@ -2,7 +2,7 @@ creation_date = "2022/08/30" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -69,7 +69,7 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name with maxspan=1m +sequence by host.name with maxspan=1m [authentication where host.os.type == "windows" and event.action:"logged-in" and event.outcome == "success" and user.id : ("S-1-5-21-*", "S-1-12-1-*") and diff --git a/rules/windows/privilege_escalation_credroaming_ldap.toml b/rules/windows/privilege_escalation_credroaming_ldap.toml index 3156a6d623a..02969034cbc 100644 --- a/rules/windows/privilege_escalation_credroaming_ldap.toml +++ b/rules/windows/privilege_escalation_credroaming_ldap.toml @@ -2,7 +2,7 @@ creation_date = "2022/11/09" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -29,7 +29,7 @@ The msPKIAccountCredentials attribute in Active Directory stores encrypted crede ### Possible investigation steps - Review the event logs for the specific event code 5136 to gather details about the modification event, including the timestamp and the user account involved. -- Examine the winlog.event_data.SubjectUserSid field to identify the user who attempted the modification, ensuring it is not the system account (S-1-5-18). +- Examine the user.id field to identify the user who attempted the modification, ensuring it is not the system account (S-1-5-18). - Investigate the history and behavior of the identified user account to determine if there are any previous suspicious activities or anomalies. - Check for any recent changes or anomalies in the affected Active Directory User Object, focusing on the msPKIAccountCredentials attribute. - Assess the potential impact of the modification by identifying any files or systems that may have been affected by the altered credentials. @@ -81,7 +81,7 @@ type = "query" query = ''' event.code:"5136" and host.os.type:"windows" and winlog.event_data.AttributeLDAPDisplayName:"msPKIAccountCredentials" and winlog.event_data.OperationType:"%%14674" and - not winlog.event_data.SubjectUserSid : "S-1-5-18" + not user.id : "S-1-5-18" ''' diff --git a/rules/windows/privilege_escalation_dmsa_creation_by_unusual_user.toml b/rules/windows/privilege_escalation_dmsa_creation_by_unusual_user.toml index 99fdd76f3e8..850cffacafc 100644 --- a/rules/windows/privilege_escalation_dmsa_creation_by_unusual_user.toml +++ b/rules/windows/privilege_escalation_dmsa_creation_by_unusual_user.toml @@ -2,7 +2,7 @@ creation_date = "2025/05/23" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -43,7 +43,7 @@ note = """## Triage and analysis #### Possible investigation steps - What dMSA object did the alert show, and where was it created? - - Focus: use `winlog.event_data.ObjectClass`, `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.SubjectUserName`, and `winlog.computer_name` to identify the new msDS-DelegatedManagedServiceAccount, new-to-this-rule writer, and controller. + - Focus: use `winlog.event_data.ObjectClass`, `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `user.name`, and `host.name` to identify the new msDS-DelegatedManagedServiceAccount, new-to-this-rule writer, and controller. - Implication: escalate when the object is in a privileged service, sync, backup, DC, or identity-infrastructure path, or when name or writer lacks a narrow service-account purpose; lower only when DN, writer, and controller match one exact planned dMSA rollout or lab path. - Did the same dMSA receive migration or privilege-enabling attributes? - Why: BadSuccessor-style abuse elevates creation with `5136` changes such as msDS-ManagedAccountPrecededByLink, msDS-DelegatedMSAState, SPNs, delegation attributes, or gMSA membership. @@ -51,14 +51,14 @@ note = """## Triage and analysis - Hint: if same-controller results have gaps, repeat the `winlog.event_data.ObjectGUID` search across DC Windows Security logs before treating missing follow-on changes as lower risk. - Implication: escalate when values link the dMSA to a privileged predecessor, advance migration state, or add SPN/delegation material; lower suspicion only when attributes form one bounded migration to the intended legacy service account. - Who created the dMSA, and what session reached the domain controller? - - Focus: identify writer and session with `winlog.event_data.SubjectUserSid` and `winlog.event_data.SubjectLogonId`, then recover `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`. $investigate_1 + - Focus: identify writer and session with `user.id` and `winlog.event_data.SubjectLogonId`, then recover `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`. $investigate_1 - Hint: this pivot uses `winlog.event_data.TargetLogonId` for `4624` or `4634`; search `4648` separately with `winlog.event_data.SubjectLogonId` when explicit-credential use matters. Missing authentication telemetry is unresolved, not benign. - Implication: escalate for an unexpected human, helpdesk account, low-privilege service identity, unusual source, interactive/RDP session, or explicit-credential path; lower suspicion only when actor and source match the narrow identity-management path for this object. - Did the same session touch other directory objects? - Focus: compare surrounding `5137` and `5136` records on the same `host.id` for `winlog.event_data.SubjectLogonId`, reading `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectClass`, and `winlog.event_data.AttributeLDAPDisplayName`. - Implication: escalate when the session creates multiple dMSAs, edits ACLs, changes delegation, or touches unrelated privileged users, computers, groups, or service accounts; lower when every change stays tied to one bounded dMSA rollout. - Did the new dMSA get used from systems that should not touch it? - - Focus: derive the dMSA from the CN in `winlog.event_data.ObjectDN`, confirm it in `winlog.event_data.TargetUserName`, then review `4624` records for `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`; search `4648` separately for explicit credential use. + - Focus: derive the dMSA from the CN in `winlog.event_data.ObjectDN`, confirm it in `user.target.name`, then review `4624` records for `source.ip`, `winlog.logon.type`, and `winlog.event_data.AuthenticationPackageName`; search `4648` separately for explicit credential use. - Hint: absent dMSA authentication is a timing or visibility gap, not proof creation is harmless. - Implication: escalate when the dMSA authenticates from unexpected servers, workstations, jump hosts, or non-service logon types; lower suspicion only when use stays inside the exact service host set for the confirmed rollout. - If local evidence is suspicious or incomplete, do related Windows Security events show broader AD abuse? @@ -69,13 +69,13 @@ note = """## Triage and analysis ### False positive analysis -- Planned dMSA rollout or service-account migration can legitimately create msDS-DelegatedManagedServiceAccount objects. Confirm expected `winlog.event_data.ObjectDN`, same-object `5136` attributes limited to the intended legacy service account, and `winlog.event_data.SubjectUserSid`, recovered `source.ip`, and `winlog.logon.type` matching the narrow migration account and host path. If change records, migration tickets, or owner confirmation are unavailable, leave unresolved unless telemetry proves the exact authorized workflow. -- Lab validation or staged service-account modernization can also trigger this rule. Confirm `winlog.event_data.ObjectDN` stays in the test/staging OU, the same `winlog.event_data.SubjectLogonId` avoids unrelated privileged objects, and any `winlog.event_data.TargetUserName`, `source.ip`, or `winlog.logon.type` activity stays limited to designated test systems. If test scope lacks outside confirmation, treat the alert as unresolved. -- Before creating an exception, validate exact writer `winlog.event_data.SubjectUserSid`, dMSA path pattern, bounded same-object `5136` attributes, controller path, and recovered source. Use a temporary or tightly scoped exception for one-time migrations, and avoid exceptions on event `5137`, all msDS-DelegatedManagedServiceAccount objects, or all dMSA creation activity. +- Planned dMSA rollout or service-account migration can legitimately create msDS-DelegatedManagedServiceAccount objects. Confirm expected `winlog.event_data.ObjectDN`, same-object `5136` attributes limited to the intended legacy service account, and `user.id`, recovered `source.ip`, and `winlog.logon.type` matching the narrow migration account and host path. If change records, migration tickets, or owner confirmation are unavailable, leave unresolved unless telemetry proves the exact authorized workflow. +- Lab validation or staged service-account modernization can also trigger this rule. Confirm `winlog.event_data.ObjectDN` stays in the test/staging OU, the same `winlog.event_data.SubjectLogonId` avoids unrelated privileged objects, and any `user.target.name`, `source.ip`, or `winlog.logon.type` activity stays limited to designated test systems. If test scope lacks outside confirmation, treat the alert as unresolved. +- Before creating an exception, validate exact writer `user.id`, dMSA path pattern, bounded same-object `5136` attributes, controller path, and recovered source. Use a temporary or tightly scoped exception for one-time migrations, and avoid exceptions on event `5137`, all msDS-DelegatedManagedServiceAccount objects, or all dMSA creation activity. ### Response and remediation -- If confirmed benign, reverse any temporary containment and document the evidence that proved the authorized workflow: `winlog.event_data.SubjectUserSid`, `winlog.event_data.ObjectDN`, same-object `5136` sequence, recovered `source.ip`, `winlog.logon.type`, and exact rollout or lab scope. +- If confirmed benign, reverse any temporary containment and document the evidence that proved the authorized workflow: `user.id`, `winlog.event_data.ObjectDN`, same-object `5136` sequence, recovered `source.ip`, `winlog.logon.type`, and exact rollout or lab scope. - If suspicious but unconfirmed, preserve a case export with the triggering `5137`, related same-object `5136` records, recovered `4624` or `4648` records, and key object/session identifiers before containment. Apply reversible containment first, such as temporary DC access restrictions for the recovered source or heightened monitoring on the writer and dMSA. Disable the writer or isolate the source host only if privileged follow-on changes, unexpected authentication, or related events appear. - If confirmed malicious, preserve the same directory-change and session evidence first, then remove the unauthorized dMSA and roll back related msDS-ManagedAccountPrecededByLink, msDS-DelegatedMSAState, SPN, delegation, or membership changes found in the same-object sequence. Isolate the recovered source host when endpoint response is available and host criticality permits, then disable or reset the compromised writer and any linked service accounts. - Before deleting objects or closing the case, review hosts and services that used the new dMSA, verify rollback replication across domain controllers, then rotate affected secrets or restore service bindings. @@ -94,8 +94,8 @@ field_names = [ "event.code", "user.name", "user.id", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "user.name", + "user.id", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectDN", @@ -104,7 +104,7 @@ field_names = [ "winlog.event_data.DSName", "host.name", "host.id", - "winlog.computer_name", + "host.name", ] [transform] @@ -147,7 +147,7 @@ providers = [ { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ], [ - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" @@ -166,7 +166,7 @@ relativeTo = "now" [rule.new_terms] field = "new_terms_fields" -value = ["winlog.event_data.SubjectUserName"] +value = ["user.name"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-7d" diff --git a/rules/windows/privilege_escalation_group_policy_privileged_groups.toml b/rules/windows/privilege_escalation_group_policy_privileged_groups.toml index f6c52dcbac0..48a6d742edf 100644 --- a/rules/windows/privilege_escalation_group_policy_privileged_groups.toml +++ b/rules/windows/privilege_escalation_group_policy_privileged_groups.toml @@ -2,7 +2,7 @@ creation_date = "2021/11/08" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -50,8 +50,8 @@ note = """## Triage and analysis - Focus: `winlog.event_data.AttributeLDAPDisplayName`, `winlog.event_data.AttributeValue`, `winlog.event_data.OperationType`, `winlog.event_data.ObjectDN`, and `winlog.event_data.ObjectGUID` confirm the 5136 "gPCMachineExtensionNames" GPO change. - Implication: escalate when the value enables Security CSE GUID "827D319E-6EAC-11D2-A4EA-00C04F79F83A" plus Computer Restricted Groups GUID "803E14A0-B4FB-11D0-A0D0-00A0C90F574B" on an unexpected GPO; lower concern only when artifacts/scope confirm a recognized hardening refresh. - Who changed the GPO, and from where? - - Focus: identify the writer: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectLogonId`, and `winlog.computer_name`. - - Hint: on `winlog.computer_name`, find "4624" where `winlog.event_data.TargetLogonId` equals the 5136 `winlog.event_data.SubjectLogonId`; search "4648" on `winlog.event_data.SubjectLogonId` for explicit credentials, then check `source.ip`, `winlog.logon.type`, `winlog.event_data.TargetUserName`, and `winlog.event_data.TargetServerName`. Missing logon telemetry is unresolved, not benign. + - Focus: identify the writer: `user.id`, `user.name`, `winlog.event_data.SubjectLogonId`, and `host.name`. + - Hint: on `host.name`, find "4624" where `winlog.event_data.TargetLogonId` equals the 5136 `winlog.event_data.SubjectLogonId`; search "4648" on `winlog.event_data.SubjectLogonId` for explicit credentials, then check `source.ip`, `winlog.logon.type`, `user.target.name`, and `winlog.event_data.TargetServerName`. Missing logon telemetry is unresolved, not benign. - $investigate_0 - $investigate_1 - Implication: escalate when the writer is outside GPO admin cohort, uses an unusual source or direct domain-controller session, or shows alternate-credential use; lower concern when account/session match a recognized GPO administration path. @@ -62,7 +62,7 @@ note = """## Triage and analysis - Implication: escalate when the operation touches other sensitive GPO attributes or combines this privilege path with GPO execution or persistence; lower concern when the 5136 set stays narrow and artifact/scope checks confirm one recognized security-template task. - What grants and recipients does the SYSVOL template define? - Why: the alert proves machine security extensions were enabled; rights or local group membership live in "GptTmpl.inf" under the SYSVOL policy folder. - - Focus: use the policy GUID from the CN portion of `winlog.event_data.ObjectDN` with `winlog.event_data.DSName` to inspect "Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf"; map SIDs/groups to admin tier, service-account role, and whether `winlog.event_data.SubjectUserSid` benefits. Treat `winlog.event_data.ObjectGUID` as the AD object pivot, not the SYSVOL folder name, unless it matches the CN. + - Focus: use the policy GUID from the CN portion of `winlog.event_data.ObjectDN` with `winlog.event_data.DSName` to inspect "Machine/Microsoft/Windows NT/SecEdit/GptTmpl.inf"; map SIDs/groups to admin tier, service-account role, and whether `user.id` benefits. Treat `winlog.event_data.ObjectGUID` as the AD object pivot, not the SYSVOL folder name, unless it matches the CN. - Hint: if SYSVOL is unavailable, preserve `winlog.event_data.ObjectDN`, `winlog.event_data.ObjectGUID`, `winlog.event_data.DSName`, and expected policy path; suspicious writer/session or companion 5136 evidence makes the missing grant an evidence gap. - Implication: escalate when "[Privilege Rights]" grants high-impact rights ("SeDebugPrivilege", "SeTakeOwnershipPrivilege", "SeEnableDelegationPrivilege", or "SeImpersonatePrivilege"), when "[Group Membership]" adds broad/unexpected identities to local Administrators ("S-1-5-32-544"), or when the writer benefits; lower concern when entries and recipients match the recognized baseline for that GPO. - Which computers consume the changed GPO? @@ -89,7 +89,7 @@ note = """## Triage and analysis ### Response and remediation - If confirmed benign, reverse temporary containment and document writer SID, GPO object, logon/correlation IDs, recovered "GptTmpl.inf", and OU/host scope matching the workflow. Keep exceptions narrow and tied to that stable pattern. -- If suspicious but unconfirmed, preserve the "5136" event, object and writer/session IDs, `winlog.event_data.OpCorrelationID`, `winlog.computer_name`, exported "GptTmpl.inf", available SYSVOL metadata, linked "4624"/"4648" events, and related activity before containment. Use reversible controls first: restrict affected-GPO edits, limit the writer's GPO admin path, or monitor linked systems during scoping. Disable accounts or roll back GPOs only if follow-on abuse or malicious grants are confirmed. +- If suspicious but unconfirmed, preserve the "5136" event, object and writer/session IDs, `winlog.event_data.OpCorrelationID`, `host.name`, exported "GptTmpl.inf", available SYSVOL metadata, linked "4624"/"4648" events, and related activity before containment. Use reversible controls first: restrict affected-GPO edits, limit the writer's GPO admin path, or monitor linked systems during scoping. Disable accounts or roll back GPOs only if follow-on abuse or malicious grants are confirmed. - If confirmed malicious, preserve evidence first, remove unauthorized "[Privilege Rights]" or "[Group Membership]" entries, roll the GPO back to known-good state, and verify exported SYSVOL metadata before forcing policy refresh. Use identity/endpoint response to contain the writer account and admin workstation identified by `source.ip` or `winlog.logon.type`; if unavailable, escalate with writer/session, GPO, correlation, and SYSVOL artifacts. - Review linked OUs and affected computers before deleting artifacts or forcing "gpupdate"; complete scoping before evidence changes. - Harden: restrict GPO edit rights to dedicated admin tiers, retain "5136" auditing, keep security-template baselines, and document abuse variants or visibility gaps for detection engineering. @@ -105,8 +105,8 @@ Setup instructions: https://ela.st/audit-directory-service-changes field_names = [ "@timestamp", "user.id", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "user.name", + "user.id", "winlog.event_data.SubjectLogonId", "winlog.event_data.ObjectDN", "winlog.event_data.ObjectGUID", @@ -116,7 +116,7 @@ field_names = [ "winlog.event_data.OpCorrelationID", "winlog.event_data.DSName", "host.id", - "winlog.computer_name", + "host.name", ] [transform] @@ -126,7 +126,7 @@ label = "Linked logon for the GPO writer" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }, { excluded = false, field = "winlog.event_data.TargetLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" } ] @@ -139,7 +139,7 @@ label = "Explicit-credential events for the GPO writer" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4648", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" } ] @@ -152,12 +152,12 @@ label = "5136 events in this GPO change operation" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, { excluded = false, field = "winlog.event_data.OpCorrelationID", queryType = "phrase", value = "{{winlog.event_data.OpCorrelationID}}", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "5136", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" } ] diff --git a/rules/windows/privilege_escalation_krbrelayup_service_creation.toml b/rules/windows/privilege_escalation_krbrelayup_service_creation.toml index eae4599db0a..bf2bb601a3c 100644 --- a/rules/windows/privilege_escalation_krbrelayup_service_creation.toml +++ b/rules/windows/privilege_escalation_krbrelayup_service_creation.toml @@ -2,7 +2,7 @@ creation_date = "2022/04/27" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -38,7 +38,7 @@ tags = [ type = "eql" query = ''' -sequence by winlog.computer_name with maxspan=5m +sequence by host.name with maxspan=5m [authentication where host.os.type == "windows" and /* event 4624 need to be logged */ @@ -59,30 +59,30 @@ note = """## Triage and analysis - Do the source events show a loopback Kerberos logon followed by service creation in the same session? - Why: sequence alerts merge fields; recover the 4624 and 4697 Timeline source events before interpreting grouped meaning. - - Focus: `winlog.computer_name`: 4624 `source.ip`, `winlog.logon.type`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.TargetLogonId`; 4697 `winlog.event_data.SubjectLogonId`. + - Focus: `host.name`: 4624 `source.ip`, `winlog.logon.type`, `winlog.event_data.AuthenticationPackageName`, `winlog.event_data.TargetLogonId`; 4697 `winlog.event_data.SubjectLogonId`. - Implication: escalate when loopback Kerberos network logon and 4697 service install share the same logon ID; lower suspicion when recovery shows no matching 4697, non-loopback source, or a different session. - Which identity received the elevated loopback Kerberos session? - - Focus: 4624 `winlog.event_data.TargetUserName`, `winlog.event_data.TargetDomainName`, `winlog.event_data.TargetUserSid`, `user.id`, and `winlog.event_data.ElevatedToken`; Subject fields are the local initiator, not the authenticated identity. + - Focus: 4624 `user.target.name`, `winlog.event_data.TargetDomainName`, `user.target.id`, `user.id`, and `winlog.event_data.ElevatedToken`; Subject fields are the local initiator, not the authenticated identity. - Implication: escalate when the authenticated identity is an unexpected admin, service, or machine-account path for this host; lower suspicion only when the same identity and lab or deployment host cohort are recognized for this validation pattern. - What service did the recovered 4697 install? - Focus: 4697 `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceAccount`, `winlog.event_data.ServiceStartType`, and `winlog.event_data.ServiceType`. - Implication: escalate when the service uses a throwaway name, shell or script command, user-writable payload, or LocalSystem execution. Public tools may use "KrbSCM" or "UACBypassedService"; lower suspicion only when stable service metadata, account, and host cohort match the same authorized validation or owner-confirmed deployment workflow. - Do same-session Windows Security events show credential use, privilege activation, or additional service activity? - Focus: same-host Windows Security events surrounding the sequence, keyed on `winlog.event_data.SubjectLogonId`; read 4624, 4648, and additional 4697 records. $investigate_0 - - Hint: query `winlog.computer_name` plus either recovered logon ID across the alert window first; expand only if source-event ordering is unclear. + - Hint: query `host.name` plus either recovered logon ID across the alert window first; expand only if source-event ordering is unclear. - Hint: Missing authentication telemetry is unresolved, not benign. - Implication: escalate when the same session shows explicit credentials or multiple service installs; keep scope local when evidence remains one recovered 4624-to-4697 chain with no contradictory activity. - If local evidence remains suspicious or unresolved, do related alerts show the same relay-to-service chain elsewhere? - - Focus: related alerts for `winlog.computer_name` in the last 48 hours that reuse the same service name or command, or show Kerberos or service-install abuse on this host. $investigate_1 + - Focus: related alerts for `host.name` in the last 48 hours that reuse the same service name or command, or show Kerberos or service-install abuse on this host. $investigate_1 - Hint: compare `user.id` only if the host view does not show whether one operator or account cohort is involved. $investigate_2 - Implication: broaden scope when related alerts show the same host or user preparing, reusing, or expanding the service-creation chain; keep response local when related-alert review is quiet and source events already resolve the case. - Escalate when source recovery confirms loopback Kerberos followed by suspicious LocalSystem service creation; close only when the session, identity, service metadata, and surrounding Windows Security evidence fit one exact benign activity with corroborating owner or test records when telemetry cannot prove legitimacy; preserve and escalate when evidence is mixed. ### False positive analysis -- Authorized exploit validation, red-team work, or security research can reproduce this rule on lab systems. Confirm the 4624-to-4697 chain, `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `user.id`, and `winlog.computer_name` match test scope and timing. Without change or test records, close only when telemetry independently proves that validation scope; mark a one-off test as non-exceptionable instead of requiring recurrence. -- Treat loopback Kerberos plus service creation as an operational anti-pattern outside authorized validation. A deployment or support claim is benign only when owner or runbook confirmation and source events prove this exact local SCM path, stable `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceAccount`, `user.id`, `winlog.computer_name`, and no relay-prerequisite or follow-on alerts. -- Before creating an exception, pin `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceAccount`, `user.id`, and `winlog.computer_name`, and add an expiry or test-scope constraint for one-off validation. Avoid exceptions on loopback `source.ip`, event 4624, event 4697, or Kerberos alone because those conditions are broader than the confirmed workflow. +- Authorized exploit validation, red-team work, or security research can reproduce this rule on lab systems. Confirm the 4624-to-4697 chain, `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `user.id`, and `host.name` match test scope and timing. Without change or test records, close only when telemetry independently proves that validation scope; mark a one-off test as non-exceptionable instead of requiring recurrence. +- Treat loopback Kerberos plus service creation as an operational anti-pattern outside authorized validation. A deployment or support claim is benign only when owner or runbook confirmation and source events prove this exact local SCM path, stable `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceAccount`, `user.id`, `host.name`, and no relay-prerequisite or follow-on alerts. +- Before creating an exception, pin `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceAccount`, `user.id`, and `host.name`, and add an expiry or test-scope constraint for one-off validation. Avoid exceptions on loopback `source.ip`, event 4624, event 4697, or Kerberos alone because those conditions are broader than the confirmed workflow. ### Response and remediation @@ -102,7 +102,7 @@ The following Windows audit policies must be enabled to generate the events used [rule.investigation_fields] field_names = [ "@timestamp", - "winlog.computer_name", + "host.name", "host.id", "user.id", "event.code", @@ -125,32 +125,32 @@ label = "Windows Security events for the same logon session" description = "" providers = [ [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4648", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4697", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.TargetLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.TargetLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4648", valueType = "string" } ], [ - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" }, + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" }, { excluded = false, field = "winlog.event_data.TargetLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4697", valueType = "string" } ] @@ -164,7 +164,7 @@ description = "" providers = [ [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.computer_name", queryType = "phrase", value = "{{winlog.computer_name}}", valueType = "string" } + { excluded = false, field = "host.name", queryType = "phrase", value = "{{host.name}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" diff --git a/rules/windows/privilege_escalation_make_token_local.toml b/rules/windows/privilege_escalation_make_token_local.toml index eff0745eb94..0fb7796d2f5 100644 --- a/rules/windows/privilege_escalation_make_token_local.toml +++ b/rules/windows/privilege_escalation_make_token_local.toml @@ -2,7 +2,7 @@ creation_date = "2023/12/04" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -33,9 +33,9 @@ type = "eql" query = ''' authentication where host.os.type : "windows" and winlog.event_data.LogonProcessName : "Advapi*" and - winlog.logon.type == "Interactive" and winlog.event_data.SubjectUserSid : ("S-1-5-21*", "S-1-12-*") and - winlog.event_data.TargetUserSid : ("S-1-5-21*", "S-1-12-*") and process.executable : "C:\\*" and - not startswith~(winlog.event_data.SubjectUserSid, winlog.event_data.TargetUserSid) and + winlog.logon.type == "Interactive" and user.id : ("S-1-5-21*", "S-1-12-*") and + user.target.id : ("S-1-5-21*", "S-1-12-*") and process.executable : "C:\\*" and + not startswith~(user.id, user.target.id) and not process.executable : ("?:\\Windows\\System32\\winlogon.exe", "?:\\Windows\\System32\\wininit.exe", @@ -52,20 +52,20 @@ note = """## Triage and analysis #### Possible investigation steps - Did Advapi create an interactive logon for a different target identity? - - Focus: `winlog.logon.type`, `winlog.event_data.LogonProcessName`, `winlog.event_data.SubjectUserSid`, `winlog.event_data.TargetUserSid`, and `host.id`. + - Focus: `winlog.logon.type`, `winlog.event_data.LogonProcessName`, `user.id`, `user.target.id`, and `host.id`. - Implication: escalate when Advapi creates a different Target session without recognized credential-switch use; lower suspicion only for bounded runas or helper use on this host. Subject initiated the action; Target received the session or token. - Which process requested the alternate-credential session? - - Focus: `process.executable`, `process.name`, `process.pid`, `winlog.event_data.SubjectUserName`, and `winlog.event_data.SubjectDomainName`. + - Focus: `process.executable`, `process.name`, `process.pid`, `user.name`, and `winlog.event_data.SubjectDomainName`. - Implication: escalate when the requester is user-writable, temporary, renamed, or unrelated to credential switching; lower suspicion only for System32 runas.exe or a recognized helper tied to the same Subject. Process identity alone does not clear token creation. - Did the Target session create privileged or linked-token access? - - Focus: `winlog.event_data.TargetUserSid`, `winlog.event_data.TargetLogonId`, `winlog.event_data.TargetLinkedLogonId`, `winlog.event_data.ElevatedToken`, and `winlog.event_data.ImpersonationLevel`. + - Focus: `user.target.id`, `winlog.event_data.TargetLogonId`, `winlog.event_data.TargetLinkedLogonId`, `winlog.event_data.ElevatedToken`, and `winlog.event_data.ImpersonationLevel`. - Implication: escalate on a privileged or unusual Target account, elevated token, linked session, or impersonation-capable token. Keep unresolved when the Target cannot be tied to the requesting Subject and process; a recognized requester does not clear elevated Target token state. - Did explicit-credential records show who supplied Target credentials? - - Focus: same-host 4648 records using `winlog.event_data.SubjectLogonId`; read `winlog.event_data.TargetUserName`, `winlog.event_data.TargetDomainName`, `winlog.event_data.TargetServerName`, and `source.ip`. + - Focus: same-host 4648 records using `winlog.event_data.SubjectLogonId`; read `user.target.name`, `winlog.event_data.TargetDomainName`, `winlog.event_data.TargetServerName`, and `source.ip`. - Hint: make-token tooling may leave only Advapi, different Subject/Target SIDs, and Target session fields; do not require endpoint command-line evidence before escalation. $investigate_0 - Implication: escalate when 4648 shows the same Subject session presenting Target credentials to an unexpected server or non-local origin. Local or absent `source.ip` can occur in make-token cases and must be weighed with requester, identity pair, and token state; missing Security telemetry is unresolved, not benign. - Did the created Target session show follow-on success or authentication-method signals? - - Focus: same-host 4624 and 4634 records using `winlog.event_data.TargetLogonId`; read `winlog.event_data.TargetUserSid`, `winlog.event_data.AuthenticationPackageName`, and `source.ip`. + - Focus: same-host 4624 and 4634 records using `winlog.event_data.TargetLogonId`; read `user.target.id`, `winlog.event_data.AuthenticationPackageName`, and `source.ip`. - Implication: escalate on unexpected authentication package use, repeated successful session activity, or a non-local origin that contradicts local workflow; absent or local source details should be weighed with Target-token evidence. Missing 4624/4634 telemetry is unresolved, not benign. - $investigate_1 - $investigate_2 @@ -83,7 +83,7 @@ note = """## Triage and analysis ### False positive analysis - Recognized runas, enterprise PAM or credential-broker helpers, and authorized assessment can trigger this rule from monitored admin hosts. Confirm `process.executable`, Subject and Target identities, `host.id`, and explicit-credential or session records bind to the same workflow or validation scope; contradictory Target token details block benign closure. -- Build exceptions only from the minimum confirmed pattern, such as `process.executable` plus `winlog.event_data.SubjectUserSid`, `winlog.event_data.TargetUserSid`, and a bounded `host.id` or host group. Avoid exceptions on `process.name`, `user.name`, or the Target account alone. +- Build exceptions only from the minimum confirmed pattern, such as `process.executable` plus `user.id`, `user.target.id`, and a bounded `host.id` or host group. Avoid exceptions on `process.name`, `user.name`, or the Target account alone. ### Response and remediation @@ -111,10 +111,10 @@ field_names = [ "winlog.event_data.LogonProcessName", "winlog.event_data.ImpersonationLevel", "winlog.event_data.ElevatedToken", - "winlog.event_data.SubjectUserSid", - "winlog.event_data.SubjectUserName", + "user.id", + "user.name", "winlog.event_data.SubjectLogonId", - "winlog.event_data.TargetUserSid", + "user.target.id", "winlog.event_data.TargetLogonId", "winlog.event_data.TargetLinkedLogonId", ] @@ -194,11 +194,11 @@ description = "" providers = [ [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ], [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "user.id", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" @@ -210,11 +210,11 @@ description = "" providers = [ [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetUserSid", queryType = "phrase", value = "{{winlog.event_data.TargetUserSid}}", valueType = "string" } + { excluded = false, field = "user.target.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" } ], [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "user.id", queryType = "phrase", value = "{{winlog.event_data.TargetUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" diff --git a/rules/windows/privilege_escalation_newcreds_logon_rare_process.toml b/rules/windows/privilege_escalation_newcreds_logon_rare_process.toml index 2789844fe42..717fb145add 100644 --- a/rules/windows/privilege_escalation_newcreds_logon_rare_process.toml +++ b/rules/windows/privilege_escalation_newcreds_logon_rare_process.toml @@ -2,7 +2,7 @@ creation_date = "2023/11/15" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -67,7 +67,7 @@ type = "new_terms" query = ''' event.category:"authentication" and host.os.type:"windows" and winlog.logon.type:"NewCredentials" and winlog.event_data.LogonProcessName:Advapi* and - not winlog.event_data.SubjectUserName:*$ and + not user.name:*$ and not process.executable: (C\:\\Program*Files*\(x86\)\\*.exe or C\:\\Program*Files\\*.exe) ''' diff --git a/rules/windows/privilege_escalation_samaccountname_spoofing_attack.toml b/rules/windows/privilege_escalation_samaccountname_spoofing_attack.toml index fa10a9c96dd..37897ef6581 100644 --- a/rules/windows/privilege_escalation_samaccountname_spoofing_attack.toml +++ b/rules/windows/privilege_escalation_samaccountname_spoofing_attack.toml @@ -2,7 +2,7 @@ creation_date = "2021/12/12" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -53,27 +53,27 @@ note = """## Triage and analysis #### Possible investigation steps - What computer-account rename did the alert capture? - - Focus: `winlog.event_data.OldTargetUserName`, `winlog.event_data.NewTargetUserName`, `winlog.event_data.TargetSid`, `winlog.event_data.TargetDomainName`, and `winlog.computer_name`. - - Implication: escalate when one `winlog.event_data.TargetSid` moves from a "$"-suffixed computer name to a name matching or imitating the logging controller or another controller-style identity; lower concern only when the object, names, domain, and controller match a lab or patch-validation object. + - Focus: `winlog.event_data.OldTargetUserName`, `winlog.event_data.NewTargetUserName`, `user.target.id`, `winlog.event_data.TargetDomainName`, and `host.name`. + - Implication: escalate when one `user.target.id` moves from a "$"-suffixed computer name to a name matching or imitating the logging controller or another controller-style identity; lower concern only when the object, names, domain, and controller match a lab or patch-validation object. - Which account and session initiated the rename? - - Focus: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectDomainName`, `winlog.event_data.SubjectLogonId`, and `user.id`. + - Focus: `user.id`, `user.name`, `winlog.event_data.SubjectDomainName`, `winlog.event_data.SubjectLogonId`, and `user.id`. - Hint: modifying-session authentication events. $investigate_0 - Implication: escalate when the modifier is a standard user, non-tier-0 administrator, unexpected service account, or session unrelated to directory management; lower concern only when the SID, account, domain, and logon session match the same recognized test or repair workflow. - Was the same object restored or prepared with surrounding directory changes? - Why: rename-back on the same object after ticket activity is common noPac-style tradecraft. - - Focus: follow-on account-management or directory-change events for `winlog.event_data.TargetSid`, `winlog.event_data.OldTargetUserName`, `winlog.event_data.NewTargetUserName`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue`. + - Focus: follow-on account-management or directory-change events for `user.target.id`, `winlog.event_data.OldTargetUserName`, `winlog.event_data.NewTargetUserName`, `winlog.event_data.AttributeLDAPDisplayName`, and `winlog.event_data.AttributeValue`. - Hint: look for sAMAccountName rewrites, authentication-related attribute changes, and a final return to the expected "$"-suffixed name. - Implication: escalate when the object is restored after suspicious ticket activity, renamed repeatedly, or has authentication-related attribute changes around the rename; lower concern only when the restore is prompt, complete, and tied to the same recognized test or repair workflow. - Did the spoofed identity request Kerberos tickets or log on after the rename? - - Focus: Windows Security authentication events for the spoofed name, especially `winlog.event_data.TargetUserName`, `event.code`, `winlog.event_data.AuthenticationPackageName`, `source.ip`, and `winlog.computer_name`. - - Hint: use the alert `@timestamp`, `winlog.computer_name`, and `winlog.event_data.NewTargetUserName` to scope authentication review. $investigate_1 Missing Kerberos or logon coverage is unresolved, not benign. + - Focus: Windows Security authentication events for the spoofed name, especially `user.target.name`, `event.code`, `winlog.event_data.AuthenticationPackageName`, `source.ip`, and `host.name`. + - Hint: use the alert `@timestamp`, `host.name`, and `winlog.event_data.NewTargetUserName` to scope authentication review. $investigate_1 Missing Kerberos or logon coverage is unresolved, not benign. - Implication: escalate when the new name requests Kerberos tickets, authenticates from an unexpected `source.ip`, or appears in privileged access flows; lack of follow-on use lowers concern only when rename and restore evidence fit one confirmed benign workflow. - If local evidence is suspicious or unresolved, does the same modifier or object appear in related directory abuse? - - Focus: related Windows Security events or alerts for the same `winlog.event_data.SubjectUserSid` and `winlog.event_data.TargetSid`, especially Active Directory manipulation, Kerberos abuse, credential access, or privilege-escalation activity. + - Focus: related Windows Security events or alerts for the same `user.id` and `user.target.id`, especially Active Directory manipulation, Kerberos abuse, credential access, or privilege-escalation activity. - Hint: modifier-SID related events. $investigate_2 - Hint: renamed-object related events. $investigate_3 - Implication: broaden scope when either SID appears in related directory or privilege-abuse activity; keep localized only when related scope is clean and local evidence supports a confirmed benign workflow. @@ -82,15 +82,15 @@ note = """## Triage and analysis ### False positive analysis -- Controlled CVE-2021-42278 testing, patch validation, and rare tier-0 directory repair are the realistic benign paths. Confirm that `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectLogonId`, `winlog.event_data.TargetSid`, old/new names, and `winlog.computer_name` match one test or repair path; the same `winlog.event_data.TargetSid` is restored to the expected "$"-suffixed name; and Kerberos/logon events show no spoofed-name use outside that path. Without workflow records or owner confirmation, keep unresolved rather than closing on telemetry shape alone. If the target name, modifier, restore behavior, or follow-on usage drifts, do not close as benign. -- Before creating an exception, validate that the same subject SID, target SID, old/new names, controller, restore sequence, and no-spoofed-authentication pattern recur across prior alerts from this rule after a benign workflow has been confirmed. Build the exception from that minimum workflow pattern, not `event.action`, `winlog.event_data.NewTargetUserName`, or `winlog.event_data.TargetSid` alone. +- Controlled CVE-2021-42278 testing, patch validation, and rare tier-0 directory repair are the realistic benign paths. Confirm that `user.id`, `user.name`, `winlog.event_data.SubjectLogonId`, `user.target.id`, old/new names, and `host.name` match one test or repair path; the same `user.target.id` is restored to the expected "$"-suffixed name; and Kerberos/logon events show no spoofed-name use outside that path. Without workflow records or owner confirmation, keep unresolved rather than closing on telemetry shape alone. If the target name, modifier, restore behavior, or follow-on usage drifts, do not close as benign. +- Before creating an exception, validate that the same subject SID, target SID, old/new names, controller, restore sequence, and no-spoofed-authentication pattern recur across prior alerts from this rule after a benign workflow has been confirmed. Build the exception from that minimum workflow pattern, not `event.action`, `winlog.event_data.NewTargetUserName`, or `user.target.id` alone. ### Response and remediation - If confirmed benign, preserve the evidence set that proved the workflow, then reverse any temporary containment and document the exact subject SID, target SID, old/new name sequence, controller, restore sequence, and follow-on authentication pattern. Create an exception only after the same workflow pattern recurs across prior alerts from this rule. - If suspicious but unconfirmed, preserve the alert document, Windows Security rename event, related account-management and directory-change events, Kerberos/logon events for the spoofed name, and related pivots before altering the object. Apply reversible containment only after weighing AD service impact with AD owners, such as temporarily disabling the renamed computer account or restoring the original sAMAccountName after evidence capture. - If confirmed malicious, preserve the same rename, controller, directory-change, Kerberos, and source-origin evidence first, then disable the renamed computer object or restore its original sAMAccountName, reset the machine-account secret or re-establish the expected trust path, and contain the modifying account and suspected source host. Escalate to broader account or host containment when ticket use, rename-back staging, or related privilege abuse shows active exploitation. -- Before destructive cleanup or final object restoration, review the same `winlog.event_data.SubjectUserSid` and `winlog.event_data.TargetSid` across domain-controller Security logs for additional renames, spoofed-name authentication, or related directory abuse so scope is known before evidence changes. +- Before destructive cleanup or final object restoration, review the same `user.id` and `user.target.id` across domain-controller Security logs for additional renames, spoofed-name authentication, or related directory abuse so scope is known before evidence changes. - If the spoofed identity obtained privileged tickets or was used for directory replication, treat the case as potential domain compromise: review issued Kerberos tickets, reset exposed accounts according to ticket and access evidence, and coordinate domain-recovery actions such as krbtgt rotation only when ticket abuse or replication access is confirmed. - Post-incident hardening: patch domain controllers for CVE-2021-42278 and related Kerberos fixes, retain account-management, directory-change, and Kerberos auditing on controllers, and record the final subject SID / target SID / old-new name / restore / follow-on-authentication pattern for future triage. """ @@ -107,15 +107,15 @@ field_names = [ "event.action", "event.code", "host.id", - "winlog.computer_name", + "host.name", + "user.id", + "user.name", "user.id", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.event_data.OldTargetUserName", "winlog.event_data.NewTargetUserName", - "winlog.event_data.TargetSid", + "user.target.id", "winlog.event_data.TargetDomainName", ] @@ -143,15 +143,15 @@ description = "" providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "4768", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetUserName", queryType = "phrase", value = "{{winlog.event_data.NewTargetUserName}}", valueType = "string" } + { excluded = false, field = "user.target.name", queryType = "phrase", value = "{{winlog.event_data.NewTargetUserName}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4769", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetUserName", queryType = "phrase", value = "{{winlog.event_data.NewTargetUserName}}", valueType = "string" } + { excluded = false, field = "user.target.name", queryType = "phrase", value = "{{winlog.event_data.NewTargetUserName}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4624", valueType = "string" }, - { excluded = false, field = "winlog.event_data.TargetUserName", queryType = "phrase", value = "{{winlog.event_data.NewTargetUserName}}", valueType = "string" } + { excluded = false, field = "user.target.name", queryType = "phrase", value = "{{winlog.event_data.NewTargetUserName}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" @@ -162,7 +162,7 @@ label = "Events associated with the modifying account" description = "" providers = [ [ - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" @@ -173,7 +173,7 @@ label = "Events associated with the renamed object" description = "" providers = [ [ - { excluded = false, field = "winlog.event_data.TargetSid", queryType = "phrase", value = "{{winlog.event_data.TargetSid}}", valueType = "string" } + { excluded = false, field = "user.target.id", queryType = "phrase", value = "{{user.target.id}}", valueType = "string" } ] ] relativeFrom = "now-48h/h" diff --git a/rules/windows/privilege_escalation_suspicious_dnshostname_update.toml b/rules/windows/privilege_escalation_suspicious_dnshostname_update.toml index b78ab7c12f1..60199bafbab 100644 --- a/rules/windows/privilege_escalation_suspicious_dnshostname_update.toml +++ b/rules/windows/privilege_escalation_suspicious_dnshostname_update.toml @@ -2,7 +2,7 @@ creation_date = "2022/05/11" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -46,7 +46,7 @@ iam where host.os.type == "windows" and event.action == "changed-computer-accoun winlog.event_data.DnsHostName : "??*" and /* exclude FPs where DnsHostName starts with the ComputerName that was changed */ - not startswith~(winlog.event_data.DnsHostName, substring(winlog.event_data.TargetUserName, 0, length(winlog.event_data.TargetUserName) - 1)) + not startswith~(winlog.event_data.DnsHostName, substring(user.target.name, 0, length(user.target.name) - 1)) ''' note = """## Triage and analysis @@ -56,25 +56,25 @@ note = """## Triage and analysis #### Possible investigation steps - What object, initiator, and DNS-name mismatch does the alert prove? - - Focus: `winlog.event_data.TargetUserName`, `winlog.event_data.TargetSid`, `winlog.event_data.DnsHostName`, `winlog.event_data.SubjectUserSid`, and `winlog.event_data.SubjectLogonId`. + - Focus: `user.target.name`, `user.target.id`, `winlog.event_data.DnsHostName`, `user.id`, and `winlog.event_data.SubjectLogonId`. - Implication: escalate or continue when the new DNS host name no longer matches the target computer account and points to another server namespace; lower suspicion only when target SID, subject SID, and logon session fit a recognized rename, promotion, re-binding, or authorized test. - Does the new DNS host name collide with a domain controller or other sensitive host? - Why: Certifried abuse makes a controlled computer account look like a trusted host before requesting or using a machine certificate. - - Focus: `winlog.event_data.DnsHostName`, `winlog.event_data.TargetUserName`, `winlog.event_data.TargetDomainName`, and `winlog.computer_name`. - - Implication: high risk when the value matches a real domain controller, CA, or privileged server different from `winlog.event_data.TargetUserName`; lower risk only when it belongs to the same object transition and does not collide with a privileged asset. + - Focus: `winlog.event_data.DnsHostName`, `user.target.name`, `winlog.event_data.TargetDomainName`, and `host.name`. + - Implication: high risk when the value matches a real domain controller, CA, or privileged server different from `user.target.name`; lower risk only when it belongs to the same object transition and does not collide with a privileged asset. - Who made the update, and does the source/session context fit that account's role? - - Focus: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectDomainName`, `winlog.event_data.SubjectLogonId`, and `source.ip`. + - Focus: `user.id`, `user.name`, `winlog.event_data.SubjectDomainName`, `winlog.event_data.SubjectLogonId`, and `source.ip`. - Implication: escalate when the subject is a standard user, non-tier-0 admin, unusual service account, machine account, or unexpected source for computer-account management; lower suspicion when subject, source when present, and logon session match a recognized AD management path. - Did the same object show SPN deletion, empty-SPN creation, or other preparation? - Why: successful DNS-name spoofing often requires removing FQDN service principal names or creating a computer account without them so SPN uniqueness checks do not block the DNS update. - - Focus: Windows Security account-management and directory-change events for `winlog.event_data.TargetSid`, especially `event.code`, `winlog.event_data.AttributeLDAPDisplayName`, `winlog.event_data.AttributeValue`, and `winlog.event_data.ObjectDN`. + - Focus: Windows Security account-management and directory-change events for `user.target.id`, especially `event.code`, `winlog.event_data.AttributeLDAPDisplayName`, `winlog.event_data.AttributeValue`, and `winlog.event_data.ObjectDN`. - Implication: escalate when the sequence removes servicePrincipalName values, creates or controls the computer object, or changes related attributes just before the DNS update; lower suspicion when the same change set follows a recognized promotion or re-binding path. - Did certificate-service or Kerberos activity use the spoofed identity after the update? - - Focus: post-alert Windows Security certificate enrollment and authentication events for `winlog.event_data.TargetUserName` or the spoofed host name, reading `event.code`, `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, and `source.ip`. + - Focus: post-alert Windows Security certificate enrollment and authentication events for `user.target.name` or the spoofed host name, reading `event.code`, `winlog.event_data.AuthenticationPackageName`, `winlog.logon.type`, and `source.ip`. - Hint: missing certificate-service or Kerberos telemetry leaves post-update use unresolved, not benign. - Implication: escalate when the modified object requests or receives a machine certificate, uses Kerberos with the spoofed identity, authenticates from unexpected `source.ip` when present, or appears in privileged follow-on activity; absence of follow-on use lowers urgency only when object, initiator, and preparation evidence also align benignly. @@ -89,7 +89,7 @@ note = """## Triage and analysis - Benign matches are uncommon because changing a computer account DNS host name to another host namespace is an AD identity anti-pattern. Authorized CVE-2022-26923 testing or patch validation explains the alert only when subject SID/logon, target SID/name, spoofed host name, event-origin controller, SPN/object-change sequence, and follow-on certificate or authentication events all match the same test scope. Without a test plan, close only when telemetry proves a bounded lab pattern; drift in initiator, hostname, or follow-on use keeps the alert suspicious. - Rare promotion, rename, migration, or re-binding explains the alert only when the same computer object intentionally assumes the new DNS identity, no privileged-host collision exists, and subject, target SID, new host name, controller, and bounded follow-on authentication path all align. Do not close if telemetry leaves object identity, collision, or follow-on use unresolved. -- Build exceptions from the minimum confirmed workflow: stable `winlog.event_data.SubjectUserSid`, `winlog.event_data.TargetSid`, `winlog.event_data.TargetUserName`, `winlog.event_data.DnsHostName`, `winlog.computer_name`, and bounded follow-on `source.ip` or `event.code`. Avoid exceptions on `event.action`, `winlog.event_data.DnsHostName`, or `winlog.event_data.TargetSid` alone. +- Build exceptions from the minimum confirmed workflow: stable `user.id`, `user.target.id`, `user.target.name`, `winlog.event_data.DnsHostName`, `host.name`, and bounded follow-on `source.ip` or `event.code`. Avoid exceptions on `event.action`, `winlog.event_data.DnsHostName`, or `user.target.id` alone. ### Response and remediation @@ -114,18 +114,18 @@ field_names = [ "user.name", "user.id", "user.domain", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "user.name", + "user.id", "winlog.event_data.SubjectDomainName", "winlog.event_data.SubjectLogonId", "winlog.logon.id", - "winlog.event_data.TargetUserName", - "winlog.event_data.TargetSid", + "user.target.name", + "user.target.id", "winlog.event_data.TargetDomainName", "winlog.event_data.DnsHostName", "host.name", "host.id", - "winlog.computer_name", + "host.name", ] [transform] diff --git a/rules/windows/privilege_escalation_thread_cpu_priority_hijack.toml b/rules/windows/privilege_escalation_thread_cpu_priority_hijack.toml index 8bf977abb83..04baeea5036 100644 --- a/rules/windows/privilege_escalation_thread_cpu_priority_hijack.toml +++ b/rules/windows/privilege_escalation_thread_cpu_priority_hijack.toml @@ -2,7 +2,7 @@ creation_date = "2025/09/25" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -37,7 +37,7 @@ type = "query" query = ''' event.category:iam and host.os.type:"windows" and event.code:"4674" and winlog.event_data.PrivilegeList:"SeIncreaseBasePriorityPrivilege" and event.outcome:"success" and -winlog.event_data.AccessMask:"512" and not winlog.event_data.SubjectUserSid:("S-1-5-18" or "S-1-5-19" or "S-1-5-20") +winlog.event_data.AccessMask:"512" and not user.id:("S-1-5-18" or "S-1-5-19" or "S-1-5-20") ''' note = """## Triage and analysis @@ -48,17 +48,17 @@ note = """## Triage and analysis - What priority-change path did 4674 preserve? - Why: this privilege manipulates process or thread priority; the target object matters as much as the requester. - - Focus: Security 4674 on `host.id`: `winlog.event_data.PrivilegeList`, `winlog.event_data.AccessMask`, `winlog.event_data.ProcessName`, `winlog.event_data.ObjectType`, and `winlog.event_data.ObjectName`. + - Focus: Security 4674 on `host.id`: `winlog.event_data.PrivilegeList`, `winlog.event_data.AccessMask`, `process.executable`, `winlog.event_data.ObjectType`, and `winlog.event_data.ObjectName`. - Hint: sparse or numeric-only `winlog.event_data.ObjectName` is the main visibility gap; keep the target unresolved and use same-session Security records, not assumed self-tuning. - Implication: escalate when the object is a "Process" or "Thread" tied to security tooling, LSASS, or another user's workload; lower suspicion only when requester, object, and `host.name` fit bounded tuning or testing. - Is the requesting image path expected for priority control on this host? - - Focus: `winlog.event_data.ProcessName`, `winlog.event_data.ProcessId`, `winlog.event_data.SubjectUserSid`, `host.name`, and `@timestamp`. + - Focus: `process.executable`, `winlog.event_data.ProcessId`, `user.id`, `host.name`, and `@timestamp`. - Hint: `winlog.event_data.ProcessId` is hexadecimal; use it only inside a tight host/time window; PID reuse can mislead. - Implication: escalate when the path is user-writable, temporary, renamed, or unrelated to local tuning; treat a recurring full path and SID as identity support, not closure, until object and session evidence align. - Which subject and local session requested this privilege use? - - Focus: `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, `winlog.event_data.SubjectDomainName`, and `winlog.event_data.SubjectLogonId`. + - Focus: `user.id`, `user.name`, `winlog.event_data.SubjectDomainName`, and `winlog.event_data.SubjectLogonId`. - Implication: escalate when a normal user, rare admin, machine account, or service account lacks a clear scheduling-priority role; matching SID, domain, and session support benignity only with matching requester and object evidence. - Does the 4624 session origin fit a priority-tuning operator? @@ -67,30 +67,30 @@ note = """## Triage and analysis - Implication: escalate when source, logon type, or authentication method is rare for `host.name` or subject SID; matching origin supports authorized tuning only after requester path and target object fit. - Do surrounding Security records show repeated or multi-target priority use by the same requester? - - Focus: Security events around `@timestamp` on the same `host.id`, grouped by `winlog.event_data.SubjectLogonId`, `winlog.event_data.ProcessId`, `winlog.event_data.ProcessName`, and `winlog.event_data.ObjectName`. + - Focus: Security events around `@timestamp` on the same `host.id`, grouped by `winlog.event_data.SubjectLogonId`, `winlog.event_data.ProcessId`, `process.executable`, and `winlog.event_data.ObjectName`. - Hint: start in the alert window with `event.code` 4674 and alert `winlog.event_data.SubjectLogonId`; expand only if the same session continues around `@timestamp`. Add `event.outcome` to separate failed attempts from successful use. $investigate_1 - Implication: escalate when one session or requester touches multiple process/thread objects, repeats against security targets, or continues after failures; a single 4674 keeps scope local but still requires requester, object, and session answers for closure. - If local evidence is suspicious or unresolved, do related alerts expand scope or urgency? - Focus: related alerts for the same `host.id`, prioritizing privilege abuse, defense evasion, security-tool interference, service-control, or authentication findings. $investigate_2 - - Hint: if the subject remains suspicious, use the subject pivot; use the `user.id` provider only after confirming it maps to `winlog.event_data.SubjectUserSid`. $investigate_3 + - Hint: if the subject remains suspicious, use the subject pivot; use the `user.id` provider only after confirming it maps to `user.id`. $investigate_3 - Implication: broaden scope when the host or user also shows privilege escalation, defense evasion, or unusual authentication; keep scope local when related alerts are absent and 4674/session evidence supports bounded work. - Escalate for unauthorized process/thread priority manipulation or security-tool interference; close only when object, requester, subject, session, and related alerts bind to one authorized tuning or troubleshooting workflow; preserve 4674 and recovered 4624 evidence and escalate when sparse object or session evidence leaves suspicious findings unresolved. ### False positive analysis -- Performance engineering, benchmark, QA, vendor, or internal support work can trigger when an administrator adjusts scheduling priority or CPU assignment for a test or latency-sensitive workload. Confirm only when `winlog.event_data.ProcessName`, `winlog.event_data.ObjectType`, `winlog.event_data.ObjectName`, `winlog.event_data.SubjectUserSid`, recovered `source.ip`, and `winlog.logon.type` align with the same recognized host, accounts, and workload. If records are unavailable, require telemetry-only recurrence of the same full requester path, SID, object family, and host class before treating as benign. +- Performance engineering, benchmark, QA, vendor, or internal support work can trigger when an administrator adjusts scheduling priority or CPU assignment for a test or latency-sensitive workload. Confirm only when `process.executable`, `winlog.event_data.ObjectType`, `winlog.event_data.ObjectName`, `user.id`, recovered `source.ip`, and `winlog.logon.type` align with the same recognized host, accounts, and workload. If records are unavailable, require telemetry-only recurrence of the same full requester path, SID, object family, and host class before treating as benign. - If the target object is sparse or numeric-only, do not close solely on tool name or user claim. -- Before creating an exception, validate that `winlog.event_data.ProcessName`, `winlog.event_data.ObjectType`, `winlog.event_data.ObjectName`, `winlog.event_data.SubjectUserSid`, `host.id`, and recovered `source.ip` or `winlog.logon.type` stay stable across known-benign occurrences. Build the exception from that minimum confirmed pattern; avoid exceptions on `winlog.event_data.PrivilegeList` or `user.name` alone. +- Before creating an exception, validate that `process.executable`, `winlog.event_data.ObjectType`, `winlog.event_data.ObjectName`, `user.id`, `host.id`, and recovered `source.ip` or `winlog.logon.type` stay stable across known-benign occurrences. Build the exception from that minimum confirmed pattern; avoid exceptions on `winlog.event_data.PrivilegeList` or `user.name` alone. ### Response and remediation -- If confirmed benign, reverse temporary containment and document the validated `winlog.event_data.ProcessName`, `winlog.event_data.ObjectType`, `winlog.event_data.ObjectName`, `winlog.event_data.SubjectUserSid`, recovered `source.ip`, `winlog.logon.type`, and `host.id` values proving the tuning or troubleshooting workflow. Create an exception only after the same pattern repeats benignly. +- If confirmed benign, reverse temporary containment and document the validated `process.executable`, `winlog.event_data.ObjectType`, `winlog.event_data.ObjectName`, `user.id`, recovered `source.ip`, `winlog.logon.type`, and `host.id` values proving the tuning or troubleshooting workflow. Create an exception only after the same pattern repeats benignly. - If suspicious but unconfirmed, preserve a case export of triggering 4674, recovered 4624 session record, surrounding same-session Security records, and related-alert links before containment. Record requester path and PID, subject SID, target object, session origin, and event time as case anchors. - If suspicious but unconfirmed, apply reversible containment first, such as restricting the subject's remote access, pausing the support workflow, or raising monitoring on `host.id`. Escalate to host isolation or account disablement only if the target maps to a security-critical process, related alerts show additional privilege abuse or defense evasion, or the recovered session suggests credential misuse. - If confirmed malicious, isolate the host when the object, requester, session, or related-alert evidence shows unauthorized priority manipulation of a security-critical process or another user's workload. Record the requester path and PID, subject SID, target object, recovered session origin, and event time before stopping processes or deleting tooling. -- Reset or suspend the implicated account only when the recovered session and related alerts show likely credential misuse, and review other hosts for the same `winlog.event_data.ProcessName`, `winlog.event_data.ObjectName`, or `winlog.event_data.SubjectUserSid` before eradicating artifacts so scoping finishes before evidence is destroyed. +- Reset or suspend the implicated account only when the recovered session and related alerts show likely credential misuse, and review other hosts for the same `process.executable`, `winlog.event_data.ObjectName`, or `user.id` before eradicating artifacts so scoping finishes before evidence is destroyed. - Eradicate only the unauthorized tuning or interference tooling and any persistence or launcher artifacts identified during the investigation, then restore affected security or service configurations to a known-good state. - Hardening: restrict assignment of "SeIncreaseBasePriorityPrivilege" to the smallest admin cohort, retain Security 4674 and 4624 visibility, and record visibility gaps that limited the case decision. """ @@ -107,10 +107,10 @@ field_names = [ "event.outcome", "host.id", "user.id", - "winlog.event_data.SubjectUserName", - "winlog.event_data.SubjectUserSid", + "user.name", + "user.id", "winlog.event_data.SubjectLogonId", - "winlog.event_data.ProcessName", + "process.executable", "winlog.event_data.ProcessId", "winlog.event_data.ObjectType", "winlog.event_data.ObjectName", @@ -148,7 +148,7 @@ providers = [ { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }, { excluded = false, field = "event.code", queryType = "phrase", value = "4674", valueType = "string" }, { excluded = false, field = "winlog.event_data.SubjectLogonId", queryType = "phrase", value = "{{winlog.event_data.SubjectLogonId}}", valueType = "string" }, - { excluded = false, field = "winlog.event_data.ProcessName", queryType = "phrase", value = "{{winlog.event_data.ProcessName}}", valueType = "string" } + { excluded = false, field = "process.executable", queryType = "phrase", value = "{{process.executable}}", valueType = "string" } ] ] relativeFrom = "now-1h" @@ -172,7 +172,7 @@ description = "" providers = [ [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ], [ { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" }, diff --git a/rules/windows/privilege_escalation_tokenmanip_sedebugpriv_enabled.toml b/rules/windows/privilege_escalation_tokenmanip_sedebugpriv_enabled.toml index 6290c960fd1..f08d4a60db4 100644 --- a/rules/windows/privilege_escalation_tokenmanip_sedebugpriv_enabled.toml +++ b/rules/windows/privilege_escalation_tokenmanip_sedebugpriv_enabled.toml @@ -2,7 +2,7 @@ creation_date = "2022/10/20" integration = ["windows", "system"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,8 +28,8 @@ SeDebugPrivilege is a powerful Windows privilege allowing processes to debug and ### Possible investigation steps - Review the event logs for the specific event.provider "Microsoft-Windows-Security-Auditing" and event.action "Token Right Adjusted Events" to gather more details about the process that enabled SeDebugPrivilege. -- Identify the process name from winlog.event_data.ProcessName and determine if it is known or expected in the environment. Investigate any unknown or suspicious processes. -- Check the winlog.event_data.SubjectUserSid to identify the user account associated with the process. Investigate if this account has a history of suspicious activity or if it should have the ability to enable SeDebugPrivilege. +- Identify the process name from process.executable and determine if it is known or expected in the environment. Investigate any unknown or suspicious processes. +- Check the user.id to identify the user account associated with the process. Investigate if this account has a history of suspicious activity or if it should have the ability to enable SeDebugPrivilege. - Analyze the parent process of the suspicious process to understand how it was initiated and if it was spawned by a legitimate or malicious process. - Correlate the timestamp of the event with other security events or alerts to identify any related activities or patterns that could indicate a broader attack or compromise. - Investigate the network activity of the suspicious process to determine if it is communicating with any known malicious IP addresses or domains. @@ -81,9 +81,9 @@ any where host.os.type == "windows" and event.provider: "Microsoft-Windows-Secur winlog.event_data.EnabledPrivilegeList : "SeDebugPrivilege" and /* exclude processes with System Integrity */ - not winlog.event_data.SubjectUserSid : ("S-1-5-18", "S-1-5-19", "S-1-5-20") and + not user.id : ("S-1-5-18", "S-1-5-19", "S-1-5-20") and - not winlog.event_data.ProcessName : ( + not process.executable : ( "?:\\Program Files (x86)\\*", "?:\\Program Files\\*", "?:\\Users\\*\\AppData\\Local\\Temp\\*-*\\DismHost.exe", diff --git a/rules/windows/privilege_escalation_windows_service_via_unusual_client.toml b/rules/windows/privilege_escalation_windows_service_via_unusual_client.toml index f08dfa2bc58..2503a64b6d5 100644 --- a/rules/windows/privilege_escalation_windows_service_via_unusual_client.toml +++ b/rules/windows/privilege_escalation_windows_service_via_unusual_client.toml @@ -2,7 +2,7 @@ creation_date = "2022/02/07" integration = ["system", "windows"] maturity = "production" -updated_date = "2026/05/03" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -40,7 +40,7 @@ query = ''' configuration where host.os.type == "windows" and event.action == "service-installed" and (winlog.event_data.ClientProcessId == "0" or winlog.event_data.ParentProcessId == "0") and - startswith~(user.domain, winlog.computer_name) and winlog.event_data.ServiceAccount == "LocalSystem" and + startswith~(user.domain, host.name) and winlog.event_data.ServiceAccount == "LocalSystem" and not winlog.event_data.ServiceFileName : ( "?:\\Windows\\VeeamVssSupport\\VeeamGuestHelper.exe*", "?:\\Windows\\VeeamLogShipper\\VeeamLogShipper.exe", @@ -62,7 +62,7 @@ note = """## Triage and analysis - Which unusual service-control path did the alert preserve? - Why: Custom Service Control Manager RPC clients can create services without normal attribution; PID 0 is the path this alert needs interpreted. - - Focus: `winlog.event_data.ClientProcessId`, `winlog.event_data.ParentProcessId`, `user.domain`, `winlog.computer_name`, and `winlog.event_data.ServiceAccount`. + - Focus: `winlog.event_data.ClientProcessId`, `winlog.event_data.ParentProcessId`, `user.domain`, `host.name`, and `winlog.event_data.ServiceAccount`. - Implication: escalate when PID 0 attribution combines with a local-account domain and LocalSystem; lower suspicion only when exact host, account, service, and time match a recognized deployment or test explaining zeroed attribution. - What would the new service execute and how privileged is it? @@ -71,7 +71,7 @@ note = """## Triage and analysis - Implication: escalate when the image path is user-writable, temporary, ProgramData, or system-masqueraded; type is driver; start type is boot, system, or disabled; or LocalSystem lacks a matching product. Lower suspicion when all service fields align with one recognized installer, endpoint agent, backup, or deployment tool. - Which account and logon session requested the service creation? - - Focus: service-install `winlog.event_data.SubjectUserSid`, `winlog.event_data.SubjectUserName`, and `winlog.event_data.SubjectLogonId`; 4624 `source.ip` and `winlog.logon.type`; 4648 explicit-credential context. + - Focus: service-install `user.id`, `user.name`, and `winlog.event_data.SubjectLogonId`; 4624 `source.ip` and `winlog.logon.type`; 4648 explicit-credential context. - Implication: escalate when the subject is an unexpected local admin or machine account, origin is remote or rare for the host, explicit credentials appear, or source is absent where remote administration is expected; lower suspicion when subject, logon type, source, and service target fit one recognized management session. Missing 4624/4648 or source fields leaves origin unresolved, not benign. - Hint: on `host.id`, search 4624 where `winlog.event_data.TargetLogonId` equals service-install `winlog.event_data.SubjectLogonId`; search 4648 where `winlog.event_data.SubjectLogonId` matches. - $investigate_0 @@ -83,9 +83,9 @@ note = """## Triage and analysis - Hint: inspect same-session 4697 records for clustered service creation. $investigate_2 - Is the same service-install pattern recurring in a bounded cohort or spreading? - - Focus: historical Event ID 4697 records by `winlog.event_data.SubjectUserSid`, `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceAccount`, and `winlog.computer_name`. + - Focus: historical Event ID 4697 records by `user.id`, `winlog.event_data.ServiceName`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceAccount`, and `host.name`. - Implication: escalate when the same subject creates PID 0 LocalSystem services across unrelated hosts, or service names or paths rotate; lower suspicion when exact service fields recur in the same managed host cohort with a stable subject and no contradictory service metadata. - - Hint: query 4697 for the same subject or service fields, group by `winlog.computer_name`, `winlog.event_data.ServiceName`, and `winlog.event_data.ServiceFileName`, then compare PID 0 recurrence. $investigate_3 + - Hint: query 4697 for the same subject or service fields, group by `host.name`, `winlog.event_data.ServiceName`, and `winlog.event_data.ServiceFileName`, then compare PID 0 recurrence. $investigate_3 - Based on the Windows Security evidence, what disposition is supported? - Implication: escalate when PID 0, LocalSystem image, actor/session evidence, or 4697 recurrence does not bind to one recognized workflow; close only when the same fields prove one exact service deployment or test on this host and no contradictory Security evidence remains; if mixed, preserve service-install and logon records, then escalate. @@ -93,7 +93,7 @@ note = """## Triage and analysis ### False positive analysis - Software deployment, endpoint agent, backup, configuration tools, or authorized service-control/RPC testing can trigger when Service Control Manager behavior leaves PID 0 attribution. Examples include Veeam, PDQ, CrowdStrike installer, SCCM/SMS, nsnetpush, or pbpsdeploy-style patterns. Confirm service name, file, account, subject SID, host cohort, logon session, and test timing align with one product or test workflow, with no contradictory Security records. -- Before creating an exception, require stable recurrence for the same `winlog.event_data.SubjectUserSid`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceName`, `winlog.event_data.ServiceAccount`, and host cohort. Avoid broad exceptions on `user.name`, `host.name`, or service name alone. +- Before creating an exception, require stable recurrence for the same `user.id`, `winlog.event_data.ServiceFileName`, `winlog.event_data.ServiceName`, `winlog.event_data.ServiceAccount`, and host cohort. Avoid broad exceptions on `user.name`, `host.name`, or service name alone. ### Response and remediation @@ -124,10 +124,10 @@ field_names = [ "@timestamp", "event.code", "host.id", - "winlog.computer_name", + "host.name", "user.id", "user.domain", - "winlog.event_data.SubjectUserSid", + "user.id", "winlog.event_data.SubjectLogonId", "winlog.event_data.ServiceName", "winlog.event_data.ServiceFileName", @@ -185,7 +185,7 @@ description = "" providers = [ [ { excluded = false, field = "event.code", queryType = "phrase", value = "4697", valueType = "string" }, - { excluded = false, field = "winlog.event_data.SubjectUserSid", queryType = "phrase", value = "{{winlog.event_data.SubjectUserSid}}", valueType = "string" } + { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" } ], [ { excluded = false, field = "event.code", queryType = "phrase", value = "4697", valueType = "string" }, diff --git a/rules_building_block/execution_common_debug_or_base_image_pod_creation.toml b/rules_building_block/execution_common_debug_or_base_image_pod_creation.toml index c3a95dab1c4..a89572ffcf1 100644 --- a/rules_building_block/execution_common_debug_or_base_image_pod_creation.toml +++ b/rules_building_block/execution_common_debug_or_base_image_pod_creation.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2026/05/04" integration = ["kubernetes"] maturity = "production" -updated_date = "2026/05/04" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -34,9 +34,9 @@ type = "new_terms" query = ''' event.dataset:"kubernetes.audit_logs" and kubernetes.audit.stage:"ResponseComplete" and -kubernetes.audit.annotations.authorization_k8s_io/decision:"allow" and -kubernetes.audit.objectRef.resource:"pods" and -kubernetes.audit.verb:"create" and +event.outcome:"success" and +orchestrator.resource.type:"pods" and +event.action:"create" and kubernetes.audit.requestObject.spec.containers.image:(alpine* or busybox* or ubuntu\:* or debian\:* or *netshoot\:* or *network-multitool\:* or *curl\:*) ''' diff --git a/rules_building_block/execution_github_repo_interaction_from_new_ip.toml b/rules_building_block/execution_github_repo_interaction_from_new_ip.toml index c048fbf59d9..05c0e4a65a6 100644 --- a/rules_building_block/execution_github_repo_interaction_from_new_ip.toml +++ b/rules_building_block/execution_github_repo_interaction_from_new_ip.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2023/10/11" integration = ["github"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ type = "new_terms" query = ''' event.dataset:"github.audit" and event.category:"configuration" and -github.actor_ip:* and github.repo:* and +source.ip:* and github.repo:* and github.repository_public:false ''' @@ -85,7 +85,7 @@ name = "Initial Access" reference = "https://attack.mitre.org/tactics/TA0001/" [rule.new_terms] field = "new_terms_fields" -value = ["github.repo", "github.actor_ip"] +value = ["github.repo", "source.ip"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-5d" diff --git a/rules_building_block/impact_azure_recovery_services_deletion.toml b/rules_building_block/impact_azure_recovery_services_deletion.toml index 7673e390133..18305556578 100644 --- a/rules_building_block/impact_azure_recovery_services_deletion.toml +++ b/rules_building_block/impact_azure_recovery_services_deletion.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2025/10/13" integration = ["azure"] maturity = "production" -updated_date = "2025/10/13" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -40,8 +40,8 @@ type = "query" query = ''' event.dataset:azure.activitylogs and - azure.activitylogs.operation_name:MICROSOFT.RECOVERYSERVICES/*/DELETE and - event.outcome:(Success or success) + event.action:MICROSOFT.RECOVERYSERVICES/*/DELETE and + event.outcome:(success) ''' diff --git a/rules_building_block/initial_access_github_new_ip_address_for_pat.toml b/rules_building_block/initial_access_github_new_ip_address_for_pat.toml index 472759c3b15..f62add4c09f 100644 --- a/rules_building_block/initial_access_github_new_ip_address_for_pat.toml +++ b/rules_building_block/initial_access_github_new_ip_address_for_pat.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2023/10/11" integration = ["github"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ type = "new_terms" query = ''' event.dataset:"github.audit" and event.category:"configuration" and -github.actor_ip:* and github.hashed_token:* and +source.ip:* and github.hashed_token:* and github.programmatic_access_type:("OAuth access token" or "Fine-grained personal access token") ''' @@ -72,7 +72,7 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["github.hashed_token", "github.actor_ip"] +value = ["github.hashed_token", "source.ip"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-5d" diff --git a/rules_building_block/initial_access_github_new_ip_address_for_user.toml b/rules_building_block/initial_access_github_new_ip_address_for_user.toml index bcd5580512d..89910c52a7d 100644 --- a/rules_building_block/initial_access_github_new_ip_address_for_user.toml +++ b/rules_building_block/initial_access_github_new_ip_address_for_user.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2023/10/11" integration = ["github"] maturity = "production" -updated_date = "2025/12/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ type = "new_terms" query = ''' event.dataset:"github.audit" and event.category:"configuration" and -github.actor_ip:* and user.name:* +source.ip:* and user.name:* ''' @@ -54,7 +54,7 @@ reference = "https://attack.mitre.org/tactics/TA0001/" [rule.new_terms] field = "new_terms_fields" -value = ["user.name", "github.actor_ip"] +value = ["user.name", "source.ip"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-5d" diff --git a/rules_building_block/initial_access_github_new_user_agent_for_pat.toml b/rules_building_block/initial_access_github_new_user_agent_for_pat.toml index a0eadada079..37aba2d86f3 100644 --- a/rules_building_block/initial_access_github_new_user_agent_for_pat.toml +++ b/rules_building_block/initial_access_github_new_user_agent_for_pat.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2023/10/11" integration = ["github"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -30,7 +30,7 @@ type = "new_terms" query = ''' event.dataset:"github.audit" and event.category:"configuration" and -github.user_agent:* and github.hashed_token:* and +user_agent.original:* and github.hashed_token:* and github.programmatic_access_type:("OAuth access token" or "Fine-grained personal access token") ''' @@ -72,7 +72,7 @@ name = "Defense Evasion" reference = "https://attack.mitre.org/tactics/TA0005/" [rule.new_terms] field = "new_terms_fields" -value = ["github.hashed_token", "github.user_agent"] +value = ["github.hashed_token", "user_agent.original"] [[rule.new_terms.history_window_start]] field = "history_window_start" value = "now-5d" diff --git a/rules_building_block/initial_access_new_okta_authentication_behavior.toml b/rules_building_block/initial_access_new_okta_authentication_behavior.toml index 30cd77e12b3..d50d24dd8a8 100644 --- a/rules_building_block/initial_access_new_okta_authentication_behavior.toml +++ b/rules_building_block/initial_access_new_okta_authentication_behavior.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2023/11/07" integration = ["okta"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -21,13 +21,13 @@ note = """## Triage and analysis This rule detects events where Okta behavior detection has identified a new authentication behavior such as a new device or location. #### Possible investigation steps: -- Identify the user involved in this action by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. +- Identify the user involved in this action by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. - Determine the authentication anomaly by examining the `okta.debug_context.debug_data.risk_behaviors` and `okta.debug_context.debug_data.flattened` fields. -- Determine the client used by the actor. Review the `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Determine the client used by the actor. Review the `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - If the client is a device, check the `okta.device.id`, `okta.device.name`, `okta.device.os_platform`, `okta.device.os_version`, and `okta.device.managed` fields. - Review the past activities of the actor involved in this action by checking their previous actions. - Examine the `okta.request.ip_chain` field to potentially determine if the actor used a proxy or VPN to perform this action. -- Evaluate the actions that happened just before and after this event in the `okta.event_type` field to help understand the full context of the activity. +- Evaluate the actions that happened just before and after this event in the `event.action` field to help understand the full context of the activity. ### False positive analysis: - A user may be using a new device or location to sign in. @@ -39,7 +39,7 @@ This rule detects events where Okta behavior detection has identified a new auth - If MFA is already enabled, consider resetting MFA for the user. - If the user is not legitimate, consider deactivating the user's account. - If this is a false positive, consider adjusting the Okta behavior detection settings. -- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `okta.client.ip` and `okta.device.id` fields. +- Block the IP address or device used in the attempts if they appear suspicious, using the data from the `source.ip` and `okta.device.id` fields. - Conduct a review of Okta policies and ensure they are in accordance with security best practices. ## Setup diff --git a/rules_building_block/initial_access_okta_admin_console_login_failure.toml b/rules_building_block/initial_access_okta_admin_console_login_failure.toml index 212cbbd12bf..40e982fbb08 100644 --- a/rules_building_block/initial_access_okta_admin_console_login_failure.toml +++ b/rules_building_block/initial_access_okta_admin_console_login_failure.toml @@ -3,7 +3,7 @@ bypass_bbr_timing = true creation_date = "2026/02/03" integration = ["okta"] maturity = "production" -updated_date = "2026/03/24" +updated_date = "2026/06/23" [rule] author = ["Elastic"] @@ -28,9 +28,9 @@ This rule detects failed authentication attempts specifically targeting the Okta Threat actors like ShinyHunters have been observed probing for valid admin credentials as part of their attack chain. Failed Admin Console access attempts often precede successful compromise through vishing (voice phishing) or credential harvesting. #### Possible investigation steps: -- Identify the user involved by examining the `okta.actor.id`, `okta.actor.type`, `okta.actor.alternate_id`, and `okta.actor.display_name` fields. -- Review the `okta.outcome.reason` field to understand why the authentication failed (e.g., invalid credentials, MFA failure, policy violation). -- Determine the client used by the actor. Review the `okta.client.ip`, `okta.client.user_agent.raw_user_agent`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. +- Identify the user involved by examining the `client.user.id`, `okta.actor.type`, `user.name`, and `user.full_name` fields. +- Review the `event.reason` field to understand why the authentication failed (e.g., invalid credentials, MFA failure, policy violation). +- Determine the client used by the actor. Review the `source.ip`, `user_agent.original`, `okta.client.zone`, `okta.client.device`, and `okta.client.id` fields. - Check if the source IP is associated with known malicious activity, VPN/proxy services, or unusual geolocations. - Examine the `okta.request.ip_chain` field to determine if the actor used a proxy or VPN. - Correlate with other failed login attempts from the same IP or user to identify patterns. @@ -75,7 +75,7 @@ query = ''' event.dataset: "okta.system" and event.category: "authentication" and okta.target.alternate_id: "Okta Admin Console" - and okta.outcome.result: "FAILURE" + and event.outcome: "failure" ''' diff --git a/tests/test_all_rules.py b/tests/test_all_rules.py index 0dd2723faa5..00013e13436 100644 --- a/tests/test_all_rules.py +++ b/tests/test_all_rules.py @@ -20,6 +20,11 @@ from detection_rules import atlas, attack from detection_rules.config import load_current_package_version +from detection_rules.ecs import ( + flatten, + get_non_ecs_schema, + get_schema, +) from detection_rules.integrations import ( find_latest_compatible_version, load_integrations_manifests, @@ -1670,3 +1675,34 @@ def test_process_fields_present_in_endpoint_schema(self): "check into a `process where` clause (e.g. via an EQL sequence) or use a field " "that the dataset actually populates.\nOffenders:\n - " + "\n - ".join(offenders) ) + + +class TestNonEcsSchema(unittest.TestCase): + """Guardrails for detection_rules/etc/non-ecs-schema.json.""" + + @classmethod + def setUpClass(cls): + cls.non_ecs_schema = get_non_ecs_schema() + cls.ecs_field_names = set(get_schema().keys()) + + def test_static_fields_belong_in_non_ecs_schema(self): + """Static non-ecs entries must not duplicate ECS fields. + + non-ecs-schema.json is for fields that validation cannot resolve elsewhere. Adding a + field here when it already exists in the ECS flat schema creates redundant maintenance + and masks the preferred field name in new rules. + """ + redundant: list[str] = [] + + for index_pattern, fields in self.non_ecs_schema.items(): + redundant.extend( + f"{index_pattern} -> {field_name} (already in ECS; use the ECS field in rules instead)" + for field_name in flatten(fields) + if field_name in self.ecs_field_names + ) + + if redundant: + self.fail( + "Remove the following entries from non-ecs-schema.json:\n - " + + "\n - ".join(sorted(redundant)) + ) From 466d28c501afc06d8036c50e76c29e2195092c73 Mon Sep 17 00:00:00 2001 From: Mika Ayenson Date: Tue, 23 Jun 2026 16:35:00 -0500 Subject: [PATCH 2/3] Revert hunting query changes from Phase 1 field migration Scope is rules/ and rules_building_block/ only. --- .../ec2_suspicious_get_user_password_request.toml | 2 +- ...hentication_attempts_behind_rare_user_agents.toml | 8 ++++---- ...tempts_from_abused_hosting_service_providers.toml | 4 ++-- ...e_code_authentication_from_unusual_principal.toml | 4 ++-- ...ve_non_interactive_sfa_sign_ins_across_users.toml | 8 ++++---- ...vice_principal_credentials_added_to_rare_app.toml | 6 +++--- .../entra_suspicious_odata_client_requests.toml | 12 ++++++------ ...al_client_app_auth_request_on_behalf_of_user.toml | 8 ++++---- ...ential_access_mfa_bombing_push_notifications.toml | 4 ++-- ..._reset_password_requests_for_different_users.toml | 10 +++++----- ...access_token_retrieval_via_public_client_app.toml | 12 ++++++------ ...application_sso_authentication_repeat_source.toml | 2 +- ...ces_reported_for_oauth_access_tokens_granted.toml | 6 +++--- ...re_oauth_access_token_granted_by_application.toml | 8 ++++---- ...ss_higher_than_average_failed_authentication.toml | 8 ++++---- .../initial_access_impossible_travel_sign_on.toml | 10 +++++----- ..._access_password_spraying_from_repeat_source.toml | 10 +++++----- ...tence_multi_factor_push_notification_bombing.toml | 6 +++--- ...istence_rare_domain_with_user_authentication.toml | 6 +++--- .../queries/windows_logon_activity_by_source_ip.toml | 2 +- 20 files changed, 68 insertions(+), 68 deletions(-) diff --git a/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml b/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml index 990ae328f11..aeb0868cadf 100644 --- a/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml +++ b/hunting/aws/queries/ec2_suspicious_get_user_password_request.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Use the `instance_id` field to identify the EC2 instance for which the `GetPasswordData` requests were made", "Check for `RunInstances` API calls to determine if the instance was recently launched or if the password was reset", -"`error.code` can provide additional context if the `GetPasswordData` request failed or was denied", +"`aws.cloudtrail.error_code` can provide additional context if the `GetPasswordData` request failed or was denied", "Review the `aws.cloudtrail.user_identity*` fields to identify the user making the requests and their role permissions", "If a valid account compromise is suspected, review source.* fields for the IP address and geographical location of the request and compare with the user's typical behavior" ] diff --git a/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml b/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml index 4c1b289b4f0..50718cc2224 100644 --- a/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml +++ b/hunting/azure/queries/entra_authentication_attempts_behind_rare_user_agents.toml @@ -11,10 +11,10 @@ license = "Elastic License v2" notes = [ "Review `azure.signinlogs.properties.authentication_protocol` to verify the authentication method used. Non-interactive SFA is typically reserved for automated processes or legacy authentication methods.", "Review `azure.signinlogs.properties.error_code` to identify the specific error codes associated with the failed authentication attempts. Common error codes include `50053` for account lockouts, `50126` for invalid credentials, and `50055` for expired passwords.", - "Investigate `user.name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", + "Investigate `azure.signinlogs.properties.user_principal_name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", "Analyze `source.as.organization.name` to determine if the request originated from a known hosting provider, VPN, or anonymization service that is unexpected in your environment.", "Examine `source.address` to check if the IP address is associated with previous suspicious activity, high-risk geolocations, or known threat infrastructure.", - "Pivot on `user.name` to identify any other high-risk activities within the same session.", + "Pivot on `azure.signinlogs.properties.user_principal_name` to identify any other high-risk activities within the same session.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to identify possible legacy protocol usage, token replay, permission scopes or bypass mechanisms.", "Review `user_agent.original` to identify the user agent used in the authentication request. Determine if this user agent is expected in your environment or if it is associated with known malicious activity.", ] @@ -35,7 +35,7 @@ from logs-azure.signinlogs* user_agent.original, azure.signinlogs.category, event.outcome, - user.name, + azure.signinlogs.properties.user_principal_name, source.ip | WHERE event.dataset == "azure.signinlogs" @@ -67,7 +67,7 @@ from logs-azure.signinlogs* // count the number of unique user login attempts | stats unique_user_app_login_count = count(*) by - user.name, + azure.signinlogs.properties.user_principal_name, azure.signinlogs.properties.authentication_requirement, azure.signinlogs.properties.app_id | sort unique_user_app_login_count asc diff --git a/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml b/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml index 361b1100e0e..7e53fd3d2fd 100644 --- a/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml +++ b/hunting/azure/queries/entra_authentication_attempts_from_abused_hosting_service_providers.toml @@ -13,7 +13,7 @@ notes = [ "Device Code Flow authentication is particularly suspicious for non-kiosk, non-IoT devices.", "Analyze `source.as.organization.name` to identify if the authentication originated from a known hosting provider, VPN, or anonymization service you are not expecting", "Investigate `source.address` to determine if the IP address has been previously flagged for suspicious activity.", - "Pivot on `user.name` to check for additional authentication attempts from different IPs, ASNs, or unusual geolocations.", + "Pivot on `azure.signinlogs.properties.user_principal_name` to check for additional authentication attempts from different IPs, ASNs, or unusual geolocations.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to check if legacy protocols, token replay, or bypass mechanisms were involved.", "Look for associated Conditional Access policy decisions in `azure.signinlogs.properties.applied_conditional_access_policies` to determine if the authentication attempt was blocked or allowed.", "Check `azure.signinlogs.properties.device_detail.browser` to see if the user agent is consistent with expected authentication patterns.", @@ -77,7 +77,7 @@ FROM logs-azure.signinlogs-* // aggregate authentication attempts by tenant, user principal name, authentication protocol, category, ASN organization name, and source address | STATS asn_count = count(*) by azure.tenant_id, - user.name, + azure.signinlogs.properties.user_principal_name, azure.signinlogs.properties.authentication_protocol, azure.signinlogs.category, source.as.organization.name, diff --git a/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml b/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml index 0a7ca088a5f..293b2614048 100644 --- a/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml +++ b/hunting/azure/queries/entra_device_code_authentication_from_unusual_principal.toml @@ -15,7 +15,7 @@ notes = [ "Device code flow IS MFA-capable. Single-factor authentication on a device code grant is meaningful — it indicates either no Conditional Access policy targeted the resource, or the policy excludes device code, or no MFA baseline exists. Treat SFA on these grants as elevated risk, not expected behavior.", "Missing `azure.signinlogs.properties.device_detail.*` fields indicate the authenticating endpoint is not Entra-joined, not Intune-enrolled, and not compliant — consistent with an attacker-controlled host completing the flow on the victim's behalf.", "Pivot on `azure.signinlogs.properties.correlation_id`, `session_id`, and `unique_token_identifier` to correlate with subsequent Microsoft Graph activity (`azure.graphactivitylogs-*`), Azure activity (`azure.activitylogs-*`), and M365 audit events (`o365.audit-*`) to map post-compromise actions on the same identity.", - "Pivot on `user.id` against detection alerts on the same cluster to surface stacked alerts on the identity (rare app ID, rare authentication requirement, OAuth phishing first-party app, high-risk sign-in).", + "Pivot on `azure.signinlogs.properties.user_id` against detection alerts on the same cluster to surface stacked alerts on the identity (rare app ID, rare authentication requirement, OAuth phishing first-party app, high-risk sign-in).", "Investigate `user_agent.original` for forged or anomalous tokens (offensive tooling like python-requests, httpx, fasthttp, kali, axiom, nuclei, msal-python, or deliberately silly forged UAs are high-confidence indicators). Real browsers in standard form are not exonerating but do reduce immediate priority.", "Inspect `source.as.organization.name` and `source.geo.country_iso_code` against the user's normal sign-in pattern. Sudden non-Microsoft hosting providers, residential VPNs, or unexpected geographies on these flows are high-priority.", "Microsoft-owned ASNs (MICROSOFT-CORP-MSN-AS-BLOCK / AS8075) are excluded by default but can be re-enabled for tenants where Azure-hosted infrastructure abuse is in scope.", @@ -103,7 +103,7 @@ FROM logs-azure.signinlogs-* correlation_ids = VALUES(azure.signinlogs.properties.correlation_id), session_ids = VALUES(azure.signinlogs.properties.session_id) BY - user.name, + azure.signinlogs.properties.user_principal_name, azure.signinlogs.properties.app_display_name, azure.signinlogs.properties.resource_display_name, azure.signinlogs.properties.authentication_requirement diff --git a/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml b/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml index 4787265b208..9f017e5ebd9 100644 --- a/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml +++ b/hunting/azure/queries/entra_excessive_non_interactive_sfa_sign_ins_across_users.toml @@ -11,10 +11,10 @@ license = "Elastic License v2" notes = [ "Review `azure.signinlogs.properties.authentication_protocol` to verify the authentication method used. Non-interactive SFA is typically reserved for automated processes or legacy authentication methods.", "Review `azure.signinlogs.properties.error_code` to identify the specific error codes associated with the failed authentication attempts. Common error codes include `50053` for account lockouts, `50126` for invalid credentials, and `50055` for expired passwords.", - "Investigate `user.name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", + "Investigate `azure.signinlogs.properties.user_principal_name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", "Analyze `source.as.organization.name` to determine if the request originated from a known hosting provider, VPN, or anonymization service that is unexpected in your environment.", "Examine `source.address` to check if the IP address is associated with previous suspicious activity, high-risk geolocations, or known threat infrastructure.", - "Pivot on `user.name` to identify any other high-risk activities within the same session.", + "Pivot on `azure.signinlogs.properties.user_principal_name` to identify any other high-risk activities within the same session.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to identify possible legacy protocol usage, token replay, permission scopes or bypass mechanisms.", ] mitre = ['T1078.004','T1110.003'] @@ -34,7 +34,7 @@ from logs-azure.signinlogs* source.as.organization.name, azure.signinlogs.category, event.outcome, - user.name, + azure.signinlogs.properties.user_principal_name, source.ip // truncate the timestamp to a 10-minute window | eval target_time_window = DATE_TRUNC(10 minutes, @timestamp) @@ -48,7 +48,7 @@ from logs-azure.signinlogs* and azure.signinlogs.properties.status.error_code in (50053, 50126, 50055, 50056, 50064, 50144) // count the number of unique user login attempts | stats - unique_user_login_count = count_distinct(user.name) by target_time_window, azure.signinlogs.properties.status.error_code + unique_user_login_count = count_distinct(azure.signinlogs.properties.user_principal_name) by target_time_window, azure.signinlogs.properties.status.error_code // filter for >= 30 failed SFA auth attempts with the same error codes | where unique_user_login_count >= 30 ''' diff --git a/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml b/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml index f59ce291f19..8124767050e 100644 --- a/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml +++ b/hunting/azure/queries/entra_service_principal_credentials_added_to_rare_app.toml @@ -31,7 +31,7 @@ FROM logs-azure.auditlogs* | WHERE @timestamp > now() - 60 day | WHERE event.dataset == "azure.auditlogs" - AND event.action == "Add service principal credentials" + AND azure.auditlogs.operation_name == "Add service principal credentials" AND event.outcome == "success" | EVAL // Extract appId from additional_details @@ -45,12 +45,12 @@ FROM logs-azure.auditlogs* // Bucket events by each week timestamp_week_bucket = DATE_TRUNC(7 day, @timestamp) | STATS - operation = VALUES(event.action), + operation = VALUES(azure.auditlogs.operation_name), app_id = VALUES(azure.auditlogs.properties.additional_details.appId), correlation_id = VALUES(azure.auditlogs.properties.correlation_id), identity = VALUES(azure.auditlogs.properties.identity), initiated_by_id = VALUES(azure.auditlogs.properties.initiated_by.user.id), - user_principal_name = VALUES(user.name), + user_principal_name = VALUES(azure.auditlogs.properties.initiated_by.user.userPrincipalName), tenant_id = VALUES(azure.auditlogs.properties.tenantId), modified_properties_new = VALUES(azure.auditlogs.properties.target_resources.`0`.modified_properties.`0`.new_value), modified_properties_old = VALUES(azure.auditlogs.properties.target_resources.`0`.modified_properties.`0`.old_value), diff --git a/hunting/azure/queries/entra_suspicious_odata_client_requests.toml b/hunting/azure/queries/entra_suspicious_odata_client_requests.toml index 53854d8f430..4b9aa793210 100644 --- a/hunting/azure/queries/entra_suspicious_odata_client_requests.toml +++ b/hunting/azure/queries/entra_suspicious_odata_client_requests.toml @@ -12,7 +12,7 @@ notes = [ "Review `azure.auditlogs.properties.additional_details.value` for `Microsoft.OData.Client/*` User-Agent strings. This is uncommon for legitimate first-party Microsoft applications and may indicate use of ROADTools or custom automation to register a device and obtain a PRT.", "Check `azure.auditlogs.properties.initiated_by` for both `user` and `app` fields. The presence of both may suggest an OAuth on-behalf-of (OBO) flow, where the app is acting with delegated permissions from a phished user token.", "Review `azure.auditlogs.properties.activity_display_name` and `operation_name` for device registration operations like `Add device` or `Add registered owner to device`. When combined with suspicious user-agents, this may indicate unauthorized device registration.", - "Review `user.full_name` for operations performed by `Device Registration Service`. This service name is commonly associated with device join flows that, if abused, may enable persistence via PRT acquisition.", + "Review `azure.auditlogs.identity` for operations performed by `Device Registration Service`. This service name is commonly associated with device join flows that, if abused, may enable persistence via PRT acquisition.", "Correlate with `azure.signinlogs` for sign-ins using the same `correlation_id` or `userPrincipalName`. Look for signs of previous OAuth token issuance or multi-geo IP behavior surrounding the device registration.", "Investigate whether the device registered (under `azure.auditlogs.properties.target_resources`) corresponds to known or authorized endpoints. Devices with names like `DESKTOP-ATTACKER1` or unexpected OS versions may indicate rogue joins.", "The source IP is likely to be Microsoft-managed infrastructure as requests are proxied through Azure services. Pivoting into which user principal the request is targeting and events leading up to the request may provide additional context." @@ -34,27 +34,27 @@ FROM logs-azure.auditlogs* METADATA _id, _index // Identify logs with the known suspicious OData user agent AND azure.auditlogs.properties.additional_details.value LIKE "Microsoft.OData.Client/*" - AND user.full_name != "Device Registration Service" + AND azure.auditlogs.identity != "Device Registration Service" // Extract time window for pattern analysis | EVAL time_window = DATE_TRUNC(1d, @timestamp) // Normalize actor: prefer user UPN if available, else fallback to app name | EVAL actor = COALESCE( - user.name, + azure.auditlogs.properties.initiated_by.user.userPrincipalName, azure.auditlogs.properties.initiated_by.app.displayName, "unknown" ) // Keep core fields -| KEEP @timestamp, actor, source.ip, event.action, azure.auditlogs.properties.activity_display_name, user.full_name, azure.auditlogs.properties.tenantId, azure.auditlogs.properties.initiated_by.app.servicePrincipalId, azure.auditlogs.properties.category, azure.auditlogs.properties.additional_details.value, time_window +| KEEP @timestamp, actor, source.ip, azure.auditlogs.operation_name, azure.auditlogs.properties.activity_display_name, azure.auditlogs.identity, azure.auditlogs.properties.tenantId, azure.auditlogs.properties.initiated_by.app.servicePrincipalId, azure.auditlogs.properties.category, azure.auditlogs.properties.additional_details.value, time_window // Group by actor per day | STATS count = COUNT(), unique_ips = COUNT_DISTINCT(source.ip), - operations = VALUES(event.action), - identities = VALUES(user.full_name), + operations = VALUES(azure.auditlogs.operation_name), + identities = VALUES(azure.auditlogs.identity), ips = VALUES(source.ip), categories = VALUES(azure.auditlogs.properties.category), clients = VALUES(azure.auditlogs.properties.additional_details.value) diff --git a/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml b/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml index 20ee0612142..0b5c48bc285 100644 --- a/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml +++ b/hunting/azure/queries/entra_unusual_client_app_auth_request_on_behalf_of_user.toml @@ -11,10 +11,10 @@ license = "Elastic License v2" notes = [ "Review `azure.signinlogs.properties.authentication_protocol` to verify the authentication method used. Non-interactive SFA is typically reserved for automated processes or legacy authentication methods.", "Review `azure.signinlogs.properties.error_code` to identify the specific error codes associated with the failed authentication attempts. Common error codes include `50053` for account lockouts, `50126` for invalid credentials, and `50055` for expired passwords.", - "Investigate `user.name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", + "Investigate `azure.signinlogs.properties.user_principal_name` to determine whether the user typically authenticates using SFA. Unusual use by regular accounts may indicate compromise.", "Analyze `source.as.organization.name` to determine if the request originated from a known hosting provider, VPN, or anonymization service that is unexpected in your environment.", "Examine `source.address` to check if the IP address is associated with previous suspicious activity, high-risk geolocations, or known threat infrastructure.", - "Pivot on `user.name` to identify any other high-risk activities within the same session.", + "Pivot on `azure.signinlogs.properties.user_principal_name` to identify any other high-risk activities within the same session.", "Correlate findings with `azure.signinlogs.properties.authentication_processing_details` to identify possible legacy protocol usage, token replay, permission scopes or bypass mechanisms.", ] mitre = ['T1078.004','T1110.003'] @@ -29,7 +29,7 @@ from logs-azure.signinlogs* event.category, azure.signinlogs.properties.app_display_name, azure.signinlogs.properties.app_id, - user.name, + azure.signinlogs.properties.user_principal_name, azure.signinlogs.properties.status.error_code, azure.signinlogs.category, source.as.organization.name, @@ -45,7 +45,7 @@ from logs-azure.signinlogs* // aggregate the number of failed sign-in attempts by user and app ID reported | stats auth_via_app_count = count(*) by - user.name, + azure.signinlogs.properties.user_principal_name, azure.signinlogs.properties.app_display_name, azure.signinlogs.properties.app_id // filter for users with less than or equal to 3 failed sign-in attempts per app diff --git a/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml b/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml index 8bb5159d6b1..b0c20360235 100644 --- a/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml +++ b/hunting/okta/queries/credential_access_mfa_bombing_push_notifications.toml @@ -9,7 +9,7 @@ name = "Rapid MFA Deny Push Notifications (MFA Bombing)" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`user.name` is the targeted user account.", + "`okta.actor.alternate_id` is the targeted user account.", "Pivot and search for `event.action` is `user.authentication.auth_via_mfa` to determine if the target user accepted the MFA push notification.", "If a MFA bombing attack is suspected, both username and password are required prior to MFA push notifications. Thus the credentials are likely compromised.", ] @@ -26,7 +26,7 @@ from logs-okta* | where event.action == "user.mfa.okta_verify.deny_push" // Count the number of MFA deny push notifications for each user in each 10 minute window -| stats deny_push_count = count(*) by target_time_window, user.name +| stats deny_push_count = count(*) by target_time_window, okta.actor.alternate_id // Filter for users with more than 5 MFA deny push notifications | where deny_push_count >= 5 diff --git a/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml b/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml index 77f5228dbbd..f74cf1453ac 100644 --- a/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml +++ b/hunting/okta/queries/credential_access_rapid_reset_password_requests_for_different_users.toml @@ -9,9 +9,9 @@ name = "Rapid Reset Password Requests for Different Users" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`user.name` is the potentially compromised account", - "An API access token may have been compromised, where user.name reflects the owner", - "To identify a list of tokens this user created, search for the `user.name` where `event.action` is `system.api_token*` which may require a larger time window" + "`okta.actor.alternate_id` is the potentially compromised account", + "An API access token may have been compromised, where okta.actor.alternate_id reflects the owner", + "To identify a list of tokens this user created, search for the `okta.actor.alternate_id` where `event.action` is `system.api_token*` which may require a larger time window" ] mitre = ['T1098.001'] query = [''' @@ -22,12 +22,12 @@ from logs-okta.system* | where event.dataset == "okta.system" and event.action == "user.account.reset_password" and source.user.full_name != user.target.full_name // Extract relevant fields -| keep @timestamp, user.name, okta.debug_context.debug_data.dt_hash, user.target.full_name, event.outcome +| keep @timestamp, okta.actor.alternate_id, okta.debug_context.debug_data.dt_hash, user.target.full_name, okta.outcome.result // Count the number of reset password attempts for each user | stats user_count = count_distinct(user.target.full_name), - reset_counts = by user.name, source.user.full_name, okta.debug_context.debug_data.dt_hash + reset_counts = by okta.actor.alternate_id, source.user.full_name, okta.debug_context.debug_data.dt_hash // Filter for more than 10 unique users and more than 15 reset password attempts by the source | where user_count > 10 and reset_counts > 15 diff --git a/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml b/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml index 9ec60555382..ea38cd6c528 100644 --- a/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml +++ b/hunting/okta/queries/defense_evasion_failed_oauth_access_token_retrieval_via_public_client_app.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Review `okta.debug_context.debug_data.flattened.grantType` to identify if the grant type is `client_credentials`", "Ignore `okta.debug_context.debug_data.flattened.requestedScopes` values that indicate read-only access", - "Review `user.full_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", + "Review `okta.actor.display_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", "Pivot for successful access token retrieval by the same public client app by searching `event.action` equal to `app.oauth2.as.token.grant.access_token` where the display name is the same." ] mitre = ['T1550.001'] @@ -24,16 +24,16 @@ from logs-okta.system* // filter on failed access token grant requests where source is a public client app and event.action == "app.oauth2.as.token.grant" and okta.actor.type == "PublicClientApp" - and event.outcome == "FAILURE" + and okta.outcome.result == "FAILURE" // filter out known Okta and Datadog actors and not ( - user.full_name LIKE "Okta%" - or user.full_name LIKE "Datadog%" + okta.actor.display_name LIKE "Okta%" + or okta.actor.display_name LIKE "Datadog%" ) // filter for scopes that are not implicitly granted - and event.reason == "no_matching_scope" + and okta.outcome.reason == "no_matching_scope" -| keep @timestamp, event.action, okta.actor.type, event.outcome, event.reason, user.full_name +| keep @timestamp, event.action, okta.actor.type, okta.outcome.result, okta.outcome.reason, okta.actor.display_name '''] \ No newline at end of file diff --git a/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml b/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml index efc050320de..168413e7d8b 100644 --- a/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml +++ b/hunting/okta/queries/defense_evasion_multiple_application_sso_authentication_repeat_source.toml @@ -33,7 +33,7 @@ from logs-okta* | dissect okta.debug_context.debug_data.request_uri"%{?}/app/%{target_application}/" // count the number of unique applications per source IP and user in a 5-minute window -| stats application_count = count_distinct(target_application), window_count = count(*) by target_time_window, source.ip, user.name +| stats application_count = count_distinct(target_application), window_count = count(*) by target_time_window, source.ip, okta.actor.alternate_id // filter for at least 15 distinct applications authenticated from a single source IP | where application_count > 15 diff --git a/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml b/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml index 0efc7ee494c..d1f76770846 100644 --- a/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml +++ b/hunting/okta/queries/defense_evasion_multiple_client_sources_reported_for_oauth_access_tokens_granted.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Review `okta.debug_context.debug_data.flattened.grantType` to identify if the grant type is `client_credentials`", "Ignore `okta.debug_context.debug_data.flattened.requestedScopes` values that indicate read-only access", - "Review `user.full_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", + "Review `okta.actor.display_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", "Filter on the public client app and aggregate by `event.action` to determine what actions were taken by the public client app after the access token was granted." ] mitre = ['T1550.001'] @@ -32,10 +32,10 @@ from logs-okta.system* and okta.actor.type == "PublicClientApp" // ignore Elastic Okta integration and DataDog actors - and not (user.full_name LIKE "Okta*" or user.full_name LIKE "Datadog*") + and not (okta.actor.display_name LIKE "Okta*" or okta.actor.display_name LIKE "Datadog*") // count the number of access tokens granted by the same public client app in a day -| stats token_granted_count = count(*), unique_client_ip = count_distinct(source.ip) by target_time_window, user.full_name +| stats token_granted_count = count(*), unique_client_ip = count_distinct(okta.client.ip) by target_time_window, okta.actor.display_name // filter where access tokens were granted on the same day but client addresses are different | where unique_client_ip >= 2 and token_granted_count >= 2 diff --git a/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml b/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml index 81d4b46d155..f01aa37cc81 100644 --- a/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml +++ b/hunting/okta/queries/defense_evasion_rare_oauth_access_token_granted_by_application.toml @@ -11,7 +11,7 @@ license = "Elastic License v2" notes = [ "Review `okta.debug_context.debug_data.flattened.grantType` to identify if the grant type is `client_credentials`", "Ignore `okta.debug_context.debug_data.flattened.requestedScopes` values that indicate read-only access", - "Review `user.full_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", + "Review `okta.actor.display_name` to identify the public client app that attempted to retrieve the access token. This may help identify the compromised client credentials.", "False-positives may exist if the public client app is new or has not been used in the last 14 days." ] mitre = ['T1550.001'] @@ -29,11 +29,11 @@ from logs-okta.system* and okta.actor.type == "PublicClientApp" // ignore Elastic Okta integration and DataDog actors - and not user_agent.original == "Okta-Integrations" - and not (user.full_name LIKE "Okta%" or user.full_name LIKE "Datadog%") + and not okta.client.user_agent.raw_user_agent == "Okta-Integrations" + and not (okta.actor.display_name LIKE "Okta%" or okta.actor.display_name LIKE "Datadog%") // count the number of access tokens granted by the same public client app -| stats token_granted_count = count(*) by user.full_name +| stats token_granted_count = count(*) by okta.actor.display_name // filter where the public client app has only been granted an access token once in the last 14 days | where token_granted_count == 1 diff --git a/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml b/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml index 96fe880dded..10c16c1aeca 100644 --- a/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml +++ b/hunting/okta/queries/initial_access_higher_than_average_failed_authentication.toml @@ -9,7 +9,7 @@ name = "Identify High Average of Failed Daily Authentication Attempts" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "Pivot to users by only keeping the first stats statement where `user.name` is the targeted accounts.", + "Pivot to users by only keeping the first stats statement where `okta.actor.alternate_id` is the targeted accounts.", "Pivot for successful logins from the same source IP by searching for `event.action` equal to `user.session.start` or `user.authentication.verify` where the outcome is `SUCCESS`.", "User agents can be used to identify anomalous behavior, such as a user agent that is not associated with a known application or user.", "Another `WHERE` count can be added to the query if activity has been baseline to filter out known behavior." @@ -25,13 +25,13 @@ from logs-okta* // filter for invalid credential authentication events event.action == "user.session.start" - and event.outcome == "FAILURE" - and event.reason == "INVALID_CREDENTIALS" + and okta.outcome.result == "FAILURE" + and okta.outcome.reason == "INVALID_CREDENTIALS" and okta.actor.type == "User" | stats // count the number of daily failed logins for each day and user - failed_daily_logins = count(*) by target_time_window, user.name + failed_daily_logins = count(*) by target_time_window, okta.actor.alternate_id | stats // calculate the average number of daily failed logins for each day diff --git a/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml b/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml index ff8f5822f55..dee9a1dca7a 100644 --- a/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml +++ b/hunting/okta/queries/initial_access_impossible_travel_sign_on.toml @@ -9,8 +9,8 @@ name = "Successful Impossible Travel Sign-On Events" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`user.name` would be target of the threat adversary", - "Pivoting into a potential compromise requires an additional search for `event.outcome` being `SUCCESS` for any `user.authentication*` value for `event.action`", + "`okta.actor.alternate_id` would be target of the threat adversary", + "Pivoting into a potential compromise requires an additional search for `okta.outcome.result` being `SUCCESS` for any `user.authentication*` value for `okta.event_type`", "Pivot to any additional Okta logs after authentication to determine if activity is still being reported by separate countries." ] mitre = ['T1078.004'] @@ -20,14 +20,14 @@ from logs-okta.system* | where event.dataset == "okta.system" // filter on successful sign-on events only - and event.action == "policy.evaluate_sign_on" - and event.outcome in ("ALLOW", "SUCCESS") + and okta.event_type == "policy.evaluate_sign_on" + and okta.outcome.result in ("ALLOW", "SUCCESS") // Truncate the timestamp to 1 hour intervals | eval time_window = DATE_TRUNC(1 hours, @timestamp) // Count the number of successful sign-on events for each user every 15 minutes -| stats country_count = count_distinct(client.geo.country_name) by user.name, time_window +| stats country_count = count_distinct(client.geo.country_name) by okta.actor.alternate_id, time_window // Filter for users who sign on from more than one country in a 15 minute interval | where country_count >= 2 diff --git a/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml b/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml index 424e2d3d201..2d1d636410a 100644 --- a/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml +++ b/hunting/okta/queries/initial_access_password_spraying_from_repeat_source.toml @@ -9,7 +9,7 @@ name = "Password Spraying from Repeat Source" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`user.name` are the targeted accounts.", + "`okta.actor.alternate_id` are the targeted accounts.", "Pivot for successful logins from the same source IP by searching for `event.action` equal to `user.session.start` or `user.authentication.verify` where the outcome is `SUCCESS`.", "User agents can be used to identify anomalous behavior, such as a user agent that is not associated with a known application or user.", "The `target_count` can be adjusted depending on the organization's account lockout policy or baselined behavior." @@ -25,14 +25,14 @@ from logs-okta* // filter for invalid credential events event.action == "user.session.start" - and event.outcome == "FAILURE" - and event.reason == "INVALID_CREDENTIALS" + and okta.outcome.result == "FAILURE" + and okta.outcome.reason == "INVALID_CREDENTIALS" | stats // count the distinct number of targeted accounts - target_count = count_distinct(user.name), + target_count = count_distinct(okta.actor.alternate_id), // count the number of invalid credential events for each source IP - source_count = count(*) by target_time_window, source.ip + source_count = count(*) by target_time_window, okta.client.ip // filter for source IPs with more than 5 invalid credential events | where target_count >= 10 diff --git a/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml b/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml index 18c3072f7f8..d67152cdd71 100644 --- a/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml +++ b/hunting/okta/queries/persistence_multi_factor_push_notification_bombing.toml @@ -9,8 +9,8 @@ name = "Multi-Factor Authentication (MFA) Push Notification Bombing" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "`user.name` would be target of the threat adversary", - "Pivoting into a potential compromise requires an additional search for `event.outcome` being `SUCCESS` for any `user.authentication*` value for `event.action`", + "`okta.actor.alternate_id` would be target of the threat adversary", + "Pivoting into a potential compromise requires an additional search for `okta.outcome.result` being `SUCCESS` for any `user.authentication*` value for `okta.event_type`", "For a smaller window (rapid denies), reduce from 1 hour to 30 minutes or lower" ] mitre = ['T1556.006'] @@ -25,7 +25,7 @@ from logs-okta.system* | eval hourly_count = date_trunc(1 hour, event.ingested) // Count the number of deny push notifications for each user every hour -| stats hourly_denies = count(*) by user.name, hourly_count +| stats hourly_denies = count(*) by okta.actor.alternate_id, hourly_count // Filter for users who deny more than 5 push notifications in a single hour | where hourly_denies > 5 diff --git a/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml b/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml index 72a0023f215..44d595f3575 100644 --- a/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml +++ b/hunting/okta/queries/persistence_rare_domain_with_user_authentication.toml @@ -9,7 +9,7 @@ name = "Rare Occurrence of Domain with User Authentication Events" language = ["ES|QL"] license = "Elastic License v2" notes = [ - "Pivot into potential compromised accounts by searching for the `user.name` in `okta.target` where `event.action` is `user.lifecycle.create`. This would identify when the user account was created. The `user.name` of this event will also be the potential compromised account.", + "Pivot into potential compromised accounts by searching for the `okta.actor.alternate_id` in `okta.target` where `event.action` is `user.lifecycle.create`. This would identify when the user account was created. The `okta.actor.alternate_id` of this event will also be the potential compromised account.", ] mitre = ['T1078.004'] query = [''' @@ -17,11 +17,11 @@ from logs-okta* | where @timestamp > NOW() - 7 day | where // Filter for user authentication events - user.name is not null + okta.actor.alternate_id is not null and event.action LIKE "user.authentication*" // Extract the top-level domain (TLD) from the user's email address -| dissect user.name "%{}@%{tld}" +| dissect okta.actor.alternate_id "%{}@%{tld}" // Count the number of user authentication events for each TLD | stats tld_auth_counts = count(*) by tld diff --git a/hunting/windows/queries/windows_logon_activity_by_source_ip.toml b/hunting/windows/queries/windows_logon_activity_by_source_ip.toml index 15eaea87f30..3647b68d90b 100644 --- a/hunting/windows/queries/windows_logon_activity_by_source_ip.toml +++ b/hunting/windows/queries/windows_logon_activity_by_source_ip.toml @@ -22,7 +22,7 @@ from logs-system.security-* /* noisy failure status codes often associated to authentication misconfiguration */ not (event.action == "logon-failed" and winlog.event_data.Status in ("0xC000015B", "0XC000005E", "0XC0000133", "0XC0000192")) | eval failed = case(event.action == "logon-failed", source.ip, null), success = case(event.action == "logged-in", source.ip, null) -| stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(user.target.name) by source.ip +| stats count_failed = count(failed), count_success = count(success), count_user = count_distinct(winlog.event_data.TargetUserName) by source.ip /* below threshold should be adjusted to your env logon patterns */ | where count_failed >= 100 and count_success <= 10 and count_user >= 20 ''' From 0c8db3c3a4c0f47509ea23a5dc41fc983109a224 Mon Sep 17 00:00:00 2001 From: Mika Ayenson Date: Tue, 23 Jun 2026 16:44:08 -0500 Subject: [PATCH 3/3] Fix CI: revert macOS rule tuning and format test file Drop unrelated JumpCloud exclusion that referenced process.Ext fields outside the endpoint file schema. Apply ruff format to TestNonEcsSchema. --- ...persistence_suspicious_launch_agent_or_launch_daemon.toml | 5 ++--- tests/test_all_rules.py | 5 +---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml b/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml index 018214cea84..9a480e1b7f1 100644 --- a/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml +++ b/rules/macos/persistence_suspicious_launch_agent_or_launch_daemon.toml @@ -2,7 +2,7 @@ creation_date = "2026/01/30" integration = ["endpoint"] maturity = "production" -updated_date = "2026/06/23" +updated_date = "2026/01/30" [rule] author = ["Elastic"] @@ -86,8 +86,7 @@ file where host.os.type == "macos" and event.type != "deletion" and not process.executable like ("/System/*", "/Library/PrivilegedHelperTools/*") and not (process.code_signature.signing_id in ("com.apple.vim", "com.apple.cat", "com.apple.cfprefsd", "com.jetbrains.toolbox", "com.apple.pico", "com.apple.shove", - "com.sublimetext.4", "com.apple.ditto") and process.code_signature.trusted == true) and - not process.Ext.effective_parent.executable : "/opt/jc/bin/jumpcloud-agent" + "com.sublimetext.4", "com.apple.ditto") and process.code_signature.trusted == true) ''' [[rule.threat]] diff --git a/tests/test_all_rules.py b/tests/test_all_rules.py index 00013e13436..54b1f44187e 100644 --- a/tests/test_all_rules.py +++ b/tests/test_all_rules.py @@ -1702,7 +1702,4 @@ def test_static_fields_belong_in_non_ecs_schema(self): ) if redundant: - self.fail( - "Remove the following entries from non-ecs-schema.json:\n - " - + "\n - ".join(sorted(redundant)) - ) + self.fail("Remove the following entries from non-ecs-schema.json:\n - " + "\n - ".join(sorted(redundant)))