mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
update ATM NosqlInjection and SqlInjection query docs
This commit is contained in:
@@ -1,50 +1,62 @@
|
||||
# NoSQL database query built from user-controlled sources (experimental)
|
||||
If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
|
||||
If a database query is built from user-provided data without sufficient sanitization, a user may be able to run malicious database queries.
|
||||
|
||||
Note: This CodeQL query is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
|
||||
|
||||
|
||||
## Recommendation
|
||||
Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements.
|
||||
|
||||
For NoSQL queries, make use of an operator like MongoDB's `$eq` to ensure that untrusted data is interpreted as a literal value and not as a query object.
|
||||
|
||||
Ensure that untrusted data is interpreted as a literal value and not as a query object, eg., by using an operator like MongoDB's `$eq`.
|
||||
|
||||
## Example
|
||||
In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object.
|
||||
In the following example, an `express.js` application is defining two endpoints that permit a user to query a MongoDB database.
|
||||
|
||||
The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters.
|
||||
In each case, the handler constructs two copies of the same query involving user input taken from the request object. In both handlers, the input is parsed using the `body-parser` library, which will transform the request data that arrives as a string to JSON objects.
|
||||
|
||||
In the first case, the query string `query1` is built by directly concatenating a user-supplied request parameter with some string literals. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack.
|
||||
In the first case, `/search1`, the input is used as a query object. This means that a malicious user is able to inject queries that select more data than the developer intended.
|
||||
|
||||
In the second case, the parameter is embedded into the query string `query2` using query parameters. In this example, we use the API offered by the `pg` Postgres database connector library, but other libraries offer similar features. This version is immune to injection attacks.
|
||||
In the second case, `/search2`, parts of the input are converted to a string representation and then used with the `$eq` operator to construct a query object.
|
||||
|
||||
|
||||
```javascript
|
||||
const app = require("express")(),
|
||||
pg = require("pg"),
|
||||
pool = new pg.Pool(config);
|
||||
mongodb = require("mongodb"),
|
||||
bodyParser = require('body-parser');
|
||||
|
||||
app.get("search", function handler(req, res) {
|
||||
// BAD: the category might have SQL special characters in it
|
||||
var query1 =
|
||||
"SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY='" +
|
||||
req.params.category +
|
||||
"' ORDER BY PRICE";
|
||||
pool.query(query1, [], function(err, results) {
|
||||
// process results
|
||||
});
|
||||
const client = new MongoClient('mongodb://localhost:27017/test');
|
||||
|
||||
// GOOD: use parameters
|
||||
var query2 =
|
||||
"SELECT ITEM,PRICE FROM PRODUCT WHERE ITEM_CATEGORY=$1" + " ORDER BY PRICE";
|
||||
pool.query(query2, [req.params.category], function(err, results) {
|
||||
// process results
|
||||
});
|
||||
app.use(bodyParser.urlencoded({ extended: true }));
|
||||
|
||||
app.get("/search1", async function handler(req, res) {
|
||||
await client.connect();
|
||||
const db = client.db('test');
|
||||
const doc = db.collection('doc');
|
||||
|
||||
const result = doc.find({
|
||||
// BAD:
|
||||
// This is vulnerable.
|
||||
// Eg., req.body.title might be the object { $ne: "foobarbaz" }, and the
|
||||
// endpoint would return all data.
|
||||
title: req.body.title
|
||||
});
|
||||
|
||||
res.send(await result);
|
||||
});
|
||||
|
||||
app.get("/search2", async function handler(req, res) {
|
||||
await client.connect();
|
||||
const db = client.db('test');
|
||||
const doc = db.collection('doc');
|
||||
|
||||
// GOOD:
|
||||
// The input is converted to a string, and matched using the $eq operator.
|
||||
// At most one datum is returned.
|
||||
const result = await doc.find({ title: { $eq: `${req.body.title}` } });
|
||||
|
||||
res.send(await result);
|
||||
});
|
||||
```
|
||||
|
||||
## References
|
||||
* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
|
||||
* Acunetix Blog: [NoSQL Injections and How to Avoid Them](https://www.acunetix.com/blog/web-security-zone/nosql-injections/).
|
||||
* MongoDB: [$eq operator](https://docs.mongodb.com/manual/reference/operator/query/eq).
|
||||
* MongoDB: [$ne operator](https://docs.mongodb.com/manual/reference/operator/query/ne).
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# SQL database query built from user-controlled sources (experimental)
|
||||
If a database query (such as a SQL or NoSQL query) is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
|
||||
If a SQL query is built from user-provided data without sufficient sanitization, a malicious user may be able to run malicious database queries.
|
||||
|
||||
Note: This CodeQL query is an experimental query. Experimental queries generate alerts using machine learning. They might include more false positives but they will improve over time.
|
||||
|
||||
@@ -7,11 +7,8 @@ Note: This CodeQL query is an experimental query. Experimental queries generate
|
||||
## Recommendation
|
||||
Most database connector libraries offer a way of safely embedding untrusted data into a query by means of query parameters or prepared statements.
|
||||
|
||||
For NoSQL queries, make use of an operator like MongoDB's `$eq` to ensure that untrusted data is interpreted as a literal value and not as a query object.
|
||||
|
||||
|
||||
## Example
|
||||
In the following example, assume the function `handler` is an HTTP request handler in a web application, whose parameter `req` contains the request object.
|
||||
In the following example, an `express.js` application is defining two endpoints that permit a user to query a postgres database.
|
||||
|
||||
The handler constructs two copies of the same SQL query involving user input taken from the request object, once unsafely using string concatenation, and once safely using query parameters.
|
||||
|
||||
@@ -47,4 +44,3 @@ app.get("search", function handler(req, res) {
|
||||
|
||||
## References
|
||||
* Wikipedia: [SQL injection](https://en.wikipedia.org/wiki/SQL_injection).
|
||||
* MongoDB: [$eq operator](https://docs.mongodb.com/manual/reference/operator/query/eq).
|
||||
|
||||
Reference in New Issue
Block a user