Handala Detection Pack v2: Pre-Positioning, PIM Gap, and Bulk Wipe Controls
All Detection Pack v1 rules remain active. Deploy v2 alongside them. This pack adds five rules covering the pre-positioning phase that preceded the Stryker wipe, the architectural PIM gap that made it possible, and the bulk wipe prevention controls.
Download the Handala Detection Pack v2
5 Sigma rules, KQL hunting queries, and prevention configuration covering MuddyWater pre-positioning IOCs, PIM Authentication Context gap, bulk wipe prevention architecture, stale session detection, and Rclone exfiltration to MuddyWater cloud infrastructure.
Download Detection Pack v2 (.yml)Rule Overview
| Rule | Name | Covers | Level |
|---|---|---|---|
| Rule 11 | MuddyWater Pre-Positioning IOCs | Dindoor, Fakeset, Rclone to Wasabi/Backblaze | High |
| Rule 12 | PIM Activation Without Auth Context | Global Admin activated without FIDO2 challenge | Critical |
| Rule 13 | Bulk Wipe Threshold + Authorization Gate | 5+ wipes in 15 min, 3-layer prevention architecture | Critical |
| Rule 14 | Stale Session for Privileged Operation | AiTM-stolen token activating admin role | High |
| Rule 15 | Rclone Exfil to MuddyWater Infrastructure | Rclone to Wasabi or Backblaze destinations | High |
Rule 11: MuddyWater Pre-Positioning IOCs
MITRE ATT&CK: T1059.007, T1567.002, T1105
Detects Dindoor (Deno-based JavaScript backdoor) and Fakeset (Python backdoor) execution patterns, and Rclone exfiltration to Wasabi and Backblaze, all documented in MuddyWater pre-positioning operations against U.S. and Israeli targets in the weeks before the Stryker wipe.
Sigma Rule
title: MuddyWater Dindoor/Fakeset Backdoor Activity
id: a7c3e1d0-4b2f-4e8a-9c1d-5f6b7a8e9d0c
status: experimental
description: >
Dindoor (Deno JS) and Fakeset (Python) backdoors used in MuddyWater
pre-positioning operations prior to Handala destructive handoffs.
Rclone to Wasabi/Backblaze is the documented exfil pattern.
tags:
- attack.persistence
- attack.t1059.007
- attack.t1567.002
- attack.t1105
logsource:
category: process_creation
product: windows
detection:
dindoor_deno_runtime:
CommandLine|contains:
- 'deno.exe'
- 'deno run'
ParentImage|endswith:
- '\powershell.exe'
- '\cmd.exe'
- '\wscript.exe'
fakeset_python:
Image|endswith: '\python.exe'
CommandLine|contains:
- 'backblaze'
- 'b2.backblaze.com'
rclone_muddywater_exfil:
Image|endswith: '\rclone.exe'
CommandLine|contains:
- 'wasabi'
- 'wasabirclone'
- 's3.wasabisys.com'
- 'backblaze'
condition: dindoor_deno_runtime or fakeset_python or rclone_muddywater_exfil
falsepositives:
- Legitimate Deno development (rare in enterprise)
- Authorized Rclone jobs (check approved tool whitelist)
level: high
KQL Query
DeviceProcessEvents
| where Timestamp > ago(30d)
| where (FileName == "deno.exe"
or (FileName == "python.exe"
and ProcessCommandLine has_any
("backblaze","wasabisys"))
or (FileName == "rclone.exe"
and ProcessCommandLine has_any
("wasabi","wasabirclone","backblaze")))
| project Timestamp, DeviceName, AccountName,
FileName, ProcessCommandLine,
InitiatingProcessFileName
| order by Timestamp desc
False positive guidance: Deno is rarely present in enterprise environments. Flag any instance. For Rclone, maintain an allowlist of approved job hashes and alert on anything outside it.
Rule 12: PIM Activation Without Fresh Authentication Context
MITRE ATT&CK: T1078.004, T1556
Critical: The PIM MFA Checkbox Is Not Enough
The "Require Azure MFA on activation" checkbox in PIM does NOT force a new challenge if a valid MFA session already exists. A stolen session token carries a valid MFA claim. PIM passes it through. Authentication Context is the fix.
Prevention Configuration (Do This First)
- Create a named Authentication Context. In Entra ID, create a named Authentication Context. Call it "High-Privilege Role Activation" or similar.
- Create a Conditional Access policy targeting that Authentication Context. Set grant control to Authentication Strength = Phishing-Resistant MFA (FIDO2 security key, Windows Hello for Business, or certificate-based auth). Scope to eligible users for privileged roles.
- Configure PIM role settings. In PIM role settings for Global Administrator, Intune Administrator, and Cloud Device Administrator, set the Authentication Context field to the context you created. Do NOT rely on the "Require Azure MFA" checkbox alone.
- Create a second Conditional Access policy. Target the Global Administrator directory role itself, enforcing phishing-resistant auth strength for the duration of the activated session, not just at activation.
Detection KQL
AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName ==
"Add member to role completed (PIM activation)"
| join kind=leftouter (
SigninLogs
| where TimeGenerated > ago(7d)
| where AuthenticationDetails has
"FIDO2 security key"
or AuthenticationDetails has
"Certificate-based authentication"
or AuthenticationDetails has
"Windows Hello for Business"
| project CorrelationId, UserId,
PhishingResistantMFA=true
) on $left.CorrelationId == $right.CorrelationId
| where isempty(PhishingResistantMFA)
| project TimeGenerated, Identity,
OperationName, InitiatedBy, CorrelationId
| order by TimeGenerated desc
This query surfaces every PIM activation that did not satisfy a fresh phishing-resistant challenge. Each result is either a gap to close or an incident to investigate.
Rule 13: Bulk Wipe Threshold with Authorization Gate
MITRE ATT&CK: T1485, T1072
5 or more wipe operations from a single identity in 15 minutes triggers the alert. The three-layer prevention architecture below ensures any bulk wipe requires a fresh FIDO2 challenge from a second admin before it executes.
Layer 1: Intune Multi-Admin Approval
Enable under Intune > Tenant Administration > Multi Admin Approval. Set wipe, retire, and delete to require approval from a designated approver group. The approver receives a notification and must actively approve in the Intune console before the action executes. Native feature, no additional cost.
Layer 2: Authentication Context Step-Up on Approval Action
Create a Conditional Access Authentication Context named "Intune Bulk Destructive Action." Apply via Conditional Access to the Intune admin center application, scoped to the approver group. Require phishing-resistant MFA for this context. When the approver attempts to approve a wipe request, they are stepped up to a fresh FIDO2 challenge. Their existing session does not satisfy it. They need the physical key.
This is the control: no bulk wipe executes without a fresh hardware key challenge from a second authorized admin. A stolen session cannot satisfy it.
Layer 3: KQL Alert on Threshold Breach
// Bulk wipe threshold alert
IntuneAuditLogs
| where TimeGenerated > ago(15m)
| where OperationName has "Wipe"
or OperationName has "Factory Reset"
or OperationName has "Delete"
| summarize
WipeCount = count(),
DeviceList = make_set(TargetName)
by Actor, bin(TimeGenerated, 15m)
| where WipeCount >= 5
| extend AlertMessage = strcat(
"BULK WIPE THRESHOLD HIT: ", Actor,
" triggered ", WipeCount,
" wipe events in 15 minutes")
| project TimeGenerated, Actor,
WipeCount, DeviceList, AlertMessage
Tune the threshold to your environment. For most organizations 5 is appropriate. If you have IT teams running scheduled bulk retires, build an allowlist of scheduled job identities and exclude them.
Rule 14: Stale Session Token Used for Privileged Entra Operation
MITRE ATT&CK: T1078.004, T1550.001
Detects when an admin-plane action (wipe, factory reset, role activation, role assignment) is correlated to a sign-in where MFA was satisfied more than 8 hours ago. AiTM-stolen tokens carry a valid MFA claim from the original authentication event. The gap between that event and the privileged action is the signal.
KQL Query
// Stale MFA session used for privileged operation
SigninLogs
| where TimeGenerated > ago(7d)
| where AppDisplayName in (
"Microsoft Intune",
"Microsoft Azure Management",
"Microsoft Entra admin center")
| extend MFAAge = datetime_diff(
'minute',
TimeGenerated,
todatetime(
AuthenticationDetails[0]
.authenticationStepDateTime))
| where MFAAge > 480
| join kind=inner (
AuditLogs
| where TimeGenerated > ago(7d)
| where Category in (
"RoleManagement",
"DeviceManagement")
| where OperationName has_any (
"wipe","factory reset",
"role activation",
"add member to role")
) on $left.CorrelationId ==
$right.CorrelationId
| project TimeGenerated,
UserPrincipalName,
IPAddress, MFAAge,
OperationName,
ResultDescription
| order by TimeGenerated desc
Tune the MFAAge threshold to your session policy. 480 minutes (8 hours) is a reasonable starting point. For Global Admin operations, consider tightening to 120 minutes.
Rule 15: Rclone Exfiltration to MuddyWater-Associated Cloud Infrastructure
MITRE ATT&CK: T1567.002
Detects Rclone transfers to Wasabi and Backblaze, the cloud storage infrastructure documented in MuddyWater exfiltration operations across U.S. and Israeli targets in 2026. Also covers Put.io, used by the sdrhi actor documented in the Full Disclosure: Iranian Threat Actor report.
Sigma Rule
title: Rclone to MuddyWater Exfil Infrastructure
id: b8d4f2e1-5c3a-4f9b-ad2e-6a7c8b9f0e1d
status: experimental
description: >
Detects Rclone transfers to Wasabi, Backblaze, and Put.io,
cloud storage used by MuddyWater (Seedworm) for data
exfiltration in 2026 U.S. and Israeli targeting operations.
tags:
- attack.exfiltration
- attack.t1567.002
logsource:
category: network_connection
product: windows
detection:
rclone_process:
Image|endswith: '\rclone.exe'
muddywater_destinations:
DestinationHostname|endswith:
- '.wasabisys.com'
- '.backblaze.com'
- 'b2.backblaze.com'
- 's3.us-west-1.wasabisys.com'
- 'put.io'
condition: rclone_process and muddywater_destinations
falsepositives:
- Authorized cloud backup jobs using Rclone
- Whitelist approved job hashes and scheduled tasks
level: high
KQL Query
DeviceNetworkEvents
| where Timestamp > ago(30d)
| where InitiatingProcessFileName == "rclone.exe"
| where RemoteUrl has_any (
"wasabisys.com",
"backblaze.com",
"b2.backblaze.com",
"put.io")
| project Timestamp, DeviceName,
AccountName, RemoteUrl,
RemoteIP, RemotePort,
InitiatingProcessCommandLine
| order by Timestamp desc
Updated IOC Table (v2 Additions)
All v1 IOCs remain valid. See the Detection Pack v1 post for the original indicator list.
| Type | Indicator | Source |
|---|---|---|
| Backdoor | Dindoor (Deno JS runtime backdoor) | Symantec/Carbon Black |
| Backdoor | Fakeset (Python, Backblaze-hosted) | Symantec/Carbon Black |
| Cert Subject | Amy Cherne | Signs Dindoor and Fakeset |
| Cert Subject | Donald Gay | Signs Fakeset, Stagecomp, Darkcomp |
| Malware Family | Stagecomp (MuddyWater downloader) | MuddyWater cert cluster |
| Malware Family | Darkcomp (MuddyWater backdoor) | MuddyWater cert cluster |
| Exfil Dest | *.wasabisys.com (Wasabi) | MuddyWater + sdrhi actor |
| Exfil Dest | b2.backblaze.com (Backblaze) | MuddyWater Fakeset C2 |
| Exfil Dest | put.io | sdrhi actor (March 6 report) |
| C2 Infra | VPS in Netherlands | MuddyWater (Ctrl-Alt-Intel) |
| Timestamp | 3:30 AM EDT, March 11, 2026 | Confirmed Intune wipe execution |
| Malware Cert CN | Trojan:Python/MuddyWater.DB!MTB (Microsoft) | Stagecomp/Darkcomp family |
| Malware Cert CN | Backdoor.Python.MuddyWater.a (Kaspersky) | Stagecomp/Darkcomp family |
Priority Action Summary
- Check PIM role settings for Global Administrator, Intune Administrator, and Cloud Device Administrator. If you see only the "Require Azure MFA" checkbox and no Authentication Context configured, you have the same gap that enabled the Stryker wipe. Configure Authentication Context with FIDO2 or certificate-based auth today.
- Enable Intune Multi-Admin Approval for wipe, retire, and delete actions. Tenant Administration > Multi Admin Approval. Under 10 minutes. No additional licensing required.
- Deploy Rule 13 (bulk wipe threshold alert). Five wipes in 15 minutes from a single identity fires the alert. Wire it to a Logic App that calls revokeSignInSessions on the triggering account via Microsoft Graph.
- Hunt sign-in logs for authentications from AS14593 (SpaceX Starlink) and the Iranian ASN list from v1 that touched admin roles in the past 30 days. This is your retroactive pre-positioning check.
- Search Intune audit logs for wipe or retire events outside business hours in the past 30 days. The Stryker wipe hit at 3:30 AM EDT. Any off-hours wipe without a corresponding change ticket is an incident.
For full context on how MuddyWater pre-positioned before the Stryker wipe, see The Setup Was Already in Your Logs. For the complete tool and IOC disclosure, see Full Disclosure: Iranian Threat Actor.
Related
ThreatHunter.ai is an 18-year SDVOSB cybersecurity company. MILBERT is our identity threat detection platform, purpose-built to catch credential-based attacks at the pre-use phase. ARGOS is our managed detection and response service with human analysts on watch around the clock. These rules are production-ready with false positive guidance and field mappings. Populate your own admin account allowlists and adjust the off-hours UTC window to your timezone before deploying to production.