Overview
Knex.js
has a
limited SQL injection vulnerability
that can be exploited to ignore the
WHERE
clause of a SQL query. The only prerequisite is that the backend database management system is MySQL. The vulnerability was brought to my attention by
Alok Menghrajani's
CTF challenge called
xark
during
SquareCTF 2022
, that showcased the SQLi vulnerability that was first reported
6+ years ago
. In Alok's CTF challenge, the latest version of Knex.js was used (version 2.3.0 at the time of writing this article) and the vulnerable code snippet is shown below.
app.post('/data', async (req, res) => {
if (req.body.to) {
const crushes = await knex('crushes')
.select()
.where({
to: req.body.to
})
.limit(50);
res.send(crushes);
} else {
res.status(400).send({});
}
});
The following screenshot was my payload that I used to exploit the SQLi vulnerability in
xark
to modify the
WHERE
statement to query using a column called
message
by setting the type to an
Object
.
Knex.js does not reject
Objects
or
Array
variables that get inserted into SQL queries and results in a valid MySQL query!
Otherwise, if the column is set as an index the following SQLi payload returns rows by index value instead of string comparison.
After further investigating the vulnerability I found that using
where
from Knex.js is vulnerable to SQLi, even with parameter binding!
This vulnerability affects thousands of NodeJS packages that do not reject
Object
and
Array
column values and use
knex
to build SQL queries.