HIGH padding oraclefeathersjscockroachdb

Padding Oracle in Feathersjs with Cockroachdb

Padding Oracle in Feathersjs with Cockroachdb — how this specific combination creates or exposes the vulnerability

A padding oracle in a Feathersjs service using Cockroachdb typically arises when error handling for encrypted data inadvertently reveals whether ciphertext is valid before decryption. If Feathersjs hooks or services call a Cockroachdb query with user-supplied encrypted payloads and the application returns different errors or timing behavior for invalid padding versus other failures, an attacker can iteratively decrypt or sign arbitrary data.

Consider a Feathersjs hook that decrypts a JWE stored in a Cockroachdb column. If the hook does not use constant-time validation and instead performs decrypt-then-authenticate patterns, an attacker can supply modified ciphertexts and observe differences in HTTP status codes or response times. Cockroachdb itself does not introduce padding issues, but queries that return distinct errors—such as row not found versus decryption failure—create an oracle surface when combined with misconfigured Feathersjs error handling.

For example, a Feathersjs before hook that directly passes encrypted input to a decryption routine and then queries Cockroachdb with the decrypted user ID can expose behavior via timing or error messages:

const jwt = require('jsonwebtoken');
const feathers = require('@feathersjs/feathers');
const app = feathers();
app.configure(require('@feathersjs/transport-commons'));

app.use('/records', {
  async create(data) {
    const { token } = data;
    let decrypted;
    try {
      // Unsafe: error messages differ between padding failures and other issues
      decrypted = jwt.verify(token, process.env.JWT_SECRET, { algorithms: ['HS256'] });
    } catch (error) {
      // If padding errors are surfaced differently, this becomes an oracle
      throw { message: 'Invalid token', code: 401 };
    }
    const { id } = decrypted;
    // Cockroachdb query that may return different errors based on prior decryption behavior
    const result = await app.service('records').Model.findOne({ where: { id } });
    if (!result) {
      throw { message: 'Record not found', code: 404 };
    }
    return result;
  }
});

In this pattern, if the JWT verification fails due to bad padding, the error path may differ from a missing record or a database constraint violation. An attacker can exploit these distinctions by observing HTTP status codes or response timing, effectively treating the Feathersjs+Cockroachdb stack as a padding oracle. This is especially risky when the service uses AES-CBC without proper AEAD and does not standardize error responses for all failure modes.

Another vector involves stored procedures or ORM queries in Cockroachdb that return distinct errors for malformed encrypted blobs. If Feathersjs relays these errors without normalization, the application unintentionally exposes whether a ciphertext’s padding is valid before higher-level checks complete.

Cockroachdb-Specific Remediation in Feathersjs — concrete code fixes

Remediation focuses on ensuring that error handling and decryption workflows do not leak padding validity. In Feathersjs, normalize all failure paths to return the same generic error and use constant-time cryptographic operations. Avoid decrypt-then-authenticate; prefer authenticated encryption with associated data (AEAD) such as AES-GCM where available. When interacting with Cockroachdb, ensure queries do not depend on the validity of the ciphertext before performing decryption.

Use a consistent error response structure and delay to mitigate timing attacks. Below is a hardened Feathersjs create hook that processes encrypted input, queries Cockroachdb via an ORM, and avoids padding oracle conditions:

const crypto = require('crypto');
const feathers = require('@feathersjs/feathers');
const app = feathers();
const { Sequelize, SequelizeCockroachdb } = require('@feathersjs/sequelize');

// Constant-time comparison helper
function safeCompare(a, b) {
  return crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b));
}

// Use AEAD (e.g., AES-GCM) for encryption; here we simulate decryption with proper error handling
async function decryptPayload(encrypted) {
  const iv = encrypted.slice(0, 12);
  const tag = encrypted.slice(-16);
  const ciphertext = encrypted.slice(12, -16);
  const key = Buffer.from(process.env.ENC_KEY, 'hex');
  try {
    const decipher = crypto.createDecipheriv('aes-256-gcm', key, iv);
    decipher.setAuthTag(tag);
    const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
    return decrypted.toString('utf8');
  } catch (err) {
    // Always throw a generic error to avoid padding oracle
    throw new Error('Invalid data');
  }
}

app.use('/records', {
  async create(data) {
    const { encrypted } = data;
    let payload;
    try {
      payload = await decryptPayload(Buffer.from(encrypted, 'base64'));
    } catch (error) {
      // Generic error prevents oracle; log internally for monitoring
      console.error('Decryption failure');
      throw { message: 'Bad request', code: 400 };
    }
    let id;
    try {
      id = JSON.parse(payload).id;
    } catch (err) {
      throw { message: 'Bad request', code: 400 };
    }
    // Cockroachdb query with parameterized inputs to avoid injection and timing leaks
    const result = await app.service('records').Model.findOne({
      where: { id },
      type: SequelizeCockroachdb
    });
    if (!result) {
      throw { message: 'Not found', code: 404 };
    }
    return result;
  }
});

Key points:

  • Use AEAD modes (e.g., AES-GCM) via crypto.createDecipheriv with an authentication tag to eliminate padding altogether.
  • Catch all decryption errors and throw a single, generic message so the application does not distinguish between padding failures and other issues.
  • Ensure Cockroachdb queries rely on parsed, validated data rather than on the success or failure of low-level decryption steps.
  • Consider integrating the middleBrick CLI (middlebrick scan <url>) to validate that your Feathersjs endpoints do not exhibit padding oracle characteristics during development.

Frequently Asked Questions

Can middleBrick detect padding oracle issues in a Feathersjs+Cockroachdb setup?
Yes. middleBrick scans unauthenticated attack surfaces and includes input validation and unsafe consumption checks that can flag abnormal error handling or timing behaviors that may indicate an oracle.
Does using Cockroachdb change how I should handle encryption in Feathersjs?
Cockroachdb does not introduce padding issues, but you should avoid leaking query or decryption errors. Use constant-time operations and consistent error responses regardless of the database.