javascript.express.security.injection.tainted-sql-string.tainted-sql-string

Author
unknown
Download Count*
License
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:
owasp:
- A07:2017 - Cross-Site Scripting (XSS)
- A03:2021 - Injection
cwe:
- "CWE-79: Improper Neutralization of Input During Web Page Generation
('Cross-site Scripting')"
references:
- https://owasp.org/www-community/attacks/SQL_Injection
category: security
technology:
- express
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
cwe2022-top25: true
cwe2021-top25: true
subcategory:
- vuln
likelihood: HIGH
impact: MEDIUM
confidence: MEDIUM
vulnerability_class:
- Cross-Site-Scripting (XSS)
languages:
- javascript
- typescript
severity: ERROR
mode: taint
pattern-sources:
- patterns:
- pattern-either:
- pattern-inside: function ... ($REQ, $RES) {...}
- pattern-inside: function ... ($REQ, $RES, $NEXT) {...}
- pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES) {...})
- pattern-inside: $APP.$METHOD(..., function $FUNC($REQ, $RES, $NEXT) {...})
- metavariable-regex:
metavariable: $METHOD
regex: ^(get|post|put|head|delete|options)$
- pattern-either:
- pattern: $REQ.query
- pattern: $REQ.body
- pattern: $REQ.params
- pattern: $REQ.cookies
- pattern: $REQ.headers
- patterns:
- pattern-either:
- pattern-inside: |
({ $REQ }: Request,$RES: Response, $NEXT: NextFunction) =>
{...}
- pattern-inside: |
({ $REQ }: Request,$RES: Response) => {...}
- focus-metavariable: $REQ
- pattern-either:
- pattern: params
- pattern: query
- pattern: cookies
- pattern: headers
- pattern: body
pattern-sinks:
- patterns:
- pattern-either:
- patterns:
- pattern-either:
- pattern-inside: |
"$SQLSTR" + $EXPR
- pattern-inside: |
"$SQLSTR".concat($EXPR)
- pattern: util.format($SQLSTR, $EXPR)
- pattern: |
`$SQLSTR${$EXPR}...`
- metavariable-regex:
metavariable: $SQLSTR
regex: .*\b(?i)(select|delete|insert|create|update|alter|drop)\b.*
- focus-metavariable: $EXPR
Examples
tainted-sql-string.js
const express = require('express')
const app = express()
const port = 3000
const { Sequelize } = require('sequelize');
const sequelize = new Sequelize('sqlite::memory:')
const util = require('util')
app.get('/test', (req, res) => {
// ruleid: tainted-sql-string
const query = "SELECT * FROM `users`" + " WHERE id = '" + req.query.message + "'"
const [results, metadata] = await sequelize.query(query);
res.send(results)
})
app.get('/test1', (req, res) => {
// ruleid: tainted-sql-string
const [results, metadata] = await sequelize.query("SELECT * FROM `users`" + " WHERE id = '" + req.query.message + "'");
res.send(results)
})
app.get('/test2', (req, res) => {
// ruleid: tainted-sql-string
let query = `SELECT * FROM users WHERE id = '${req.query.message}'`
const [results, metadata] = await sequelize.query(query);
res.send(results)
})
app.get('/test3', (req, res) => {
let query = "SELECT * FROM `users` WHERE id = '"
// ruleid: tainted-sql-string
query = query.concat(req.query.message)
query = query.concat("'")
const [results, metadata] = await sequelize.query(query);
res.send(results)
})
app.get('/test4', (req, res) => {
// ruleid: tainted-sql-string
const query = util.format("SELECT * FROM users WHERE id = '%s'", req.query.message)
const [results, metadata] = await sequelize.query(query);
res.send(results)
})
app.get('/ok', async (req, res) => {
// ok: tainted-sql-string
res.send("message: " + req.query.message);
})
app.post('/ok2', async (req, res) => {
// ok: tainted-sql-string
res.send(`message: ${req.query.message}`);
})
app.post('/ok3', async (req, res) => {
// ok: tainted-sql-string
var data = "message: " + req.query.message;
res.send(data);
})
app.post('/ok4', async (req, res) => {
var data = "message: "
// ok: tainted-sql-string
data = data.concat(req.query.message)
res.send(data);
})
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`))
Short Link: https://sg.run/66ZL