Back to the index

LAB PASS

JWT Algorithm Confusion - Authentication - alg none

JWT Algorithm Confusion — Authentication — alg none

CWE-347: Improper Verification of Cryptographic Signature · OWASP A07:2021 - Identification and Authentication Failures

Vulnerability

[PASS] JWT Algorithm Confusion - Authentication - alg none

Description

The test attempted to bypass JWT signature verification by changing the algorithm header to none and emptying the signature section, a classic token forgery technique. The source code lists none among the accepted algorithms, so this endpoint was tested specifically.

Impact

No impact. Control holds: tokens with alg none are rejected on every tested endpoint, both ordinary user endpoints and the administrative panel, with HTTP 401. The JWT library in use rejects the none algorithm when a verification key is provided, so the permissive code intent cannot be exploited through this path. Note: this does NOT mean token validation is safe. Another forgery path succeeds and is reported separately in the JWT Signature Not Verified finding, where tokens with an invalid signature are still accepted.

CWE

CWE-347: Improper Verification of Cryptographic Signature

OWASP

A07:2021 - Identification and Authentication Failures

Scenario

A legitimate token is decoded, the header is changed to alg none, the is_admin claim is changed to true, then the token is reassembled without a signature. The token is sent to the user endpoint and the administrative endpoint. Result: both reject it with HTTP 401.

Endpoint

GET http://127.0.0.1:5001/dashboard GET http://127.0.0.1:5001/sup3r_s3cr3t_admin

Affected feature

JWT validation (none algorithm)

Remediation

- Keep rejecting the none algorithm, and remove none from the configured algorithm list so the code intent matches library behavior. - Pin the algorithm explicitly to a single expected value.

Proof of concept

  1. (Screenshot 1) PROCESS: a legitimate token is decoded, the header is changed to alg none and the is_admin claim to true, then it is reassembled without a signature.
  2. (Screenshot 2) RESULT: the alg none token is sent to /dashboard -> HTTP 401 Invalid token, control holds.
  3. (Screenshot 3) RESULT: the alg none token is sent to /sup3r_s3cr3t_admin -> HTTP 401, control holds.

The complete record

LAB All targets are lab systems. Nothing here is a client engagement. Evidence is shown as recorded; secrets are blacked out.

Prepare an alg:none JWT

  1. Captured token [REDACTED-LAB-TOKEN]
  2. Modified header { "typ": "JWT", "alg": "none" }
  3. Modified payload { "user_id": 1, "username": "admin", "is_admin": true, "iat": 1790736461 }
  4. Re-encoded token (empty signature) [REDACTED-LAB-TOKEN]
Screenshot
HTTP request
GET /dashboard HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]

HTTP response
HTTP/1.1 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 31
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:06 GMT

{
  "error": "Invalid token"
}
Screenshot
HTTP request
GET /sup3r_s3cr3t_admin HTTP/1.1
User-Agent: python-requests/2.33.1
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Authorization: Bearer [REDACTED-LAB-TOKEN]

HTTP response
HTTP/1.1 401 UNAUTHORIZED
Content-Type: application/json
Content-Length: 31
Access-Control-Allow-Origin: *
Server: Werkzeug/2.0.1 Python/3.9.25
Date: Wed, 30 Sep 2026 03:13:07 GMT

{
  "error": "Invalid token"
}
Screenshot

← Previous case: Insufficient Session Expiration - Authentication - JWT Lifetime Next case: JWT Signature Not Verified - Authentication - Token Validation →