Hacker's view for easy-spoofing an IP address.
The way for protecting our sites against this fake.
It has been told very much about IP spoofing, as this is a desirable feature wanted in order to obtain priviledges or get a credential for accessing a site.
I am not going to talk about TCP, packet sniffing, or such other hacker techniques involving networking stuff, as competence for solving those troubles is of network administrator and not of webmasters.
What i am going to talk about, is the fact of faking a source IP for a connection to a webhost by the use of the HTTP protocol. This way we as web programmers can see the dangers of giving some confidence to IPs when the user authenticates into a restricted or priviledged area.
For instance, consider the case of phpBB forums. You can get logged as an administrator if you get to fake the administrator's session ID and IP. Getting session IDs is a topic that we won't talk about in this text. Maybe i'll explain in further texts aimed to prevent XSS and SQL injection attacks, but what i want to state here is that once we get the session ID, it's really easy to fake the source IP (because of the way phpBB is programmed) so we can get rid of those security checks.
Many ISPs use what is named as "transparent proxies" for web browsing connections (port 80), these are cache servers that act as gateways between users and webservers. The ISP choses to impose those transparents to users, because such proxies can save previous webpage requests and send a local copy (cached) when the same pages are requested again. This way the ISP doesn't have to establish a full internet connection, but an intranet, that costs much less. The process is in most cases transparent, that is, the user has no clue that is using a proxy.
The downside is that webservers can't see a direct connection from the user. The only connection they see is the one coming from the proxy. An often used workaround for this, is to set up some HTTP variables at the proxy, indicating the real IP of the user (then it can be used for checking that a certain user is loggin into an area of the website).
For those who don't know about HTTP variables, these are parameters that the browser and server exchange in order to set up the transmission of a webpage or a file (these are transmited in the part of HTTP protocol that is reserved to the header of the HTTP request), or data in general. For instance, one well-known HTTP variable are the cookies that the browser send to the server.
There are some HTTP request header variables related to proxy identification. One of them is the "X-Forwarded-For" variable. This variable is automatically added when the request goes through the proxy, and holds a list of the IPs that the conection has crossed through. The last IP is the originatin IP, that is, the IP of the user.
Let's see an example:
If i do a request for www.google.com, the browser will connect to www.google.com and will send something like this:
GET / HTTP/1.1 Host: www.google.com Pragma: no-cache Referer: http://www.astahost.com/index.php Cookie: Blablabla=blalbalbla; User-Agent: Netscape Connection: Close Content-Length: 0
This is easy to explain. The first line is the request for the index page at www.google.com, the Host variable says that efectivelly, we want to contact to the google.com that is located at the server we have connected to. Referer says where we were visiting before we went to google.com, Cookies no need of an explanation. User-Agent identifies what is the browser that the user use to navigate with. Connection variable in this case says that there is a non persistent connection, that is, one connection per request. Content-Length in this case is 0 because we won't transmit more data once finished the header field.
If i do a request for www.google.com, and my ISP establish a proxy beween my internet connection and the target server, then the browser will connect to the proxy (without realizing that in effect it is connected to the proxy instead to the webserver) and will send the request mentioned above. Once the request is relayed by the proxy, it modifies it by sending to www.google.com something like this:
GET / HTTP/1.1 Host: www.google.com X-Forwarded-For: 184.108.40.206 Pragma: no-cache Referer: http://www.astahost.com/index.php Cookie: Blablabla=blalbalbla; User-Agent: Netscape Connection: Close Content-Length: 0
Where 220.127.116.11 is the IP of the user. In this case, when the server script read the REMOTE_ADDR variable, it will find the Proxy IP. If exists the X-Forwarder-For header, then the server sets its value to the HTTP_X_FORWARDED_FOR variable. Then the script, once it sees that the HTTP_X_FORWARDED_FOR exist, it takes this value (the IP at the end of the chain) as the originating IP and discards the REMOTE_ADDR value, because it usually means that it hold the value of the proxy's IP.
So what if we include manually this header to our requests? For example, in the first case, we connect directly to the www.google.com server, but we add the X-Forwarded-For field of the header, and we set any IP we want, for example: 18.104.22.168.
GET / HTTP/1.1 Host: www.google.com X-Forwarded-For: 22.214.171.124 Pragma: no-cache Referer: http://www.astahost.com/index.php Cookie: Blablabla=blalbalbla; User-Agent: Netscape Connection: Close Content-Length: 0
Then www.google.com will assume that we are a proxy server, and the real IP comes from the variable X-Forwarded-For. And you see that we invented that IP, then we can fake any IP address by the use of this header variable.
For this, we use Proxomitron. There are many tutorials out there at the internet so i won't cover how to insert this header with proxomitron. Other choice may be achilles. Both programs are local proxies that modify requests the way they are set up by the user.
This is not a thing that works for all scripts. Only for those that asume that X-Forwarded-For, if present, comes from a true proxy. phpBB is one such example among many others.
Wait, so why should we use the value of X-Forwarded-For?, because a proxy is used at the same time by many users, and those users will show the same IP address when connecting to the webserver through the IP.
So, how we should program our scripts in order to avoid faked IPs and thus preventing account intrusion?
The short answer is: Not to rely on IPs when giving credentials to a request. You might focus the access security over other authentication mechanisms, such as, certificates, encryption, SSL, etc.
The no so short answer is: Not in every case is possible to get rid of the use of IP authentication. In those cases, you would like to know how to detect a fake proxy request. This is simple. Transparent proxies aren't intermitent. These are 24/7 machines. Although there is a chance that (because of balance load) a connection from a certain user goes through a proxy and the next connection from the same user crosses by a different proxy. But there are little chance that one ip is comming direct from a first connection, and proxyied from a second connection. This means that the second connection may be originated from a hacker that is faking a proxy request in order to simulate the legitimate original IP (that connected directly at a first place).
Then the script should sort those cases and then choose the appropiate action depending up on where the request came from and where the request seemed to come from.