4

Context

While studying HTTP smuggling attack patterns, i found this nice article wrote by Regilero

There is one point that i want to clarify on the credential hijacking pattern. I was more or less able to reproduce this attack in my lab:

         [Attacker]                     [Proxy]             [End Server]
             |                            |                       |
             >-req. Smuggling[+Req.evil]->|                       |
             |                            >-req. Smuggling ------>|
             |                            |                       |
             |                            |<----- resp. Smuggling-<
             |<---------- resp. Smuggling |                       |
             |                            |                       |
 [Victim]    |                            | \-req. evil --------->|
     |       |                            | (pending partial req.)|
     >------------------- req. Victim --->|                       |
     |                                    >-req. Victim --------->|[+ pending partial req]
     |                                    |                       |
     |                                    |<----- resp. evil -----<
     |<---------------- resp. evil -------<                       |
     |                                    |                       |

scenario

  • Lets assume that the end server allow the trace method.
  • The attacker own a malicious domain.
  • The attacker will forge the response (resp. evil) to be a http 302 which redirect the victim to page that contain a malicious Js script.
  • The malicious script use the trace method on the endpoint server and store the response somewhere.

Question

Hoping that this scenario is not technically wrong, does the attacker had succeeded in stealing the victim's session cookies ?

0

1 Answer 1

5

You are talking about forging redirect response. There are several problems with that:

  • forging a response means an HTTP Response splitting issue, but here the 1.5 query hijacking trick is an HTTP Request splitting issue
  • even if you were able to send a 302 redirect response to the user, this response would not contain the user credentials, and when following the redirection the victim's browser would not send the first website credentials.

But having a backend with TRACE enable may still be used in HTTP smuggling. That would be a quite complex attack, where a lot of things could fail, but that's maybe something you can reach in a lab.

The goal

  • we have TRACE available on the backend, so we want to force the victim HTTP query to be a TRACE query (implying building the first line of the HTTP query with a TRACE request and adding the real victim query to that unterminated query).
  • TRACE will echo the victim credentials (cookies) in the Response body
  • We want to see the response body (that's the very hard thing, as by default the response goes to the victim, not to the attacker)

Problems

Using the classical 1.5 query attack, where the Reverse Proxy thinks there's only one query, and the backend thinks there is 1.5 queries is already something quite hard:

  • you need to have a response from the backend for the first query in the pipeline (If you take Apache, for example, you will never get this first response until the pipeline is complete). This way the reverse proxy can believe everything is done and can reuse the tcp/ip connection with the victim query.
  • you need to have a connection reused between the Reverse Proxy and the Backend (so a keepalive connection or a tcp/ip sockets spool)
  • All this already means several exploits were used (to hide the 0.5 query from the reverse proxy, like with an hidden header, and quite certainly another to trick the backend in revealing this header and interpret the body as another unterminated query). It also means the attacker is quite certainly running a long loop of strange queries hoping to capture one of the victim query sometime (and that's a blind attack).

I made a video on this sort of attacks, the first example on this demo is a 1.5 query attack, and you can see that's a blind loop, but the victim is enforced in running a delete-user query on the application.

The result is only hijacking the user credential for the 0.5 query (so you decide for the user what is the query running on the backend), but the response goes to the victim, and he will see that the wrong query was done. You do not have the user credentials, you just have control on the victim queries. You do not even have the victim responses.

To exploit a TRACE query we need to get the hijacked query response...

So we need to add another smuggling problems, with shifting of the response stream. If we can add a shift in the order of backend response to the Reverse Proxy then the *trace response containg the credentials in the body** may not reach the victim. It may reach anybody, so maybe also the attacker.

Shifting responses

So how to shift response? That's the kind of attacks used in cache poisoning models.

Here it would be sending 2.5 queries, not 1.5. The reverse proxy would still think that's only 1 query.

         [Attacker]                     [Proxy]              [End Server]
             |                            |                        |
             >----req. A[+Req.B+Req.C]--->|                        |
             |                            >-req. A[+B+C]---------->|
             |                            |                        |
             |                            |<----- resp. A----------<
             |<---------- resp. A---------<                        |
             |                            |                        |
             |                            |      [*X*]\-req. B --->|
             |                            |                        |
             |                           [?1]<--- resp. B----------<
             |                            |                        |
 [Victim]    |                            |      [*X*]\-req. C --->|
     |       |                            | (pending partial req.) |
     >------------------- req. Victim --->|                        |
     |                                    |                        |
     |<------------------ resp. B-------<[?2]                      |
     |                                    |                        |
                                         [?3]>-req. Victim--->[+ending req C]
       [Someone]                          |                        |
           |                              |                        |
           >----req. D------------------->|                        |
           |                             [?4]<- resp.C[TRACE BODY]-<
           |<--- resp. C[TRACE BODY]-----[?5]                      |
           |                             [?6]>------ req.D ------->|
           |                              | (...) <--- resp.D------<

Ok, that's a big mess, shifting responses is always a big mess.

  • req B and req C are hidden from the reverse proxy (same attack as the classical one but you hide one complete and one incomplete response)
  • req C is a TRACE query, unterminated (unterminated header)
  • [?1],[?2] and [?3] may need to appear in a very strict and different order ([?1] after [?3], so [?3]-[?1]-[?2]), and that's tricky.
  • same thing for [?4],[?5] and [?6], [?6]-[?4]-[?5] has more chances of succeeding
  • if you have a way to control the timing of request B (slow query), you may succeed for [?3],[?1],[?2]. That's harder for [?4],[?5] and [?6]
  • socket buffering poisoning issues may help you avoiding these timing issues. The reverse proxy would store the response and reuse it on the next query (not checking that the socket already had a response before adding a request in it).
  • you have to hope the [Someone] will be the attacker, the attack is running on a loop so this may effectively happen (but it also means req. D is in fact req. A[+Req.B+Req.C].
  • there's more than one way to fail this sort of attack. That's really very theoretical.
  • who's still running Trace enabled backends? I known you can enforce it in Apache, but Apache cannot be the backend in this attack, has incomplete pipelines does not send early responses (so no resp. A and no resp. B).

Just for fun, same schema with [?3]-[?1]-[?2] and [?6]-[?4]-[?5] :

         [Attacker]                     [Proxy]              [End Server]
             |                            |                        |
             >----req. A[+Req.B+Req.C]--->|                        |
             |                            >-req. A[+B+C]---------->|
             |                            |                        |
             |                            |<----- resp. A----------<
             |<---------- resp. A---------<                        |
             |                            |                        |
             |                            |      [*X*]\-req. B --->|
 [Victim]                                 |                        |
     |                                    |                        |
     >------------------- req. Victim --->|                        |
     |                                    |                        |
     |                                    |                        |
     |                                   [?3]>-req. Victim--->[+ending req C]
     |                                   [?1]<--- resp. B----------<
     |                                    |      [*X*]\-req. C --->|
     |                                    |  (filled with victime) |
     |<------------------ resp. B-------<[?2]                      |
                                          |                        |
       [Someone]                          |                        |
           |                              |                        |
           >----req. D------------------->|                        |
           |                             [?6]>------ req.D ------->|
           |                             [?4]<- resp.C[TRACE BODY]-<
           |<--- resp. C[TRACE BODY]-----[?5]                      |
           |                              | (...) <--- resp.D------<
1
  • Wow, perfect answer. Merci Régis :)
    – Baptiste
    Jul 6, 2017 at 13:12

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .