PHP: Checking domain referrer with an API - php

Is there any way to validate that a request to my API is coming from a specific domain without the risk of someone tampering with it?
For instance, if I get a request to:
http://www.mydomain.com/api?request=something&key=12345
I can check to be sure that the API key 12345 has been assigned to a user before returning the results. However, I would like to confine that API key 12345 to a specific domain so that only a person from theirdomain.com would be able to send API requests using the key 12345.
I'm not asking how to program that part, I know that. I'm just asking if there's any way to do so (or any other ideas you may have) aside from using $_SERVER['HTTP_REFERER'] (something more secure)?

There is nothing built into HTTP that allows you to detect the "context" of a request, apart from voluntary (and therefore trivially spoofable) information from the client, such as the Referer header.
If this is a server-to-server API (rather than something which will be requested directly by a user's browser), you could check the source IP address, using $_SERVER['REMOTE_ADDR']. This is much trickier to fake, particularly if you're whitelisting rather than blacklisting IPs. (It's easy to find another IP, to avoid a blacklist, but near-impossible to choose your IP, to avoid a whitelist).
This is often used in e-commerce and e-payment APIs, where the owner of an account provides a list of IP addresses on setup, or in a customer control panel, to make it harder for third parties to use a stolen username and password.

Related

Is saving users' $_SERVER['REMOTE_ADDR'] for identification ethically okey?

I want to skip a login process and instead save users' server IP with PHP's "$_SERVER['REMOTE_ADDR']" function and keep them in a database for later identification when activities are performed on my site, now to the question...
Will I have to notify users that I am saving this information from them, just like if I would use cookies?
$_SERVER['REMOTE_ADDR'] is
the source IP of the TCP connection and can't be substituted by
changing an HTTP header.
And:
While it is technically possible to bidirectionally spoof IP addresses
on the Internet (by announcing foul routes via BGP), such attacks are
likely to be spotted and not available to the typical attacker -
basically, your attacker must have control over an ISP or carrier.
There are no feasible unidirectional spoofing attacks against TCP
(yet). Bidirectional IP spoofing is trivial on a LAN though.
Reference: Is it safe to trust $_SERVER['REMOTE_ADDR']?
Doing IP address filtering would be a method to reduce surface of attack by having a whitelist of IP addresses, but not doing authentication because it will only authenticate the network address and not the person.
E.g. if somebody else happens to use the same computer, he didn't need to enter any password to get the equivalent features. So you can't enforce accountability at the person level.
However if you used IP filtering in combination of something else, e.g. a PIN number on top of the IP filtering, that's already a bit better.
You don't have to notify. The cookies are notified because of a EU law.
Apache, by default, like most other similar programs keeps access logs, and many other tools you probably have in your server. These all save user-ip addresses, anyway. so you are already saving them. https://httpd.apache.org/docs/2.4/logs.html
the problem with this approach is, people on a mobile connection(an entire area using the same IP), on the same house, or using a different browser will share the same IP. Or people travelling on a mobile device will be constantly changing IP's, people with dynamic IP addresses(there are entire countries like this, this is super common)
Imagine you are using two gmail accounts and regardless of the browser, it just logs you in to the same account. Normally one would expect a site to be "fresh" when run in a different browser, for example.
Check out sessions, it is probably what you want.

Detect access by api to password protected area

I'm using a simple service called I'm PDF to create PDF versions on online invoices. Right now, the client has to login to see the online version, but as a result, the api service doesn't have access to it either. How would I detect that the pdf service is accessing the site and allow it accordingly without a password?
I thought $_Server['http_referrer'] would do it, but I didn't have any luck. I wasn't sure even what the variables would be, so I had a var_dump($_Server)it emailed to me, whenever the page was visited. It sent it beautifully when I went to the page, but when the pdf was generated, no luck.
Any ideas?
Thanks for your help!
You need to identify the user. The only way with this service seems to be to append something to the pdf URL (GET parameter).
So create some secret on the server side, sign user id with it, append it to impdf URL and parse it with your secret on request. You will end up with user id that you can use for authorization.
Have you tried looking at the IP address?
The service probably accesses the site from the same IP address (or range of addresses). If that's the case, then all you have to do is check the remote IP address of the request, which I believe is in $_SERVER['REMOTE_ADDR'] for PHP.
I should also mention that IP address ACLs are not quite perfect, though, because IP addresses can be spoofed. They probably should not be too heavily relied upon for security unless there is absolute control over (or guarantee of safety) of packets leaving and entering the network. That said, they are most likely sufficient for your "simple" security requirements.
The HTTP referer is pretty much trivial to circumvent. As such, it is not reliable enough for security and should be taken with a grain of salt.
I wouldn't go for any of the above mentioned advices. Basically they all bring down your security measures.
I'd use an API such as PDFmyURL's API, which allows you to login directly via a host of standard ways. This makes sure you don't have to build anything new.
Direct link to section on accessing secure area: PDFmyURL API documentation
Disclosure: I work for Kaiomi, which owns this service.

Implementing (secure) Api Keys in an app

I wrote a Web Application and I would like to allow other developers to get the information from it.
The server Im working on is not that awsome and cant handle that many request, so the idea is to generate and assign api keys to everyone that wants to query our information. With Api keys I can limit the daily requests and perhaps collect some statistics to see what information is really useful for the other developers.
The thing is, Im concerned about the security aspect of it. Since the Api key is going to be sent to our server (via GET/POST etc), someone could sniff the request with wireshark and get the developers API key without much effort, right?
I thought about generating a secret key and an API key. I could then instruct the other developers to concatenate them and send a hash of it to our API. I would then validate that the hash is valid and allow the request... But then the same problem would persist. A hacker could still sniff that hash and make requests on behalf of the other developer's app.
So my questions are
How can I avoid this problem?
Or better yet, Is my concern even valid? Is that a real problem?
Is there a better and secure way to allow access to my information without making it too complicated for the other developers?
What do you guys think?
I think you're trying to solve a bunch of different questions here.
If your objective is to limit the number of requests to your server, you should create a throttling mechanism. This is non-trivial, but I'd base it on IP address rather than a license key - a single licensed user might swamp your system with lots of requests. You can throttle by IP address without implementing a license mechanism.
If you want to create a licensing scheme, you need to understand cryptography etc. - it's a non-trivial problem. For instance, how do you stop a legitimate user sharing their license key with all their friends? How do you stop a hacker from stealing your key and sharing it with all of his friends?
There are a number of solutions to this - they all impose some degree of pain on your users. For instance, you can run your service on HTTPS; this stops snooping, but reduces performance. You can issue "tokens" for your service which expire after a certain number of uses; getting new tokens requires a cryptographic exchange (which might check your IP address). You might require a "challenge/response" type of logic (including an IP address validation). All these steps make life harder for your users; they probably won't thank you much for the extra work they have to do.
With respect to sniff, your problem can be solved with HTTPS on your server.
it definitely makes sense to put some authentication on the API if you want to limit access + potential some usage rate limits. If you use an API key and want to avoid sniffing then HTTPS is definitely the way to go. If that's not an option then you can also use a hash-style auth like oAuth 1.0 (http://oauth.net/core/1.0/) or Amazon AWS authentication. These work by issuing your API users with an ID and a Secret. They use the secret on the client side by inserting it into the message body, computing a hash and including the hash (not the secret) in the request. On the incoming side you compare the hash with the same operation done on the message content with their specific secret included.
This means that you can verify the sender without having to send the secret over the wire (note that the content still isn't secure - but you avoid passing the key over the wire with every request). The downside is that it's complex for developers to implement. Even if you use the oAuth 1.0 pattern which there are libraries for it's a bit of an overhead.
I work at 3scale and some of our tools might be helpful also - our systems provide API Keys, oAuth Secret sharing and also API rate limits out of the box (http://www.3scale.net and the PHP libraries are here: https://github.com/3scale/3scale_ws_api_for_php).

How do I authenticate users with a site API?

I want to build an API for users to build applications that easily interact with a site, and I was wondering what the best way to authenticate users would be.
Taking a look at other API's a lot of them have the user send the username and password as a GET parameter over a HTTPS connection. Is this the best way to go about it? Or are there other methods that I should look into or consider?
I've seen OAuth been tossed around and it looks like a good solution, but just for a simple API is it overkill?
You can use API key's. Generate a unique hash tied to an account upon request. Then check that the key is a valid key. As long as the API doesn't have any major security issues with someone using someone else's key then Authorization isn't needed. If there is a problem with someone using someone else's key then Authentication would be justified.
This is usually achieved with cookies.
The client sends their username and password with a POST request to your API (do not use GET, that's insecure). If the credentials are acceptable, then generate a random, unique session key, store it on your side and send it in a cookie back to the client (see setcookie()).
When the client now makes further requests, they send the session key cookie with the request. Check $_COOKIE for the session key if it matches a stored key on your side; if yes, that means the user authenticated.
Take note that this minimal example is vulnerable to brute-force attacks trying to guess valid session keys. You need to log invalid keys that clients send in their cookies and block their IP address for some period of time to prevent this.
Username / password in a GET isn't a great way to do this because you're potentially exposing the whole user account for hijacking even if the API has more limited functionality than logging into the site. So it's good practice to separate concerns between Web-site login and API access.
I'm not sure which case you're in but:
If the users are business customers of somekind who are embedding some type of widget or code in another website then it's probably best to use an API key which is scoped to the referrer domain (much like Google Maps does).
If they are end-users who won't know anything about the API but are going to be using Apps built by third parties then oAuth is likely to be your best bet, otherwise your users might literally be giving their usernames/passwords to unknown third parties. It's more complex but likely to be worth it in the long run.
To get a bunch of this stuff out of the box you can use something like 3scale (http://www.3scale.net) and it'll handle most of it for you (disclaimer, I work there so adjust for bias!) or there are open source libraries for oAuth in most languages (in PHP Zend-OAuth component might do the job for you).

php web based portal authentication through IP

i have a web portal running which involves basic data entry. The issue being that this is highly sensitive data. And the credibility of the data entry personel is very low.
Therefore i have implemented recording of IP when an entry is made.
The Problem i am facing is if this if this person starts forwarding his IP from a proxy server then i am unable to track authenticity of the data.
How do i detect if the IP forwarding is happening/ get the real ip address of the person.
You can't. Not in any reliable fashion.
You will only ever know the IP address of the request sender with 100% certainty. Whether this sender is a proxy or not can't be reliably detected. If it's a proxy, there's no way to get the originating IP address (reliably).
Require user logins with strong passwords or otherwise enhance your authentication mechanism.
The point of some proxy servers is to not reveal the real IP of the user. However, some proxies supply a HTTP header such as "X-Forwarded-For" or "X-Real-IP". But those headers should neither be taken granted nor should they be trusted. A user might as well just put another faked IP in there.
Basically, using the IP address as a user identifier is not reliable.
Another way to identify a user is cookies. The most simple case: You store the user ID into a cookie and store it with the data. Now the user may use browser privacy modes that flush cookies soonishly.
A way around that might be storing the user ID in different places too. See, for example, evercookie. It tries really hard, to never ever loose the user ID. But then again, the user could just change computers and you might not be able to track that. You can't be 100% sure.
You can check the X-Forwarded-For header. However, if they are using an anonymous proxy, you won't be able to retrieve the ip. You might be better off implementing a stronger username/password policy, i.e., forcing password changes often.

Categories