You are on page 1of 3

In Strict Commercial Confidence

Author: Ethan Rubinson (erubinson@ebay.com | ethanrubinson@gmail.com)

Security Vulnerability in the Node.js


http_parser Library
Impact
Affected Node.js versions can be exploited to perform HTTP desync attacks and deliver
malicious payloads to unsuspecting users. The payloads can be crafted by an attacker to hijack
user sessions, poison cookies, perform clickjacking, and a multitude of other attacks depending
on the architecture of the underlying system.

Affected http_parser Versions


● 2.8.0 (​https://github.com/nodejs/node/tree/v12.x/deps/http_parser​)

Affected Node.js Versions


● v6.x
● v7.x
● v8.x
● v9.x
● v10.x
● v11.x
● v12.x

Node.js v5.x and below use an older version of the http_parser; these are probably also
vulnerable but I have not tested these versions.

Node.js v13.x uses a different http-parser library (llhttp); this may also be vulnerable but I have
not tested this version.

Summary
The http_parser used in the core http module of the aforementioned Node.js versions does not
comply with the RFC-7320 HTTP 1.1 specification. The vulnerability discussed in this document
focuses on ​Section 3.3.3, Subsection 3, Paragraph 2​ which states:

...If a message is received with both a Transfer-Encoding and a Content-Length header


field ... Such a message might indicate an attempt to perform request smuggling
​ ection 9.5​) or response splitting (S
(S ​ ection 9.4)​ and o
​ ught to be handled as an error....
In Strict Commercial Confidence
Author: Ethan Rubinson (erubinson@ebay.com | ethanrubinson@gmail.com)

Today, the behavior of the http-parser when both of these headers are present in an HTTP
message is not compliant with this specification. Instead, it's behavior is as follows:

1. If the Transfer-Encoding header is exactly equal to "chunked", the server correctly


responds with "400 Bad Request". ​This is compliant behavior

2. If the Transfer-Encoding header is not exactly equal to "chunked", the server ignores the
Transfer-Encoding header, respects the Content-Length header, and processes the
received HTTP message. ​This is non-compliant behavior.
a. This behavior is also non-compliant for the obsolete RFC-2616 specification
which says to ignore the Content-Length header if both are received in an HTTP
message
b. It is this newer RFC-7320 specification which says to handle it as an error.

The behavior outlined in #2 makes the Node.js versions using this vulnerable http_parser
susceptible to ​HTTP smuggling attacks​, which, in turn, allows an attacker to perform the attacks
mentioned at the start of the document.

Here are some examples demonstrating the vulnerability being exploited in the wild:

This shows a POST request to "/sample" which smuggles in a POST request to


/attack_attack_attack... The response we receive is the expected response for
making a POST request to /sample even though we smuggled in another request.
In Strict Commercial Confidence
Author: Ethan Rubinson (erubinson@ebay.com | ethanrubinson@gmail.com)

This smuggled request's response, because of the http-desync, can then


be served to an unsuspecting user in place of their actual response:

Solution
I have developed a patch for the http_parser library (v2.8.0) to address this vulnerability and
would like to share and review it with you via this disclosure process. The patch adheres to the
RFC-7320 specification and ensures that a "400 Bad Response" is returned whenever both a
Content-Length header and a Transfer-Encoding header are present in an HTTP message,
regardless of their value. Specifically, it makes changes to the http_parser.c and http_parser.h
files. Please let me know the best way of sharing this patch, I did not want to make a public PR
from GitHub as this is a sensitive issue.

You might also like