Anatomy of a 4-day mobile app credential stuffing attack

In this article, we cover the details of a distributed credential-stuffing attack that targeted the mobile application of a major US on-demand staffing company. By the end of the bot attack, which lasted 4 days, Castle blocked more than 558K malicious login attempts.

Credential stuffing attack metrics

  • Date: from December 27th around ~3 am UTC lasted until December 30th 8 am UTC
  • Attack duration: 4 days
  • Endpoint targeted: mobile application login
  • Type of attack: credential stuffing
  • Volume of requests: 558,624 malicious login events
  • Maximum velocity: 14.4k login events per hour
  • Number of IPs involved: 18,287 IP addresses

Credential stuffing attack overview

As a reminder, credential stuffing is the act of using bots to try large amounts of stolen credentials to gain unauthorized access to accounts (account takeover). It can target both websites and mobile applications. While credential stuffing attacks targeting websites may be easier to conduct, fraudsters love to target mobile application APIs as well since they tend to be less protected than their website counterparts.

In this attack, the attacker targeted the mobile login endpoint and made 558,624 login attempts over 4 days. The attack was split into two waves, as we can see in the graph below. In the first wave, on December 27th, the attack reached a spike of a whopping 14.4k login attempts per hour.

Why did the attacker conduct a two-stage attack? The first stage was certainly to test the correctness of the bot during a small timeframe before running it at a bigger scale, for a longer time.

Why didn’t the attacker stop after the first wave if the attack was blocked? Castle avoids providing any direct/explicit feedback to the attacker — like a CAPTCHA or a specific error message — to make it more difficult for them to know whether or not their attack is successful. Instead, Castle provides a risk score and a recommendation (allow/challenge/deny) to customers. Thus, they can implement their own custom logic when a login attempt is flagged as malicious, such as challenging the end user with a second authentication factor, or simply displaying a generic error message in the UI to make it look like the login attempt was not correct, as recommended by OWASP.

The attacker used proxies to distribute the credential-stuffing attack. The proxies were either data center proxies or low-quality free proxies located in developing countries.

The graph below shows the evolution of the number of unique IP addresses per hour used by the attacker. We see that during the bot attack, the attacker was often using more than 1,500 distinct IPs per hour to spread the attack.

Proxies are a key component of credential-stuffing attacks. It enables bots to spread their attack across thousands of IP addresses, which avoids being detected by simple IP-based rate-limiting techniques.

Attack Indicators of Compromise (IoCs)

The attacker used different techniques to minimize their chances of being detected, such as forging proper mobile application HTTP headers and using proxies to distribute the attack.

  • The attacker used HTTP headers and POST payloads that were consistent with the latest version of mobile application targeting.
  • They pretended to run on an iPhone 16,2.
  • Bots sent a Castle SDK payload that contained the device fingerprint. However, the payload was always the same, including the dynamic parts of the Castle SDK payload. The attacker must have extracted a valid login payload and replayed it (replay attack).
  • Bots operated in low and slow mode. The average volume of login attempts per IP address was quite low, around 30 login attempts/IP, spread over 4 days.

How did Castle block the attack?

Castle’s detection uses a multi-layered approach to ensure that even if attackers properly forge their device fingerprints or use clean residential proxies, it still detects malicious bot traffic.

In the case of this attack, the attacker was detected by a combination of signals and approaches:

  • Replay attack detection: While trying to forge proper mobile application HTTP headers and login payloads, the attacker hard-coded the Castle SDK payload as part of the HTTP request. Thus, while the HTTP headers sent by the bots were consistent, the fingerprints collected by Castle’s SDK were always the same and triggered our anti-forgery mechanisms.
  • Abnormal behavior: Even though the volume of requests per IP was relatively low, we still detected an abnormal volume of failed login events linked to a specific fingerprint
  • Our detection engine also detected several suspicious weak signals, such as:
    • The use of low-quality data center proxies and free proxies;
    • A mismatch between the location of the IP and the timezone collected using the Castle mobile SDK

A good recommendation to protect against similar attacks would be to implement an anti-replay mechanism on your login APIs. Similarly to what’s recommended by the OWASP against CSRF attacks, you could add a per-request nonce to the URL and all forms in addition to the standard session, or a custom-based time verification. However, contrary to CSRF attacks where an attacker tries to force an end user to conduct an action, here the attacker has full control of his own browser. Thus, he can analyze and extract the potential per-request nonce/tokens or your anti-replay logic. This can often lead to a cat-and-mouse game situation that requires frequent code updates and strong JavaScript obfuscation.

Conclusion

Fraudsters often conduct credential-stuffing attacks against mobile applications since their login endpoint tends to be less protected than their website counterparts. These attacks can significantly strain server resources and pose a serious risk of account takeovers. These incidents can harm the brand's reputation and degrade the customer experience. While such attacks can originate from a small number of IP addresses, attackers increasingly rely on residential proxies to highly distribute their attacks and to evade defenses.

Traditional bot detection techniques such as geo-blocking and IP-based rate limiting are not enough against today’s attackers. This is why Castle uses a multi-layered approach that leverages advanced machine learning (ML) with all signals available: from device fingerprint to advanced residential proxy detection and user behavioral analysis.