graygnuorg / pound

Light-weight reverse proxy, load balancer and HTTPS front-end for Web servers.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Pound forwards requests with multiple `Transfer-Encoding: chunked` headers

kenballus opened this issue · comments

When I send the following request to Pound:

GET / HTTP/1.1\r\n
Host: a\r\n
Transfer-Encoding: chunked\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n

It forwards the following to my backend:

GET / HTTP/1.1\r\n
Host: a\r\n
Transfer-Encoding: chunked\r\n
Transfer-Encoding: chunked\r\n
X-Forwarded-For: 172.19.0.1\r\n
X-Forwarded-Proto: http\r\n
X-Forwarded-Port: 80\r\n
\r\n
0\r\n
\r\n

Note that the two Transfer-Encoding headers are preserved. This is problematic for the many servers that misinterpret such requests, and can lead to request smuggling.

There are three potential fixes for this problem:

  1. Reject messages with multiple Transfer-Encoding: chunked headers. This is what Apache, Caddy, Envoy, HAProxy, nghttpx, Nginx, LiteSpeed, Squid, Traefik, Akamai, AWS, Azure, CloudFlare, Fastly, and Google Cloud do.
  2. Normalize the request to have only one Transfer-Encoding: chunked header. This is what Apache Traffic Server does.
  3. Buffer the request and use Content-Length instead. This is what H2O and Varnish do.