资源耗尽¶
ID: js/resource-exhaustion
Kind: path-problem
Security severity: 7.5
Severity: warning
Precision: high
Tags:
- security
- external/cwe/cwe-400
- external/cwe/cwe-770
Query suites:
- javascript-code-scanning.qls
- javascript-security-extended.qls
- javascript-security-and-quality.qls
应用程序受其可以利用的资源数量的限制。不尊重这些限制可能会导致应用程序无响应或崩溃。因此,如果攻击者可以控制分配对象的尺寸或生命周期,则这是一个问题。
建议¶
确保攻击者无法控制对象的尺寸及其生命周期。如果对象的尺寸和生命周期必须由外部方控制,请确保限制对象的尺寸和生命周期,以确保它们在可接受的范围内。
示例¶
以下示例分配了一个尺寸由用户控制的缓冲区。
var http = require("http"),
url = require("url");
var server = http.createServer(function(req, res) {
var size = parseInt(url.parse(req.url, true).query.size);
let buffer = Buffer.alloc(size); // BAD
// ... use the buffer
});
这存在问题,因为攻击者可以选择一个尺寸,使应用程序耗尽内存。更糟糕的是,在旧版本的 Node.js 中,这可能会泄露机密内存。为了防止此类攻击,请限制缓冲区尺寸
var http = require("http"),
url = require("url");
var server = http.createServer(function(req, res) {
var size = parseInt(url.parse(req.url, true).query.size);
if (size > 1024) {
res.statusCode = 400;
res.end("Bad request.");
return;
}
let buffer = Buffer.alloc(size); // GOOD
// ... use the buffer
});
示例¶
作为另一个示例,请考虑一个应用程序,该应用程序分配一个尺寸由用户控制的数组,然后用值填充它
var http = require("http"),
url = require("url");
var server = http.createServer(function(req, res) {
var size = parseInt(url.parse(req.url, true).query.size);
let dogs = new Array(size).fill("dog"); // BAD
// ... use the dog
});
数组本身的分配没有问题,因为数组是稀疏分配的,但随后填充数组将需要很长时间,导致应用程序无响应,甚至耗尽内存。同样,对尺寸的限制将阻止攻击
var http = require("http"),
url = require("url");
var server = http.createServer(function(req, res) {
var size = parseInt(url.parse(req.url, true).query.size);
if (size > 1024) {
res.statusCode = 400;
res.end("Bad request.");
return;
}
let dogs = new Array(size).fill("dog"); // GOOD
// ... use the dogs
});
示例¶
最后,以下示例允许用户选择执行函数后的延迟时间
var http = require("http"),
url = require("url");
var server = http.createServer(function(req, res) {
var delay = parseInt(url.parse(req.url, true).query.delay);
setTimeout(f, delay); // BAD
});
这存在问题,因为长时间延迟实际上会使应用程序无限期地等待,然后再执行函数。因此,反复注册此类延迟将耗尽应用程序中的所有内存。对延迟的限制将阻止攻击
var http = require("http"),
url = require("url");
var server = http.createServer(function(req, res) {
var delay = parseInt(url.parse(req.url, true).query.delay);
if (delay > 1000) {
res.statusCode = 400;
res.end("Bad request.");
return;
}
setTimeout(f, delay); // GOOD
});