javascript.aws-lambda.security.mysql-sqli.mysql-sqli

profile photo of semgrepsemgrep
Author
unknown
Download Count*

Detected SQL statement that is tainted by $EVENT object. This could lead to SQL injection if the variable is user-controlled and not properly sanitized. In order to prevent SQL injection, use parameterized queries or prepared statements instead. You can use parameterized statements like so: connection.query('SELECT $1 from table', [userinput])

Run Locally

Run in CI

Defintion

rules:
  - id: mysql-sqli
    message: "Detected SQL statement that is tainted by `$EVENT` object. This could
      lead to SQL injection if the variable is user-controlled and not properly
      sanitized. In order to prevent SQL injection, use parameterized queries or
      prepared statements instead. You can use parameterized statements like so:
      `connection.query('SELECT $1 from table', [userinput])`"
    metadata:
      references:
        - https://www.npmjs.com/package/mysql2
      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
        - mysql
        - mysql2
      cwe2022-top25: true
      cwe2021-top25: true
      subcategory:
        - vuln
      likelihood: MEDIUM
      impact: HIGH
      confidence: MEDIUM
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
      vulnerability_class:
        - SQL Injection
    languages:
      - javascript
      - typescript
    severity: WARNING
    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:
          - focus-metavariable: $QUERY
          - pattern-either:
              - pattern: $POOL.query($QUERY, ...)
              - pattern: $POOL.execute($QUERY, ...)
          - pattern-either:
              - pattern-inside: |
                  require('mysql')
                  ...
              - pattern-inside: |
                  require('mysql2')
                  ...
              - pattern-inside: |
                  require('mysql2/promise')
                  ...
              - pattern-inside: |
                  import 'mysql'
                  ...
              - pattern-inside: |
                  import 'mysql2'
                  ...
              - pattern-inside: |
                  import 'mysql2/promise'
                  ...

Examples

mysql-sqli.js

var AWS = require('aws-sdk');
const mysql = require('mysql2');

exports.handler = async (event, context) => {
  console.log(event);
  var secretsManager = new AWS.SecretsManager();
  var secretId = event.arguments[0][2];
  const secret = await secretsManager.getSecretValue({
      SecretId: secretId
      }).promise();

  var secretJson = JSON.parse(secret.SecretString);

  var host = secretJson.host;
  var user = secretJson.username;
  var password = secretJson.password;

  let connectionConfig = {
    host: host,
    user: user,
    password: password,
    connectTimeout: 60000
  };

  var pool = await mysql.createPool(connectionConfig);
  var conn = pool.promise();

  var table = event.arguments[0][0];
  var columnName = event.arguments[0][1];

  var createStmt = 'create temporary table ' + table + '_jointemp (temp_seq int, '+ columnName + ' varchar(100)); ';
  // ruleid: mysql-sqli
  await conn.query(createStmt);


  var values = event.arguments.map((x, i) => "("+i+",'"+x[3]+"')");
  var insertStmt = 'insert into ' + table + '_jointemp(temp_seq, '+ columnName +') values ' + values.join(',') + ';';
  // ruleid: mysql-sqli
  await conn.query({sql: insertStmt, rowsAsArray: true});

  var selectStmt = 'select t2.* FROM ' + table + '_jointemp t1 LEFT OUTER JOIN ' + table + ' t2 using ('+ columnName +') order by temp_seq;'
  // ruleid: mysql-sqli
  const [results, fields] = await conn.execute(selectStmt);

  // ok: mysql-sqli
  const [results2, fields2] = await conn.execute('SELECT * FROM foobar WHERE id = ?', [columnName]);

  var res = {};
  if(results.length > 0){
    res = results.map((row) => JSON.stringify(row));
    }
    var response = JSON.stringify({"results": res});
    conn.end();
  return response;
};