HIGH brute force attackspring boot

Brute Force Attack in Spring Boot

How Brute Force Attack Manifests in Spring Boot

In Spring Boot applications, brute force attacks typically target authentication endpoints like /login, /authenticate, or OAuth2 token endpoints. Attackers automate rapid credential stuffing or password guessing to exploit weak authentication controls. Spring Boot's convention-over-configuration nature can inadvertently expose these risks if developers rely solely on Spring Security's defaults without additional hardening.

Common Attack Patterns:

  • Credential Stuffing: Using breached username/password pairs against /login (often a UsernamePasswordAuthenticationFilter endpoint).
  • Password Guessing: Systematic attempts with common passwords or dictionary words against form-login or basic-auth endpoints.
  • Token Brute Force: Guessing JWT signatures, OAuth2 client_id/client_secret, or API keys in authorization headers.

Spring Boot-Specific Vulnerabilities:

  • Missing rate limiting on authentication endpoints allows unlimited attempts.
  • Default DaoAuthenticationProvider without account lockout policies.
  • Exposing sensitive error messages (e.g., Bad credentials) that confirm valid usernames.
  • Stateless JWT authentication without tracking failed attempts per user/IP.

For example, a typical vulnerable Spring Boot login controller without throttling:

@RestController
public class AuthController {
    @PostMapping("/login")
    public ResponseEntity login(@RequestBody LoginRequest request) {
        // Authentication handled by Spring Security filter chain
        return ResponseEntity.ok("Authenticated");
    }
}

// Security config with no rate limiting
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
                .anyRequest().authenticated()
            .and()
            .formLogin();
        return http.build();
    }
}

Here, an attacker can send unlimited POST requests to /login with different passwords. Spring Security will process each attempt against the UserDetailsService without delay or lockout.

Spring Boot-Specific Detection

Detecting brute force vulnerabilities in Spring Boot APIs requires testing authentication endpoints for absence of throttling mechanisms. middleBrick's rate limiting check actively probes these endpoints by sending rapid sequences of authentication attempts (e.g., 20–30 requests in quick succession) with invalid credentials. The scanner evaluates responses for HTTP 429 (Too Many Requests), increasing latency, or consistent 200/401 status codes indicating no rate limiting.

What middleBrick Looks For:

  • No Retry-After header or X-RateLimit-* headers in responses.
  • Identical response times and status codes across rapid requests.
  • Lack of account lockout triggers after repeated failures (if user enumeration is possible).

Example Scan Output (middleBrick Report):

Check: Rate Limiting
Status: FAIL
Severity: High
Endpoint: POST /api/v1/login
Details: No rate limiting detected. Sent 30 requests in 5 seconds, all returned 401 in ~120ms. No 429 responses or latency increases observed.
Remediation: Implement IP-based or user-based rate limiting using Bucket4j or Spring Cloud Gateway.
Compliance: OWASP API Top 10 A07:2021, PCI-DSS 8.6.2

Manual Verification: You can replicate middleBrick's test using curl in a loop:

for i in {1..30}; do curl -X POST http://api.example.com/login -d '{"username":"admin","password":"wrong"}' -H 'Content-Type: application/json' -s -o /dev/null -w '%{http_code} '; done

If all responses are 401 with no 429, rate limiting is missing.

Spring Boot-Specific Remediation

Remediation in Spring Boot involves implementing rate limiting and account lockout at the filter or controller level. Use battle-tested libraries like Bucket4j (in-memory or Redis-backed) integrated via Spring Security's filter chain. Avoid custom in-memory counters that fail in distributed deployments.

Step 1: Add Bucket4j Dependency

<dependency>
    <groupId>com.github.vladimir-bukhtoyarov</groupId>
    <artifactId>buck4j-core</artifactId>
    <version>8.10.0</version>
</dependency>

<dependency>
    <groupId>com.bucket4j</groupId>
    <artifactId>bucket4j-redis</artifactId>
    <version>8.10.0</version>
</dependency>

Step 2: Configure Rate Limiter Filter

@Component
public class RateLimitFilter extends OncePerRequestFilter {
    
    @Value("${rate.limit.bandwidth:10}")
    private int bandwidth;
    
    @Value("${rate.limit.duration:1}")
    private int duration;
    
    private final Map<String, Bucket> buckets = new ConcurrentHashMap<>();
    
    private Bucket resolveBucket(String key) {
        return buckets.computeIfAbsent(key, k -> {
            Bandwidth limit = Bandwidth.classic(bandwidth, Refill.greedy(bandwidth, Duration.ofMinutes(duration)));
            return Bucket.builder()
                    .addLimit(limit)
                    .build();
        });
    }
    
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {
        
        String ip = request.getRemoteAddr();
        String path = request.getRequestURI();
        
        // Apply rate limit only to login endpoint
        if (path.equals("/api/v1/login") && request.getMethod().equals("POST")) {
            Bucket bucket = resolveBucket(ip);
            if (bucket.tryConsume(1)) {
                chain.doFilter(request, response);
            } else {
                response.setStatus(429);
                response.getWriter().write("Too many requests. Please try again later.");
            }
            return;
        }
        chain.doFilter(request, response);
    }
}

Step 3: Integrate with Spring Security

@Configuration
@EnableWebSecurity
public class SecurityConfig {
    
    @Autowired
    private RateLimitFilter rateLimitFilter;
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .addFilterBefore(rateLimitFilter, UsernamePasswordAuthenticationFilter.class)
            .authorizeRequests()
                .antMatchers("/api/v1/login").permitAll()
                .anyRequest().authenticated()
            .and()
            .formLogin()
                .loginProcessingUrl("/api/v1/login");
        return http.build();
    }
    
    // Also enforce strong password encoding
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(12);
    }
}

Production Considerations:

  • Use Redis-backed Bucket4j for distributed systems to synchronize limits across instances.
  • Combine IP-based limits with username-based limits to prevent targeted user locking.
  • Set reasonable thresholds (e.g., 5–10 attempts per minute per IP).
  • Log blocked attempts for security monitoring.

With this configuration, Spring Boot will respond with 429 Too Many Requests after exceeding the threshold, effectively mitigating brute force attacks.

Continuous Monitoring with middleBrick

While code fixes are essential, brute force protections can degrade over time due to configuration drift or new endpoint additions. middleBrick's continuous monitoring (available in Pro and Enterprise tiers) automatically re-scans your APIs on a schedule, alerting you if rate limiting is removed or misconfigured. For example, if a developer accidentally removes the RateLimitFilter bean, middleBrick will detect the regression and notify your team via Slack or email, ensuring consistent security posture.

Integrate middleBrick into your CI/CD pipeline with the GitHub Action to catch missing rate limits before deployment:

# .github/workflows/api-security.yml
name: API Security Scan
on: [pull_request]
jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - name: Run middleBrick scan
        uses: middlebrick/github-action@v1
        with:
          api-url: ${{ secrets.STAGING_API_URL }}
          fail-below-score: 80 # Fail PR if security score drops below B

This prevents brute force vulnerabilities from reaching production.

Frequently Asked Questions

How does middleBrick test for brute force vulnerabilities without valid credentials?
middleBrick sends rapid sequences of authentication attempts (e.g., 30 requests in 5 seconds) with deliberately invalid credentials to login endpoints. It analyzes responses for HTTP 429 status codes, increasing latency, or consistent 401/200 responses that indicate no rate limiting is active. This black-box approach requires no credentials and tests the unauthenticated attack surface.
Does Spring Security provide built-in brute force protection out of the box?
No. Spring Security focuses on authentication mechanisms (e.g., password encoding, session management) but does not include automatic account lockout or IP-based rate limiting. Developers must explicitly configure these controls, typically by integrating libraries like Bucket4j or using Spring Cloud Gateway's RedisRateLimiter. Without such additions, Spring Boot APIs remain vulnerable to unlimited login attempts.