REVERSE ENGINEERING // CLIENT-SIDE ENCRYPTION // API ABUSE
WEB APPLICATION SECURITY

Analysis of Client-Side Encryption Reverse Engineering

AES CBC // REST API // HARDCODED ENCRYPTION KEYS

researcher
Naveen Jagadeesan
published
2023-02-18
platform
Web / Android / iOS

An in-depth analysis of reverse engineering client-side encryption in a web application.

Target Background

The target is a web application accessible through both web browsers and mobile applications on Android and iOS platforms.

The application utilizes a centralized CDN (Content Delivery Network) system indicating multiple applications sharing the same resources and architecture.

Through subdomain enumeration it was discovered that the target had more than 15 applications sharing the same technology stack.

Overview

Reconnaissance identified an interesting implementation where all REST API communications were encrypted.

The request and response bodies were encoded before transmission. However the developers hardcoded encryption keys and IVs directly inside client-side JavaScript.

Client-side encryption becomes ineffective once secrets are embedded inside distributed JavaScript bundles.

Recon

Files Discovered

Initial keyword searches focused on:

Further analysis of main.js exposed the encryption logic.


91622: function (e, t) {
  'use strict';
  t.Z = {
    apiDomain: 'https://api.abc.com',
    bookingApiDomain: 'https://bookings.abc.com',
    cdnPath: 'https://cdn.abc.com',
    dataHasKey: '###################=',
    dataIVKey: 'jm8lgqa3j1d0ajus',
    encryptionKeys: '[...]'
  }
}

The application exposed both the encryption key and initialization vector directly within the frontend bundle.

Request and response analysis

Encryption Function Discovery

Additional CDN-hosted JavaScript files were analyzed.

A file named app.js exposed both encryption and decryption routines used by the API layer.


abc.factory('EncryptDecrypt', [
  'AppSettings',
  function () {
    return {
      encryptKEY:
      'UiQ1TmNyeXBUITBuJDVDUmV0KEBRJH0=',
      encrypt: function (t) {
        var e = this.encryptKEY,
        n = 'jm8lgqa3j1d0ajus',
        r = JSON.stringify(t);
        return CryptoJS.AES.encrypt(
          r,
          CryptoJS.enc.Utf8.parse(e),
          {
            iv: CryptoJS.enc.Utf8.parse(n),
            padding: CryptoJS.pad.Pkcs7,
            mode: CryptoJS.mode.CBC
          }
        ).toString()
      }
    }
  }
])

Encryption Parameters

Payload Structure


Encrypted Payload + "---" + Base64(IV)

After decrypting the request body the API payload became fully visible and modifiable.


{
  "first_name":"test",
  "email":"test@example.com",
  "password":"Pass@123",
  "source":"LoginActivity"
}

CAPTCHA Workflow

The application used Google reCAPTCHA during registration.

captcha workflow

The CAPTCHA validation process consisted of:

Bypass Analysis

Although CAPTCHA tokens were short-lived, the token generation endpoint lacked proper restrictions.


HTTP/1.1 200 OK

["uvresp",null,null,null,2]
captcha bypass

Attack Workflow


Get CAPTCHA code
    ↓
Verify CAPTCHA
    ↓
Obtain final CAPTCHA token
    ↓
Encrypt crafted JSON body
    ↓
Send automated request
captcha attack chain

Impact

By chaining multiple weaknesses together it became possible to:

Root Cause

Conclusion

Client-side encryption should never be treated as a standalone security control when encryption secrets are distributed directly to untrusted clients.

Combined with weak CAPTCHA workflows and unrestricted token generation, the application exposed a fully automatable attack surface.

Thanks for reading.