Detect Credential Stuffing Against Authentication Endpoints (nginx / web logs)
MITRE ATT&CK: T1110.004T1110.001
Sigma Rule
title: Credential Stuffing Against Web Authentication Endpoint
id: 6f1c2a7e-1d34-4b2e-9a1f-2c8e0b4d5a01
status: experimental
description: >
Detects a high volume of failed authentication requests (HTTP 401) to a login
endpoint from a single source IP within a short window — the signature of an
automated credential-stuffing or password-spraying campaign. Pair with a
follow-on 2xx from the same IP to confirm account compromise.
references:
- https://attack.mitre.org/techniques/T1110/004/
author: LogTriage
date: 2026/06/22
logsource:
category: webserver
detection:
selection:
cs-method: POST
cs-uri-stem|contains:
- '/auth/login'
- '/api/v1/auth/login'
- '/signin'
- '/oauth/token'
sc-status: 401
timeframe: 5m
condition: selection | count() by src_ip >= 10
falsepositives:
- Misconfigured client or expired token producing legitimate 401 bursts
- Login load tests / synthetic monitors
level: high
tags:
- attack.credential_access
- attack.t1110.004
What this rule detects
Credential stuffing is the automated replay of breached username/password pairs against a login endpoint. In a web access log it has a distinctive shape: many POSTs to an authentication path from a single source IP, almost all returning HTTP 401, packed into a short time window — then, if the attacker gets lucky, a 200 from that same IP marking a successful takeover.
This Sigma rule fires when a single source IP produces 10 or more failed (401) logins to an auth endpoint within 5 minutes. The threshold and window are deliberately conservative to keep the false-positive rate low; tune them to your traffic.
Detection logic
The rule keys on three signals that are present in every web access log:
- Method + path — a
POSTto a login/token endpoint (/auth/login,/oauth/token, …). - Outcome —
sc-status: 401(authentication rejected). - Volume by source —
count() by src_ip >= 10within a 5-minutetimeframe.
The follow-on success (a 200 to the same path from the same IP) is what turns “someone is
guessing” into “someone got in.” LogTriage’s credential-stuffing detector
correlates the failure burst with the subsequent success automatically and raises the severity to
critical when it sees one.
Validated against a real sample
This rule is validated against a real attack sample shipped with LogTriage
(nginx_credential_stuffing.log): 19 POSTs to /api/v1/auth/login, 17 of them 401, all from a
single Tor-exit source — followed by two 200s confirming compromise. The rule fires on that sample
and stays silent on the matching benign browsing log.
False positives
A legitimate burst of 401s can come from a misconfigured client, an expired token, or a login load
test. Confirm by checking whether the source IP is a known office egress, whether a success
follows, and whether the user-agent looks automated (e.g. python-requests, curl).
Frequently Asked Questions
- Why count by source IP instead of by username?
- Credential stuffing reuses one source (or a small pool) to test many breached username/password pairs. Counting failures per source IP catches the campaign even when each individual account is only tried once or twice, which by-username thresholds miss.
- How do I confirm an account was actually compromised?
- Look for a 2xx response to the same auth endpoint from the same source IP shortly after the burst of 401s. LogTriage's pattern detector does this automatically and escalates severity to critical when a success follows the failures.
- Does this work for Apache and load-balancer logs too?
- Yes — any access log with a method, URI, status code, and client IP works. Map the field names (e.g. AWS ALB elb_status_code, Cloudflare EdgeResponseStatus) to the Sigma fields and the logic is identical.
Related Resources
See this detection run on a real report
Try the live demo with a pre-loaded malicious log set — no signup required — or upload your own log file and get a full AI-reviewed threat report in minutes.