From b774c2bd8d55e7588d43c1f363a5172415ffe28c Mon Sep 17 00:00:00 2001 From: bcaller Date: Thu, 7 May 2020 23:51:08 +0100 Subject: [PATCH 1/2] Prevent DoS on large integer packet When maxHttpBufferSize is large (1e8 bytes), a payload of length 100MB can be sent like so: 99999991:422222222222222222222222222222222222222222222... This massive packet can cause OOM via building up many many `ConsOneByteString` objects due to concatenation: 99999989 `ConsOneByteString`s and then converting the massive integer to a `Number`. The performance can be improved to avoid this by using `substring` rather than building the string via concatenation. Below I tried one payload of length 7e7 as the 1e8 payload took so long to process that it timed out before running out of memory. ``` ==== JS stack trace ========================================= 0: ExitFrame [pc: 0x13c5b79] Security context: 0x152fe7b808d1 1: decodeString [0x2dd385fb5d1] [/node_modules/socket.io-parser/index.js:~276] [pc=0xf59746881be](this=0x175d34c42b69 ,0x14eccff10fe1 ) 2: add [0x31fc2693da29] [/node_modules/socket.io-parser/index.js:242] [bytecode=0xa7ed6554889 offset=11](this=0x0a2881be5069 ,0x14eccff10fe1 Date: Fri, 8 May 2020 00:29:46 +0100 Subject: [PATCH 2/2] Improve performance parsing other long packets --- index.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 732e62c..ff613cc 100644 --- a/index.js +++ b/index.js @@ -286,11 +286,9 @@ function decodeString(str) { // look up attachments if type binary if (exports.BINARY_EVENT === p.type || exports.BINARY_ACK === p.type) { - var buf = ''; - while (str.charAt(++i) !== '-') { - buf += str.charAt(i); - if (i == str.length) break; - } + var start = i + 1; + while (str.charAt(++i) !== '-' && i != str.length) {} + var buf = str.substring(start, i); if (buf != Number(buf) || str.charAt(i) !== '-') { throw new Error('Illegal attachments'); } @@ -299,13 +297,13 @@ function decodeString(str) { // look up namespace (if any) if ('/' === str.charAt(i + 1)) { - p.nsp = ''; + var start = i + 1; while (++i) { var c = str.charAt(i); if (',' === c) break; - p.nsp += c; if (i === str.length) break; } + p.nsp = str.substring(start, i); } else { p.nsp = '/'; }