Name:PingID New MFA Method Registered For User id:892dfeaf-461d-4a78-aac8-b07e185c9bce version:8 date:None author:Steven Dick status:production type:TTP Description:The following analytic detects the registration of a new Multi-Factor Authentication (MFA) method for a PingID (PingOne) account. It leverages JSON logs from PingID, specifically looking for successful device pairing events. This activity is significant as adversaries who gain unauthorized access to a user account may register a new MFA method to maintain persistence. If confirmed malicious, this could allow attackers to bypass existing security measures, maintain long-term access, and potentially escalate their privileges within the compromised environment. Data_source:
-PingID
search:`pingid` "result.message"="Device Paired*" result.status="SUCCESS" | rex field=result.message "Device (Unp)?(P)?aired (?<device_extract>.+)" | 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 by src,user,object,action,reason | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `pingid_new_mfa_method_registered_for_user_filter`
how_to_implement:Target environment must ingest 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 for user device registration. References: -https://twitter.com/jhencinski/status/1618660062352007174 -https://attack.mitre.org/techniques/T1098/005/ -https://attack.mitre.org/techniques/T1556/006/ -https://docs.pingidentity.com/r/en-us/pingoneforenterprise/p14e_subscriptions?tocId=3xhnxjX3VzKNs3SXigWnQA drilldown_searches: name:'View the detection results for - "$user$" and "$src$"' search:'%original_detection_search% | search user = "$user$" src = "$src$"' earliest_offset:'$info_min_time$' latest_offset:'$info_max_time$' name:'View risk events for the last 7 days for - "$user$" and "$src$"' search:'| from datamodel Risk.All_Risk | search normalized_risk_object IN ("$user$", "$src$") | stats count min(_time) as firstTime max(_time) as lastTime values(search_name) as "Search Name" values(risk_message) as "Risk Message" values(analyticstories) as "Analytic Stories" values(annotations._all) as "Annotations" values(annotations.mitre_attack.mitre_tactic) as "ATT&CK Tactics" by normalized_risk_object | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)`' earliest_offset:'7d' latest_offset:'0' analytic_story:['Compromised User Account']