Skip to content

Discrepancies in parsing http messages #158

@blessingcharles

Description

@blessingcharles

Version

nodejs :17.8.0

Platform

linux nodejs docker

Subsystem

node http

What steps will reproduce the bug?

Dockerfile

FROM node

# Create app directory
WORKDIR /usr/src/app

# Bundle app source
COPY . .
EXPOSE 80
CMD [ "node", "app.js" ]

Code to reproduce

const http = require("http");
const fs = require("fs")

// https://nodejs.org/en/docs/guides/anatomy-of-an-http-transaction/

let request_count = 0 ;

console.log("server started at 80");
http.createServer((request, response) => {

    let body = [];
    request
        .on("error", (err) => {
            response.end("error while reading body: " + err);
        })
        .on("data", (chunk) => {
            body.push(chunk);
        })
        .on("end", () => {
            body = Buffer.concat(body).toString();
            console.log("\n----------------------------\n")
            console.log(request.headers);
            console.log("Body : " , body , " length  : " , body.length.toString())
            console.log(response.statusCode)
            
            request_count += 1
            
            content = `\n---Count : ${request_count}---- Status : ${response.statusCode} --------\n${JSON.stringify(request.headers)}\nBody:[${body.toString()}]\n`
            
            fs.writeFile('output.txt', content, { flag: 'a+' }, err => {})

            response.on("error", (err) => {
                response.end("error while sending response: " + err);
            });

            response.end(
                "Body length: " + body.length.toString() + " Body: " + body
            );
        });
}).listen(80);

POC

 echo -ne "GET / HTTP/1.1\r\nHost: localhost\r\nTransfer-encoding: chunked\r\n\r\n2 erfrferferf\r\naa\r\n0 rrrr\r\n\r\n" | nc localhost 8003

How often does it reproduce? Is there a required condition?

Reproducible in all environments

What is the expected behavior?

  1. According to RFC grammar , For chunked body each chunk size should be terminated by CRLF , or can have chunked extension preceding with ";" . RFC chunked transfer coding .

RFC ABNF Grammar

chunk          = chunk-size [ chunk-ext ] CRLF
                 chunk-data CRLF
                 
chunk-size     = 1*HEXDIG
last-chunk     = 1*("0") [ chunk-ext ] CRLF
chunk-data     = 1*OCTET ; a sequence of chunk-size octets
chunk-ext      = *( ";" chunk-ext-name [ "=" chunk-ext-val ] )
  1. All requestline , request headers and terminating headers-field must be terminated with CRLF . RFC grammar

What do you see instead?

  1. For chunked body , each chunksize can be preceded with space and then any random ascii characters are allowed , even though semicolon is not provided for chunked extendsion , which violates RFC grammar
echo -ne "GET / HTTP/1.1\nHost: localhost\nTransfer-encoding: chunked\r\n\r\n2        fereg\r\naa\r\n0 rvrtvgrwtv\r\n\r\n"
  1. Requestline , Requestheaders and terminating headers in nodejs instead of CRLF , LF was treated as terminator .
 echo -ne "GET / HTTP/1.1\nHost: localhost\nTransfer-encoding: chunked\n\n2\r\naa\r\n0\r\n\r\n" | nc localhost 8003 

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions