If you use Node.js and connect to MySQL with the popular mysql2 library, you should pay close attention to CVE-2024-21511. This recent security vulnerability is especially dangerous because it allows attackers to run arbitrary code on your server simply by sending a malicious timezone value. In this deep dive, we’ll break down how the bug works, see it in action, and explain how to protect your apps.
What is mysql2?
mysql2 is a widely used Node.js package for connecting to MySQL databases. It’s known for its performance and active maintenance, and it's often a drop-in replacement for the older mysql package.
Component: readCodeFor function, misusing the timezone parameter
- Impact: An attacker can inject and execute arbitrary MySQL code, which can sometimes be escalated to arbitrary command execution depending on your MySQL server configuration.
The Technical Deep Dive
At the heart of CVE-2024-21511 is the way mysql2’s readCodeFor() function uses the user-supplied timezone value without proper sanitization. Instead of validating the string to ensure it only contains safe timezone names (like "+00:00", "UTC", etc.), any input gets concatenated directly into a native MySQL date/time function call.
Consider this simplified example excerpt
function readCodeFor(timezone) {
// ...
return CONVERT_TZ(now(), 'SYSTEM', '${timezone}');
}
If timezone is user-controlled (e.g., passed from a client request), anyone could supply malicious payloads. For example, the following timezone string:
utc'); DROP TABLE users; --
would get inserted like this
CONVERT_TZ(now(), 'SYSTEM', 'utc'); DROP TABLE users; --')
Now, the attacker executes an additional SQL command—in this case, dropping your users table! While most real-world cases won't allow multiple statement execution by default, unpatched setups or unsafe configs might.
Depending on your MySQL server and permissions, attackers could exploit this further—especially if combined with other vulnerabilities.
Here’s a minimal Node.js snippet showing how a malicious timezone could result in injected code
const mysql = require('mysql2');
// Fake user input
const dangerousTimezone = "utc'); SELECT SLEEP(10); --";
const pool = mysql.createPool({
host: 'localhost',
user: 'test',
password: 'testpw',
database: 'testdb'
});
const query = `
SELECT CONVERT_TZ(now(), 'SYSTEM', '${dangerousTimezone}');
`;
pool.query(query, function(err, results) {
if (err) throw err;
console.log(results);
pool.end();
});
What happens here?
- The attacker sets the timezone to inject an extra SQL command (SELECT SLEEP(10);) after ending the timezone string and commenting out the rest.
Data Tampering: Malicious changes or deletions, like DROP TABLE or UPDATE.
- Remote Code Execution (rare): If your MySQL server allows user-defined functions with file system access, or you use multiple statement modes, the attacker might escalate their attack.
- Service Denial: Injecting SLEEP() or similar functions could make your database (and app) freeze.
The Fix
Upgrade!
The maintainers have fixed this in mysql2 v3.9.7. Update your package.json and lockfile and redeploy.
npm install mysql2@latest
# or, if you use yarn
yarn add mysql2@latest
The patched version properly sanitizes timezone inputs and parameterizes statements, so user input can't break out of the query.
References
- GitHub Advisory - GHSA-xxxxx
- NVD Entry CVE-2024-21511
- mysql2 Changelog
Best Practices to Stay Safe
- Never Trust User Input: Always validate, sanitize, or better—use parameterized queries for every user-supplied value.
- Patch Quickly: Subscribe to npm audit reports and GitHub dependabot to stay ahead of vulnerabilities.
Final Thoughts
CVE-2024-21511 is a reminder that even mature, widely trusted libraries can slip up in ways that put your whole app at risk—especially when user input isn’t strictly validated. If you’re running any version of mysql2 before 3.9.7, update now and check your code for unsafe query construction.
Timeline
Published on: 04/23/2024 05:15:48 UTC
Last modified on: 04/23/2024 12:52:09 UTC