Executive Summary
CVE-2025-15618 is a critical cryptographic weakness (CVSS 9.1) in the Perl CPAN module Business::OnlinePayment::StoredTransaction through version 0.01. The module generates its internal secret key by computing the MD5 hash of a single call to Perl's built-in rand() function — a method that is entirely unsuitable for cryptographic use.
CVSS Score: 9.1 (Critical)
Perl's rand() is a pseudorandom number generator seeded with a predictable value (typically the current time). Combined with MD5, the resulting key space is trivially small and brute-forceable. Any attacker who can observe or interact with a system using this module — even with limited timing information — may be able to reconstruct the secret key and forge or decrypt stored transaction records.
Vulnerability Overview
| Attribute | Value |
|---|---|
| CVE ID | CVE-2025-15618 |
| CVSS Score | 9.1 (Critical) |
| Type | Cryptographic Weakness / Insecure Randomness |
| Attack Vector | Network |
| Privileges Required | None |
| User Interaction | None |
| Confidentiality Impact | High |
| Integrity Impact | High |
| Availability Impact | None |
| Published | 2026-03-31 |
| Patch Available | No — module deprecated at v0.01 |
Affected Products
| Product | Affected Versions | Remediation |
|---|---|---|
| Business::OnlinePayment::StoredTransaction (Perl/CPAN) | All versions through 0.01 | Remove or replace module — no patch available |
Technical Analysis
Root Cause
The module generates a secret key using the following pattern:
# Pseudocode representation of the vulnerable key generation
use Digest::MD5 qw(md5_hex);
my $secret_key = md5_hex(rand());This is fundamentally broken for two reasons:
-
Perl's
rand()is not cryptographically secure. It is a linear congruential or Mersenne Twister pseudorandom number generator seeded with the current time (or a fixed seed ifsrand()has not been called). An attacker with approximate knowledge of when the module was initialised can enumerate the possible seed values in a fraction of a second. -
A single
rand()call produces at most 2^32 to 2^53 unique values depending on the platform, giving an extremely limited key space compared to what any cryptographic operation requires. -
MD5 is not a key derivation function. Even if the input were random, using raw MD5 without salt, iteration, or a proper KDF (such as PBKDF2, bcrypt, or Argon2) does not produce a cryptographically safe key.
Attack Flow
1. Attacker identifies a system using Business::OnlinePayment::StoredTransaction
2. Attacker determines approximate startup time of the application (e.g. via process listing,
uptime data, log timestamps, or web server response headers)
3. Attacker enumerates plausible rand() seeds across a time window
4. For each candidate seed: compute MD5(rand()) to derive the predicted secret key
5. Attacker tests candidate keys against captured encrypted/authenticated transaction data
6. Correct key found — attacker can now forge, decrypt, or tamper with stored transactionsWhy This Is Dangerous
Stored payment transaction modules hold or process sensitive financial data:
- Card tokens or partial card data stored for recurring billing
- Transaction authentication codes used to verify payment records
- Session or authorization tokens for payment processor callbacks
- Stored customer identifiers tied to payment methods
A compromised secret key allows an attacker to forge transaction records, decrypt stored payment data, and potentially bypass payment authorisation checks — with serious financial and compliance consequences.
Impact Assessment
| Impact Area | Description |
|---|---|
| Secret Key Recovery | Attacker reconstructs the secret key via brute-force of seeded rand() output |
| Transaction Forgery | With the key, attackers can forge valid stored transaction records |
| Data Decryption | Encrypted stored transaction data becomes readable |
| PCI DSS Exposure | Any application storing card data with this module is at risk of PCI DSS violation |
| Financial Fraud | Forged transactions may be used to authorise fraudulent payments |
Affected Ecosystem
This module is part of the Business::OnlinePayment family on CPAN — a widely used Perl payment processing abstraction layer. Applications built on the Perl ecosystem for e-commerce, subscription billing, and payment gateway integration may use this module. It is particularly common in legacy Perl web applications running on Apache/mod_perl stacks.
Immediate Remediation
Step 1: Identify Usage
# Check if the module is installed
perl -MBusiness::OnlinePayment::StoredTransaction -e 'print "installed\n"' 2>/dev/null
# Check CPAN installations
cpan -l | grep StoredTransaction
# Search for usage in your application code
grep -r "StoredTransaction" /var/www/ /opt/app/ --include="*.pl" --include="*.pm"Step 2: Remove or Replace the Module
There is no patched version of this module. The only remediation is to remove it and replace it with a properly implemented alternative:
# Remove via cpanm
cpanm --uninstall Business::OnlinePayment::StoredTransaction
# Or via CPAN shell
perl -MCPAN -e 'CPAN::Shell->uninstall("Business::OnlinePayment::StoredTransaction")'Step 3: Replace with Cryptographically Secure Key Generation
If you need to generate secret keys in Perl, use a cryptographically secure source:
# Correct approach: use /dev/urandom or Crypt::URandom
use Crypt::URandom qw(urandom);
use Digest::SHA qw(sha256_hex);
# Generate 32 bytes of cryptographically secure randomness
my $raw_key = urandom(32);
my $secret_key = sha256_hex($raw_key);
# Or using MIME::Base64 for a URL-safe representation
use MIME::Base64 qw(encode_base64url);
my $secret_key = encode_base64url(urandom(32));Step 4: Rotate All Compromised Keys
If the module was in use, all keys it generated must be treated as compromised:
# Find and regenerate any keys or tokens created by the vulnerable module
# Invalidate all existing stored transaction tokens
# Force re-authorisation for any stored payment methods
# Notify your payment processor if card data may be affectedStep 5: Review for PCI DSS Compliance
If your application processes payment card data:
- Engage a Qualified Security Assessor (QSA) to assess the scope of the exposure
- File a self-assessment questionnaire update if required
- Notify your acquiring bank if stored card data may have been exposed
- Consider whether a data breach notification is required under applicable law
Secure Key Generation Reference
| Method | Security Level | Use Case |
|---|---|---|
rand() (Perl built-in) | Insecure — do NOT use for secrets | Simulation, non-security uses |
Crypt::URandom | Cryptographically secure | Secret keys, tokens, nonces |
Data::GUID | Unique, not cryptographically strong | Identifiers only |
/dev/urandom directly | Cryptographically secure | Any security-sensitive value |
Bytes::Random::Secure | Cryptographically secure | CPAN-standard secure random |
Post-Remediation Checklist
- Remove
Business::OnlinePayment::StoredTransactionfrom all systems - Audit all stored transaction keys for signs of compromise
- Rotate all keys generated by the vulnerable module
- Replace with secure key generation using
Crypt::URandomor/dev/urandom - Review all other uses of Perl's
rand()in security-sensitive contexts - Notify stakeholders if payment data may have been exposed
- Update application security scanning to flag insecure random usage in Perl