- Hello. My name is Martin Doyhenard.
I'm a security researcher at the Onapsis Labs.
And today I'm going to present a new set of techniques
that can be used to obtain control over the response queue
in a persistent connection by exploiting different HTTP
desynchronization vulnerabilities.
The agenda for today. First,
I'm going to make a quick recap on HTTP request smuggling.
And even though I expect the most of you
already know what request smuggling is,
I'm still going to make a quick introduction.
And then we'll also talk about desynchronization variants,
and about one in particular that will be used
through the same, through the rest of the presentation
for both demos and examples.
After this introduction,
I'm going to explain what is response smuggling
and how to use it for different malicious purposes.
And I will show how to hijack responses and requests
from a persistent connection,
and how to obtain reliable results in real systems.
Next, I'm going to demonstrate how to
concatenate multiple responses
and build malicious payloads to take control
of the victim's browser. And also using this,
I will demonstrate how to poison the whole cache
of a, of an HTTP proxy,
by storing a crafted message as the response
of any endpoint the attacker wants.
Finally, I'll explain how to split responses
and inject arbitrary messages
that will be stored in the response queue and will be
delivered back to other clients by the proxy.
So, request smuggling is an attack introduced in 2005
by Watchfire
which abuses the differences between a front end
and a back end server.
These differences are related to the way the HTTP parser
calculates the body length of our request.
And this, the idea is to, the attacker
sends a request containing multiple message length headers
such as content-length or different (indistinct) encodings.
And if the front end calculates the length of the body
using a different header, then
it will be possible to split the request and inject the
prefix for the next message.
Let's see an example of this in which
two content-length headers are sent in the same request.
In this example, the proxy will only use
the first content-length
if multiple headers with the same name you are sent.
And the back end will instead only use the last
content-length to calculate the body size.
When the attacker sends this request,
the front end will forward the entire message,
as it will think that the body is 32 bytes.
However, when this message reaches the back end,
only the first five bytes of the body
will be considered to be part of the request.
The extra 27 bytes will be split
and used as the prefix of the next request
processed by the back end.
If a victim's request arrives after the attacker's one,
it will be concatenated to the injected prefix,
causing the back end to believe that the victim
issued a request to "DeleteMyAccount" where,
when instead it was issued to the "myAccount" endpoint.
And, as the session cookies of victim are also included,
the application will probably delete his account.
But also the response of this request will be sent
back to the victim.
And if it contained any malicious payloads
such as JavaScript, it will be executed
on the client's browser as well.
But these attacks were forgotten for many years,
as they were thought to be,
that they wouldn't be used in real systems.
But this changed in 2019,
when James Kettle "reborned" this idea
by providing a new methodology to, first,
detect different desynchronization vulnerabilities,
then, confirm that it is possible to use them to
smuggle our request,
and finally, to explore and exploit the different
features provided by the web application.
What's more, he was able to demonstrate
that these techniques could be
applied in many real systems,
and it was possible to collect a lot of bounties
from different vendors.
Also in 2019 and 2020,
many of these desynchronization variants
were presented by researchers.
These are techniques that can be used to force
the discrepancy between servers
by hiding messages in the headers,
such as the content-length, from a specific parser.
In most cases, this is done by
placing extra special characters,
such as a space or an unprintable letter.
And in this way, a server will fail to recognize
the header name or the value
as a valid content-length header.
But even though these flaws can be found in many parsers,
it is also possible to cause desynchronization
by using a feature that is provided just by
the HTTP protocol itself.
And to understand this technique, first,
I'll explain the difference between
an end-to-end and a hop-by-hop header.
So, end-to-end headers are those that are intended
to travel from the client to the back end server,
and forwarded by any proxy in the middle.
On the other hand, hop-by-hop headers are intended to
travel only to the next node in the communication chain.
And for this reason, proxies must not forward these headers,
and they should be removed from the request
before being forwarded.
And one of the most interesting hop-by-hop headers
defined in the HTTP RFC is the connection header.
This directive can be used to specify connection options
that could be used to establish and maintain
the connection between two nodes.
And these options must not affect other connections.
So again, they should not be forwarded by any proxy
receiving them.
Some of the known collection options are
"close" or "keep-alive",
but also the protocol allows the client to declare
any custom value he wants.
And also allows to use these connection options
as an extra header
to give the proxy or the servers more information
on how to persist the HTTP communication.
So let's see an example of a request containing
two connection options.
First, the client will declared them as a connection value,
and then, the two options are also declared
as separated headers.
But when a proxy forwards this request,
it will remove both the option and keep-alive header,
and as well as all the connection directives.
But what if instead of specifying some useless value
as a connection option,
we declare an end-to-end header such as the content-length.
When the proxy receives the request,
it will consider the bodies of 13 bytes,
and it will forward it.
But before it does, it will remove the content-length header
as it was declared as a connection option.
So when the back-end receives this,
it will think that the body is empty
and it was split the message.
This would cause that the smuggled data
is used as the prefix for the next arriving request.
Now this issue was reported under the
Google vulnerability reward program,
and Google fixed it, confirmed that it was possible
to use it to smuggle requests in older public domains.
Now let's see how this desynchronization vulnerabilities
can be leveraged to produce useful exploits
in web applications.
First, we could use request smuggling
to bypass front-end controls,
such as filters to forbidden endpoints.
And this can be done by smuggling the forbidden request,
which will not be seen by the proxy,
and will be forwarded to the backend.
However, this technique does not bypass authentication
for most resources, and in most real applications,
it will fail if the response is not received
by the attacker, and if the filter is not
placed in the vulnerable proxy.
Another exploitation technique is
hijacking the victim's request,
but this can only be done if the web application
offers some data storage feature.
That is, the attacker can only hijack victim information
if it can be stored or retrieved,
which is not that common in all applications.
And also these kind of features are offered only to,
or in most cases, are only offered to authenticated users.
So the attacker would need to have a valid account
or a valid session.
Next, we can use request smuggling to upgrade
existing vulnerabilities, such as cross-site scripting.
But in this case, the attacker will be able to distribute
the payload without having to interact with the victim.
And in this case,
you will not have to force the,
the client to trigger the attack in some action.
The same idea could be applied for any vulnerability
regrading interaction, such as an open redirect,
but to do this, or to improve
these kinds of vulnerabilities, the attacker needs first
to find another vulnerability, such as the
cross-site scripting,
because if not, there will be nothing to be upgraded.
And finally, the desynchronization vulnerabilities
can be used to perform different web cache attacks,
such as web cache poisoning.
And this can be done by modifying the response
for caching a resource, by playing a prefix
in the backend's request.
However, this is only possible to,
it's only possible to poison resources that were cacheable,
and only if the proxy ignores the cache-control header.
If this is not the case,
then the malicious response will not be stored
by the web cache, and the attack will fail.
Some other techniques might also be possible.
But in most cases,
it is required that the system provides some rather
uncommon features, or have other vulnerabilities,
so I'm not going to talk about them.
So... (clears throat)
By now, all attacks rely on injecting a prefix in
the request queue of a persistent connection.
However, exploiting these might not be as trivial
as you would like.
There are many (indistinct) to successfully take advantage
of these vulnerabilities.
So we would like to look for other options.
But what if instead of placing focus on the request,
we would look at attacks effecting the response queue
of the connection?
With this in mind, I started thinking about
what would happen if instead of injecting a prefix
for the next message,
we will smuggle a complete request
that will alone produce an extra response.
If this happens, the proxy will issue one request,
but it will receive two different responses from the,
from the backend.
And if a victim later sends another message to the proxy,
it will be forwarded, but in this case,
the remaining extra response,
which corresponds to the (indistinct) request
will be sent back to the victim.
And as the victim's response got desynchronized too,
an attacker could then send another request
to hijack the form response.
And if this response was issued after a login message,
for example, then the attacker will be able to receive
some sensitive information, such as the session cookies
or any other session token
that was intended to the victim.
To better understand this technique, let's see how
requests and responses are associated at the proxy
and at the backend.
First, both the attacker and the victim will send a request
to the front end.
They will be stored in the request queue and forwarded to
the backend server through the same connection.
However, when the malicious payload reaches the backend,
it will get split, producing two different responses.
And now all three responses, the two that were generated
by the attacker and the one generated by the victim,
will go back to the proxy.
Here, the first,
the first response would be forwarded to the attacker.
And the second one, which corresponds to
the smuggled message, would be forwarded to the victim.
However, as the proxy only issued two requests,
it will wait for a new,
for a new message before it can, before it can
forward the last response.
In this case, if the attacker is able to send a new message,
he will be obtaining, he will end up obtaining
the victim's response, and in that response,
also some sensitive information,
such as, as we already said, for example,
the session cookies that were,
that were created after a login request.
But what if instead, what if we tried to use
these techniques in real, in real systems.
We would find that the results that we obtain are,
are not as we expected.
And that their reliability of these attacks
can make us think that they are not as useful as it sounds.
So here we can see some,
the communication between the proxy and the backend.
And in this capture, an attacker was trying to
desynchronize the response queue, but each time
a request was sent,
the connection was closed by the proxy.
This means that the attack is failing.
And the reason for this is that the,
the proxy resets the connection every time it
receives an extra response.
And therefore we cannot send extra responses
before the proxy creates a new request.
And only after a thousand requests,
I was able to smuggle a single response,
and actually hijack a victim's message.
But of course, this is not the desired or expected result.
So why this is happening?
And to understand this,
first let's take a look at what's going on under the hood.
And to do so, I will explain one concept
that was introduced in HTTP 1.1.
And in which all the desynchronization attacks rely on.
First, remember that the biggest change
between HTTP 1.2 or 1.1
is the ability to persist TCP connections
and just send multiple request and response pairs
through the same connection.
This means that the client is not forced anymore
to close the connection after receiving a response.
Instead, it could use it to send more messages,
increasing the performance of the network.
However, this concept is sometimes confused
with another important feature that is provided
by the HTTP protocol,
which is the ability to pipeline different messages
through the same connection.
So, HTTP pipelining is what allows a client to send
multiple requests without having to wait for
previous responses.
This means that if a client needs to send,
let's say, two requests, to the same server.
This can be done at the same time,
concatenating them through the same channel.
And it is the job of the server or the, or the proxy,
to split them and resolve each,
producing the corresponding responses.
And as we saw in previous examples,
the way each request is matched with its response
depends only on the order they were received and forwarded.
The first response would correspond to the first request,
and this will be done by using the
first-in-first-out scheme order.
And that's why we will call them
request and response queues,
because they will actually work as queues.
There is no other way of matching different responses
and requests, such as an ID or anything.
So the only way to do it is using the order that
where they were issued and they were received.
But here's the catch:
Most proxies won't enforce pipelining,
meaning that if two or more requests from different sources
reach the proxy, they will be concatenated,
they won't be concatenated together,
and they will be,
they won't be forwarded together to the backend server.
Instead, they will be sent through different
free TCP connections, which won't affect each other.
And so the attacker won't be able to
play with the connection queue of the victim,
and this will prevent the attack.
But also future requests, or future client requests,
which in the server, won't go through the same connection
that the attacker used previously.
And this is because the extra response injected
by the attacker is received by the proxy,
and will be interpreted as a communication error.
This is because the proxy did not issue any,
any new requests,
and so it shouldn't be receiving any extra response.
If this happens, then the proxy will think that there is
a problem in the communication,
and will just close the connection.
And also, when closing this connection,
the extra response that was received will be discarded,
and so it won't affect any, any future requests.
So what can an attacker do to solve this problem?
First to hijack our response, an attacker would need to
smuggle two responses,
but they cannot be sent back together to the proxy,
because as we saw in this case,
the proxy will close the connection
because it will see an extra response.
So to avoid this, a new request must be forwarded
by the proxy, so when the response arrives,
the connection is persisted.
But these new requests can only be sent after
the first response goes back to the proxy.
This is because the proxy won't forward
any other requests through the same connection
until the request, until the request queue
of this connection is free.
So the idea will be to send a time-consuming request
as this final message,
and this request will take some time to be processed,
and the server would take some time to generate
a response for this request.
And this time will be just enough
for the next victim's message to reach the proxy
and reach the proxy's request queue.
Therefore, when the response is forwarded back,
it would be sent back to the client,
and the attacker will now be able to send a fast request
and hijack the extra response, which in this case,
is the response that was issued for the, for the victim.
It's not necessarily that this (indistinct) request
take a lot of time.
It is just about knowing that,
it's just about knowing this time,
and calculate the transmission time, to play with them.
This will allow an attacker to know
the best time between payloads,
and the best time that he has to wait
before sending the next attack.
And, under normal conditions using different proxies
and backend servers, I was able to observe
huge improvements. Okay?
So I was able to actually see how these requests are being
smuggled and the connection is being persisted.
And as you can see, the same attack
using a different smuggled endpoint
will, will give much, much better results.
In this case, the connection was persisted for 14 requests.
This means that the responses were desynchronized
for 14 clients.
And that is a really, really good number,
if we think that before we were only getting
one of a thousand.
And so, if we are able to inject complete requests
that will produce an extra response,
what would stop us from injecting multiple messages?
From a technical perspective, it's the same
to smuggle 1, 2, or 10 requests,
that would produce 1, 2, or 10 extra responses.
And this will be useful for other, more complex exploits,
but for now, we can see that there are some simple attacks
that we can, that we can perform
and that we can leverage from these techniques.
First, it is possible to inject multiple nested responses
to effectively distribute a malicious payload,
such as JavaScript using reflected cross-site scripting,
as we already saw.
If we send instead of one,
many different smuggled requests
that will produce this payload,
then we will be able to poison the next
N amount of clients.
Also, nested requests can be used
to consume resources from both the backend
and the front end server, and as well,
requests can produce multiple messages
that would need to be processed at the backend.
This could consume a lot of CPU time.
And as the responses must also generate, sorry,
and thus the responses must also be generated,
and in some case stored, then this could affect also
the memory buffer of the application.
But it could also combine nested injections
with classic request smuggling technique.
And if an application with a desync vulnerability
allows for content reflection,
even if this reflected parameter is properly encoded,
it is possible to also hijack a request from the victim,
instead of only a response.
And this will be done by smuggling two different messages.
The first one will be an HTTP request, as we already saw,
which only propose is to desynchronize the response queue,
just as we, I explained previously.
And next, the second smuggled request,
will not be completed, and will,
will try to reflect some, some data that is,
that is also concatenated with it.
This is done, as in any other request smuggling attack,
by using a content-length that is greater than
the body of the, of the request.
So, as always the first response will be sent back
to the attacker.
And this will allow that the new victim's request
arrive to the backend, because if not, as we saw,
the proxy won't forward the request through the,
through the TCP connection.
After this, the sleeper request will get resolved
and the response will be forwarded to the victim.
Now, if this last smuggled request contained
a large content-length, it would be used as the,
sorry, it would use the victim's request
as part of the body,
but it was still need more data.
And as the connection is empty,
and the attacker can now send a large request
that will complete the body,
it will cause that the response containing
the victim's request as the reflected data,
is sent back to the attacker.
So after seeing this work in a real system,
I was kind of excited, but then I started wondering,
is it possible to also confuse the HTTP parser
when responses are sent back?
Of course, we could perform the same tricks
as with desync variants, but for this,
we would need to control the message length headers
of the response.
And that will probably not going to happen.
And that's not something that's not going to happen.
However, I also start thinking,
is there a difference on how the length of the body
is calculated between the requests and responses?
And the answer, given by the HTTP RFC, is yes.
The difference is that for some specific responses,
the body must always be empty.
And these responses are some special status codes,
like the 204 and 304,
but also responses that are generated out of a HEAD request.
So what makes it so interesting, these kinds of responses,
is that not only they depend on the request
that generated them, but that it must always
be an exact replica of the headers in the same GET response.
So when a, when a HEAD response is generated,
the only difference that we have from a GET response
to the same end point will be that
the body will not be there,
but the rest of the headers should be the same.
And this includes, of course, the content-length.
Even though it is optional that the content-length appear,
it does most real applications.
And if it appears, the value will not be zero
if the GET response contained a body.
Instead, it will contain the same value,
and will hope that the proxy knows that the response
is special, and that it contains a content-length
that should be ignored,
because it's the, it's the response of a HEAD request.
But if the proxy fails to match that this response
was issued from a GET, from a HEAD request,
then what would happen?
And of course, the body, in this case,
the content-length in this case, will be used,
and it will indicate our own value because
the HEAD response will contain no body and a content-length
header with a different value than zero.
A desynchronization will cause that requests and responses
are not properly matched by the proxy.
It would be possible to use a HEAD smuggle request
to generate a malicious response.
This will contain a content-length header,
which in this case will be considered to contain
the actual size of the body.
If an attacker smuggles two requests to the backend,
the first response generating,
will generate the carried message, which,
generated by the carried message, will go back to him.
Next, another request will arrive to the proxy
and it will be forwarded to the backend.
Now the back end will send it,
will send the first response,
which in this case will be to a HEAD request.
When this message is received by the proxy,
it won't be forwarded right away.
This is because the content-length header
states that the body is not empty.
And the request matching this,
this response contains the GET method
and not the HEAD method.
This means that if the body,
if the body of the response was empty,
but the content-length states that it shouldn't be,
then the proxy will wait for more data to be used,
and then forward this response.
So when the next response arrives to the proxy,
it will be used as part of the body of the previous message.
This will now be delivered back to the client,
which is the, which issued the second request.
And also the remaining of their response will be
sent back to the next client issuing a request.
But that's only if the proxy thinks that this is
a valid HTTP message, which in this case, is not.
To understand these ideas,
let's see how the different HTTP messages
travel through the connection.
First the attacker would send its request to the proxy,
which will forward it to the backend server.
There, the message will be split into three
and the first response will be sent back to the attacker,
as always.
After this, the victim will issue a new request,
in this case, a GET request, but it could also be any other,
except for the HEAD one.
Their request will also be forwarded to the backend server.
And when the smuggled response arrives to the proxy,
they will be concatenated together
and sent back to the victim.
If the remaining of the split response
are not a valid response,
then the connection would be closed,
and the response will be discarded, the extra response.
And that is because the proxy would think that, again,
there was a communication error.
But why it could be useful to concatenate
multiple responses?
We were already able to control the response queue
and the responses that the victim were receiving.
So anything that we can concatenate,
we could also have sent it with a single request.
And is that right?
Well, not really. And this is because we,
when we concatenate two responses,
one of them will have its headers used as the body
of the previous message.
This means that if the data is reflected in headers, then,
which is something rather common in most applications,
let's think of a redirect or something that can
allow an attacker to reflect some data
in the headers of their response.
Then an attacker would be able to reflect these
in the body of the request, of their response, sorry.
And if the headers contain any specific content-type
directive, such as the text/html,
then this reflected content that was present in the,
in the headers will now be considered as HTML data.
And this could allow an attacker to inject,
let's say, a malicious JavaScript payload,
or any HTML attack that he desires.
And of course this will be executed in the client's browser.
And the same applies for any parameter reflected
in a non-scriptable content-length, content-type, sorry.
So if we are able to reflect some content in,
let's say, the plain text type,
then we can convert this to another content-type by using
different headers to, to,
to change the behavior of the authored response.
And of course, this effect can be combined
with other techniques to reflect other
requests and responses in the message body.
So now we will see a demo.
I was able to prove all these techniques
in three major vendors, but unfortunately,
they were not able to fix the issues at
the time of this presentation.
So to solve this problem, I deployed a small testing lab
using a (indistinct) version as the front end,
and the nginx last version as the backend server.
In this case, the (indistinct) HTTP parser
is vulnerable to the desync variant
that I explained previously, the connection desync variant,
so it will be possible to smuggle a request using the
connection header to hide the content-length.
First, we can see that the web application consists of
three endpoints, all with almost static responses.
The paths are /home, /helloSmuggle,
and also any other path we,
with any other string will be used to
redirect to the homepage.
Again,
Here, in the,
we can see this in the Burp Repeater window.
If I send the helloSmuggle request with the GET method,
we can see that the response contains a content-length,
written as zero, and a content-type header
saying that the body should be treated as an HTML document.
The same header will, with the, sorry,
the same healers with the same value are obtained
if a HEAD request is sent.
And just as expected by the HTTP RFC specification.
Also, we can see that the behavior of the redirect
feature (indistinct) reflecting the query string
in the location header.
This will be used to place the malicious JavaScript
and hijack the victim's browser.
So now, using Turbo Intruder, which is another
great contribution from James Kettle,
I will smuggle the concatenated response,
which will be sent back to the victim.
Also consider that this demo was built using
the same features found in all three mentioned vendors,
and so this applies to, to many,
to many real systems that can be, can be found in,
in almost any, any company.
You can see that once the attack is started,
all following victim's requests
obtain the malicious response.
And only when any request is sent with the browser,
this JavaScript will be executed,
and this will happen every time we, we request for,
for anything in the, in the system.
But finally, if the attacks stop,
if the attacker stops sending this malicious payload,
then the desynchronization will conclude,
and the user will see that the application
works as expected.
Still, this attack gets even worse
when a web cache is available.
Remember that the,
that request smuggling could be used
to poison certain endpoints
with other existing responses?
Well, with response smuggling, those restrictions are gone.
An attacker would be able to poison any endpoint he wants,
and the responses that can be used to,
to poison these endpoint just need that the,
that the HEAD response contains a cache-control header,
which will cause that the message to be stored in the cache.
And, as the attacker can send multiple pipelined requests,
it is possible to poison the cache with a single request,
which will be split also by the proxy.
And this will cause that the second request gets poisoned
with the response of the smuggled message.
As an example, let's see what happens when an attacker
smuggles a HEAD cache, cacheable request.
As you saw, the proxy will send the first response
back to the attacker.
Next, it will concatenate the HEAD request,
or the HEAD response with a cache-control header
that will tell the web cache to store this response
with the second smuggled response,
in this case, containing the malicious JavaScript.
And finally, the next request,
which was also issued by the attacker,
will be responded, this time with the concatenated message,
which will force the web cache to store this
for the future requests.
So, when a client request,
so, when a client requests for the same resource
that the attacker specified,
the malicious response will be sent back
without the need of any instructions, because it will be
stored in the cache for this specific resource.
Again, I believe it will help to see this
in the following diagram.
As I said, the attacker will send two pipelined requests,
one containing the smuggled payload,
and the other specifying the URL that will be poisoned.
This can be any endpoint that the attacker wants,
even non-existent endpoints will work.
The request will get split by the proxy
and forwarded to the backend server.
And as you can see, the messages are pipelined
from the source, so this will work,
even if pipelining is not enforced or even allowed.
In this case, the request will still be enqueued
in the same connection,
the only difference is that they will be sent consecutively,
but not concatenated.
Now the backend server will, again,
split the messages and produce four isolated responses
that will, that are returned back to the proxy.
Here, both responses will go back to the attacker,
but sorry, the,
yeah, both responses will go back to the attacker,
but the second one will be stored in the cache
for the endpoint indicated in this second pipeline request.
So the second request that the proxy was able to recognize
will be used to store the, the results of these,
of the response.
This way, when a victim issues a request
for the same endpoint that the attacker specified,
the proxy will find a match with this key the cache table,
and it will return the stored response, and in this case,
the malicious payload with the JavaScript
will be sent back to the, to the victim,
that the attacker injected.
Remember that this technique can be used
every time a web cache exists,
as there are no extra requirements.
Even if the cache-control header is not used,
there will be at least one URL that can be used
to start poisoning the cache with malicious responses.
And that is if the,
if there is a web cache existing in any proxy
of the communication chain.
And the same thing can be used to force victims
into storing their own responses in the cache.
And if their response contain sensitive,
sensitive victim's data,
it will be placed in the cache, and later,
an attacker can access it through the same end point
that the victim requests.
This is known as web cache deception,
and in this case, it can even be used to store
dynamic responses, such as those that are issued
from login requests.
They will contain among any other data,
data such as session cookies or any other token
that the victim will receive in his response.
So again, in this case, the attacker can use these
to store anything, and it will work as an improved
cache deception attack, because in this case, as I said,
the dynamic information can be stored.
Now for the second demo,
I will use the same lab in the previous example,
but this time with a new endpoint, that can be cacheable.
In this case, it will also be called "cacheable".
And this will be available in the homepage.
As you can see, this is also a static resource,
but in this case, the cache-control header
is used to indicate that the response to this request
should be stored by the web cache.
In this attack, I will attempt to poison
the /helloSmuggler endpoint to return a malicious script
using the same redirect URL to inject the payload
in the body of the HEAD response,
as we already saw in the previous example.
However, this time, the HEAD response will contain
the cache directive and will cause that this response
gets stored for any endpoint that the attacker wants.
The same connection desync vulnerability will be leveraged
to smuggle the response,
and also our request for the poisoned endpoint
will be placed pipelined after the malicious one.
So the second request that we are seeing, or this,
the last request that we are seeing is actually
the request that will be poisoned.
When these, once this request is sent,
the /helloSmuggler endpoint will get poisoned
and all following requests will receive the response
containing the JavaScript injected by the attacker.
This will cause that their browser executes an eval function
to open an error message, and the same effect can be caused
on any end point the attacker wants.
So the same test is performed against the /home path,
and again, the URL gets poisoned,
and every time a victim requests this resource,
the JavaScript will be retrieved and it will be executed,
opening an alert box, and showing that the attacker,
that the attack was successful.
Finally, the last exploitation technique
involves using the remaining bytes of the split response
as another extra message that will also be placed
in the response queue.
Exploiting these behaviors will be almost the same as
exploiting HTTP response split vulnerabilities,
such as those obtained from line break header injections,
and in those cases, an attacker would split our response
using some reflection in the header name
or in the header value,
which will allow the attacker to place extra line breaks,
to control the boundaries of the headers.
In this case, the idea will be to use the HEAD,
the HEAD message to split the response,
which contains reflected data in this body
and in these headers.
In this reflected data, it must be possible
to include line break characters to build
a valid HTP response.
This behavior is not that rare in,
in reflected data is inside the body,
as there is vulnerability associated with this feature.
This is not true for line breaks for reflection
in the headers.
So that's why it's so rare to find them in the wild,
and that's why it's so rare to find
HTTP response split vulnerabilities.
So again, the first non-standard response
will go back to the attacker, as seen in previous examples.
And then the following request arriving to the proxy
will be forwarded through the same connection.
The backend will send back both smuggled responses,
and they will be concatenated at the proxy,
which will forward the first message to the client,
which issued the last request.
And then, as in the case, as in this case,
the remaining bytes are also a valid response,
a valid HTTP response.
They will be forwarded back to the next client
which sends a request to the proxy.
And this case, if the attacker was able to
reflect the line break, it would be possible
to set any arbitrary response,
controlling both the headers
and the body of the message.
However, this attack is not that easy to perform,
because it requires that the proxy either
stores the response, or that the pipeline,
or pipelining is allowed, and even enforced,
if no web cache is available.
So that's why it's hard to, to exploit this kind of,
of attacks, or this kind of techniques,
and why is not that easy to actually exploit
HTTP response splitting vulnerabilities.
So, some conclusions to finish.
First, we can say that the response smuggling,
that response smuggling does not rely
on extra vulnerabilities or special conditions to work.
This is because most of the requirements
for the explained techniques rely on the features
that the HTTP protocol offers.
What's more, almost no exploration,
no exploration phase is required,
and attacks presented in this talk can work
only with few static endpoints,
such as the one we, I showed me the, in the demo.
Also, using response smuggling
will allow an attacker to hijack both
requests and responses, in all cases,
fully compromising the confidentiality of the application.
Next, using nested injections,
and arbitrary cache poison,
it will be possible to (indistinct) users
taking valid responses from the web application,
either by affecting the resources of the server,
or by storing malicious payloads, replacing valid endpoints.
What's more, response concatenation and scripting,
as well as classic request smuggling can be used
to modify or control a request or response queue
of a persistent connection.
This completely compromises the integrity
of the connection queue, and the web application itself.
And also client process can be controlled
using arbitrary JavaScript when response injection
is possible, or when the web cache of a proxy is enabled.
And finally, with a detailed analysis
of the transmission and processing time,
is it possible to increase the reliability of the attack
and obtain these results with a few malicious requests.
So all this should be enough for vendors to
once and for all understand that
a desynchronization vulnerability just by itself
should be seen as one of the most critical vulnerabilities
or the most critical web vulnerabilities,
that a system can have.
Now, I will answer any questions that you might have,
and you can also send me any question
or doubt that you have,
or if you would like to talk about the subject,
you can do it through my email
or through my Twitter account.
Thank you.