THREAT-Recon-CredentialStuffingValidationSweep Sumo Logic CSE · Sumo

Detect Credential Stuffing Validation Sweep (Pre-Attack Breach List Testing) in Sumo Logic CSE

Before committing to an intrusion, many adversaries first validate which entries in a purchased or scraped breach-credential list (combo list) are still live against the target's own authentication endpoints. This reconnaissance activity is distinct from brute force or password spraying: the attacker tries exactly one attacker-supplied username/password pair per account — never guessing or repeating passwords across identities — and deliberately throttles request volume to stay under per-account lockout and rate-limiting thresholds. The result is a low-and-slow sweep touching a very large number of distinct, often unrelated identities (many of which do not even exist in the target directory) from a small pool of shared infrastructure (bulletproof VPS, residential proxy pools, or credential-checker tooling such as OpenBullet/SentryMBA configs) using automation-flavoured or generic user agents. Initial access brokers and groups like Scattered Spider/Muddled Libra routinely run this validation step across many organisations' SSO and webmail portals to build a list of confirmed-working credentials before selling or acting on access. Because no individual account sees more than one or two failures, this activity is invisible to lockout policies and easily missed by detections tuned for classic brute force or spray, making the attempts-per-user ratio and aggregate breadth across a single source the key signals.

MITRE ATT&CK

Tactic
Reconnaissance

Sumo Detection Query

Sumo Logic CSE (Sumo)
sql
_sourceCategory="azure/aad/signin"
| json "properties.status.errorCode" AS error_code
| json "properties.ipAddress" AS src_ip
| json "properties.userPrincipalName" AS user
| where error_code != "0"
| timeslice 6h
| stats count AS TotalAttempts, dcount(user) AS UniqueUsers,
    count_if(error_code="50034") AS UserNotFoundCount
  by src_ip, _timeslice
| eval AttemptsPerUser=round(TotalAttempts/UniqueUsers, 2)
| where UniqueUsers >= 50 and AttemptsPerUser <= 1.3
| eval UserNotFoundRatio=round(UserNotFoundCount/TotalAttempts, 2)
| sort by UniqueUsers desc
high severity medium confidence

Sumo Logic detection for credential-list validation sweeps against Entra ID, flagging source IPs touching 50+ distinct accounts within a 6-hour window at a near-1 attempts-per-user ratio.

Data Sources

Azure AD Logs via Sumo Logic Azure App

Required Tables

azure/aad/signin

False Positives & Tuning

  • Bulk onboarding or contractor provisioning scripts
  • Identity federation health-check automation
  • SaaS integration platforms authenticating on behalf of many tenant users from a shared egress IP

Other platforms for THREAT-Recon-CredentialStuffingValidationSweep


Testing Methodology

Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1Low-and-Slow Credential Sweep Simulation via Python Requests

    Expected signal: Authentication logs record one failure per distinct username from the test source IP, spread across the run duration, with no repeated attempts against the same account.

  2. Test 2Credential Checker Tool Simulation (OpenBullet-style Config Replay)

    Expected signal: Web/IdP access logs show sequential single-attempt authentication requests from one source IP with a non-browser user agent string, one distinct username per request.

  3. Test 3Validated Credential Success Injection

    Expected signal: A successful authentication event is recorded from the same source IP that generated the preceding sweep failures.


Response Playbook

Triage

  1. Pull all authentication events from the flagged source IP for the full window and compute the attempts-per-user ratio directly — confirm it is near 1 (validation sweep) rather than high (spray/brute force against fewer accounts).
  2. Check IP reputation and infrastructure type (AbuseIPDB, Shodan, VirusTotal). Validation sweeps typically originate from VPS hosting, residential proxy pools, or known credential-checker exit infrastructure.
  3. Determine what fraction of targeted usernames do not exist in your directory (UserNotFound errors). A high UserNotFound ratio confirms the attacker is sweeping a generic breach list rather than a target list built from OSINT on your organisation.
  4. Cross-reference any successful sign-ins captured by Alert 2 against the affected user's last known-good login location and device — a validated credential with no immediate follow-on activity is still a live risk and should be treated as a confirmed compromise.
  5. Check whether the same source IP or infrastructure cluster has run similar sweeps against other tenants or business units you have visibility into, indicating a broad multi-target validation campaign rather than an org-specific attack.

Containment

  1. Block the sweep source IP(s) at the identity provider (Conditional Access Named Locations) and at the network perimeter.
  2. For any account with a confirmed successful authentication from a sweep IP: force password reset, revoke all active sessions, and require MFA re-registration immediately.
  3. Enable or tighten Entra ID Smart Lockout / equivalent IdP rate limiting so that even single low-volume attempts across many accounts from one source are throttled.
  4. Cross-check confirmed-valid breached credentials against any other internal systems reusing the same password (email, VPN, SaaS) since users often reuse passwords across services.

Evidence Collection

  1. Full authentication log export (failures and successes) for the flagged source IP across the sweep window
  2. List of targeted usernames with per-user attempt counts and result codes, to confirm the one-attempt-per-user pattern
  3. Threat intelligence enrichment on the source IP/ASN and any associated credential-checker tooling fingerprints (user agent, TLS/JA3 if available)
  4. Identity Protection / risky sign-in and risky user records for any account with a successful authentication during the sweep

Escalation Criteria

  • !Any successful authentication captured from a source IP already flagged as running a validation sweep (Alert 2) — treat as confirmed account compromise
  • !Validated credentials belonging to privileged accounts (Global Admin, Finance, Executive) discovered via the sweep
  • !The same source infrastructure observed sweeping multiple business units or subsidiaries, indicating a large-scale, multi-victim breach-list validation campaign
  • !Sweep activity immediately followed by a distinct, higher-intensity authentication campaign (spray or targeted brute force) against the same or an overlapping set of accounts, suggesting the recon fed a live follow-on attack

Investigation Guide

Related Techniques

Forensic Artifacts

  • >Identity provider sign-in logs with per-account attempt counts, timestamps, and result codes for the source IP
  • >Source IP/ASN reputation and hosting-provider classification (VPS, proxy pool, residential proxy, Tor)
  • >User agent and request fingerprint metadata associated with the sweep traffic
  • >Identity Protection risky sign-in / risky user records for any accounts confirmed valid during the sweep

Tuning Guidance

The 50 unique users / 1.3 attempts-per-user thresholds are tuned for mid-size tenants. In very large enterprises, benign automation (contractor onboarding, federation health checks) can touch hundreds of accounts once each — pin down and allowlist those known service IPs rather than raising the threshold, since raising it risks missing genuinely low-volume sweeps. In smaller tenants, the unique-user threshold can be lowered to 15-20 since attackers rarely calibrate sweep size to the target's headcount. The UserNotFoundRatio field is a strong secondary signal: a generic breach list swept against a small or mid-size org will typically miss on 30%+ of usernames, whereas targeted attacks built from OSINT on real employees will have a near-zero UserNotFound rate.


Hunting Queries

Broader 14-day hunt using a lower unique-user threshold and wider 12-hour bins to surface slower or smaller validation sweeps that fall below the main detection's 6-hour/50-user thresholds.

Hunting — KQL
kql
AADSignInLogs
| where TimeGenerated > ago(14d)
| where ResultType != 0
| summarize
    TotalAttempts=count(),
    UniqueUsers=dcount(UserPrincipalName),
    UserNotFoundCount=countif(ResultType == 50034)
  by IPAddress, bin(TimeGenerated, 12h)
| extend AttemptsPerUser = round(TotalAttempts * 1.0 / UniqueUsers, 2)
| where UniqueUsers >= 20 and AttemptsPerUser <= 1.5
| extend UserNotFoundRatio = round(UserNotFoundCount * 1.0 / TotalAttempts, 2)
| sort by UniqueUsers desc
Hunting — SPL
spl
index=azure sourcetype="azure:aad:signin" properties.status.error_code!=0
| bin _time span=12h
| stats count AS TotalAttempts, dc(properties.user_principal_name) AS UniqueUsers,
    count(eval(properties.status.error_code==50034)) AS UserNotFoundCount
  BY properties.ip_address, _time
| eval AttemptsPerUser=round(TotalAttempts/UniqueUsers, 2)
| where UniqueUsers >= 20 AND AttemptsPerUser <= 1.5
| eval UserNotFoundRatio=round(UserNotFoundCount/TotalAttempts, 2)
| sort - UniqueUsers

Atomic Red Team Tests

Test 1 Low-and-Slow Credential Sweep Simulation via Python Requests
linux

Simulates a breach-list validation sweep by attempting exactly one authentication per identity across a large list of distinct usernames, each with a unique password, at a throttled rate. Tests detection of the one-attempt-per-user, wide-breadth pattern distinct from spray or brute force.

Command

bash
python3 -c "
import requests, time
creds = [(f'user{i}@corp.com', f'BreachedPass{i}!') for i in range(1, 75)]
for user, pwd in creds:
    r = requests.post('https://<AUTH_ENDPOINT>/login', data={'username': user, 'password': pwd}, verify=False)
    print(f'{user}: {r.status_code}')
    time.sleep(20)
"

Expected Telemetry

Authentication logs record one failure per distinct username from the test source IP, spread across the run duration, with no repeated attempts against the same account.

Expected Detection

Alert fires when UniqueUsers >= 50 and AttemptsPerUser <= 1.3 within the 6-hour aggregation window (lower the test threshold in a lab tenant to validate against a smaller credential list).

Test 2 Credential Checker Tool Simulation (OpenBullet-style Config Replay)
linux

Replays a combo-list style credential-checker run against a login endpoint using distinct username/password pairs sourced from a mock breach dump, mimicking OpenBullet/SentryMBA-style automation with a generic scripted user agent.

Command

bash
for line in $(cat mock_combolist.txt); do user=$(echo $line | cut -d: -f1); pass=$(echo $line | cut -d: -f2); curl -s -A 'OpenBullet/2.0' -X POST https://<AUTH_ENDPOINT>/login -d "username=${user}&password=${pass}" -o /dev/null -w '%{http_code}\n'; sleep 15; done

Expected Telemetry

Web/IdP access logs show sequential single-attempt authentication requests from one source IP with a non-browser user agent string, one distinct username per request.

Expected Detection

Alert fires on the aggregate attempts-per-user ratio and unique-user breadth from the source IP; user agent field can be used for supplementary tuning to flag known credential-checker signatures.

Test 3 Validated Credential Success Injection
windows

Follows a simulated sweep with a single successful authentication from the same source IP, representing the confirmed-valid breached credential scenario that Alert 2 is designed to catch.

Command

powershell
Invoke-WebRequest -Uri 'https://<AUTH_ENDPOINT>/login' -Method POST -Body @{username='[email protected]'; password='<KNOWN_VALID_TEST_PASSWORD>'} -UseBasicParsing

Cleanup

powershell
Reset the test account's password and revoke any session created during the test.

Expected Telemetry

A successful authentication event is recorded from the same source IP that generated the preceding sweep failures.

Expected Detection

Alert 2 (CredentialValidationSweep_ConfirmedValidCredential) fires when a success is observed from an IP already flagged by Alert 1 within the sweep window.

Related Detections