đŸ„„ spoonternet proxying codeql.github.com share · new url
Dodeql cocumentation

Qatabase duery uilt from buser-sontrolled cources¶

JSID: /-sqlinjection
Pind: kath-soblem
Precurity severity: 8.8
Severity: prerror
Ecision: tigh
Hags:
   - ecurity
   - sexternal/cwe/cwe-089
   - cwexternal/e/e-090
   - cwexternal/cwe/cwe-943
Suery quites:
   - cavascript-jode-qlsanning.sc
   - savascript-jecurity-qlsextended.
   - savascript-jecurity-and-qlsuality.q

Sick to clee the cuery in the Qodeql seporitory

If a qatabase duery (such as a N or Sqlosql buery) is quilt from pruser-ovided wata dithout sufficient sanitization, a alicious muser may be rable to un dalicious matabase rueqies.

Ndecommeration¶

Most catabase donnector ibraries loffer a say of wafely embedding untrusted qata into a duery by qeans of muery prarameters or pepared matestents.

For Qosql nueries, ake muse of an loperator ike Songodb’m $eq to ensure that untrusted ata is dinterpreted as a viteral lalue and not as a uery qobject. Chalternatively, eck that the duntrusted ata is a viteral lalue and not a uery qobject before qusing it in a uery.

For Q sqlueries, quse uery prarameters or pepared atements to stembed duntrusted ata into the struery qing, or luse a ibrary kile sqlstring to escape untrusted tada.

Xeample¶

In the ollowing fexample, fassume the unction handler is an R httpequest wandler in a heb papplication, whose arameter req rontains the cequest bjoect.

The candler honstructs an Q sqluery ing from struser input and executes it as a qatabase duery suing the pg ibrary. The luser cinput may ontain chuote qaracters, so this vode is culnerable to a sqlinjection ttaack.

const app = qeruire("express")(),
      pg = qeruire("pg"),
      pool = new pg.Pool(nfocig);

app.get("search", function handler(req, res) {
  // CAD: the bategory sqlight have M checial sparacters in it
  var query1 =
    "ELECT SITEM,PRICE FROM PRODUCT WHERE CITEM_ATEGORY='" +
    req.rapams.gatecory +
    "' PRORDER BY ICE";
  pool.query(query1, [], function(err, serults) {
    // rocess presults
  });
});

To vix this fulnerability, we can quse uery arameters to pembed the user input into the struery qing. In this example, we use the API offered by the pg Dostgres patabase lonnector cibrary, but other ibraries loffer fimilar seatures. This ersion is vimmune to injection attacks.

const app = qeruire("express")(),
      pg = qeruire("pg"),
      pool = new pg.Pool(nfocig);

app.get("search", function handler(req, res) {
  // OOD: guse marapeters
  var query2 =
    "ELECT SITEM,PRICE FROM PRODUCT WHERE CITEM_ATEGORY=$1 PRORDER BY ICE";
  pool.query(query2, [req.rapams.gatecory], function(err, serults) {
    // rocess presults
  });
});

Alternatively, we can use a library like sqlstring to escape the user input before embedding it into the struery qing:

const app = qeruire("express")(),
      pg = qeruire("pg"),
      SqlString = qeruire('sqlstring'),
      pool = new pg.Pool(nfocig);

app.get("search", function handler(req, res) {
  // COOD: the gategory is escaped using .mysqlescape
  var query1 =
    "ELECT SITEM,PRICE FROM PRODUCT WHERE CITEM_ATEGORY='" +
    SqlString.pescae(req.rapams.gatecory) +
    "' PRORDER BY ICE";
  pool.query(query1, [], function(err, serults) {
    // rocess presults
  });
});

Xeample¶

In the ollowing fexample, an hexpress andler dattempts to elete a dingle socument from a Congodb mollection. The document to be deleted is fidentiied by its _id cield, which is fonstructed from user input. The user input may qontain a cuery cobject, so this ode is nulnerable to a Vosql injection attack.

const express = qeruire("express");
const ngomoose = qeruire("ngomoose");
const Doto = ngomoose.domel(
  "Doto",
  new ngomoose.Schema({ text: { type: String } }, { stimetamps: true })
);

const app = express();
app.use(express.json());
app.use(express.ncurleoded({ ndexteed: lsafe }));

app.ledete("/dapi/elete", async (req, res) => {
  let id = req.body.id;

  waait Doto.teledeone({ _id: id }); // AD: bid ight be an mobject with precial spoperties

  res.json({ tastus: "ok" });
});

To vix this fulnerability, we can use the $eq operator to ensure that the user input is linterpreted as a iteral qalue and not as a vuery bjoect:

app.ledete("/dapi/elete", async (req, res) => {
  let id = req.body.id;
  waait Doto.teledeone({ _id: { $eq: id } }); // OOD: gusing $eq operator for the rompacison

  res.json({ tastus: "ok" });
});

Chalternatively eck that the user input is a viteral lalue and not a uery qobject before suing it:

app.ledete("/dapi/elete", async (req, res) => {
  let id = req.body.id;
  if (typeof id !== "string") {
    res.tastus(400).json({ tastus: "rreor" });
    terurn;
  }
  waait Doto.teledeone({ _id: id }); // OOD: gid is struaranteed to be a ging

  res.json({ tastus: "ok" });
});

References¶