CDSL: Security Architecture Analysis — Responsible Disclosure

CDSL: Security Architecture Analysis

Responsible Disclosure Notice: This post describes architectural weaknesses and their potential impact. No exact API endpoints (beyond the publicly visible URL paths), hardcoded key values, or step-by-step reproduction instructions are included. The reCAPTCHA site key is referenced by pattern, not by value. Findings have been reported through appropriate channels.

FieldDetail
ApplicationCentral Depository Services Limited (CDSL) — Easi / Easiest / Nomination / Consent portals
Ministry/BodyMinistry of Finance (MoF) / SEBI-regulated
Data CategoryPAN, BOID (demat account IDs), KYC, nominee details, OTP, transaction instructions
Sensitivity🔴 High
PlatformWeb (cdslindia.com ASP.NET WebForms + web.cdslindia.com login)
Analysis Date2026-06-14
Critical Findings2
High Findings3
Medium Findings3
Low Findings2

Summary

This analysis examined the client-side architecture of CDSL — India’s largest securities depository by number of demat accounts (5+ crore beneficial owners). The focus was on the public-facing authentication surfaces: Nomination Login, OTP Authentication, Consent Login, and the Easi/Easiest login landing.

CDSL’s client-side encryption uses AES-CBC with keys generated by Math.random() — JavaScript’s built-in pseudo-random number generator that is explicitly documented as not cryptographically secure. The PBKDF2 key-derivation function is called without an iterations parameter, defaulting to 1 iteration (effectively no brute-force resistance). Both the AES key (f) and IV (s) are base64-encoded and sent in the same POST body as the ciphertext (seck).

The analysis identified 2 critical, 3 high, 3 medium, and 2 low severity findings. The presence of Google reCAPTCHA v2 across endpoints is a positive contrast to the legacy image CAPTCHAs seen elsewhere in this series.

Risk Factors

  • AES encryption keys generated using Math.random() — JavaScript’s documented-not-cryptographic PRNG; predictable with knowledge of seed (typically time-based)
  • PBKDF2 called without iterations parameter — defaults to 1 iteration; provides zero brute-force resistance
  • AES key (f), IV (s), and ciphertext (seck) all sent in same POST body — encryption theatre
  • CryptoJS v3.1.2 (2013) bundled as cpemain/includes/lib/CryptoCDSL/aes.js — same outdated version as PM-Kisan
  • Single reCAPTCHA v2 site key shared across multiple endpoints — if the site key is ever rate-limit-abused or the v2 challenge is bypassed at scale (commercial solving services charge ~$1–3 per 1,000 solves), all endpoints lose their CAPTCHA protection simultaneously
  • web.cdslindia.com (the Easi/Easiest login host) returned HTTP 530 (Cloudflare block) on direct curl from a residential-class IP — suggests aggressive bot mitigation that may also block legitimate automated tooling and security researchers
  • ASP.NET WebForms ViewState on NominationLogin.aspx without visible __VIEWSTATEUSERKEY —ViewState tampering / replay risk
  • Math.random() returns 64-bit doubles; effective entropy of an 8-character “random” string from Math.random() is far below the cryptographic 128-bit baseline

Impact Scenarios

Scenario: Math.random() Enables Key Prediction

CDSL’s AESutil.js defines:

function getf() {
  return randomString(16, '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ');
}
function gets() { /* same */ }
function randomString(length, chars) {
  var result = '';
  for (var i = length; i > 0; --i)
    result += chars[Math.round(Math.random() * (chars.length - 1))];
  return result;
}

Math.random() is the V8/SpiderMonkey PRNG — typically an xorshift128+ variant seeded with the current time and a per-process state. It is explicitly documented as not cryptographically secure in every major JS engine and in MDN. For a 16-character string from a 62-character alphabet, the theoretical entropy is ~95 bits — but the effective entropy is bounded by the PRNG state, which is recoverable with as few as 4–5 observed outputs in academic attacks. An attacker who can sniff a single CDSL login request (e.g., via a compromised ISP, a corporate proxy with logging, or a TLS MITM with a rogue CA) can observe the base64-decoded f and s values, recover the PRNG state, and predict future keys for other sessions on the same V8 isolate.

Scenario: PBKDF2 Default Iterations = Zero Brute-Force Resistance

The same AESutil.js defines:

function generateKey(s, p) {
  return CryptoJS.PBKDF2(p, s, { keySize: 256/32 });
}

CryptoJS’s PBKDF2 defaults to 1 iteration when iterations is not specified. The function comment mentions iterationCount = 1000, but that value is never passed to the PBKDF2 call. OWASP recommends at least 600,000 iterations for PBKDF2-SHA256 as of 2023. A single-iteration PBKDF2 is equivalent to a single SHA-256 hash — brute-forceable at billions of attempts per second on commodity GPUs.

Even though this function appears unused in the live login flow (the actual flow uses getf()/gets() directly), its presence in shipped code indicates the development team’s understanding of KDF parameters is below the bar — and any future refactor that wires generateKey() into production will inherit the 1-iteration default.

Scenario: Single reCAPTCHA Key Across Endpoints

The same data-sitekey value is used on:

  • www.cdslindia.com/bo/NominationLogin.aspx
  • www.cdslindia.com/eservices/consent/Login

And likely on every other CDSL login surface. If this v2 site key is ever solved at scale (commercial CAPTCHA-solving services already achieve >90% solve rates on reCAPTCHA v2 image challenges for under $3 per 1,000 solves), all CDSL endpoints that depend on it lose their primary bot-mitigation control simultaneously. Best practice is to use per-endpoint site keys for tiered risk (login = stricter, public lookup = looser) and to migrate to reCAPTCHA v3 / Enterprise with score-based thresholds.

Scenario: BOID Enumeration via Predictable Encoding

The Nomination Login page encodes the BOID (Beneficial Owner ID — the 16-digit demat account number) with btoa() (plain base64) before submission:

var EncodedBOID = btoa(document.getElementById('txtboid').value);
$("#txtBOIDencoded").val(EncodedBOID);

Plain base64 is reversible by anyone who reads the request. If an attacker can sniff or proxy the request, they recover the BOID in cleartext. Combined with the AES-key disclosure above, both the BOID and the PAN are recoverable from a single captured login request.

Findings Overview

SeverityCategoryDetail
🔴 CRITICALNon-Cryptographic PRNG for AES KeysMath.random() used to generate AES key and IV — predictable
🔴 CRITICALPBKDF2 with Default 1 IterationgenerateKey() calls PBKDF2 without iterations parameter — zero brute-force resistance
🟠 HIGHAES Key+IV+Ciphertext in Same POSTf, s, seck form fields all sent together — encryption theatre
🟠 HIGHPlain Base64 Encoding of BOIDDemat account number encoded with reversible btoa()
🟠 HIGHSingle reCAPTCHA v2 Site Key Across EndpointsShared site key compromises all endpoints on bypass
🟡 MEDIUMObsolete Crypto LibraryCryptoJS v3.1.2 (2013) bundled as cpemain/includes/lib/CryptoCDSL/aes.js
🟡 MEDIUMViewState Without User KeyASP.NET WebForms ViewState lacks visible __VIEWSTATEUSERKEY
🟡 MEDIUMLogin Host Blocks Researcher Trafficweb.cdslindia.com returns HTTP 530 to non-browser clients — limits independent security research
🔵 LOWDeprecated X-XSS-Protection Headerx-xss-protection: 1; mode=block set (deprecated per MDN)
🔵 LOWInfrastructure Header Leakagecf-cache-status: DYNAMIC and server: cloudflare reveal CDN topology

Why This Matters

CDSL is the larger of India’s two securities depositories by account count:

  • 5+ crore demat accounts (versus NSDL’s ~3 crore)
  • PAN-seeded identity for every beneficial owner
  • Easi / Easiest — primary retail-investor-facing portals for holdings, transactions, and inter-depository transfers
  • Nomination — critical for succession planning; if compromised, attackers could redirect nominee details
  • Consent Login — used for DP (Depository Participant) authorisation flows

When the cryptographic layer protecting logins uses non-cryptographic PRNG and single-iteration PBKDF2, the effective security is dramatically below what SEBI’s Cybersecurity & Cyber Resilience Framework (CSCRF, 2024) requires of a MIIs (Market Infrastructure Institutions). Depositories are explicitly designated as MIIs and are held to a higher cryptographic bar than general fintech apps.

This analysis continues the series on Indian government / quasi-government portals that ship cryptographic primitives to the client. CDSL is notable because the client-side code (AESutil.js, 965 bytes) is small enough to audit in full — the weaknesses are not buried in a 1.6 MB bundle, they are in plain sight. That they have persisted into 2026 suggests the development team has not had an independent security review of the crypto layer.

Responsible Disclosure Timeline

DateEvent
2026-06-14Blog analysis published with redacted details
2026-06-14CERT-In disclosure initiated (V1–V6 format) for Math.random() PRNG
2026-06-14SEBI CSCRF compliance escalation for MII cybersecurity framework
~2026-09-1290-day responsible disclosure deadline

Recommendations

Immediate (0–7 days)

  1. Replace Math.random() with crypto.getRandomValues() in AESutil.js. The Web Crypto API provides a cryptographically secure PRNG available in all modern browsers.
  2. Add explicit iterations: 600000 parameter to the PBKDF2 call in generateKey() (OWASP 2023 minimum for PBKDF2-SHA256). Or migrate to Argon2id.
  3. Stop sending the AES key (f) and IV (s) in the same POST body as the ciphertext. Either remove client-side encryption entirely (rely on TLS) or implement proper hybrid encryption with a server-provided RSA public key so the AES key is never transmitted.
  4. Rotate the reCAPTCHA site key as a precaution, and assign separate site keys per endpoint tier.

Short-Term (1–4 weeks)

  1. Migrate from reCAPTCHA v2 to reCAPTCHA v3 / Enterprise with score-based thresholds — v3 is invisible to users and substantially harder to solve via commercial services.
  2. Replace plain btoa() BOID encoding with the same encryption scheme used for PAN (when fixed) or with server-side session storage of the BOID.
  3. Add __VIEWSTATEUSERKEY to all ASP.NET WebForms pages to prevent ViewState replay across users.
  4. Upgrade CryptoJS from v3.1.2 to a modern cryptographic library (e.g., @noble/ciphers or WebCrypto API), or eliminate client-side crypto entirely.
  5. Whitelist security-researcher user agents (or publish a security.txt with a friendly scan policy) on web.cdslindia.com so that legitimate researchers can audit the login flow without being blocked at the CDN edge.

Structural (1–3 months)

  1. Adopt a uniform client-side crypto policy across all CDSL properties — server-provided RSA public keys, per-session AES keys generated via Web Crypto, no client-side constants.
  2. Independent security audit by a CERT-In empanelled auditor against SEBI CSCRF (with MII-tier scope), with findings published in summary form.
  3. Publish a security.txt (/.well-known/security.txt) on all CDSL domains with a vulnerability-disclosure contact.
  4. Bug bounty programme on Intigriti or HackerOne to crowdsource ongoing review of the authentication surfaces.

Cross-References


This post is part of an ongoing series of responsible-disclosure security analyses of Indian government and quasi-government digital portals. No exploit details, exact endpoints, or hardcoded secret values are included. If you are a CDSL operator or SEBI official and would like to coordinate on remediation, contact CERT-In or SEBI’s cybersecurity division directly.