From 3dfc0a2cccd1e37d04c0327c2d5ed323397e677c Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Tue, 29 Sep 2026 09:56:41 -0500 Subject: [PATCH 1/8] Fix PingID credential-reset username matching and reset selection Normalize UPN and domain-prefixed usernames on both sides of the Windows password-event join while preserving the original PingID user in findings. Consider all matching password events and retain the nearest qualifying reset per complete stats group, preserving source-distinct pairings. Add the synthetic regression fixture from splunk/attack_data#1230 and increment the detection version. Local unit tests return two findings for the original fixture and four for the new fixture. Separate local assertions verify the exact results and nearest qualifying reset; the current CI unit runner only requires nonzero results. Co-Authored-By: Claude Opus 5.5 --- ...ngid_new_mfa_method_after_credential_reset.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index 534ffc8cb25..a9226ce3e8a 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -1,15 +1,15 @@ name: PingID New MFA Method After Credential Reset id: 2fcbce12-cffa-4c84-b70c-192604d201d0 -version: 9 +version: 10 creation_date: '2023-12-20' -modification_date: '2026-05-13' +modification_date: '2026-09-29' author: Steven Dick status: production type: TTP description: The following analytic identifies the provisioning of a new MFA device shortly after a password reset. It detects this activity by correlating Windows Event Log events for password changes (EventID 4723, 4724) with PingID logs indicating device pairing. This behavior is significant as it may indicate a social engineering attack where a threat actor impersonates a valid user to reset credentials and add a new MFA device. If confirmed malicious, this activity could allow an attacker to gain persistent access to the compromised account, bypassing traditional security measures. data_source: - PingID -search: "`pingid` \"result.message\" = \"*Device Paired*\" | rex field=result.message \"Device (Unp)?(P)?aired (?.+)\" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel'), user = upper('actors{}.name'), reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) | eval action=CASE(match('result.message',\"Device Paired*\"),\"created\",match('result.message', \"Device Unpaired*\"),\"deleted\") | stats count min(_time) as firstTime, max(_time) as lastTime, values(reason) as reason by src,user,action,object | join type=outer user [| search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time, user = upper(user) | fields user,src_user,EventID,PW_Change_Time] | eval timeDiffRaw = round(lastTime - PW_Change_Time) | eval timeDiff = replace(tostring(abs(timeDiffRaw) ,\"duration\"),\"(\\d*)\\+*(\\d+):(\\d+):(\\d+)\",\"\\2 hours \\3 minutes\") | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `security_content_ctime(PW_Change_Time)` | where timeDiffRaw > 0 AND timeDiffRaw < 3600 | `pingid_new_mfa_method_after_credential_reset_filter`" +search: "`pingid` \"result.message\" = \"*Device Paired*\" | rex field=result.message \"Device (Unp)?(P)?aired (?.+)\" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel'), user = upper('actors{}.name'), reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) | eval action=CASE(match('result.message',\"Device Paired*\"),\"created\",match('result.message', \"Device Unpaired*\"),\"deleted\") | stats count min(_time) as firstTime, max(_time) as lastTime, values(reason) as reason by src,user,action,object | eval join_user = replace(user, \"^[^\\x5c]*\\x5c|@.*$\", \"\") | join type=outer max=0 join_user [| search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time, join_user = replace(upper(user), \"^[^\\x5c]*\\x5c|@.*$\", \"\") | fields join_user,src_user,EventID,PW_Change_Time] | eval timeDiffRaw = round(lastTime - PW_Change_Time) | eval timeDiff = replace(tostring(abs(timeDiffRaw) ,\"duration\"),\"(\\d*)\\+*(\\d+):(\\d+):(\\d+)\",\"\\2 hours \\3 minutes\") | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `security_content_ctime(PW_Change_Time)` | where timeDiffRaw > 0 AND timeDiffRaw < 3600 | dedup src, user, action, object, lastTime sortby +timeDiffRaw | fields - join_user | `pingid_new_mfa_method_after_credential_reset_filter`" how_to_implement: Target environment must ingest Windows Event Log and PingID(PingOne) data sources. Specifically from logs from Active Directory Domain Controllers and JSON logging from a PingID(PingOne) enterprise environment, either via Webhook or Push Subscription. known_false_positives: False positives may be generated by normal provisioning workflows that generate a password reset followed by a device registration. references: @@ -57,3 +57,12 @@ tests: source: PINGID sourcetype: _json test_type: unit + - name: True Positive Test - UPN usernames and multiple resets + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1621/pingid/windows_pw_reset_upn_multi_reset.log + source: XmlWinEventLog:Security + sourcetype: XmlWinEventLog + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1621/pingid/pingid_upn_multi_reset.log + source: PINGID + sourcetype: _json + test_type: unit From 98ee4dd43544f1604257c66c3e633eeec77526e2 Mon Sep 17 00:00:00 2001 From: Onur Mustafa Erdogan <156806007+onurmerdogan@users.noreply.github.com> Date: Fri, 9 Oct 2026 16:17:48 +0200 Subject: [PATCH 2/8] Update pingid_new_mfa_method_after_credential_reset.yml --- ..._new_mfa_method_after_credential_reset.yml | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index a9226ce3e8a..3c901734ba8 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -6,10 +6,41 @@ modification_date: '2026-09-29' author: Steven Dick status: production type: TTP -description: The following analytic identifies the provisioning of a new MFA device shortly after a password reset. It detects this activity by correlating Windows Event Log events for password changes (EventID 4723, 4724) with PingID logs indicating device pairing. This behavior is significant as it may indicate a social engineering attack where a threat actor impersonates a valid user to reset credentials and add a new MFA device. If confirmed malicious, this activity could allow an attacker to gain persistent access to the compromised account, bypassing traditional security measures. +description: |- + The following analytic identifies the provisioning of a new MFA device shortly after a password reset. It detects this activity by correlating Windows Event Log events for password changes + (EventID 4723, 4724) with PingID logs indicating device pairing. This behavior is significant as it may indicate a social engineering attack where a threat actor impersonates a valid user + to reset credentials and add a new MFA device. If confirmed malicious, this activity could allow an attacker to gain persistent access to the compromised account, bypassing traditional security measures. data_source: - PingID -search: "`pingid` \"result.message\" = \"*Device Paired*\" | rex field=result.message \"Device (Unp)?(P)?aired (?.+)\" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel'), user = upper('actors{}.name'), reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) | eval action=CASE(match('result.message',\"Device Paired*\"),\"created\",match('result.message', \"Device Unpaired*\"),\"deleted\") | stats count min(_time) as firstTime, max(_time) as lastTime, values(reason) as reason by src,user,action,object | eval join_user = replace(user, \"^[^\\x5c]*\\x5c|@.*$\", \"\") | join type=outer max=0 join_user [| search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time, join_user = replace(upper(user), \"^[^\\x5c]*\\x5c|@.*$\", \"\") | fields join_user,src_user,EventID,PW_Change_Time] | eval timeDiffRaw = round(lastTime - PW_Change_Time) | eval timeDiff = replace(tostring(abs(timeDiffRaw) ,\"duration\"),\"(\\d*)\\+*(\\d+):(\\d+):(\\d+)\",\"\\2 hours \\3 minutes\") | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `security_content_ctime(PW_Change_Time)` | where timeDiffRaw > 0 AND timeDiffRaw < 3600 | dedup src, user, action, object, lastTime sortby +timeDiffRaw | fields - join_user | `pingid_new_mfa_method_after_credential_reset_filter`" +search: | + `pingid` "result.message" = "*Device Paired*" + + | rex field=result.message "Device (Unp)?(P)?aired (?.+)" + | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel') + | eval user = replace(upper('actors{}.name'), "[^\\]*\\|@.*$", "") + | eval reason = 'result.message' + | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) + | eval action=CASE(match('result.message',"Device Paired*"),"created",match('result.message', "Device Unpaired*"),"deleted") + + | stats count min(_time) as firstTime, max(_time) as lastTime, values(reason) as reason by src,user,action,object + + | join type=outer max=0 user [ + | search `wineventlog_security` EventID IN(4723,4724) + | eval PW_Change_Time = _time + | eval user = replace(upper(user), "^[^\\]*\\|@.*$", "") + | fields user,src_user,EventID,PW_Change_Time + ] + + | eval timeDiffRaw = round(lastTime - PW_Change_Time) + | eval timeDiff = replace(tostring(abs(timeDiffRaw) ,"duration"),"(\d*)\+*(\d+):(\d+):(\d+)","\2 hours \3 minutes") + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `security_content_ctime(PW_Change_Time)` + + | where timeDiffRaw > 0 AND timeDiffRaw < 3600 + | dedup src, user, action, object, lastTime sortby +timeDiffRaw + + | `pingid_new_mfa_method_after_credential_reset_filter` how_to_implement: Target environment must ingest Windows Event Log and PingID(PingOne) data sources. Specifically from logs from Active Directory Domain Controllers and JSON logging from a PingID(PingOne) enterprise environment, either via Webhook or Push Subscription. known_false_positives: False positives may be generated by normal provisioning workflows that generate a password reset followed by a device registration. references: From 1f9689d54f95ff61f0564abdb74cf94206c5fe72 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Fri, 9 Oct 2026 10:09:01 -0500 Subject: [PATCH 3/8] Restore \x5c escapes in username normalization In an eval string literal "\\" reaches the regex engine as a single backslash, so "[^\\]*\\|@.*$" parses as an unterminated character class and the search fails: "Regex: missing terminating ] for character class". \x5c survives both YAML and SPL unescaping. Also restores the ^ anchor on the PingID side to match the Windows side. Co-Authored-By: Claude Fable 5.1 --- .../pingid_new_mfa_method_after_credential_reset.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index 3c901734ba8..4a790f5439f 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -17,7 +17,7 @@ search: | | rex field=result.message "Device (Unp)?(P)?aired (?.+)" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel') - | eval user = replace(upper('actors{}.name'), "[^\\]*\\|@.*$", "") + | eval user = replace(upper('actors{}.name'), "^[^\x5c]*\x5c|@.*$", "") | eval reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) | eval action=CASE(match('result.message',"Device Paired*"),"created",match('result.message', "Device Unpaired*"),"deleted") @@ -27,7 +27,7 @@ search: | | join type=outer max=0 user [ | search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time - | eval user = replace(upper(user), "^[^\\]*\\|@.*$", "") + | eval user = replace(upper(user), "^[^\x5c]*\x5c|@.*$", "") | fields user,src_user,EventID,PW_Change_Time ] From 4bd8317dbaef2e364b8b7e9d908f08ac0717c223 Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Fri, 9 Oct 2026 10:19:31 -0500 Subject: [PATCH 4/8] Strip trailing whitespace for YAML validation Co-Authored-By: Claude Fable 5.1 --- .../pingid_new_mfa_method_after_credential_reset.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index 4a790f5439f..221b14cd3bd 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -14,23 +14,23 @@ data_source: - PingID search: | `pingid` "result.message" = "*Device Paired*" - + | rex field=result.message "Device (Unp)?(P)?aired (?.+)" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel') | eval user = replace(upper('actors{}.name'), "^[^\x5c]*\x5c|@.*$", "") | eval reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) | eval action=CASE(match('result.message',"Device Paired*"),"created",match('result.message', "Device Unpaired*"),"deleted") - + | stats count min(_time) as firstTime, max(_time) as lastTime, values(reason) as reason by src,user,action,object - + | join type=outer max=0 user [ | search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time | eval user = replace(upper(user), "^[^\x5c]*\x5c|@.*$", "") | fields user,src_user,EventID,PW_Change_Time ] - + | eval timeDiffRaw = round(lastTime - PW_Change_Time) | eval timeDiff = replace(tostring(abs(timeDiffRaw) ,"duration"),"(\d*)\+*(\d+):(\d+):(\d+)","\2 hours \3 minutes") | `security_content_ctime(firstTime)` @@ -39,7 +39,7 @@ search: | | where timeDiffRaw > 0 AND timeDiffRaw < 3600 | dedup src, user, action, object, lastTime sortby +timeDiffRaw - + | `pingid_new_mfa_method_after_credential_reset_filter` how_to_implement: Target environment must ingest Windows Event Log and PingID(PingOne) data sources. Specifically from logs from Active Directory Domain Controllers and JSON logging from a PingID(PingOne) enterprise environment, either via Webhook or Push Subscription. known_false_positives: False positives may be generated by normal provisioning workflows that generate a password reset followed by a device registration. From 1e5a5a312eb55fd08cb86efdf36db88afc666acd Mon Sep 17 00:00:00 2001 From: Onur Mustafa Erdogan <156806007+onurmerdogan@users.noreply.github.com> Date: Fri, 9 Oct 2026 17:40:01 +0200 Subject: [PATCH 5/8] Update pingid_new_mfa_method_after_credential_reset.yml --- .../pingid_new_mfa_method_after_credential_reset.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index 221b14cd3bd..9592b129c20 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -17,6 +17,7 @@ search: | | rex field=result.message "Device (Unp)?(P)?aired (?.+)" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel') + ```Standardizes user field by removing NetBIOS and email from reported user name``` | eval user = replace(upper('actors{}.name'), "^[^\x5c]*\x5c|@.*$", "") | eval reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) @@ -27,6 +28,7 @@ search: | | join type=outer max=0 user [ | search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time + ```Standardizes user field by removing NetBIOS and email from reported user name``` | eval user = replace(upper(user), "^[^\x5c]*\x5c|@.*$", "") | fields user,src_user,EventID,PW_Change_Time ] From 77812d5c6e0403ad5f080799dc86fe9207e8e317 Mon Sep 17 00:00:00 2001 From: nasbench <8741929+nasbench@users.noreply.github.com> Date: Mon, 12 Oct 2026 13:01:10 +0200 Subject: [PATCH 6/8] Update pingid_new_mfa_method_after_credential_reset.yml --- ...ingid_new_mfa_method_after_credential_reset.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index 9592b129c20..3810a5a3fae 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -13,11 +13,14 @@ description: |- data_source: - PingID search: | - `pingid` "result.message" = "*Device Paired*" + `pingid` + "result.message" = "*Device Paired*" | rex field=result.message "Device (Unp)?(P)?aired (?.+)" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel') + ```Standardizes user field by removing NetBIOS and email from reported user name``` + | eval user = replace(upper('actors{}.name'), "^[^\x5c]*\x5c|@.*$", "") | eval reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) @@ -43,8 +46,10 @@ search: | | dedup src, user, action, object, lastTime sortby +timeDiffRaw | `pingid_new_mfa_method_after_credential_reset_filter` -how_to_implement: Target environment must ingest Windows Event Log and PingID(PingOne) data sources. Specifically from logs from Active Directory Domain Controllers and JSON logging from a PingID(PingOne) enterprise environment, either via Webhook or Push Subscription. -known_false_positives: False positives may be generated by normal provisioning workflows that generate a password reset followed by a device registration. +how_to_implement: |- + Target environment must ingest Windows Event Log and PingID(PingOne) data sources. Specifically from logs from Active Directory Domain Controllers and JSON logging from a PingID(PingOne) enterprise environment, either via Webhook or Push Subscription. +known_false_positives: |- + False positives may be generated by normal provisioning workflows that generate a password reset followed by a device registration. references: - https://techcommunity.microsoft.com/t5/microsoft-entra-azure-ad-blog/defend-your-users-from-mfa-fatigue-attacks/ba-p/2365677 - https://www.bleepingcomputer.com/news/security/mfa-fatigue-hackers-new-favorite-tactic-in-high-profile-breaches/ @@ -61,11 +66,12 @@ drilldown_searches: earliest_offset: 7d latest_offset: "0" finding: - title: An MFA configuration change was detected for [$user$] within [$timeDiff$] of a password reset. The device [$object$] was $action$. + title: An MFA configuration change was detected for [$user$] within [$timeDiff$] of a password reset. The device [$object$] was [$action$]. entity: field: user type: user score: 50 +threat_objects: [] analytic_story: - Compromised User Account - Scattered Lapsus$ Hunters From c9e519f4060183ec2b513c7a015e9073f966e1ba Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Mon, 12 Oct 2026 08:39:56 -0500 Subject: [PATCH 7/8] Keep the full PingID user in findings; join on a separate key The reformat normalized user in place, so findings and drilldowns showed the bare account name instead of the PingID username used by the other PingID detections. Join on join_user again and drop it before output. Co-Authored-By: Claude Opus 5.5 --- ...ngid_new_mfa_method_after_credential_reset.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index 3810a5a3fae..be76ff05922 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -19,21 +19,21 @@ search: | | rex field=result.message "Device (Unp)?(P)?aired (?.+)" | eval src = coalesce('resources{}.ipaddress','resources{}.devicemodel') - ```Standardizes user field by removing NetBIOS and email from reported user name``` - - | eval user = replace(upper('actors{}.name'), "^[^\x5c]*\x5c|@.*$", "") + | eval user = upper('actors{}.name') | eval reason = 'result.message' | eval object=CASE(ISNOTNULL('resources{}.devicemodel'),'resources{}.devicemodel',true(),device_extract) | eval action=CASE(match('result.message',"Device Paired*"),"created",match('result.message', "Device Unpaired*"),"deleted") | stats count min(_time) as firstTime, max(_time) as lastTime, values(reason) as reason by src,user,action,object - | join type=outer max=0 user [ + ```Join key: user name without NetBIOS domain or email suffix, so UPN and bare names match. user keeps the full PingID name``` + + | eval join_user = replace(user, "^[^\x5c]*\x5c|@.*$", "") + | join type=outer max=0 join_user [ | search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time - ```Standardizes user field by removing NetBIOS and email from reported user name``` - | eval user = replace(upper(user), "^[^\x5c]*\x5c|@.*$", "") - | fields user,src_user,EventID,PW_Change_Time + | eval join_user = replace(upper(user), "^[^\x5c]*\x5c|@.*$", "") + | fields join_user,src_user,EventID,PW_Change_Time ] | eval timeDiffRaw = round(lastTime - PW_Change_Time) @@ -44,6 +44,7 @@ search: | | where timeDiffRaw > 0 AND timeDiffRaw < 3600 | dedup src, user, action, object, lastTime sortby +timeDiffRaw + | fields - join_user | `pingid_new_mfa_method_after_credential_reset_filter` how_to_implement: |- From 0b220c9cef3c49fc1f59b9c28f744f9d9ab8e10f Mon Sep 17 00:00:00 2001 From: Steve Baker Date: Mon, 12 Oct 2026 15:26:45 -0500 Subject: [PATCH 8/8] Restore inline comments from review Co-Authored-By: Claude Opus 5.5 --- .../pingid_new_mfa_method_after_credential_reset.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/detections/application/pingid_new_mfa_method_after_credential_reset.yml b/detections/application/pingid_new_mfa_method_after_credential_reset.yml index be76ff05922..7b0097d43ca 100644 --- a/detections/application/pingid_new_mfa_method_after_credential_reset.yml +++ b/detections/application/pingid_new_mfa_method_after_credential_reset.yml @@ -26,12 +26,13 @@ search: | | stats count min(_time) as firstTime, max(_time) as lastTime, values(reason) as reason by src,user,action,object - ```Join key: user name without NetBIOS domain or email suffix, so UPN and bare names match. user keeps the full PingID name``` + ```Standardizes user field by removing NetBIOS and email from reported user name``` | eval join_user = replace(user, "^[^\x5c]*\x5c|@.*$", "") | join type=outer max=0 join_user [ | search `wineventlog_security` EventID IN(4723,4724) | eval PW_Change_Time = _time + ```Standardizes user field by removing NetBIOS and email from reported user name``` | eval join_user = replace(upper(user), "^[^\x5c]*\x5c|@.*$", "") | fields join_user,src_user,EventID,PW_Change_Time ]