From eb43bc04b1390ce2506144b46d081e63f7a7d5b7 Mon Sep 17 00:00:00 2001 From: Matteo Collina Date: Thu, 23 Aug 2018 16:46:07 +0200 Subject: [PATCH] http,https: protect against slow headers attack CVE-2018-12122 An attacker can send a char/s within headers and exahust the resources (file descriptors) of a system even with a tight max header length protection. This PR destroys a socket if it has not received the headers in 40s. PR-URL: https://github.com/nodejs-private/node-private/pull/150 Ref: https://github.com/nodejs-private/node-private/pull/144 Reviewed-By: Sam Roberts Reviewed-By: Ben Noordhuis Reviewed-By: James M Snell --- doc/api/http.md | 20 ++++++++ doc/api/https.md | 7 +++ lib/_http_server.js | 22 ++++++++- lib/https.js | 1 + lib/internal/http.js | 27 +++++++--- test/async-hooks/test-graph.http.js | 4 +- test/parallel/test-http-slow-headers.js | 50 +++++++++++++++++++ test/parallel/test-https-slow-headers.js | 63 ++++++++++++++++++++++++ 8 files changed, 183 insertions(+), 11 deletions(-) create mode 100644 test/parallel/test-http-slow-headers.js create mode 100644 test/parallel/test-https-slow-headers.js diff --git a/doc/api/http.md b/doc/api/http.md index c34e6cded4d5a7..a06d0e44bf9e83 100644 --- a/doc/api/http.md +++ b/doc/api/http.md @@ -941,6 +941,26 @@ added: v0.7.0 Limits maximum incoming headers count. If set to 0, no limit will be applied. +### server.headersTimeout + + +* {number} **Default:** `40000` + +Limit the amount of time the parser will wait to receive the complete HTTP +headers. + +In case of inactivity, the rules defined in [server.timeout][] apply. However, +that inactivity based timeout would still allow the connection to be kept open +if the headers are being sent very slowly (by default, up to a byte per 2 +minutes). In order to prevent this, whenever header data arrives an additional +check is made that more than `server.headersTimeout` milliseconds has not +passed since the connection was established. If the check fails, a `'timeout'` +event is emitted on the server object, and (by default) the socket is destroyed. +See [server.timeout][] for more information on how timeout behaviour can be +customised. + ### server.setTimeout([msecs][, callback])