javascript.aws-lambda.security.tainted-sql-string.tainted-sql-string

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Detected user input used to manually construct a SQL string. This is usually bad practice because manual construction could accidentally result in a SQL injection. An attacker could use a SQL injection to steal or modify contents of the database. Instead, use a parameterized query which is available by default in most database engines. Alternatively, consider using an object-relational mapper (ORM) such as Sequelize which will protect your queries.

Run Locally

Run in CI

Defintion

rules:
  - id: tainted-sql-string
    message: Detected user input used to manually construct a SQL string. This is
      usually bad practice because manual construction could accidentally result
      in a SQL injection. An attacker could use a SQL injection to steal or
      modify contents of the database. Instead, use a parameterized query which
      is available by default in most database engines. Alternatively, consider
      using an object-relational mapper (ORM) such as Sequelize which will
      protect your queries.
    metadata:
      references:
        - https://owasp.org/www-community/attacks/SQL_Injection
      category: security
      owasp:
        - A01:2017 - Injection
        - A03:2021 - Injection
      cwe:
        - "CWE-89: Improper Neutralization of Special Elements used in an SQL
          Command ('SQL Injection')"
      technology:
        - aws-lambda
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: LOW
      impact: MEDIUM
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - SQL Injection
    languages:
      - javascript
      - typescript
    severity: ERROR
    mode: taint
    pattern-sources:
      - patterns:
          - pattern-either:
              - pattern-inside: |
                  exports.handler = function ($EVENT, ...) {
                    ...
                  }
              - pattern-inside: |
                  function $FUNC ($EVENT, ...) {...}
                  ...
                  exports.handler = $FUNC
              - pattern-inside: |
                  $FUNC = function ($EVENT, ...) {...}
                  ...
                  exports.handler = $FUNC
          - pattern: $EVENT
    pattern-sinks:
      - patterns:
          - pattern-either:
              - patterns:
                  - pattern-either:
                      - pattern: |
                          "$SQLSTR" + $EXPR
                      - pattern: |
                          "$SQLSTR".concat(...)
                      - pattern: util.format($SQLSTR, ...)
                  - metavariable-regex:
                      metavariable: $SQLSTR
                      regex: .*\b(?i)(select|delete|insert|create|update|alter|drop)\b.*
              - patterns:
                  - pattern: |
                      `...${...}...`
                  - pattern-regex: >
                      .*\b(?i)(select|delete|insert|create|update|alter|drop)\b.*
          - pattern-not-inside: |
              console.$LOG(...)

Examples

tainted-sql-string.js

let response;

const prettyPrint = (ob) => JSON.stringify(ob, null, 2).replace('\'','');

const { Client } = require('pg');
exports.handler = async function (event, context) {
  const client = new Client();
  await client.connect();

  // ruleid: tainted-sql-string
  const query = `INSERT INTO messages (body) VALUES ('${prettyPrint(event)}');`;

  try {
    await client.query(query)
    
    // ruleid: tainted-sql-string
    await client.query("INSERT INTO messages (body) VALUES ('" + prettyPrint(event) + "');")

    // ok: tainted-sql-string
    await client.query('INSERT INTO messages (body, message) VALUES ($1, $2);', [prettyPrint(event), records[0]]);

    // ok: tainted-sql-string
    const query2 = 'INSERT INTO messages ' + '(body, message) VALUES ($1, $2);';
    await client.query(query2, [prettyPrint(event), records[0]]);

    // ok: tainted-sql-string
    console.log(`INSERT INTO messages (body) VALUES ('${event['smth']});`);

    await client.end();
  } catch (error) {
    console.log('Could not add row to postgres, soz');
    console.log(error);
  }

  return { key: JSON.stringify(records) };
};