How do I securely identify a remote device in PHP? - php

Is there a safe way, to identify a device which might be behind a Router (so the IP is not unique) in PHP?
Background: I have several embedded devices (self programmed & adaptable) which contact a webserver (php+mysql) with status updates. These updates are then - if the source is confirmed - saved to the database.
As I understand it $_SERVER['REMOTE_ADDR'] usually can be trusted (except some IIS configuration where it may - under special circumstances - wrongfully return 127.0.0.1; but different story)
Anyhow since I use SSL, the IP address really should not be a problem, because there a handshake is required and if the IP is faked or simply wrong, the connection should not be established
For now I require IP addresses to be whitelisted by admin, for an status update to be acceppted
The device additionally sends the MAC address via $_POST to identify the different modules with identical IP address (I know this can very easily be forged, and right now will be trusted if the IP address is trusted)
So first of all I am not sure if the IP address in itself is enough for it to be safe from attacks from the outside
Secondly if the device is behind a router, it will have the same IP address as every PC/device on that network. So about anyone there could forge a status update with a fake MAC address (simply as post variable), and since the IP address is whitelisted it will be trusted
So is there any way of confirming the identity of a device, or do you know a better way of doing this?
Aside: Going the other way, and have the webserver poll the different devices might be an option, but since there might be many (> 2000) devices of which we need the very last status (change) I thought it to be inefficient.

IP addresses can be spoofed, MAC addresses can be forged, so theses methods are not sufficient. The general approach is to assign a key to each client device (possibly the same key to all devices, even if this probably a bad idea). The "key" can be anything from a predefined string (weak, think username/password) to a signed certificate (strong, think SSL).
Both can be implemented either at the application level (by PHP) or at server level. If your application runs on Apache httpd server, I would rather recommend using its built-in features as it supports both approaches.

Related

How to be safe from IP address hacking

I'm trying to make a website. I want to be safe from 'IP address hacking'.
Is there any full proof way to be safe from IP address hacking by php?
How can i hide my server's IP address by php?
Is there a [fool-proof] way to be safe from IP address hacking by php?
No1. The same applies to other web server technologies as well.
However, if you follow "best practice" for securing your PHP site, you should be relatively safe. In this case, "best practice" would include:
Making sure that you following the relevant advice on how to write secure PHP code.
Applying all relevant security patches in a timely fashion.
Avoiding complication 3rd-party applications, libraries, plugins, etc that have a dubious record as far as security is concerned ... or that are old and/or poorly maintained.
But I'm not a PHP developer / security expert. I suggest you Google for articles on securing PHP ... or buy a book.
How can i hide my server's IP address by php?
You can't.
If you want your server's IP address to be hidden, that has to be implemented at the networking level. The most obvious way to hide the IP address is to change it to a private IP address; i.e. an address in one of the ranges listed here:
http://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
Another way to do it would be to put it behind a firewall that blocked incoming traffic; e.g. TCP connects.
HOWEVER, if you hide your server's IP address using a firewall or a private IP address, that means that external clients (for whom the IP is hidden) won't be able to use your server (directly).
A final option would be to implement a "reverse proxy" between your server and the clients. HTTP requests sent to the reverse proxy are then relayed to the server the responses are passed back. Note that the IP address of the reverse proxy cannot be hidden ... for the reasons given above.
1 - Actually there is one way. Disconnect the server from all networks! Unfortunately, that defeats the purpose of implementing a web server in the first place ...

how to solve the issue of "referer value is wrong" in form sending?

I'm a user of a certain forum, but recently my IP adress has been being blocked.That's not my fault but some users probalbly broke the rule and his ISP or IP address is same or close to mine, so I was enmeshed.
I rent a web server, so now I try to post comments to the forum from my server, but it fails.
When I post a comment using a form in the site, the error says that the referer was wrong.
I tried header() function using PHP but it doesn't work.
I tries to change referer but still it doesn't work.
I think if I could have a client in my web server, the IP and host change in posting comments, without changing referer information.But I don't know how to do this.
The restriction is temporary, maybe a few weeks, so I don't necessarily need a perfect and permanent solution.
Is there any ways to solve this problem?
If they're blocking you based on IP address, then it's the web IP address of your local network that they're blocking. If they've decided to block a range of IPs then you have a larger problem depending on your host.
A few things you can try:
Chances are (unless this is a work account) that you're using a dynamic ip address from your host. A lot of work accounts use a dynamic IP too, but you would need access to the modem (since you're probably not the corporate network administrator). Sometimes to get a new IP address from a completely different range by unplugging your cable or DSL modem and plugging it back in after about 30 seconds. Most electronics clear instantaneously (unless they have an onboard battery backup), but in the case of network components they purposely build in a few seconds of wait time in DHCP servers before providing a completely different IP address. Usually when I'm having a problem on my local network or doing an upgrade and unplug my modem after about 10 minutes of work when I plug my modem back in I have a new IP so I have to go through all of the trouble of re-whitelisting myself everywhere (so I know this works).
You could try connecting to the boards through your cell phone if you can tether your cell phone to your workstation or desktop. This will provide you with an IP address through the cell phone carrier's network (Note: it might violate the TOS).
You could do as #Bergi suggested and use a proxy. Some web browsers (like Opera) allow you to specify a proxy in the browser without forcing all of your desktop traffic to a different network. You can obtain a proxy server address from several resources, but this is one of my favorites. Be sure to use an HTTPS proxy in order to have the best defense against someone packet filtering and catching your credentials. People can still capture the initial handshake for SSL and decrypt your communications (so make sure this is what you want to do.)
You can try to force inject headers into the message board and make your server post for you. Good forum software will check the referrer and the user_agent to see if you are a "real person" (however real the programmer felt you needed to prove). If there is a CAPTCHA you will need to be able to see the image, hear the sound, or use a plug-in to break it. (This will require research). Chances are your web server is using a static IP, so there is nothing to prevent the board from blocking this one as well. (You will not be able to change it.) If the web host has strict guidelines about using their servers for this sort of thing it might *cost you your account*. I will not provide an example for this on this board. But you can check out a book called WebBots, Spiders, and Screen Scrapers.

How to fake $_SERVER['REMOTE_ADDR'] variable?

Is it possible to fake or hijack a content of $_SERVER['REMOTE_ADDR'] variable?
I would like to fake a request with:
$_SERVER['REMOTE_ADDR']='127.0.0.1';
How could I do that with PHP? Can CURL do that somehow?
I assume that you mean faking it remotely. The short answer is yes you can. The long answer about how easy it is depends on how you want to fake it.
If you don't care about receiving a response, it's as trivial as opening a raw socket to the destination and forging the source IP address. I'm not sure if it's really easy to do in PHP since all of PHP's socket implementations are at or above the TCP level. But I'm sure it's possible. Now, since you're not in control of the network, the response will not go back to you. So that means that you cannot (reliably anyway) create a TCP connection via a trivial forged TCP header (since the syn-ack does prevent this by requiring two-way communication).
However, if you can compromise the gateway the IP is off of, you can do whatever you'd like. So if you compromise the wifi router a computer is connected to, you can pretend to be that computer, and the server won't tell the difference. If you compromise the ISP's outbound router, you can (in theory at least) pretend to be the computer and the server won't tell the difference.
For some more info, see these following links:
ServerFault Question
Symantec Article
Linux Security Article
However, you will only be able to forge the 127.0.0.1 loopback address under TCP if you actually compromise the local machine/server. And at that point does it really matter?
Important
If you're using a framework to access this information, be absolutely sure that it does not check the X-HTTP-FORWARDED-FOR header! Otherwise it's trivial to fake the IP address. For example, if you're using Zend Framework's Zend_Controller_Request_Http::getClientIp method, be absolutely sure that you pass false as the parameter! Otherwise someone just needs to send an HTTP header: X-Http-Forwarded-For: 127.0.0.1 and they now appear to be local! This is one case where using a framework without understanding how it works in the backend can really be bad...
Edit: Relevant
I wrote a blog post recently about how I stumbled across a vulnerability in StackOverflow's application. It's very relevant here, since it exploits a very similar mechanism to what this question is looking for (although the circumstances around it are somewhat narrow):
How I Hacked StackOverflow
The remote address is not something added out of courtesy, it's used in the IP protocol to route packages, so if you send a package with a fake address, you will not receive a response, and since you're talking about a HTTP request, which is delivered over a TCP connection, which takes several IP packets (and the matching responses) to set up:
No, that's impossible (except of course by actually sending the request from the same host via the loopback interface).
Apache populates $_SERVER['REMOTE_ADDR'] from a TCP socket that it uses to communicate with your browser. It is IMPOSSIBLE to influence this variable over the open internet because of the three-way-handshake. If the client and the server is on a broadcast network, like wifi, then you can sniff the wire and complete the handshake.
If you browse via a proxy, $_SERVER['REMOTE_ADDR'] may be set to the proxy's IP address rather than the end user's.
There are other headers which you can use instead in this case: This page gives a function which checks all the possibilities and provides the address most likely to be the end user's:
http://roshanbh.com.np/2007/12/getting-real-ip-address-in-php.html
However if the user is proxying using a badly configured proxy, or a malicious one, or one designed to anonymise the end user, then you won't be able to guarantee any of the headers other than REMOTE_ADDR (which would only lead you as far as the proxy).
If your end user is browsing via HTTPS, then REMOTE_ADDR will always be his IP address; you can't use proxy forwarding via HTTPS. Therefore, the one way to be absolutely sure of his address is to get him to open your site in HTTPS.
You can overwrite any item in the $_SERVER array, including the one you mention, in your server; of course, not in someone else's.
However, it won't change your computer's IP address.
REMOTE_ADDR
The IP address from which the user is viewing the current page.
You can request script using proxy, etc. to change IP address but you cannot set there any text you want.
That is a variable set by apache or whatever server you're using. You cannot spoof it.
You may run $_SERVER['REMOTE_ADDR']='127.0.0.1'; at the beginning of the scripts, but i doubt thats what you're trying to do

Website - nearly same clients, different informations

There are two (or more) computers on LAN with internet access.
They have the same:
operating system,
browser and browser version,
user name.
They are visiting my webpage which can use js and php to retrive informations.
Is there any way I can find differences between these clients with retrived information?
Which informations are different?
Set a (random valued) cookie or a session.
The two machines will have unique identities.
Their IP addresses would be different, unless they're using a proxy and/or NAT firewall. That information can be retrieved trivially via $_SERVER['REMOTE_ADDR']. There may an X-Forwarded-For header that some proxies might put in place, revealing the internal address, but it's not guaranteed to be there, and definitely not guaranteed to be reliable.
There's a few client-side tricks you can use to get machine's local address, but again, if they're behind a NAT firewall and/or proxy, there's no guaranteed that both machines aren't on two seperate networks and both coincidentally have the same private IP address.

What are the possible return values for $_SERVER['REMOTE_ADDR'];?

In writing a login module, I want to log IP's as an additional measure for verifying who's on the other side is still the same person on the other side.
I'm using $_SERVER['REMOTE_ADDR'] as one (of many) ways to get the remote machine's IP address. Aside from an IPv4 or IPv6 address, are there any other values i should expect this to return?
According to the PHP online documentation only an IP address should be returned.
http://us.php.net/manual/en/reserved.variables.server.php
“'REMOTE_ADDR':
The IP address from which the user is viewing the current page.”
The value can be an IPv4 or IPv6 address. Although you will probably only get canonical values be aware that IP addresses can be written in several ways. 192.0.2.1 is the same as 192.000.002.001, 2001:db8::1 is the same as 2001:0db0:0000:0000:0000:0000:0000:0001, etc. IPv4 addresses can even be written in IPv6 notation like ::ffff:192.0.2.1 or ::ffff:c000:0201 if the webserver accepts IPv4 connections on IPv6 sockets. I see that on Linux systems a lot.
Logging IP addresses should not be a problem as long as you reserve enough space. Actually using IP addresses for access control is getting more and more tricky these days. Because big parts of the world have run out of new IPv4 addresses you will see that ISPs have to use NAT on a large scale to keep connecting new customers to the IPv4 internet. These large scale NATs will use a pool of public IPv4 addresses for maybe thousands of customers. One IP address can be used by many customers, and one customer might end up using different addresses from the pool.
In IPv6 tracking the IP address has other things to take into account. The original IPv6 auto-configuration mechanism is based on using the MAC address as part of the IPv6 address. Because of privacy concerns most operating systems now use a (kind of) randomly generated interface identifier (usually the last 64 bits of the address) for outgoing connections, and those bits can/will can change over time. Some operating systems (Mac OS X) even keep statistics on whether IPv4 or IPv6 is faster and I have seen clients switch back and forth between IPv4 and IPv6 on occasion.
And then you can have users that roam from one wireless hotspot or office network to another, thereby switching IP addresses.
So I think logging IP addresses might make sense based on what you want to do with the data, but using them as (part of) a form of access control might cause more trouble than it's worth.
There's really no added security to checking IP addresses as these can be easily spoofed and anyone who's savvy enough to be intercepting POST transactions is probably doing this anyways.
Also, you may be potentially annoying legitimate users. Think of the instance where a person may be in a location where there are several free open wifi hotspots. When they get to your login page, they may be connected to one hotspot but by the time they sign in, their machine may have decided another router is a better option and therefore their IP will change. Believe it or not, this may deter some (albeit, very few) easily-frustrated users.
Honestly, I just wouldn't bother. Using SSL, if you can, is usually the best way to go to avoid security issues like the one you're describing. Good luck with your project.

Categories