ASVS 5.0 V6.6.4 requires that where push notifications are used for multi-factor authentication, you use rate limiting to prevent push bombing. Number matching may also reduce the risk. It is a Level 3 requirement.
Why it matters
Push bombing, also called MFA fatigue, works like this: the attacker has the password and triggers login after login. The victim gets prompt after prompt, often at night, and eventually taps Approve to make it stop. A single mistaken tap gives the attacker a session.
How to implement it
Three controls work together.
Rate limit prompts. Cap pushes per user per window, and add a cooldown after denials.
def can_send_push(user_id) -> bool:
key = f"push:{user_id}"
n = r.incr(key)
if n == 1:
r.expire(key, 3600)
return n <= 3
def on_denied(user_id):
r.setex(f"push:cooldown:{user_id}", 900, 1) # no prompts for 15 minutes
Number matching. Show a two digit number on the login screen and ask the user to type it into the approving app. A tap alone is no longer enough, since the attacker's screen number is not in front of the victim.
React to denials. A denial is a signal. After a couple, alert the user and security, and require a stronger factor like a hardware key.
Also expire pending prompts quickly (V6.5.5) and bind each to its request (V6.6.2).
How to test it
- Trigger logins repeatedly with a valid password and count prompts delivered. It should stop at your cap.
- Deny twice and confirm cooldown and an alert.
- With number matching on, approve without the number and confirm failure.
Common mistakes
- Unlimited prompts for a valid first factor.
- Treating a denial as a normal event with no alert.
- Allowing approval without the matching number.
Quick check
Does number matching replace rate limiting?
No. It reduces blind approvals, but limits still stop the flood of prompts and the load it creates.