Exhibit A
Spot the attack in a week of OTP traffic
Tuesday · 02:00
100
OTP SMS sent per hour, IST (illustrative, scaled 0–100)
- Peak
- Tue 02:00
- 100
- Busiest day
- Tuesday
- avg 43
- Best hour
- 20:00
- avg 59
Genuine demand peaks in the evening. The 00:00–05:00 blocks on Tuesday, Thursday and Sunday are pumping: one foreign prefix, sequential numbers, almost no codes entered.
Focus the grid and use the arrow keys (Home / End for 00:00 / 23:00), or point at a cell.
What is SMS pumping?
SMS pumping, also called artificially inflated traffic (AIT) or SMS toll fraud, is an attack on businesses that send SMS on demand, above all SMS OTP flows. A fraudster points bots at any form that triggers a text (sign-up, login OTP, password reset, "send me the app link") and makes it send thousands of messages to numbers in ranges they profit from. Every message is billed to the business, and somewhere along the chain a party that collects termination fees on those ranges shares the revenue with the fraudster.
The numbers are usually not real customers. They are often sequential numbers within one prefix, frequently in a country the business does not serve, and nobody ever enters the codes. That gives the attack its signature: a sudden rise in SMS to an unusual country or prefix, often at night in the business's own time zone, with a verification (conversion) rate close to zero. Because each request looks like a legitimate OTP, the gateway delivers them faithfully, and the first sign is often the invoice.
It is different from neighbouring problems. A brute-force attack guesses codes to break into accounts; pumping does not care about the code, only the sending. A grey route cheats carriers by sneaking traffic past termination fees; pumping exploits those fees against the sender. In India, domestic OTPs run on DLT-registered templates, but DLT checks the sender and wording, not whether a real person asked for the code, so most attacks aim at international destinations through your own forms.
Key takeaways
- SMS pumping is fraud in which bots request OTP or sign-up SMS to numbers whose termination fees the fraudsters share.
- The sender pays for every pumped message; nobody ever enters a code, so the verification rate on the targeted range collapses.
- The fastest single defence is a country allowlist: never send SMS to destinations you do not serve.
- Rate limits per number, prefix, IP and device plus a conversion-based circuit breaker stop most remaining attacks.
- Pumping cheats the sender; a grey route cheats carriers. Both hide in low-quality SMS traffic but need different fixes.
How does SMS pumping work?
Fraudster lines up the revenue
They arrange to share termination fees on a block of numbers, typically in a high-cost destination, through a party in the delivery chain that is paid per terminated SMS.
Bots find your SMS trigger
Scripts or headless browsers submit your sign-up, OTP or password-reset form with numbers from that block, rotating IPs and devices to look like many users.
Your system sends and pays
Each request passes basic validation, so your gateway sends a real SMS and bills you for it. Thousands of requests per hour become thousands of billed segments.
Nobody verifies
No code is ever entered. The tell-tale pattern is high volume to one country or prefix with a verification rate near zero, often outside your normal traffic hours.
You cut it off in layers
Block countries you do not serve, throttle per number, prefix, IP and device, trip a circuit breaker when conversion collapses, and move verification to channels without termination revenue.
Example: A Bengaluru fintech's overnight spike
Between 01:00 and 04:00 IST, a Bengaluru lending app sends 38,000 sign-up OTPs to numbers in one foreign prefix, nearly all sequential, and 0.4% are verified. Its normal daytime OTP conversion is 78%. The team switches on a country allowlist (India plus the one Gulf market where it serves non-resident customers), caps OTPs at three per number per hour and 200 per prefix per hour, and pauses SMS to any prefix whose hourly conversion falls under 20% after 100 sends. The next night's attempt is stopped at the form after 12 messages.
Common mistakes with SMS pumping
Allowing every country by default
Most attacks target destinations the business never serves. Start from an allowlist of your real markets and add countries deliberately, each with a daily budget.
Rate-limiting only per phone number
Attackers use a different number for every request. Limit per IP, device, session and number prefix as well, and keep a global hourly budget per country.
Watching volume instead of conversion
A busy sale day also raises volume. The reliable signal is codes verified divided by codes sent, per country and prefix; alert when it falls well below your baseline.
Switching SMS off entirely
Blocking all OTPs locks out genuine users. Pause only the affected prefixes or countries and offer another verification channel while the attack runs.
SMS pumping in code
import { parsePhoneNumberFromString } from "libphonenumber-js";const ALLOWED = new Set(["IN", "AE"]); // countries you actually serveconst LIMITS = { number: 3, ip: 10, prefix: 200 }; // per hourasync function hit(key, limit) {const n = await redis.incr(key);if (n === 1) await redis.expire(key, 3600);return n <= limit;}export async function canSendOtp(phone, ip) {const p = parsePhoneNumberFromString(phone);if (!p?.isValid() || !ALLOWED.has(p.country)) return { ok: false, why: "geo" };const prefix = p.number.slice(0, 7); // e.g. +91 plus first digitsif (await redis.get(`breaker:${prefix}`)) return { ok: false, why: "breaker" };const ok = (await hit(`otp:n:${p.number}`, LIMITS.number))&& (await hit(`otp:ip:${ip}`, LIMITS.ip))&& (await hit(`otp:p:${prefix}`, LIMITS.prefix));return ok ? { ok: true } : { ok: false, why: "rate" };}// Run every few minutes: trip the breaker when nobody verifies.export async function checkConversion(prefix, sent, verified) {if (sent >= 100 && verified / sent < 0.2) {await redis.set(`breaker:${prefix}`, "1", "EX", 3600);alertOps(`OTP conversion ${verified}/${sent} on ${prefix}: SMS paused for 1 hour`);}}
Check geography first, then layered rate limits, then a conversion breaker. Thresholds here are illustrative; set them from your own baseline.
Why does SMS pumping matter?
An attack can run up a large SMS bill in hours, and because pumped traffic is mixed with genuine OTPs, a blunt response (switching SMS off) locks real users out of sign-up and login. The defences are cheap if built in early: geo-permissions, layered rate limiting, a conversion-rate alarm and, where possible, verification channels that carry no termination fees, such as a WhatsApp authentication template or silent network authentication.
Best practices for SMS pumping
- Put invisible bot checks on every form that can trigger an SMS, not just on login.
- Ask your gateway for per-country spend caps and fraud alerts, and set them below what an attack could cost you in a night.
- Log country, prefix, IP and device for each OTP request so you can reconstruct an attack.
- Drop invalid, unallocated and inactive numbers before sending; an HLR lookup or line-type check costs less than a pumped SMS.
- Offer WhatsApp or silent network authentication first where your users have them; there is no SMS termination fee to exploit.