← All writeups

Unauthenticated IDOR Allows Modification of Payment Customer Billing Information

Author : Vision KC

Overview

An insecure direct object reference (IDOR) vulnerability was identified in the payment billing information editing functionality of a Django-based application.

The application allowed an unauthenticated user to access a payment’s edit endpoint by supplying a valid payment UUID in the URL. The server did not properly verify whether the requester was authenticated or authorized to modify the payment’s associated customer information.

As a result, an unauthenticated attacker could modify persistent customer billing information by directly accessing the payment edit endpoint.

Severity: High (unauthenticated data integrity violation, no direct financial or authentication bypass)

Stack: Django

Testing note: The vulnerability was reproduced in a local development environment using a test payment and synthetic data. No real customer or production payment information was used.


Vulnerability Details

The affected functionality uses a payment UUID to identify the payment whose associated customer billing information is being edited. The endpoint follows this structure:

/en/payment/<payment_uuid>/edit/

The security issue was caused by missing server-side authentication and object-level authorization checks before allowing the associated customer record to be modified. Possessing a valid payment UUID was effectively sufficient to reach and use this endpoint, regardless of session state.


Reproduction Setup

A synthetic user, customer, and payment were created locally using the Django shell to generate a valid payment UUID for testing.

from django.contrib.auth import get_user_model
from xxx_web.payments.models import Payment, Customer

User = get_user_model()

user = User.objects.create_user(
    username="evidence_user",
    email="evidence@test.local",
    password="TestPassword123!"
)

customer = Customer.objects.create(
    email="evidence@test.local",
    user_id=user.pk,
    origin="http://127.0.0.1:8000",
)
customer.users.add(user)

payment = Payment.objects.create(
    customer=customer,
    amount=100,
    description="IDOR evidence payment",
    backend="pay",
)

print("Payment UUID:", payment.pk)
print("Payment URL:", payment.get_absolute_url())

This produced the following synthetic payment UUID, used throughout this write-up:

01f82084-20dc-498a-b004-2694d51be433

This UUID and all associated data were generated specifically for local testing and do not represent a real production payment or customer.


Proof of Concept

Step 1 — Create a Test Payment

The reproduction script above was run in a local Django shell, creating a test user, customer, and payment, and printing the resulting payment UUID.

Screenshot — Payment creation and UUID:

Payment UUID


Step 2 — Access the Edit Page Without Authentication

Logged out of the application (fresh unauthenticated browser session), then navigated directly to:

http://127.0.0.1:8000/en/payment/01f82084-20dc-498a-b004-2694d51be433/edit/

Despite being unauthenticated, the payment billing information edit page was accessible.

Screenshot — Unauthenticated payment edit page:

Unauthenticated payment edit page

This demonstrates that access to the sensitive modification functionality does not require an authenticated session.


Step 3 — Modify and Submit the Billing Information

The available billing information fields were modified using synthetic test data:

Name: IDOR_EVIDENCE_TEST
Address: IDOR_ADDRESS_TEST

The modification was submitted. The server accepted the request even though the requester was unauthenticated, and the modified billing information was reflected by the application.

Screenshot — Modified billing information:

Modified billing information


Step 4 — Verify Database Persistence

The associated customer record was checked directly. The modified values remained stored:

Name: IDOR_EVIDENCE_TEST
Address: IDOR_ADDRESS_TEST

Screenshot — Persisted customer information:

Database persistence

This confirms the issue results in a persistent server-side modification rather than merely a client-side UI change.


Impact

An unauthenticated attacker could modify persistent customer billing information associated with a payment.

Potential consequences include:

The demonstrated impact is primarily a data integrity violation, as unauthorized users can alter stored customer information without ever authenticating.


Root Cause

The root cause is a missing server-side authorization check in the payment editing functionality.

Conceptually, the vulnerable flow behaves like:

payment = get_payment(payment_uuid)

# Missing authentication and authorization checks

update_customer(payment.customer, submitted_data)

The application should instead verify authentication and object-level authorization before modifying the customer record:

if not request.user.is_authenticated:
    deny_access()

payment = get_payment(payment_uuid)

if not user_can_modify_payment(request.user, payment):
    deny_access()

update_customer(payment.customer, submitted_data)

The exact implementation may differ, but authorization must be enforced server-side for the specific payment and associated customer object.


Remediation

The payment editing functionality should:

  1. Require authentication before allowing access to the edit endpoint.
  2. Perform object-level authorization against the requested payment.
  3. Verify that the authenticated user has permission to modify the associated customer information.
  4. Enforce authorization server-side rather than relying on UUID secrecy or client-side restrictions.
  5. Add regression tests for unauthenticated and unauthorized payment modification attempts.

Conclusion

This vulnerability demonstrates a classic IDOR / broken access control issue where possession of a payment identifier was effectively sufficient to reach a sensitive modification function.

Although UUIDs are difficult to guess, they should never be treated as an authorization mechanism. Sensitive payment and customer information should always be protected with server-side authentication and object-level authorization checks before any modification is performed.


Title: Unauthenticated IDOR Allows Modification of Payment Customer Billing Information

Author: Vision KC

Date: July 16, 2026

Link: blog.visionkc.com.np/idor-billing-info

License: CC BY 4.0