CVE-2024-21508 - Remote Code Execution in `mysql2` < 3.9.4 Explained

A fresh and critically important vulnerability has surfaced in the Node.js world. If you’re building with mysql2 and haven’t updated lately, this post is for you. Let's break down CVE-2024-21508, how it works, and what you should do about it—using clear language, practical code, and links for deeper reading.

What Is CVE-2024-21508?

CVE-2024-21508 is a Remote Code Execution (RCE) vulnerability discovered in all versions of the mysql2 library before 3.9.4. The flaw exists in how the readCodeFor function handles options—specifically, the supportBigNumbers and bigNumberStrings flags. The library failed to properly validate these user-controlled values, letting attackers execute arbitrary code on your server.

Why Does It Matter?

RCE is as bad as it sounds—attackers can run any code they like on your system. If you’re accepting any user input and pass it directly (or indirectly) into the affected mysql2 options, you could be in trouble.

If an attacker can tweak the values of supportBigNumbers or bigNumberStrings to something unexpected, they can exploit this to inject code.

The Technical Details

Let’s look at a simplified example of vulnerable code.

Imagine you have backend code like this

const mysql = require('mysql2');

const dbOptions = {
  host: 'localhost',
  user: 'root',
  password: 'secret',
  database: 'unsafe',
  // WARNING: These are directly from user input, which is unsafe!
  supportBigNumbers: req.body.supportBigNumbers,
  bigNumberStrings: req.body.bigNumberStrings,
};

const connection = mysql.createConnection(dbOptions);

If req.body.supportBigNumbers or req.body.bigNumberStrings is maliciously crafted, they could trigger remote code execution.

How The Exploit Works

The underlying issue is a lack of input validation inside mysql2’s readCodeFor function. If the crafted input gets passed in, readCodeFor can be tricked into *executing injected JavaScript code*. Attackers could pass in unexpected objects or functions instead of booleans.

Suppose an attacker sends this payload in a POST request

{
  "supportBigNumbers": {},
  "bigNumberStrings": "evil_function()"
}

If mysql2 uses these directly, the attacker could force code to run in your process.

Proof of Concept

Here's a minimal demonstration. This is for educational purposes only—never run untrusted code.

// Simulating part of the attack
const mysql = require('mysql2');

// Simulating attacker-supplied values
const userInput = {
  supportBigNumbers: {}, // Not a boolean!
  bigNumberStrings: "console.log('RCE!')",
};

const dbOptions = {
  host: 'localhost',
  user: 'root',
  password: 'example',
  database: 'demo',
  supportBigNumbers: userInput.supportBigNumbers,
  bigNumberStrings: userInput.bigNumberStrings,
};

const connection = mysql.createConnection(dbOptions);

// Depending on the exact exploit, the attacker's code may run in the process.

Note: Modern patched versions will reject these types, but older versions (<3.9.4) are vulnerable.

1. Upgrade Immediately

Update your mysql2 dependency to version 3.9.4 or later.

npm install mysql2@latest

Or set in your package.json

"dependencies": {
  "mysql2": "^3.9.4"
}

2. Validate All Inputs

Never trust user input, especially if you pass it into configuration objects. Type-check and sanitize all fields.

// Safe pattern: only allow booleans, reject anything else
supportBigNumbers: typeof userInput.supportBigNumbers === 'boolean' ? userInput.supportBigNumbers : false,
bigNumberStrings: typeof userInput.bigNumberStrings === 'boolean' ? userInput.bigNumberStrings : false,

3. Monitor Vulnerabilities Regularly

Use npm audit or Snyk to scan dependencies for security holes.

Original References

- Original CVE Report
- mysql2 package on npmjs
- mysql2 GitHub Security Advisory
- Patch Commit

Always validate and sanitize configuration coming from user input.

Keeping your dependencies up to date and validating your configuration settings isn’t just a best practice—it’s essential for keeping attackers out. Stay safe!

Timeline

Published on: 04/11/2024 05:15:47 UTC
Last modified on: 06/18/2024 20:18:04 UTC