Hacking Vulnerable Bank Part 3: The PCI Compliance Audit

Jan. 26, 2026
vuln-bank-pci-compliance

Welcome back to the Vulnerable Bank series. In previous walkthroughs, we exploited authentication logic such as Broken Object Level Authorization (BOLA) and other OWASP Top 10 vulnerabilities to gain access to unauthorized accounts, among other things.

If you have not read the previous parts, you can catch up here:

Now, we are shifting our focus from exploitation to auditing. We will evaluate the Vulnerable Bank API against PCI DSS, which is the standard framework for securing payment card data.

It is important to identify vulnerabilities, but equally important to understand why they matter in a professional context. In this lab, I audited the API to see if it met the requirements for handling sensitive financial information safely.

What is PCI Compliance?

PCI DSS stands for the Payment Card Industry Data Security Standard. It is a set of security requirements designed to ensure that all companies that accept, process, store, or transmit credit card information maintain a secure environment.

Is it a Law?

It is not. Unlike GDPR (for data privacy) or HIPAA (for healthcare), PCI DSS is a consensus standard. It is a set of rules enforced by contracts, not by the government.

If a merchant wants to accept Visa, MasterCard, or American Express, they must agree to follow these rules. If a company fails to comply, it may face fines or lose the ability to process credit card payments entirely.

Evolution of the Standard

In the early days of online payments, each card brand had its own security program. This created a complex situation for merchants who had to follow multiple sets of rules.

In 2004, the major card brands formed the PCI Security Standards Council (SSC) to create a single, unified standard.

The standard has evolved over time to keep up with technology. We are currently transitioning to PCI DSS v4.0, which places a stronger emphasis on API security and continuous monitoring. You can learn more about the specific requirements on the official PCI Security Standards Council website.

Key Sections for APIs

As security professionals auditing an API, we focus on specific requirements:

  • Requirement 3: Protect stored account data. This section strictly prohibits storing sensitive data like the CVV code after a transaction is authorized.
  • Requirement 4: Protect cardholder data with strong cryptography during transmission.
  • Requirement 6: Develop and maintain secure systems. This covers preventing common vulnerabilities like Injection flaws.
  • Requirement 8: Identify users and authenticate access to system components. This section mandates Multi-Factor Authentication (MFA) for administrative access.

Now that we have established the criteria, let us examine the Vulnerable Bank API.

The Audit: Identifying Violations

My objective for this audit was to identify data leaks. I tested specific endpoints to see if they exposed the Primary Account Number (PAN), which is the 16-digit card number, or Sensitive Authentication Data (SAD), such as the CVV code.

1. Transaction History Endpoint

Endpoint: GET /transactions/{account_number}

I started by requesting the transaction history for a user.

When I sent a request to the endpoint using a specific account number, the API returned that full account number in the JSON response body.

transaction-history-endpoint

The Violation:

While a bank account number is different from a credit card number, this finding highlights a failure in Data Minimization. If this field were a credit card number, displaying it in plain text would violate PCI DSS Requirement 3.4, which states that the PAN must be rendered unreadable anywhere it is stored or displayed. Additionally, using sensitive identifiers directly in the URL is poor practice because URLs are often saved in browser history and server logs.

The Fix:

  • Tokenization: The API should use a random transaction token in the URL instead of the actual account number.
  • Masking: The response should only display the last four digits (e.g., ******1008) to allow the user to identify the account without exposing the full number.

2. Virtual Card Creation

Endpoint: POST /api/virtual-cards/create

Next, I tested the function that creates new virtual cards. This is a critical feature because it generates new financial data.

Upon successful creation, the API returned the full 16-digit PAN and the CVV code in the response.

new-vitualcard-endpoint

The Violation:

This is a significant compliance failure for two reasons:

Violation of Requirement 3.2: The standard states that you must not store sensitive authentication data after authorization. The fact that the API returns the CVV implies that the system handled and likely stored it. Storing the CVV is strictly prohibited because it allows anyone who breaches the database to use the card for online fraud.

Violation of Requirement 3.4: The full 16-digit PAN is displayed in clear text.

The Fix:

  • Immediate Encryption: The PAN should be encrypted immediately upon generation.
  • No CVV Storage: The CVV should be displayed to the user once via a secure session and never stored in the database or returned in standard API logs.

3. Retrieving Virtual Cards

Endpoint: GET /api/virtual-cards

I then checked the endpoint that retrieves a list of existing cards.

The API returned a list of all cards associated with the user, including the full PAN and the CVV for each one

get-virtualcard-endpoint

The Violation:

This confirms that the application is storing the CVV in the database, which is a critical violation of Requirement 3.2. It also confirms that the PAN is stored without masking, violating Requirement 3.4.

The Fix:

  • Database Purge: The column containing the CVV data must be deleted from the database.
  • Detokenization: The database should store an encrypted version or a token. The API should return a masked version (e.g., ************2895) by default.

4. The Administrative Panel

Endpoint: GET /sup3r_s3cr3t_admin

Finally, I tested the administrative interface.

I accessed this endpoint using a standard authentication token. The response listed all users along with their full Account Numbers and Balances in plain text.

admin-panel-endpoint

The Violation:

PCI DSS Requirement 8.4.2 mandates that administrators accessing the Cardholder Data Environment must use Multi-Factor Authentication (MFA). Accessing this sensitive data with only a single factor (the token) is non-compliant.

The Fix:

  • MFA Enforcement: Access to administrative endpoints should require a second form of verification, such as a Time-based One-Time Password (TOTP).
  • Masking: Administrative views should also mask sensitive account numbers to adhere to the principle of least privilege.

Remediation Strategy

To achieve compliance, Vulnerable Bank needs to implement two key technologies:

  1. Encryption: Data stored in the database, such as the Primary Account Number, must be encrypted using strong algorithms like AES-256. This ensures that even if the database file is stolen, the data remains unreadable without the key.
  2. Tokenization: For data in transit and general storage, sensitive data should be replaced with a token. A token is a random string that has no value to an attacker. The actual data is stored in a secure vault, and the main application only handles the token.

Most importantly, the application must delete the CVV data entirely.

This audit demonstrates that securing an application requires more than just fixing code bugs. It requires strict data governance and adherence to established security standards.

That's it for this one, until next time!

Made With Traleor