JS: Add query for resource exhaustion from deep object handling

This commit is contained in:
Asger Feldthaus
2021-02-24 15:33:15 +00:00
parent b978359803
commit 24199a5499
6 changed files with 227 additions and 0 deletions

View File

@@ -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>

View File

@@ -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

View File

@@ -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;
}
// ...
});

View File

@@ -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;
}
// ...
});