Wiz Research has published findings on an active campaign in which an AI-driven attack agent — designated ARTEX — is being operated by a threat actor whose activity overlaps with Microsoft's Storm-0940 cluster. The campaign is targeting IT and software vendors, and its point of entry is not a software vulnerability: it is the identity layer itself. ARTEX has been observed attacking Okta, Microsoft Entra ID, and AWS Cognito — the three identity providers (IdPs) that collectively front-door most SaaS and cloud estates in the enterprise market.
This matters for two reasons. First, software vendors are force-multiplier targets: compromising one vendor's identity infrastructure opens downstream access to every customer that trusts it — the same supply-chain logic that made SolarWinds and MOVEit strategic events. Second, ARTEX represents the operationalization of autonomous AI agents as attack tooling. An agent that can reason about identity provider responses, adapt its authentication attempts in real time, and rotate infrastructure without operator fatigue changes the economics of identity attacks. Techniques that were previously low-and-slow because of human cost — password spraying, MFA prompt probing, token replay testing — can now run at machine tempo with adaptive logic.
There is no CVE here and no patch to deploy. The defensive response is detection engineering against identity telemetry and hardening of IdP configurations. If your organization is a software vendor, IT services firm, or depends on one — which is to say, everyone — this campaign is directly relevant to your threat model today.
Technical Analysis
What ARTEX Is and Who It Targets
Per Wiz Research, ARTEX is an AI attack agent observed in the wild conducting operations against multiple targeted software vendors. The activity overlaps with Storm-0940, a threat actor cluster previously associated with password spraying and credential-based intrusions against enterprise environments. The vendor targeting is deliberate: IT and software suppliers hold privileged integrations, API keys, OAuth grants, and federation trust relationships with their customers — making their identity estates disproportionately valuable.
Attack Chain (Defender's View)
While Wiz's reporting centers on the identity providers abused, the operational pattern consistent with Storm-0940 tradecraft and an autonomous agent looks like this:
-
Reconnaissance of the IdP perimeter. The agent identifies which IdP fronts the target — Okta tenant URLs (
*.okta.com), Entra ID endpoints (login.microsoftonline.com), or Cognito user pools — and enumerates valid accounts through authentication response differentials (error message variance, response timing, password reset flow behavior). -
Adaptive credential attacks. Password spraying and credential stuffing against the IdP, with the AI agent adjusting request cadence, user-agent strings, and source infrastructure to stay under lockout and rate-limit thresholds. This is the key difference from scripted spraying: an agent can interpret throttling responses and back off dynamically, which defeats naive rate-based detection.
-
MFA probing and fatigue. Where a valid credential pair is obtained, the agent drives push notification floods or tests for SMS/voice fallback and legacy authentication paths (IMAP, SMTP AUTH, basic auth endpoints) that bypass modern MFA.
-
Session token harvesting and replay. Stolen session tokens or refresh tokens are replayed from attacker infrastructure — frequently cloud-hosted, producing log entries that are technically valid authentications from anomalous networks.
-
Persistence via the IdP itself. New OAuth application consents, additional MFA factor enrollment, API token creation, and federation changes — all of which appear as legitimate administrative actions in IdP logs unless you are specifically watching for them.
What It Left Behind in the Logs
The critical insight from the Wiz reporting is that ARTEX operations are visible in IdP telemetry — but only if that telemetry is collected, centralized, and analyzed. The observable artifacts include:
- Authentication failures distributed across many accounts from a small set of source IPs or ASNs, at adaptive (non-constant) intervals — the signature of intelligent spraying rather than fixed-cadence scripts
- Successful authentications immediately following failure clusters, often from hosting-provider IP space with no prior history for that user
- Okta System Log events such as
user.authentication.auth_via_mfapush events in rapid succession (fatigue), followed byuser.mfa.factor.updateorsystem.oauth2.*grant events - Entra ID sign-ins with anomalous
authenticationRequirementdowngrades, legacy protocol use, or token replay indicators (token issued in one geography, redeemed in another) - Cognito
InitiateAuth/RespondToAuthChallengeAPI call volume anomalies in CloudTrail, particularly against user pools not expected to see external brute-force pressure - Post-auth administrative events: new app registrations, consent grants, factor enrollments, and API key minting within minutes of initial access
Exploitation Status
This is confirmed active exploitation in the wild against named vendor targets, per Wiz Research. There is no associated CVE and no CISA KEV entry — the campaign abuses identity trust and valid credentials, not software flaws. Treat this as an active TTP campaign requiring detection coverage, not a patch cycle.
Detection & Response
The detection strategy below targets the identity-layer behaviors described above. Because these attacks rarely touch a managed endpoint, your IdP logs are your EDR. If Okta System Log, Entra sign-in/audit logs, and CloudTrail are not streaming into your SIEM today, close that gap before anything else in this section.
Sigma Rules
---
title: Entra ID Password Spraying - Distributed Failures From Single Source
id: 4b8f2c61-9a3d-4e75-b812-6c1d9f0a2345
status: experimental
description: Detects password spraying against Microsoft Entra ID by identifying a single source IP generating authentication failures across many distinct accounts, consistent with ARTEX/Storm-0940 adaptive spraying behavior.
references:
- https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
- https://attack.mitre.org/techniques/T1110/003/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.credential_access
- attack.t1110.003
logsource:
product: azure
service: signinlogs
detection:
selection:
ResultType:
- '50055' # Invalid password, expired or wrong
- '50057' # User disabled (probing valid accounts)
- '50126' # Invalid username or password
- '50140' # Keep me signed in interrupt during spray
condition: selection
falsepositives:
- Misconfigured service accounts retrying expired credentials
- Corporate VPN egress IPs aggregating legitimate user failures
level: high
---
title: Okta MFA Push Flood Followed by Factor Enrollment Change
id: 8d2e5a17-3c4f-4b96-a721-5e9b0d6c8412
status: experimental
description: Detects MFA push fatigue patterns in Okta followed by suspicious factor lifecycle events (enroll, reset, or update), consistent with post-compromise persistence observed in identity-agent campaigns.
references:
- https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
- https://attack.mitre.org/techniques/T1621/
- https://attack.mitre.org/techniques/T1556/006/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.credential_access
- attack.t1621
- attack.persistence
- attack.t1556.006
logsource:
product: okta
service: okta
detection:
selection_fatigue:
eventType: 'user.authentication.auth_via_mfa'
outcome.result: 'FAILURE'
selection_factor_change:
eventType:
- 'user.mfa.factor.enroll'
- 'user.mfa.factor.update'
- 'user.mfa.factor.reset_all'
- 'user.mfa.attempt_bypass'
condition: 1 of selection_*
falsepositives:
- Users enrolling new devices during onboarding
- Help desk driven factor resets
level: high
---
title: AWS Cognito Authentication Anomaly - Brute Force Against User Pool
id: 6f1a9c34-7d2b-4e58-9034-c8b2e1f5a967
status: experimental
description: Detects elevated InitiateAuth or RespondToAuthChallenge failures against AWS Cognito user pools, indicating credential stuffing or password spraying consistent with ARTEX targeting of Cognito-fronted applications.
references:
- https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
- https://attack.mitre.org/techniques/T1110/004/
author: Security Arsenal
date: 2026/04/06
tags:
- attack.credential_access
- attack.t1110.004
logsource:
product: aws
service: cloudtrail
detection:
selection:
eventSource: 'cognito-idp.amazonaws.com'
eventName:
- 'InitiateAuth'
- 'RespondToAuthChallenge'
- 'ForgotPassword'
errorCode:
- 'NotAuthorizedException'
- 'UserNotFoundException'
- 'PasswordResetRequiredException'
condition: selection
falsepositives:
- Legitimate users with expired passwords in consumer-facing pools
- Load testing against staging user pools
level: medium
KQL (Microsoft Sentinel / Defender)
The following hunt assumes Entra sign-in data via SigninLogs and Okta/CloudTrail data ingested via their respective Sentinel connectors. Run this as a broad first-pass sweep for the spraying and token-replay patterns described above:
// ARTEX / Storm-0940 adaptive password spray hunt across Entra sign-in data
// Flags source IPs failing auth against many distinct accounts with
// irregular cadence (agent-driven rather than scripted), plus any successes
// from the same source infrastructure.
let Lookback = 24h;
let FailThreshold = 10;
let AccountThreshold = 5;
let SpraySources =
SigninLogs
| where TimeGenerated > ago(Lookback)
| where ResultType in ("50055", "50057", "50126", "50140", "50053")
| summarize
FailedAccounts = dcount(UserPrincipalName),
TotalFailures = count(),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
TargetedApps = make_set(AppDisplayName, 10),
UserAgents = make_set(UserAgent, 10)
by IPAddress
| where FailedAccounts >= AccountThreshold and TotalFailures >= FailThreshold
| extend SprayDurationMinutes = datetime_diff("minute", LastSeen, FirstSeen)
| project IPAddress, FailedAccounts, TotalFailures, SprayDurationMinutes, TargetedApps, UserAgents;
// Correlate: did any spraying source IP also produce a SUCCESS?
SigninLogs
| where TimeGenerated > ago(Lookback)
| where IPAddress in (SpraySources | project IPAddress)
| where ResultType == 0
| summarize
SuccessfulAccounts = make_set(UserPrincipalName),
SuccessCount = count(),
AuthMethods = make_set(AuthenticationRequirement),
Locations = make_set(Location)
by IPAddress
| join kind=inner SpraySources on IPAddress
| project IPAddress, FailedAccounts, TotalFailures, SuccessfulAccounts, SuccessCount, AuthMethods, Locations, TargetedApps, UserAgents
| order by SuccessCount desc;
Velociraptor VQL
Identity attacks often culminate in token theft from developer or admin workstations at software vendors — exactly the environment Storm-0940 targets. This artifact hunts for non-browser, non-CLI processes touching cloud credential stores and token caches, a strong post-compromise indicator:
-- Hunt: Unauthorized access to cloud credential stores and token caches
-- Targets theft of AWS credentials, Azure CLI/MSAL caches, and Okta session
-- material from developer workstations -- the payload stage of identity attacks
LET cred_paths = SELECT FullPath FROM glob(globs=[
'C:/Users/*/.aws/credentials',
'C:/Users/*/.aws/config',
'C:/Users/*/.azure/msal_token_cache*',
'C:/Users/*/.azure/accessTokens.json',
'C:/Users/*/.azure/azureProfile.json',
'C:/Users/*/AppData/Local/.IdentityService/AccountStore.json'
])
SELECT
FullPath,
Mtime,
Size,
timestamp(epoch= Mtime.Sec) AS LastModifiedUTC
FROM cred_paths
WHERE LastModifiedUTC > timestamp(epoch=1600000000)
AND LastModifiedUTC > (now() - 86400 * 7)
Follow this with process lineage review on any hit: msal_token_cache or .aws/credentials modified within the last 7 days by anything other than the legitimate CLI tooling (az, aws, terraform) warrants immediate credential rotation and session revocation for that user.
Remediation / Hardening Script
This PowerShell audit uses Microsoft Graph to surface the exact conditions ARTEX-style campaigns exploit: legacy authentication still reachable, risky sign-ins unactioned, and app consents granted recently. Run it with an account holding AuditLog.Read.All, IdentityRiskEvent.Read.All, and Policy.Read.All:
# ARTEX / Storm-0940 Entra ID Exposure Audit
# Identifies legacy auth exposure, risky sign-ins, and recent suspicious consents
# Requires: Microsoft.Graph PowerShell SDK, appropriate Graph scopes
Connect-MgGraph -Scopes "AuditLog.Read.All","IdentityRiskEvent.Read.All","Policy.Read.All","Application.Read.All" -NoWelcome
$report = [ordered]@{}
# 1. Check for legacy auth usage in the last 7 days (bypasses MFA entirely)
$legacySignins = Get-MgAuditLogSignIn -Filter "createdDateTime ge $((Get-Date).AddDays(-7).ToString('yyyy-MM-ddTHH:mm:ssZ'))" -Top 999 |
Where-Object { $_.ClientAppUsed -in @('Exchange ActiveSync','IMAP4','POP3','SMTP','Authenticated SMTP','Other clients','MAPI Over HTTP') }
$report['LegacyAuthSignins'] = $legacySignins.Count
$legacySignins | Select-Object CreatedDateTime, UserPrincipalName, IPAddress, ClientAppUsed, Status |
Export-Csv -Path ".\artex-legacy-auth-exposure.csv" -NoTypeInformation
# 2. Unactioned high/medium risk sign-ins (agent-driven spray leaves these behind)
$riskySignins = Get-MgIdentityProtectionRiskyUser -Filter "riskState eq 'atRisk'" -All
$report['UsersAtRiskUnremediated'] = ($riskySignins | Where-Object { $_.RiskLevel -in @('high','medium') }).Count
# 3. OAuth consents granted in the last 7 days (persistence indicator)
$recentGrants = Get-MgAuditLogDirectoryAudit -Filter "activityDisplayName eq 'Consent to application' and activityDateTime ge $((Get-Date).AddDays(-7).ToString('yyyy-MM-ddTHH:mm:ssZ'))" -All
$report['RecentConsentGrants'] = $recentGrants.Count
$recentGrants | Select-Object ActivityDateTime, InitiatedBy, TargetResources, Result |
Export-Csv -Path ".\artex-recent-consents.csv" -NoTypeInformation
# 4. Verify Conditional Access blocks legacy auth tenant-wide
$caPolicies = Get-MgIdentityConditionalAccessPolicy -All
$legacyBlock = $caPolicies | Where-Object {
$_.State -eq 'enabled' -and
$_.Conditions.ClientAppTypes -contains 'exchangeActiveSync' -and
$_.Conditions.ClientAppTypes -contains 'other' -and
$_.GrantControls.BuiltInControls -contains 'block'
}
$report['LegacyAuthBlockedByCA'] = [bool]$legacyBlock
# Output summary
Write-Host "`n=== ARTEX Identity Exposure Summary ===" -ForegroundColor Cyan
$report.GetEnumerator() | ForEach-Object { Write-Host ("{0,-28} {1}" -f $_.Key, $_.Value) }
if (-not $legacyBlock) { Write-Host "`n[!] CRITICAL: No enabled Conditional Access policy blocks legacy auth. Remediate immediately." -ForegroundColor Red }
if ($report['UsersAtRiskUnremediated'] -gt 0) { Write-Host "[!] Unremediated risky users detected - force password resets and revoke sessions." -ForegroundColor Yellow }
Remediation
Because this campaign exploits identity configuration and valid credentials rather than a software flaw, remediation is architectural. Prioritize in this order:
Immediate (24 hours):
- Pull the logs. Confirm Okta System Log, Entra sign-in + audit logs, and CloudTrail (including Cognito IdP events) are streaming to your SIEM with at least 90-day retention. If they are not, you are blind to this campaign class — full stop.
- Run the hunts above. Any spray source with a correlated success is an active incident: revoke all sessions for the affected identities (
Revoke-MgUserSignInSession/ OktaDELETE /api/v1/users/{id}/sessions), force credential reset, and review the 72 hours post-compromise for consent grants, factor changes, and API token creation. - Kill legacy authentication. Enforce a Conditional Access policy blocking legacy auth client types tenant-wide in Entra. In Okta, disable basic-auth app integrations and enforce MFA on every sign-on policy. Legacy auth is the single largest MFA bypass these actors exploit.
Short term (1-2 weeks):
- Deploy phishing-resistant MFA for all administrators, developers with production access, and vendor-integration service accounts: FIDO2/passkeys or certificate-based auth. Push-based MFA is demonstrably insufficient against fatigue-driving agents.
- Enable Cognito Advanced Security on all user pools (
ADVANCED_SECURITYmode) with compromised-credential detection and adaptive risk responses — it exists precisely for credential-stuffing pressure of this kind. - Alert on IdP administrative events as a class, not individually: OAuth consent grants, MFA factor enrollment, federation metadata changes, and API key creation should each page a human when sourced from infrastructure with no prior history for that principal.
- Constrain detection by cadence, not just count. Because ARTEX adapts its tempo to evade rate limits, tune spraying detections on distinct-account-per-source ratios and failure-type diversity rather than raw request volume thresholds.
Strategic:
- If you are a software vendor or IT provider, treat your IdP estate as production crown-jewel infrastructure: dedicated monitoring, break-glass account review, and quarterly adversary simulation against your own sign-in flows. Your compromise is your customers' compromise.
- Review the Wiz Research post directly for campaign-specific indicators and log samples: https://www.wiz.io/blog/artex-in-the-wild-storm-0940-expands-targeting-of-it-and-software-vendors
Related Resources
Security Arsenal Penetration Testing Services AlertMonitor Platform Book a SOC Assessment vulnerability-management Intel Hub
Is your security operations ready?
Get a free SOC assessment or see how AlertMonitor cuts through alert noise with automated triage.