50.5. Injections, SQL, and Others

The perennial number 1 on the OWASP Top Ten list is injection. Originally SQL Injection, but nowadays when databases might not be relational, also NoSQL, including the MongoDB used in these materials.

There serious issues with injections are all derived from the program taking the user entered data at face value. First look at the following MongoDB code:

Example 50.1. Querying the User Collection - I
db.user.find().pretty()
{
    "_id" : ObjectId("5e79fd3131f468145cb92c2b"),
    "email" : "nmla@iba.dk",
    "__v" : 0,
    "created" : ISODate("2020-03-24T12:29:37.690Z"),
    "firstName" : "Niels",
    "lastName" : "Larsen",
    "password" : "$2a$10$4qaT09Yyy9CdREncdaGGleA1b7pCjuWj7Do0kF8IZFfab1GXDuo0O"
}
{
    "_id" : ObjectId("5ea18bb90cb6c8975e345410"),
    "email" : "admin@iba.dk",
    "__v" : 0,
    "created" : ISODate("2020-04-23T12:36:09.718Z"),
    "firstName" : "admin",
    "lastName" : "Adm",
    "password" : "$2a$10$z.q1y1DtKVpQl9JAjksl7uq.Hyn6e0AX/4dBBqSkm5jbgi0MHENV."
}
{
    "_id" : ObjectId("5ea18bf90cb6c8975e345411"),
    "email" : "doe@iba.dk",
    "__v" : 0,
    "created" : ISODate("2020-04-23T12:37:13.799Z"),
    "firstName" : "anonymous",
    "lastName" : "Anon",
    "password" : "$2a$10$6tlgjPflyF0BqA2vYUB3WelLFVmUQjoy7Po1Y1oW1A7wsDKj.KKMu"
}

This is a read of all objects in the collection. Now if we supply a query parameter such as {email: "nmla@iba.dk"} we get

Example 50.2. Querying the User Collection - II
db.user.find({email: "nmla@iba.dk"}).pretty()
{
    "_id" : ObjectId("5e79fd3131f468145cb92c2b"),
    "email" : "nmla@iba.dk",
    "__v" : 0,
    "created" : ISODate("2020-03-24T12:29:37.690Z"),
    "firstName" : "Niels",
    "lastName" : "Larsen",
    "password" : "$2a$10$4qaT09Yyy9CdREncdaGGleA1b7pCjuWj7Do0kF8IZFfab1GXDuo0O"
}

Let us assume we do not know any users, we could enter the query param {email: {$ne:""}} to get

Example 50.3. Querying the User Collection - III
db.user.find({email: {$ne:""}}).pretty()
{
    "_id" : ObjectId("5ea18bb90cb6c8975e345410"),
    "email" : "admin@iba.dk",
    "__v" : 0,
    "created" : ISODate("2020-04-23T12:36:09.718Z"),
    "firstName" : "admin",
    "lastName" : "Adm",
    "password" : "$2a$10$z.q1y1DtKVpQl9JAjksl7uq.Hyn6e0AX/4dBBqSkm5jbgi0MHENV."
}
{
    "_id" : ObjectId("5ea18bf90cb6c8975e345411"),
    "email" : "doe@iba.dk",
    "__v" : 0,
    "created" : ISODate("2020-04-23T12:37:13.799Z"),
    "firstName" : "anonymous",
    "lastName" : "Anon",
    "password" : "$2a$10$6tlgjPflyF0BqA2vYUB3WelLFVmUQjoy7Po1Y1oW1A7wsDKj.KKMu"
}
{
    "_id" : ObjectId("5e79fd3131f468145cb92c2b"),
    "email" : "nmla@iba.dk",
    "__v" : 0,
    "created" : ISODate("2020-03-24T12:29:37.690Z"),
    "firstName" : "Niels",
    "lastName" : "Larsen",
    "password" : "$2a$10$4qaT09Yyy9CdREncdaGGleA1b7pCjuWj7Do0kF8IZFfab1GXDuo0O"
}

Now this is very interesting with a node/Express application in mind. In such a case we might do

User.find(query, null, sort);

Look at the way the query might be built.

let query = { email: req.body.email };

Whatever collection obj represents will be queried with the query parameters held in query. The normal way of getting the email address is letting the user key it into a form and we, the developers get it from req.body.email which we use directly to build out query object. Thus if the user is required to key in an email address we build

query = { email: "nmla@iba.dk"}

and we are at the second example above. But if the devious user enters {$ne: ""} or something like that, we build

query = {email: {$ne: ""}}

This is the cue to solving today's assignment, and indeed to play with challenging Mongo databases.

It goes without saying that any decent test of a web application includes asserting that injection attempts fail. This means sanitizing any user input. Period!