I was wondering if there's a way to control access to a website on a similar way than app licensing works, allowing only given computers on the entire Internet to access them... I can't find a way to uniquely identify a given computer OR to discard all machines except the authorized ones... I don't want a user/password approach as it can be shared.
Your best option here is SSL certificates. Get the client to send you a certificate signing request, sign it with your custom CA, and give them a certificate to use to connect to you with. Ensure that it ties directly to a particular hostname, the hostname of the system. Not entirely fool proof, but better.
IP addresses change. MAC addresses can be spoofed. Computer names are set by the user, and computers can change locations, operating systems, hardware components, and owners.
There's a reason that the username/password combination is so prevalent on the web. And, personally, if it's secure enough for Google, it's secure enough for me.
You can limit the access by IP restriction or mac address restriction. Http server such as apache have access control modules. You can find more information about it from http://httpd.apache.org/docs/2.2/howto/access.html
Related
My office network provides internet access to my employees when they connect to it through the office's router. I want to make a web application in which only computers connected to the internet through my office router, can access. So that my employees have to be in my office area before they can login into the php web application.
If they are connected to the internet, but not through my office network they should not be able to log in to the application. (I know I could have deployed the php app in a local server setup in my office but I want the app to be on a remote server on the internet for my personal reason).
What hardware do i need to setup my office network and how do I make PHP detect the id of the hardware of my network so php can determine that a request is coming from my network.
Some options to recognise your private office from a public website:
IP address
This will only work if you know what IP address is in use at any given time by your allowed clients. In the case you use a NAT gateway, this has to be the outside address.
It becomes pretty easy to do this if you have static IP addresses for all your allowed clients, if they change, it quickly becomes a nightmare to keep them right at all times.
Security: since HTTP is based on TCP it's not trivial for other to get to use your IP address through spoofing, but it's by far not foolproof either. Consider it a poor-man solution at the very best.
Caveat: if any of your staff can get remotely to their machine, they can access it remote (so e.g. a time registration system is going to get circumvented by this quickly)
VPN
VPN stands for Virtual Private Network.
This is the goto solution from a security perspective. Essentially you build up tunnels between either individual clients or networks as a whole with the VPN server.
On the central end of those tunnel(s), your webserver answers to web requests (but not to the internet at large).
There is a whole range of VPN products out there. There are equally relatively easy to build solutions using free software (e.g. OpenVPN).
Things on how the client (network or computers) will authenticate to the server and what traffic is attracted to the VPN and much more are all possible parameters you can set.
Security: it depends a bit on the choices made, but unless unproven or outdated solutions are picked, this can be done "top notch". It is however in skill level probably just above your typical IT shop around the corner (but you might be in luck).
Same remark as above: your staff that can gain access to it, might be tunnelling into their machine at work or might use credentials and settings on an office machine at home as well.
DNS
reverse mapping of IP to names is far too easy to spoof, don't try this.
Login/Password
This is a relatively easy solution: allow access from anywhere, but give authorised users a login and password and let them have access after being logged in properly.
Security: It's non-trivial to get this fully secure, there's plenty of opportunity to make errors in how the application works so that it becomes a problem.
But if you have to have a zero footprint on the clients, this is your best option.
Add in 2 factor authentication to increase the password security and make passing on passwords a bit more difficult.
TL;DR
I'd setup an OpenVPN based VPN, they are relatively easy to setup, the clients exist for most OSes (take care not all: e.g. iOS: I don't know of one) and it'll give you more than average protection without you having to delve deeply into the details of encryption protocols and the like.
Still there's a learning curve, but there's plenty of tutorials out there that don't assume much prior knowledge either.
For your clients you setup a certificate-based authentication system using EasyRSA (included with OpenVPN). It's a bit of a habit you need to create, but once setup properly, adding and removing users becomes relatively painless.
On your server all you need to do is make sure the http server only binds to the IP address of the tunnel interface.
I'm using multiple services to accept mobile payments for stuff like virtual currency.
Many companies will include an MD5 signature in the POST or GET callback which I can calculate to verify that the request is authentic and then reward the user with the purchased credits.
This method is very secure as it's nearly impossible to guess the signature.
Other companies will not provide a signature and just tell me to check if the call is from their server IP like the following code:
<?php
if(!in_array($_SERVER['REMOTE_ADDR'],array('xxx.xx.x.xx'))) {
header('HTTP/1.0 403 Forbidden');
die('Error: Unknown IP');
}
?>
Is this IP check secure enough?? Isn't it now very easy to spoof an IP address and make a GET or a POST request using that IP?
The other answers are incorrect. So I'll write my own.
With the exception of exceedingly rare situations, REMOTE_ADDR is 100% trust worthy. It comes from the TCP connection to the server, so it's practically impossible to forge without actually compromising something on the network (like the router the IP belongs to) or without having your server misconfigured (severely, Apache doesn't even let you misconfigure it like that).
So, there are two questions that I can see:
Is it safe to trust REMOTE_ADDR
Yes.
If the REMOTE_ADDR variable in PHP indicates the request came from their server, then it came from their server.
If you're using a remote proxy, then X-HTTP-FORWARDED-FOR is not to be trusted. That's where you can get into problems if you're not careful.
Is MD5() of the request safer than REMOTE_ADDR verification
NO!!!
It's a lot easier to forge an MD5 signature than it is to forge an IP address (which requires you to breach specific network hardware). And if the attacker breaches the network hardware, the game is over anyway.
What's The Best Solution?
The best solution is three fold:
Use HTTPS with Certificate Pinning
On your app, store the public key of their server. Then force the peer verification to use that certificate. That means that an attacker would need to steal the certificate of the remote server to be able to connect.
Verify IP Addresses
Using REMOTE_ADDR
Sign requests using HMAC+SHA2
Use HMAC with SHA-256 or SHA-512.
But yes, the IP check alone is quite secure.
To go deeper, we'd need to go into what types of attacks you're defending from.
Relying on server remote address is not a secure way since IP spoofing can breach the security.
But yes there are some ways by which you can prevent it like key exchange between the machines but still there is no assurance.
Better you should not rely on IP based security.
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.
I have a small web function that should run only when the user is in the office . But the problem is that our internet provider changes its IP regularly and i cant keep track of it. We have windows 7 systems in our office and they dont have any static IP. I cant even set a static IP as it will hamper the internet provider settings and will stop connecting to internet. Im stuck now. Is there a way with which i can make sure that a person is in office only when he is using that function?
The surest way is to ID using MAC adresse since IP can be changed, MAC address is harder to spoof and does not change. It is the "serial number" of the network card. So unless they take the card home, they won't be able to access it. Have a read at
this post
You could use dyndns to get the current ip.
Dynamic dns allows ypou to redirrect a host name to a dynamic ip.
So if you get a request from a unkown ip or more then x seconds have passed since the last request you can use gethostbyname to retrive the offic ip.
Free Dynamic DNS:
http://www.dnsdynamic.org/
Getting the IP:
$ip = gethostbyname('http://sample.dnsdynamic.org/');
One way to do it would be to set up the server so it exposes 2 services - 'A' with the "special office-only function" available, and 'B' without.
Then, set up the network security so that Service A is only accessible over a VPN tunnel from your office.
--
An alternative approach might be to use PKI - get the office computers installed with certificates that are required to access the Service A functionality. However, while complicated, it is still possible for users with sufficient authority and knowledge to copy the certificate and install it at home.
If your users aren't nerds, you can set a special cookie in the office computers, and check against that every time the user accesses the application.
(If your users know to to set and unset cookies, that would fail, as they would simply copy this behavior to their home).
Also, there should still be a specific range of IPs when connecting from the office (even if the IP changes), sample a few IPs and check for a recurring pattern.
Provide your office user with some kind of token, after they authorize. Then use the token to determine if access is granted or not.
The token can be stored in a cookie on the the office users computer, so authorization is done only once.
If you have an access to office network - you may try to config your server, which gives an access to the internet, so it will add some token (cookie?) to all requests (sent to your server). And you will check it in your code.
Is there a way to get a unique serial number for machines such as Mac,Windows and devices such as iPhone,Blackberry using php/javascript?
It really requires at least one reference datum - javascript can't read things like IP addresses or MAC addresses - so that's ruled out. There are implementations of uuid for PHP - but to create a valid one, you need a real IP address assigned.
And if have code deployed serverside, its straightforward to implement a counter based system.
What is a machine?
Machines are made from parts, so determining wether a machine is still the same can be a philosophical question in its own right.
For example a computer's hard drive probably has a unique serial number, if the machine has a network card, it has a unique MAC-Address, and it might even be considered a "different machine" when running a different operating systems (Windows, Mac, etc). All those unique IDs can be mungled together to create a unique machine-ID, and this is exactly what some software vendors such as Mathematica do to make sure you don't run the software on a machine or an operating system, you have not licensed it for.
Using Interface Identifiers
With IPv6 finally becoming widely available, the Interface identifier of the protocol can serve as an identifier of your machine (or at least its network card), since it contains the MAC-address of the network card. IPv6 provides privacy extensions to prevent this kind of identification, since in the age of personal computers and mobile devices machine identification equals user identification, which is a huge privacy issue.
Currently, Apple and Android mobile devices, don't provide privacy extension, and they are deactivated on Mac and Linux by default. Only Windows 7 seems to have them enabled by default.
Accessing the IP address in PHP and javascript
In PHP it's pretty simple to access the IP address via $_SERVER['REMOTE_ADDR']
In javascript you could issue a JSONP request to a server that returns the user's IP address.
See: Can I perform a DNS lookup (hostname to IP address) using client-side Javascript?
Accessing the MAC address in Javascript
Even if the machine only has IPv4 - there is a proof of concept hack (http://samy.pl/mapxss/) that retrieves the MAC address from some routers via javascript XSS. The MAC address of your router is then sent to the google geolocation service to identify the machine's exact location. (Of course this only is a weak identifier for mobile devices)
Combining Identifiers
Webbrowsers will provide you with a useragent string, that can make your identifier even "more unique", and then there are cookies, geolocation services etc.
While none of these techniques provide a way to create a 100% unique identifier, several of those techniques combined can provide a very high accuracy of identificiation. Even if parts of a machine are changed, you might be able to re-identify it, when applying an array of identification techniques. Also note that when using browser identification etc, you may face the problem of over-identification, especially if a machine is using more than one browser to access your service.
Asking the user
Due to potential privacy issues, you should consider using an opt-in approach for creating the unique id. Also since it's the users who are in touch with their machines, they are the only ones who can uniquely identify their machine with a 100% certanity. So the best thing is to provide an incentive to the user to trust you with identifying their machines. A simple scenario, would be to provide the user with a login (so you have user identification) and then ask the user to help you with machine identification. Of course this only works if you trust your user, but if you don't, they should probably not trust you either.
No, there is no way to do that.
This is a good thing, since it makes it harder to track people via websites.
Privacy is precious ;)
Martin hurries off to delete all his cookies and put on his tinfoil hat
What is a machine?
Machines are made from parts, so determining wether a machine is still the same can be a philosophical question in its own right.
For example a computer's hard drive probably has a unique serial number, if the machine has a network card, it has a unique MAC-Address, and it might even be considered a "different machine" when running a different operating systems (Windows, Mac, etc). All those unique IDs can be mungled together to create a unique machine-ID, and this is exactly what some software vendors such as Mathematica do to make sure you don't run the software on a machine or an operating system, you have not licensed it for.
Using Interface Identifiers
With IPv6 finally becoming widely available, the Interface identifier of the protocol can serve as an identifier of your machine (or at least its network card), since it contains the MAC-address of the network card. IPv6 provides privacy extensions to prevent this kind of identification, since in the age of personal computers and mobile devices machine identification equals user identification, which is a huge privacy issue. Currently, Apple and Android mobile devices, don't provide privacy extension, and they are deactivated on Mac and Linux by default. Only Windows 7 seems to have them enabled by default.