mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
Add query for detecting potential DOS form a tainted .length property
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
nodes
|
||||
| TaintedLengthBad.js:8:10:8:17 | req.body |
|
||||
| TaintedLengthBad.js:10:12:10:19 | req.body |
|
||||
| TaintedLengthBad.js:12:22:12:29 | req.body |
|
||||
| TaintedLengthBad.js:14:16:14:23 | req.body |
|
||||
| TaintedLengthBad.js:17:18:17:20 | val |
|
||||
| TaintedLengthBad.js:21:22:21:24 | val |
|
||||
| TaintedLengthBad.js:26:20:26:22 | val |
|
||||
| TaintedLengthBad.js:30:13:30:15 | val |
|
||||
| TaintedLengthBad.js:37:30:37:32 | val |
|
||||
| TaintedLengthBad.js:40:12:40:14 | val |
|
||||
| TaintedLengthBad.js:49:24:49:26 | val |
|
||||
| TaintedLengthBad.js:54:22:54:24 | val |
|
||||
| TaintedLengthExitBad.js:8:9:8:16 | req.body |
|
||||
| TaintedLengthExitBad.js:10:9:10:16 | req.body |
|
||||
| TaintedLengthExitBad.js:12:10:12:17 | req.body |
|
||||
| TaintedLengthExitBad.js:14:14:14:21 | req.body |
|
||||
| TaintedLengthExitBad.js:17:17:17:19 | val |
|
||||
| TaintedLengthExitBad.js:20:22:20:24 | val |
|
||||
| TaintedLengthExitBad.js:30:17:30:19 | val |
|
||||
| TaintedLengthExitBad.js:33:22:33:24 | val |
|
||||
| TaintedLengthExitBad.js:46:18:46:20 | val |
|
||||
| TaintedLengthExitBad.js:49:22:49:24 | val |
|
||||
| TaintedLengthExitBad.js:59:22:59:24 | val |
|
||||
| TaintedLengthExitBad.js:60:8:60:10 | val |
|
||||
| TaintedLengthLodash.js:9:10:9:17 | req.body |
|
||||
| TaintedLengthLodash.js:14:18:14:20 | val |
|
||||
| TaintedLengthLodash.js:15:10:15:12 | val |
|
||||
edges
|
||||
| TaintedLengthBad.js:8:10:8:17 | req.body | TaintedLengthBad.js:17:18:17:20 | val |
|
||||
| TaintedLengthBad.js:10:12:10:19 | req.body | TaintedLengthBad.js:26:20:26:22 | val |
|
||||
| TaintedLengthBad.js:12:22:12:29 | req.body | TaintedLengthBad.js:37:30:37:32 | val |
|
||||
| TaintedLengthBad.js:14:16:14:23 | req.body | TaintedLengthBad.js:49:24:49:26 | val |
|
||||
| TaintedLengthBad.js:17:18:17:20 | val | TaintedLengthBad.js:21:22:21:24 | val |
|
||||
| TaintedLengthBad.js:26:20:26:22 | val | TaintedLengthBad.js:30:13:30:15 | val |
|
||||
| TaintedLengthBad.js:37:30:37:32 | val | TaintedLengthBad.js:40:12:40:14 | val |
|
||||
| TaintedLengthBad.js:49:24:49:26 | val | TaintedLengthBad.js:54:22:54:24 | val |
|
||||
| TaintedLengthExitBad.js:8:9:8:16 | req.body | TaintedLengthExitBad.js:17:17:17:19 | val |
|
||||
| TaintedLengthExitBad.js:10:9:10:16 | req.body | TaintedLengthExitBad.js:30:17:30:19 | val |
|
||||
| TaintedLengthExitBad.js:12:10:12:17 | req.body | TaintedLengthExitBad.js:46:18:46:20 | val |
|
||||
| TaintedLengthExitBad.js:14:14:14:21 | req.body | TaintedLengthExitBad.js:59:22:59:24 | val |
|
||||
| TaintedLengthExitBad.js:17:17:17:19 | val | TaintedLengthExitBad.js:20:22:20:24 | val |
|
||||
| TaintedLengthExitBad.js:30:17:30:19 | val | TaintedLengthExitBad.js:33:22:33:24 | val |
|
||||
| TaintedLengthExitBad.js:46:18:46:20 | val | TaintedLengthExitBad.js:49:22:49:24 | val |
|
||||
| TaintedLengthExitBad.js:59:22:59:24 | val | TaintedLengthExitBad.js:60:8:60:10 | val |
|
||||
| TaintedLengthLodash.js:9:10:9:17 | req.body | TaintedLengthLodash.js:14:18:14:20 | val |
|
||||
| TaintedLengthLodash.js:14:18:14:20 | val | TaintedLengthLodash.js:15:10:15:12 | val |
|
||||
#select
|
||||
| TaintedLengthBad.js:21:22:21:24 | val | TaintedLengthBad.js:8:10:8:17 | req.body | TaintedLengthBad.js:21:22:21:24 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthBad.js:8:10:8:17 | req.body | here |
|
||||
| TaintedLengthBad.js:30:13:30:15 | val | TaintedLengthBad.js:10:12:10:19 | req.body | TaintedLengthBad.js:30:13:30:15 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthBad.js:10:12:10:19 | req.body | here |
|
||||
| TaintedLengthBad.js:40:12:40:14 | val | TaintedLengthBad.js:12:22:12:29 | req.body | TaintedLengthBad.js:40:12:40:14 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthBad.js:12:22:12:29 | req.body | here |
|
||||
| TaintedLengthBad.js:54:22:54:24 | val | TaintedLengthBad.js:14:16:14:23 | req.body | TaintedLengthBad.js:54:22:54:24 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthBad.js:14:16:14:23 | req.body | here |
|
||||
| TaintedLengthExitBad.js:20:22:20:24 | val | TaintedLengthExitBad.js:8:9:8:16 | req.body | TaintedLengthExitBad.js:20:22:20:24 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthExitBad.js:8:9:8:16 | req.body | here |
|
||||
| TaintedLengthExitBad.js:33:22:33:24 | val | TaintedLengthExitBad.js:10:9:10:16 | req.body | TaintedLengthExitBad.js:33:22:33:24 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthExitBad.js:10:9:10:16 | req.body | here |
|
||||
| TaintedLengthExitBad.js:49:22:49:24 | val | TaintedLengthExitBad.js:12:10:12:17 | req.body | TaintedLengthExitBad.js:49:22:49:24 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthExitBad.js:12:10:12:17 | req.body | here |
|
||||
| TaintedLengthExitBad.js:60:8:60:10 | val | TaintedLengthExitBad.js:14:14:14:21 | req.body | TaintedLengthExitBad.js:60:8:60:10 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthExitBad.js:14:14:14:21 | req.body | here |
|
||||
| TaintedLengthLodash.js:15:10:15:12 | val | TaintedLengthLodash.js:9:10:9:17 | req.body | TaintedLengthLodash.js:15:10:15:12 | val | Iterating over user controlled object with an unbounded .length property $@. | TaintedLengthLodash.js:9:10:9:17 | req.body | here |
|
||||
@@ -0,0 +1 @@
|
||||
Security/CWE-834/TaintedLength.ql
|
||||
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
rootRoute.post(function(req, res) {
|
||||
problem(req.body);
|
||||
|
||||
whileLoop(req.body);
|
||||
|
||||
useLengthIndirectly(req.body);
|
||||
|
||||
noNullPointer(req.body);
|
||||
});
|
||||
|
||||
function problem(val) {
|
||||
var ret = [];
|
||||
|
||||
// Potential DOS! .length property could have been set to an arbitrary
|
||||
// value!
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function whileLoop(val) {
|
||||
var ret = [];
|
||||
var i = 0;
|
||||
// Potential DOS! .length property could have been set to an arbitrary
|
||||
// value!
|
||||
while (i < val.length) {
|
||||
ret.push(val[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
function useLengthIndirectly(val) {
|
||||
var ret = [];
|
||||
|
||||
var len = val.length;
|
||||
|
||||
// Same as above, but the .length access happens outside the loop.
|
||||
for (var i = 0; i < len; i++) {
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// the obvious null-pointer detection should not hit this one.
|
||||
function noNullPointer(val) {
|
||||
var ret = [];
|
||||
|
||||
const c = 0;
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[c].foo); // constantly accessing element 0, therefore not
|
||||
// guaranteed null-pointer.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
var _ = require("lodash");
|
||||
|
||||
rootRoute.post(function (req, res) {
|
||||
breaks(req.body);
|
||||
|
||||
throws(req.body);
|
||||
|
||||
returns(req.body);
|
||||
|
||||
lodashThrow(req.body);
|
||||
});
|
||||
|
||||
function breaks(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
for (var k = 0; k < 2; k++) {
|
||||
if (k == 3) {
|
||||
// Does not prevent DOS, because this is inside an inner loop.
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function throws(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
if (val[i] == null) {
|
||||
try {
|
||||
throw 2; // Is catched, and therefore the DOS is not prevented.
|
||||
} catch(e) {
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// the obvious null-pointer detection should not hit this one.
|
||||
function returns(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
if (val[i] == null) {
|
||||
(function (i) {
|
||||
return i+2; // Does not prevent DOS.
|
||||
})(i);
|
||||
}
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function lodashThrow(val) {
|
||||
_.map(val, function (e) {
|
||||
if (!e) {
|
||||
try {
|
||||
throw new Error(); // Does not prevent DOS
|
||||
} catch(e) {
|
||||
// ignored.
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
var _ = require("lodash");
|
||||
|
||||
rootRoute.post(function (req, res) {
|
||||
breaks(req.body);
|
||||
|
||||
throws(req.body);
|
||||
|
||||
returns(req.body);
|
||||
|
||||
lodashThrow(req.body);
|
||||
});
|
||||
|
||||
function breaks(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
if (val[i] == null) {
|
||||
break; // prevents DOS.
|
||||
}
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function throws(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
if (val[i] == null) {
|
||||
throw 2; // prevents DOS.
|
||||
}
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// the obvious null-pointer detection should not hit this one.
|
||||
function returns(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
if (val[i] == null) {
|
||||
return 2; // prevents DOS.
|
||||
}
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function lodashThrow(val) {
|
||||
_.map(val, function (e) {
|
||||
if (!e) {
|
||||
throw new Error(); // prevents DOS.
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
rootRoute.post(function(req, res) {
|
||||
sanitized(req.body);
|
||||
|
||||
sanitized2(req.body);
|
||||
|
||||
sanitized3(req.body);
|
||||
|
||||
sanitized4(req.body);
|
||||
});
|
||||
|
||||
function sanitized(val) {
|
||||
var ret = [];
|
||||
|
||||
if (!Array.isArray(val)) {
|
||||
return [];
|
||||
}
|
||||
// At this point we know that val must be an Array, and an attacked is
|
||||
// therefore not able to send a cheap request that spends a lot of time
|
||||
// inside the loop.
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i] + 42);
|
||||
}
|
||||
}
|
||||
|
||||
function sanitized2(val) {
|
||||
var ret = [];
|
||||
|
||||
if (typeof val === "object") {
|
||||
return [];
|
||||
}
|
||||
// Val can only be a primitive. Therefore no issue!
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i] + 42);
|
||||
}
|
||||
}
|
||||
|
||||
function isArray(foo) {
|
||||
return foo instanceof Array;
|
||||
}
|
||||
|
||||
function sanitized3(val) {
|
||||
var ret = [];
|
||||
|
||||
if (!isArray(val)) {
|
||||
return [];
|
||||
}
|
||||
// At this point we know that val must be an Array, and an attacked is
|
||||
// therefore not able to send a cheap request that spends a lot of time
|
||||
// inside the loop.
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i] + 42);
|
||||
}
|
||||
}
|
||||
|
||||
function sanitized4(val) {
|
||||
var ret = [];
|
||||
|
||||
if (!(val instanceof Array)) {
|
||||
return [];
|
||||
}
|
||||
// At this point we know that val must be an Array, and an attacked is
|
||||
// therefore not able to send a cheap request that spends a lot of time
|
||||
// inside the loop.
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i] + 42);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
rootRoute.post(function(req, res) {
|
||||
problem(req.body);
|
||||
|
||||
useLengthIndirectly(req.body);
|
||||
});
|
||||
|
||||
function problem(val) {
|
||||
// can take an arbitrary amount of time with a tainted .length property
|
||||
_.chunk(val, 2);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
var global;
|
||||
|
||||
rootRoute.post(function(req, res) {
|
||||
for (i = 0; i < req.body.personas.length; i++) {
|
||||
req.body.personas[i].parentesco.id;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
rootRoute.post(function(req, res) {
|
||||
problem(req.body);
|
||||
});
|
||||
|
||||
function problem(val) {
|
||||
var ret = [];
|
||||
|
||||
// Prevents DOS
|
||||
if (val.length > 100) {
|
||||
return [];
|
||||
}
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
var _ = require("lodash");
|
||||
|
||||
rootRoute.post(function(req, res) {
|
||||
nullPointer(req.body);
|
||||
|
||||
nullPointer2(req.body);
|
||||
|
||||
nullPointer3(req.body);
|
||||
|
||||
lodashPointer(req.body);
|
||||
|
||||
lodashArrowFunc(req.body);
|
||||
});
|
||||
|
||||
function nullPointer(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i].foo + 42);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function nullPointer2(val) {
|
||||
var ret = [];
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
var element = val[i];
|
||||
ret.push(element.foo + 42);
|
||||
}
|
||||
}
|
||||
|
||||
function nullPointer3(val) {
|
||||
let arr = val.messaging
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
let event = val.messaging[i]
|
||||
let sender = event.sender.id
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function lodashPointer(val) {
|
||||
return _.map(val, function(e) {
|
||||
return e.foo;
|
||||
})
|
||||
}
|
||||
|
||||
function lodashArrowFunc(val) {
|
||||
return _.map(val, (e) => {
|
||||
return e.foo;
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
var express = require('express');
|
||||
var router = new express.Router();
|
||||
var rootRoute = router.route('foobar');
|
||||
|
||||
var _ = require("lodash");
|
||||
|
||||
rootRoute.post(function(req, res) {
|
||||
nullPointer(req.body);
|
||||
});
|
||||
|
||||
function nullPointer(val) {
|
||||
var ret = [];
|
||||
|
||||
// Has obvious null-pointer. And guards the next loop.
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i].foo);
|
||||
}
|
||||
|
||||
for (var i = 0; i < val.length; i++) {
|
||||
ret.push(val[i]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user