Anatomi Celah Authentication Bypass pada Middleware

Authentication bypass sering terjadi bukan karena algoritma kriptografi yang rusak, melainkan logika parsing header dan normalisasi request yang inkonsisten di level middleware. Pola kegagalan yang jamak ditemukan mencakup pengecekan prefix token yang longgar, whitespace stripping parsial, kegagalan menangani duplikasi header, serta handling status non-eksplisit saat parsing error terjadi.

Untuk menghentikan regresi celah autentikasi, unit dan integration test harus memperlakukan middleware sebagai boundary pertahanan ketat. Testing yang reliabel wajib menyertakan negative assertion eksplisit: memastikan payload token korup, format malformed, dan edge cases parsing selalu menghasilkan respons deterministik (HTTP 401 Unauthorized atau 403 Forbidden).

Target Implementasi: Auth Middleware Handler

Berikut adalah implementasi handler autentikasi berbasis ASGI/FastAPI/Starlette minimal tanpa boilerplate berlebih yang akan diuji:

# middleware.py
import hmac
from starlette.middleware.base import BaseHTTPMiddleware
from starlette.responses import JSONResponse

SECRET_KEY = b"fixed-production-secret-demo"

class AuthMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        # Exclude public paths
        if request.url.path in ["/health", "/public"]:
            return await call_next(request)

        auth_header = request.headers.get("Authorization")
        if not auth_header:
            return JSONResponse({"error": "Missing authorization header"}, status_code=401)

        # Strict scheme check: exact 'Bearer ' prefix required
        parts = auth_header.strip().split(" ", 1)
        if len(parts) != 2 or parts[0] != "Bearer":
            return JSONResponse({"error": "Invalid authorization scheme"}, status_code=401)

        token = parts[1].strip()
        if not token or not self._verify_token(token):
            return JSONResponse({"error": "Invalid or expired token"}, status_code=401)

        request.state.user = "authenticated_user"
        return await call_next(request)

    def _verify_token(self, token: str) -> bool:
        # Constant-time comparison prevents timing attacks
        return hmac.compare_digest(token.encode("utf-8"), SECRET_KEY)

Desain Test Suite Otomatis dengan pytest

Gunakan pytest dan httpx untuk memverifikasi reliabilitas logika middleware terhadap variasi request malformed, header injection, dan manipulasi token.

# test_auth_middleware.py
import pytest
from httpx import AsyncClient, ASGITransport
from starlette.applications import Starlette
from starlette.responses import PlainTextResponse
from starlette.routing import Route
from middleware import AuthMiddleware

async def protected_endpoint(request):
    return PlainTextResponse("OK")

app = Starlette(routes=[Route("/admin/dashboard", protected_endpoint)])
app.add_middleware(AuthMiddleware)

@pytest.fixture
async def client():
    transport = ASGITransport(app=app)
    async with AsyncClient(transport=transport, base_url="http://testserver") as c:
        yield c

@pytest.mark.asyncio
async def test_auth_success(client):
    headers = {"Authorization": "Bearer fixed-production-secret-demo"}
    res = await client.get("/admin/dashboard", headers=headers)
    assert res.status_code == 200
    assert res.text == "OK"

@pytest.mark.asyncio
@pytest.mark.parametrize("auth_header", [
    "",                                       # Empty string
    "Bearer",                                 # Missing token body
    "Bearer ",                                # Space with no token
    "Bearer  fixed-production-secret-demo",   # Double spaces (malformed parts)
    "bearer fixed-production-secret-demo",    # Wrong casing scheme
    "Basic fixed-production-secret-demo",     # Unsupported scheme
    "Bearer malicious-token-xyz",             # Invalid secret
    "Bearer \x00fixed-production-secret-demo",# Null byte injection
    "Bearer fixed-production-secret-demo\r\n" # CRLF injection attempt
])
async def test_auth_bypass_negative_assertions(client, auth_header):
    headers = {"Authorization": auth_header} if auth_header is not None else {}
    res = await client.get("/admin/dashboard", headers=headers)
    assert res.status_code == 401
    assert "error" in res.json()

Menangani Edge Cases Parsing Header

Parsing token secara naif sering membuka celah auth bypass. Pertimbangkan aturan berikut saat mendesain regression test:

  • Whitespace Sensitivity: Karakter tab (\t) atau whitespace ganda dapat memicu kegagalan regex tokenizer atau split logic tak terduga.
  • Case Sensitivity: Skema autentikasi (Bearer) harus ditolak bila parser internal mengasumsikan format case-sensitive tetapi engine proxy mengabaikannya.
  • Duplicate Headers: Ketika proxy reverse melewatkan dua header Authorization, pastikan middleware tidak memilih header pertama yang kosong atau mengeksekusi header kedua secara tidak terkontrol.

Integrasi Verification Workflow pada CI Pipeline

Regression test wajib dieksekusi secara otomatis pada setiap pull request untuk memastikan tidak ada perubahan routing atau refactoring handler yang melonggarkan validasi.

# .github/workflows/security-regression.yml
name: Security Regression Pipeline

on:
  pull_request:
    branches: [ main ]
  push:
    branches: [ main ]

jobs:
  auth-regression:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install pytest pytest-asyncio httpx starlette
      - name: Run Middleware Regression Suite
        run: |
          pytest -q test_auth_middleware.py --assert=plain

Catatan: Eksekusi test suite dengan flag --assert=plain atau runner standar tanpa silent-fail assertion memastikan pipeline CI langsung berhenti (exit code non-zero) saat terjadi kegagalan otentikasi.