HIGH broken access controlspring bootbasic auth

Broken Access Control in Spring Boot with Basic Auth

Broken Access Control in Spring Boot with Basic Auth — how this specific combination creates or exposes the vulnerability

Broken Access Control (BOLA/IDOR) in Spring Boot applications using HTTP Basic Auth commonly occurs when authorization checks are missing or incorrectly applied after authentication. With Basic Auth, credentials are sent in an encoded (not encrypted) header on each request. If endpoints rely only on authentication (verifying who you are) and omit authorization (verifying what you are allowed to do), attackers can manipulate identifiers in URLs or parameters to access other users' resources.

For example, consider a Spring Boot REST endpoint like /api/users/{userId}/profile. If the application authenticates the request with Basic Auth but does not verify that the authenticated user matches the {userId} in the path, an authenticated user can change the ID and browse other profiles. This is a classic BOLA/IDOR scenario. The unauthenticated attack surface is particularly relevant for Basic Auth because scanning tools can send valid credentials and still probe for IDOR by iterating resource identifiers.

Spring Boot’s method-level security (e.g., @PreAuthorize) and URL-based security (e.g., antMatchers) must align with domain ownership rules. Common mistakes include:

  • Exposing repository methods that return data based only on an identifier without checking the authenticated user.
  • Relying on UI-level hiding of links instead of enforcing server-side checks.
  • Using role-based checks alone (e.g., hasRole('ADMIN')) when the rule should be user-to-resource ownership.

Because Basic Auth transmits credentials in an easily reversible format, it is also important to ensure transport encryption (TLS). Without TLS, intercepted credentials and session tokens can be reused. In a black-box scan, an authentication check may pass, but a BOLA scan can still uncover missing authorization logic by probing other users’ IDs once authenticated.

Basic Auth-Specific Remediation in Spring Boot — concrete code fixes

Remediation focuses on enforcing ownership checks and avoiding over-privileged roles. Below are specific fixes and code examples tailored for Basic Auth in Spring Boot.

1. Use Authentication-aware queries

Always resolve the current user from the SecurityContext and use it in queries rather than trusting path parameters. Here is a secure controller pattern:

@RestController
@RequestMapping("/api/users")
public class UserProfileController {

    private final UserProfileRepository userProfileRepository;

    public UserProfileController(UserProfileRepository userProfileRepository) {
        this.userProfileRepository = userProfileRepository;
    }

    @GetMapping("/{userId}/profile")
    public ResponseEntity<UserProfileDto> getProfile(@PathVariable UUID userId, Authentication authentication) {
        String authenticatedUsername = authentication.getName(); // e.g., the username used in Basic Auth
        UserProfile profile = userProfileRepository.findByUsernameAndUserId(authenticatedUsername, userId);
        if (profile == null) {
            return ResponseEntity.notFound().build();
        }
        return ResponseEntity.ok(toDto(profile));
    }
}

The repository method should enforce ownership:

@Repository
public interface UserProfileRepository extends JpaRepository<UserProfile, UUID> {
    @Query("SELECT u FROM UserProfile u WHERE u.userId = :userId AND u.username = :username")
    Optional<UserProfile> findByUsernameAndUserId(@Param("username") String username, @Param("userId') UUID userId);
}

2. Method-level security with domain ownership

Use @PreAuthorize to express ownership rules clearly. This ensures checks are applied consistently:

@Service
public class UserProfileService {

    private final UserProfileRepository userProfileRepository;

    public UserProfileService(UserProfileRepository userProfileRepository) {
        this.userProfileRepository = userProfileRepository;
    }

    @PreAuthorize("@profileOwnershipValidator.isOwner(authentication, #userId)")
    public UserProfileDto getProfile(UUID userId, Authentication authentication) {
        // fetch and DTO conversion
        return ...;
    }
}

Implement a validator bean:

@Component
public class ProfileOwnershipValidator {
    @Autowired
    private UserProfileRepository userProfileRepository;

    public boolean isOwner(Authentication authentication, UUID userId) {
        String username = authentication.getName();
        return userProfileRepository.existsByUsernameAndUserId(username, userId);
    }
}

3. Secure Basic Auth configuration with TLS enforcement

Ensure HTTP is redirected to HTTPS and Basic Auth is configured with role-based entry points:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
            .requiresChannel(channel -> channel
                .anyRequest().requiresSecure() // enforce TLS
            )
            .authorizeHttpRequests(auth -> auth
                .requestMatchers(HttpMethod.GET, "/api/users/**").authenticated()
                .anyRequest().denyAll()
            )
            .httpBasic(Customizer.withDefaults());
        return http.build();
    }

    @Bean
    public UserDetailsService users() {
        UserDetails user = User.withDefaultPasswordEncoder()
            .username("alice")
            .password("secret') // in production, use a proper PasswordEncoder
            .roles("USER")
            .build();
        return new InMemoryUserDetailsManager(user);
    }
}

Remediation guidance includes:

  • Never trust path or query parameters for access control — always cross-check with the authenticated identity.
  • Prefer method-level security for fine-grained rules and ensure repository methods filter by username or tenant ID.
  • Use HTTPS to protect Basic Auth credentials in transit; consider deprecating Basic Auth in favor of token-based flows where feasible.
  • Combine role checks with ownership checks; roles alone are insufficient for BOLA prevention.

By aligning authentication with domain-specific authorization, Spring Boot applications using Basic Auth can mitigate BOLA/IDOR risks while maintaining straightforward credential handling.

Frequently Asked Questions

Does using Basic Auth with Spring Security automatically prevent IDOR?
No. Authentication only confirms identity; you must add authorization checks that verify the authenticated user is allowed to access the specific resource. Always validate ownership server-side.
Can middleBrick detect Basic Auth IDOR in unauthenticated scans?
middleBrick can test unauthenticated attack surfaces and, when provided with credentials, can authenticate to probe deeper. To find BOLA/IDOR, it combines authenticated scanning with identity manipulation to identify missing authorization checks.