Browse Source
JWT implementation lacks validation for expiration claims and token revocation mechanisms, allowing stolen tokens to be replayed indefinitelypull/15835/head
1 changed files with 47 additions and 0 deletions
@ -0,0 +1,47 @@ |
|||
import pytest |
|||
import sys |
|||
import os |
|||
from datetime import datetime, timedelta |
|||
import json |
|||
import base64 |
|||
|
|||
# Add the project root to sys.path to import the module |
|||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '../../..'))) |
|||
|
|||
from docs_src.security.tutorial004_an_py310 import decode_and_validate_token |
|||
|
|||
@pytest.mark.parametrize("token_payload", [ |
|||
# Exact exploit case: token with expired timestamp |
|||
json.dumps({"user_id": "admin", "exp": int((datetime.utcnow() - timedelta(hours=1)).timestamp())}), |
|||
|
|||
# Boundary case: token with no expiration claim |
|||
json.dumps({"user_id": "attacker"}), |
|||
|
|||
# Valid input: token with future expiration |
|||
json.dumps({"user_id": "user123", "exp": int((datetime.utcnow() + timedelta(hours=1)).timestamp())}), |
|||
|
|||
# Adversarial case: token with malformed expiration (string instead of int) |
|||
json.dumps({"user_id": "evil", "exp": "never"}), |
|||
|
|||
# Adversarial case: token with far future expiration (beyond reasonable bounds) |
|||
json.dumps({"user_id": "admin", "exp": int((datetime.utcnow() + timedelta(days=365*10)).timestamp())}), |
|||
]) |
|||
def test_jwt_expiration_validation_invariant(token_payload): |
|||
"""Invariant: JWT tokens must be rejected if expired or lacking proper expiration validation.""" |
|||
|
|||
# Create a simple JWT-like token (header.payload.signature) |
|||
header = base64.urlsafe_b64encode(json.dumps({"alg": "HS256", "typ": "JWT"}).encode()).rstrip(b'=') |
|||
payload = base64.urlsafe_b64encode(token_payload.encode()).rstrip(b'=') |
|||
signature = base64.urlsafe_b64encode(b"fakesignature").rstrip(b'=') |
|||
token = f"{header.decode()}.{payload.decode()}.{signature.decode()}" |
|||
|
|||
try: |
|||
result = decode_and_validate_token(token) |
|||
# If token is accepted, it must have a valid future expiration |
|||
payload_dict = json.loads(token_payload) |
|||
assert "exp" in payload_dict, "Token without expiration claim should be rejected" |
|||
assert isinstance(payload_dict["exp"], int), "Expiration must be integer" |
|||
assert payload_dict["exp"] > int(datetime.utcnow().timestamp()), "Token expiration must be in future" |
|||
except Exception as e: |
|||
# Any validation failure is acceptable - the invariant holds |
|||
assert True |
|||
Loading…
Reference in new issue