Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFedor Indutny <fedor.indutny@gmail.com>2012-01-15 23:45:31 +0400
committerFedor Indutny <fedor.indutny@gmail.com>2012-01-16 00:45:05 +0400
commit8a98c2f1d81cabb6594dc388789d60d2f3f67c09 (patch)
tree2c07a8026b7e28255e399d2f04707f2f4eaad949 /lib
parent93465d30511db82d0f759905d0cde52c8d5ea53e (diff)
http, querystring: added limits to prevent DoS
Diffstat (limited to 'lib')
-rw-r--r--lib/http.js23
-rw-r--r--lib/querystring.js14
2 files changed, 33 insertions, 4 deletions
diff --git a/lib/http.js b/lib/http.js
index 0598ac0c8bb..ea540541249 100644
--- a/lib/http.js
+++ b/lib/http.js
@@ -43,6 +43,10 @@ var parsers = new FreeList('parsers', 1000, function() {
parser._headers = [];
parser._url = '';
+ // Limit incoming headers count as it may cause
+ // hash collision DoS
+ parser.maxHeadersCount = 1000;
+
// Only called in the slow case where slow means
// that the request headers were either fragmented
// across multiple TCP packets or too large to be
@@ -78,7 +82,14 @@ var parsers = new FreeList('parsers', 1000, function() {
parser.incoming.httpVersion = info.versionMajor + '.' + info.versionMinor;
parser.incoming.url = url;
- for (var i = 0, n = headers.length; i < n; i += 2) {
+ var n = headers.length;
+
+ // If parser.maxHeadersCount <= 0 - assume that there're no limit
+ if (parser.maxHeadersCount > 0) {
+ n = Math.min(n, parser.maxHeadersCount << 1);
+ }
+
+ for (var i = 0; i < n; i += 2) {
var k = headers[i];
var v = headers[i + 1];
parser.incoming._addHeaderLine(k.toLowerCase(), v);
@@ -1158,6 +1169,11 @@ ClientRequest.prototype.onSocket = function(socket) {
parser.incoming = null;
req.parser = parser;
+ // Propagate headers limit from request object to parser
+ if (req.maxHeadersCount) {
+ parser.maxHeadersCount = req.maxHeadersCount;
+ }
+
socket._httpMessage = req;
// Setup "drain" propogation.
httpSocketSetup(socket);
@@ -1444,6 +1460,11 @@ function connectionListener(socket) {
parser.socket = socket;
parser.incoming = null;
+ // Propagate headers limit from server instance to parser
+ if (this.maxHeadersCount) {
+ parser.maxHeadersCount = this.maxHeadersCount;
+ }
+
socket.addListener('error', function(e) {
self.emit('clientError', e);
});
diff --git a/lib/querystring.js b/lib/querystring.js
index 58b90250c44..f2038f5b21f 100644
--- a/lib/querystring.js
+++ b/lib/querystring.js
@@ -160,16 +160,24 @@ QueryString.stringify = QueryString.encode = function(obj, sep, eq, name) {
};
// Parse a key=val string.
-QueryString.parse = QueryString.decode = function(qs, sep, eq) {
+QueryString.parse = QueryString.decode = function(qs, sep, eq, options) {
sep = sep || '&';
eq = eq || '=';
- var obj = {};
+ var obj = {},
+ maxKeys = options && options.maxKeys || 1000;
if (typeof qs !== 'string' || qs.length === 0) {
return obj;
}
- qs.split(sep).forEach(function(kvp) {
+ qs = qs.split(sep);
+
+ // maxKeys <= 0 means that we should not limit keys count
+ if (maxKeys > 0) {
+ qs = qs.slice(0, maxKeys);
+ }
+
+ qs.forEach(function(kvp) {
var x = kvp.split(eq);
var k = QueryString.unescape(x[0], true);
var v = QueryString.unescape(x.slice(1).join(eq), true);