mirror of
https://github.com/github/codeql.git
synced 2026-03-06 23:56:48 +01:00
JS: Add query for resource exhaustion from deep object handling
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>
|
||||
Processing user-controlled data with a method that allocates excessive amounts
|
||||
of memory can lead to denial of service.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
If the JSON schema validation library <code>ajv</code> is configured with
|
||||
<code>allErrors: true</code> there is no limit to how many error objects
|
||||
will be allocated. An attacker can exploit this by sending an object that
|
||||
deliberately contains a huge number of errors, and in some cases, with
|
||||
longer and longer error messages. This can cause the service to become
|
||||
unresponsive due to the slow error-checking process.
|
||||
</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>
|
||||
Do not use <code>allErrors: true</code> in production.
|
||||
</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>
|
||||
In the example below, the user-submitted object <code>req.body</code> is
|
||||
validated using <code>ajv</code> and <code>allErrors: true</code>:
|
||||
</p>
|
||||
|
||||
<sample src="examples/DeepObjectResourceExhaustion.js"/>
|
||||
|
||||
<p>
|
||||
Although this ensures that <code>req.body</code> conforms to the schema,
|
||||
the validation itself could be vulnerable to a denial-of-service attack.
|
||||
An attacker could send an object containing so many errors that the server
|
||||
runs out of memory.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A solution is to not pass in <code>allErrors: true</code>, which means
|
||||
<code>ajv</code> will only report the first error, not all of them:
|
||||
</p>
|
||||
|
||||
<sample src="examples/DeepObjectResourceExhaustion_fixed.js"/>
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>Ajv documentation: <a href="https://github.com/ajv-validator/ajv/blob/master/docs/security.md#untrusted-schemas">security considerations</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,23 @@
|
||||
/**
|
||||
* @name Resources exhaustion from deep object traversal
|
||||
* @description Processing user-controlled object hierarchies inefficiently can lead to denial of service.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @precision high
|
||||
* @id js/resource-exhaustion-from-deep-object-traversal
|
||||
* @tags security
|
||||
* external/cwe/cwe-400
|
||||
*/
|
||||
|
||||
import javascript
|
||||
import DataFlow::PathGraph
|
||||
import semmle.javascript.security.dataflow.DeepObjectResourceExhaustion::DeepObjectResourceExhaustion
|
||||
|
||||
from
|
||||
Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink, DataFlow::Node link,
|
||||
string reason
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
sink.getNode().(Sink).hasReason(link, reason)
|
||||
select sink, source, sink, "Denial of service caused by processing user input from $@ with $@.",
|
||||
source.getNode(), "here", link, reason
|
||||
@@ -0,0 +1,14 @@
|
||||
import express from 'express';
|
||||
import Ajv from 'ajv';
|
||||
|
||||
let ajv = new Ajv({ allErrors: true });
|
||||
ajv.addSchema(require('./input-schema'), 'input');
|
||||
|
||||
var app = express();
|
||||
app.get('/user/:id', function(req, res) {
|
||||
if (!ajv.validate('input', req.body)) {
|
||||
res.end(ajv.errorsText());
|
||||
return;
|
||||
}
|
||||
// ...
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
import express from 'express';
|
||||
import Ajv from 'ajv';
|
||||
|
||||
let ajv = new Ajv({ allErrors: process.env['REST_DEBUG'] });
|
||||
ajv.addSchema(require('./input-schema'), 'input');
|
||||
|
||||
var app = express();
|
||||
app.get('/user/:id', function(req, res) {
|
||||
if (!ajv.validate('input', req.body)) {
|
||||
res.end(ajv.errorsText());
|
||||
return;
|
||||
}
|
||||
// ...
|
||||
});
|
||||
Reference in New Issue
Block a user