question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

String `id` field + bulkCreate does not escape the String primary key—SQL injection vulnerability?

See original GitHub issue

Issue Description

Due to #11714, I have decided to just name my String primaryKey id. However, when using a String primary key with bulkCreate, it does not add the quotation marks to the String that gets inserted, which blows up.

The relevant piece of my config.json:

{
    "development": {
        "username": null,
        "password": null,
        "database": "experiment",
        "host": "127.0.0.1",
        "dialect": "postgres"
    }
}

After initializing the project, I ran npx sequelize-cli models:generate --name Foo --attributes foo:string,bar:string,quux:integer and edited the migrations/…-create-foo.js file as such:

module.exports = {
  up: (queryInterface, Sequelize) => {
    return queryInterface.createTable('Foos', {
      id: {
        allowNull: false,
        autoIncrement: false,
        primaryKey: true,
        type: Sequelize.STRING
      },
      bar: {
        type: Sequelize.STRING
      },
      quux: {
        type: Sequelize.INTEGER
      },
      createdAt: {
        allowNull: false,
        type: Sequelize.DATE
      },
      updatedAt: {
        allowNull: false,
        type: Sequelize.DATE
      }
    });
  },
  down: (queryInterface, Sequelize) => {
    return queryInterface.dropTable('Foos');
  }
};

Small test script:

const db = require('./models/index.js');

const Foo = db.Foo;

Foo.bulkCreate([{ id: "Foo", bar: "Bar", quux: 42 }]).then(() => console.log("It worked!"));

What do you expect to happen?

It worked!

What is actually happening?

The generated SQL inserted Foo directly into the query and does not add the quotation marks with it.

Executing (default): INSERT INTO "Foos" ("id","bar","quux","createdAt","updatedAt") VALUES (Foo,'Bar',42,'2019-12-02 02:29:43.780 +00:00','2019-12-02 02:29:43.780 +00:00') RETURNING *;

Unhandled rejection SequelizeDatabaseError: column "foo" does not exist
    at Query.formatError (/Users/Mitch/sequelize/sequelize-bug/node_modules/sequelize/lib/dialects/postgres/query.js:366:16)
    at query.catch.err (/Users/Mitch/sequelize/sequelize-bug/node_modules/sequelize/lib/dialects/postgres/query.js:72:18)
    at tryCatcher (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/promise.js:547:31)
    at Promise._settlePromise (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/promise.js:604:18)
    at Promise._settlePromise0 (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/promise.js:649:10)
    at Promise._settlePromises (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/promise.js:725:18)
    at _drainQueueStep (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/async.js:93:12)
    at _drainQueue (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/async.js:86:9)
    at Async._drainQueues (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/async.js:102:5)
    at Immediate.Async.drainQueues [as _onImmediate] (/Users/Mitch/sequelize/sequelize-bug/node_modules/bluebird/js/release/async.js:15:14)
    at runCallback (timers.js:705:18)
    at tryOnImmediate (timers.js:676:5)
    at processImmediate (timers.js:658:5)

Additional context

This seems like a weird corner-case, as I’ve only seen this behavior with bulkCreate paired with a string id field (that in this case at least is the primary key). I’m not sure if there are other weird situations where something like this might happen. This also definitely feels like it’s rife for a SQL injection attack.

Follow-up: contrived example, but this SQL injection will work.

Foo.bulkCreate([
    { 
        id: "'Foo', '1', 2, '2019-12-02 04:05:46.971 +00:00', '2019-12-02 04:05:46.971 +00:00'); \
            select count(*) from \"Foos\"; \
            drop table \"Foos\"; \
            insert into \"Foos\" (\"id\", \"bar\", \"quux\", \"createdAt\", \"updatedAt\") values ('hello'", 
        bar: "Bar", 
        quux: 42 
    }
]).then(() => console.log("It worked!"));

Environment

  • Sequelize version: 5.21.2
  • Node.js version: 10.16.3
  • Operating System: macOS Mojave 10.14.5

Issue Template Checklist

How does this problem relate to dialects?

  • I don’t know, I was using Postgres, with connector library version pg@7.21.1 and database version PostgreSQL 11.3

Would you be willing to resolve this issue by submitting a Pull Request?

  • Yes, I have the time but I don’t know how to start, I would need guidance. --> (bulkCreate isn’t the easiest thing to parse 😃 )

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
papbcommented, Jan 16, 2020

I will close this in favor of #11830 now since your original problem was solved.

0reactions
papbcommented, Jan 16, 2020

Hi @alirizwan, thanks for helping @gamburgm solve this issue 😃

As for your last comment, @gamburgm, I agree that the current ‘developer experience’ on this is quite messy. I have opened #11830 with a different idea on how to improve this. Please share your thoughts 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

SQL Injection Prevention - OWASP Cheat Sheet Series
To avoid SQL injection flaws is simple. Developers need to either: a) stop writing dynamic queries with string concatenation; and/or b) prevent user...
Read more >
Which characters are actually capable of causing SQL ...
The short answer to your question is, as far as I'm aware, no - such characters (even if unescaped) will not terminate the...
Read more >
SQL Injection in Java and How to Easily Prevent it | DigitalOcean
In simple words, SQL Injection means injecting/inserting SQL code in a query via user-inputted data. It can occur in any applications using ...
Read more >
SQL Injection Tutorial - w3resource
SQL injection is a technique (like other web attack mechanisms) to attack data ... Injection through cookie fields contains attack strings.
Read more >
Data Security: Stop SQL Injection Attacks Before They Stop You
The basic idea behind a SQL injection attack is this: you create a Web page ... Using all of these techniques not just...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found