# Abusing hop-by-hop headers

Most of the content of this post was extracted from [https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers](https://nathandavison.com/blog/abusing-http-hop-by-hop-request-headers) \(come copy/pasted and some redacted by me\)

## What is a hop-by-hop header?

A hop-by-hop header is a header which is designed to be processed and consumed by the proxy currently handling the request, as opposed to an end-to-end header.

According to [RFC 2612](https://tools.ietf.org/html/rfc2616#section-13.5.1), the HTTP/1.1 spec treats the following headers as hop-by-hop by default: `Keep-Alive`, `Transfer-Encoding`, `TE`, `Connection`, `Trailer`, `Upgrade`, `Proxy-Authorization` and `Proxy-Authenticate`. When encountering these headers in a request, a compliant proxy should process or action whatever it is these headers are indicating, and not forward them on to the next hop.

Further to these defaults, a request [may also define a custom set of headers to be treated as hop-by-hop](https://tools.ietf.org/html/rfc2616#section-14.10) by adding them to the `Connection` header, like so:

```text
Connection: close, X-Foo, X-Bar
```

## The theory on abusing hop-by-hop headers

In theory, proxies should remove hop-by-hop headers received before sending them to the next address. But you can find in the wild that this is done by some proxies and others just send all the headers adding its own `Connection`header.

![](../.gitbook/assets/image%20%2897%29.png)

## Testing hop-by-hop deletions

If you find a header that makes the response of the server changes if it is set of if it is not, then you can search for hop-by-hop deletions. For example, the cookie header will make the response of the server to be dramatically different if it is set \(with a valid content\) and if it is not.

So, send a request with a valid header and with this value of the Connection header `Connection: close, Cookie` if the response is the same as if the cookie wasn't sent, then there is a proxy removing headers.

You can find if the response of the server is any different if a header is deleted using this technique using[ this script](https://gist.github.com/ndavison/298d11b3a77b97c908d63a345d3c624d). Then, if you pass in a list of known headers, such as [this one](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/BurpSuite-ParamMiner/lowercase-headers), you can observe which headers are causing effects despite not being in your original request:

```text
for HEADER in $(cat headers.txt); do python poison-test.py -u "https://target" -x "$HEADER"; sleep 1; done
```

This will cycle through the entire header list and print out if its presence in the hop-by-hop list created a different status code or response body size.

## Abusing X-Forwarded-For

In general, proxies will add the IPs of the clients inside the `X-Forwarded-For` header so the next hop will know where does the petition comes from. However, if an attacker sends a Connection value like `Connection: close, X-Forwarded-For` and the first proxy sends the hop-by-hop headers with their values \(it sends the special Connection value\), then the second value may delete the X-Forward-For header.  
At the end, the final App won't know who sent the request and may think that it was the last proxy, and is this scenario an attacker may be able to access resources protected by IP whitelisting \(maybe some `/admin` ?\).

Depending on the system being targeted, you may also have `Forwarded`, `X-Real-IP`, and a bunch of others that are less common.

## Detecting Proxies and fingerprinting services

This technique may be useful to detect proxies \(using the cookie technique\) or even to detect services. For example, if you abuse this technique to delete the header `X-BLUECOAT-VIA` and an error is thrown, then you have find that Bluecoat was being used.

## Other Attacks

* For a possible DoS Cache poisoning abusing this technique read the original link
* This could be useful in attacks that may allow you to insert new headers \(low probability\)
* Also,it could be useful to bypass defensive functionalities. For example, if the lack of a header means that a request shouldn't be processed by a WAF, you could bypass a WAF with this technique.

