I have an RSS feed, users will be using it to rip content to display on there site. However I need todo a check that the site doing so has access.
Its just occurred to me that I have no idea in PHP how to detect if the script is being read by a server and what the URL is of the fetch.
Is it possible?
The best approaches for this are...
Give each rss reader it's own key (or maybe even login, password). You'll be sure that nobody can read your RSS without key.
You can allow reading rss only from ips from allowed list.
Checking referer, but it's not a good idea, because referer could be faked as well as any HTTP header.
Strictly speaking it is not, unless the server/client goes to lengths to identify themselves (HTTP authentication, custom header, data provided in a POST request, etc.).
It is possible to tell the IP address of the fetching server using $_SERVER["REMOTE_ADDR"]. Whether anything else is possible to tell depends on the methods your users use to "rip" the feed.
$_SERVER["REMOTE_ADDR"] gives you the IP of the requesting server. By checking this you could implement a basic access control check.
Related
When I print $data = file_get_contents('php://input'),It printed lots of messy code. I want to know from the php server which android device has uploaded a certain file to the server. Thank you so much!
That isn't messy code, it's details about the request which you do not understand.
Go learn how the HTTP protocol works, you can't tackle this problem if you don't understand what you're working with.
You can only find out what a user-agent provides. If they are not sending a request header over HTTP with a device version number, then no you will not get that.
Typically the OS is included in the User-agent string. This is likely to be the only place you'll find anything close to what you're looking for.
If you want to identify the specific user, the best you can do (by design of many of the systems between you and the device), is implement "sessions" using HTTP cookies. If the requests are coming from a browser, once you set a cookie, every subsequent request from that individual user will have the same cookie with it.
The general pattern we use is to look for an existing cookie, and if there isn't one (i.e. new user): create a unique random string, store it somewhere on the server associated with this "user", and then send it to the user as a cookie.
The PHP session features can greatly assist you in this.
Keep in mind you can only track a user in this anonymous way. You cannot get an actual device ID from the device unless you also wrote the app on the device which is sending the request. and this is good.
This may have a simple answer (and I hope it does) but looking online I only found examples of how to get the current URL/Domain. No where could I find how to get that of the incoming http requst.
My set up is a REST api that handles the typical GET/POST/DELETE/PUT requests. I have to return domain information for clients about the domain they're pulling from. Hence, if a client using my CMS clicks on info, he must receive info about the domain he is logged into (and thus sending the request from).
I chose not to add code here, seeing as my question pertains less to actual code as it does to methodology. Thanks in advance for any and all answers!
In Internet every address could be faked (VPN, proxies etc). It's one of fundamental principles of the network.
You will never could detect with 100% warranty, so the maximum what You could have is $_SERVER['HTTP_REFERER'] and $_SERVER['REMOTE_ADDR'].
You could make additional verification for it's existence before to save/process it, but it could cost some additional performance of Your server.
If Your aim is to provide some additional access rules to some methods / data, You should use an other verification mechanism (tokens, passwords etc).
print_r($_SERVER);
may be it'll useful for you
It sounds as though you're looking for the HTTP referer, accessible in PHP through $_SERVER['HTTP_REFERER'].
As far as I know, there are no reliable ways to determinate the domain where a request comes from. Maybe you could check the client's IP address and/or the HTTP referer and match it to a set of domains,... but that wouldn't be 100% safe in my opinion.
How about implementing an (optional) parameter for your API calls, which has to be the domainname?
I ended up defining a key constant in an external php file that I will deliver to the client within the CMS. (Already have a bunch of constants anyway).
On the server side I put the key in the database and compare these keys on every request. This is not fool proof but I realized I could use the key for other functions aswell and so I implemented it anyway.
Using this combined with various other security checks I found it unnecessary to have to track the request domain. Thanks for the responses guys!
I have a script that uses JSONP to make cross domain ajax calls. This works great but my question is, is there a way to prevent other sites from accessing and getting data from these URL's? I basically would like to make a list of sites that are allowed and only return data if they are in the list. I am using PHP and figure I might be able to use "HTTP_REFERER" but have read that some browsers will not send this info.... ??? Any ideas?
Thanks!
There really is no effective solution. If your JSON is accessible through the browser, then it is equally accessible to other sites. To the web server a request originating from a browser or another server are virtually indistinguishable aside from the headers. Like ILMV commented, referrers (and other headers) can be falsified. They are after all, self-reported.
Security is never perfect. A sufficiently determined person can overcome any security measures in place, but the goal of security is to create a high enough deterrent that laypeople and or most people would be dissuaded from putting the time and resources necessary to compromise the security.
With that thought in mind, you can create a barrier of entry high enough that other sites would probably not bother making requests with the barriers of entry put into place. You can generate single use tokens that are required to grab the json data. Once a token is used to grab the json data, the token is then subsequently invalidated. In order to retrieve a token, the web page must be requested with a token embedded within the page in javascript that is then put into the ajax call for the json data. Combine this with time-expiring tokens, and sufficient obfuscation in the javascript and you've created a high enough barrier.
Just remember, this isn't impossible to circumvent. Another website could extract the token out of the javascript, and or intercept the ajax call and hijack the data at multiple points.
Do you have access to the servers/sites that you would like to give access to the JSONP?
What you could do, although not ideal is to add a record to a db of the IP on the page load that is allowed to view the JSONP, then on the jsonp load, check if that record exists. Perhaps have an expiry on the record if appropriate.
e.g.
http://mysite.com/some_page/ - user loads page, add their IP to the database of allowed users
http://anothersite.com/anotherpage - as above, add to database
load JSONP, check the IP exists in the database.
After one hour delete the record from the db, so another page load would be required for example
Although this could quite easily be worked around if the scraper (or other sites) managed to work out what method you are using to allow users to view the JSONP, they'd only have to hit the page first.
How about using a cookie that holds a token used with every jsonp request?
Depending on the setup you can also use a variable if you don't want to use cookies.
Working with importScript form the Web Worker is quite the same as jsonp.
Make a double check like theAlexPoon said. Main-script to web worker, web worker to sever and back with security query. If the web worker answer to the main script without to be asked or with the wrong token, its better to forward your website to the nirvana. If the server is asked with the wrong token don't answer. Cookies will not be send with an importScript request, because document is not available at web worker level. Always send security relevant cookies with a post request.
But there are still a lot of risks. The man in the middle knows how.
I'm certain you can do this with htaccess -
Ensure your headers are sending "HTTP_REFERER" - I don't know any browser that wont send it if you tell it to. (if you're still worried, fall back gracefully)
Then use htaccess to allow/deny access from the right referer.
# deny all except those indicated here
order deny,allow
deny from all
allow from .*domain\.com.*
I have a web application that pulls data from my newly created JSON API.
My static HTML pages dynamically calls the JSON API via JavaScript from the static HTML page.
How do I restrict access to my JSON API so that only I (my website) can call from it?
In case it helps, my API is something like: http://example.com/json/?var1=x&var2=y&var3=z... which generates the appropriate JSON based on the query.
I'm using PHP to generate my JSON results ... can restricting access to the JSON API be as simple as checking the $_SERVER['HTTP_REFERER'] to ensure that the API is only being called from my domain and not a remote user?
I think you might be misunderstanding the part where the JSON request is initiated from the user's browser rather than from your own server. The static HTML page is delivered to the user's browser, then it turns around and executes the Javascript code on the page. This code opens a new connection back to your server to obtain the JSON data. From your PHP script's point of view, the JSON request comes from somewhere in the outside world.
Given the above mechanism, there isn't much you can do to prevent anybody from calling the JSON API outside the context of your HTML page.
The usual method for restricting access to your domain is prepend the content with something that runs infinitely.
For example:
while(1);{"json": "here"} // google uses this method
for (;;);{"json": "here"} // facebook uses this method
So when you fetch this via XMLHttpRequest or any other method that is restricted solely to your domain, you know that you need to parse out the infinite loop. But if it is fetched via script node:
<script src="http://some.server/secret_api?..."></script>
It will fail because the script will never get beyond the first statement.
In my opinion, you can't restrict the access, only make it harder. It's a bit like access-restriction by obscurity. Referrers can be easily forged, and even with the short-lived key a script can get the responses by constantly refreshing the key.
So, what can we do?
Identify the weakness here:
http://www.example.com/json/getUserInfo.php?id=443
The attacker now can easily request all user info from 1 to 1.000.000 in a loop. The weak point of auto_increment IDs is their linearity and that they're easy to guess.
Solution: use non-numeric unique identifiers for your data.
http://www.example.com/json/getUserInfo.php?userid=XijjP4ow
You can't loop over those. True, you can still parse the HTML pages for keys for all kinds of keys, but this type of attack is different (and more easily avoidable) problem.
Downside: of course you can't use this method to restrict queries that aren't key-dependent, e.g. search.
Any solution here is going to be imperfect if your static pages that use the API need to be on the public Internet. Since you need to be able to have the client's browser send the request and have it be honored, it's possibly for just about anyone to see exactly how you are forming that URL.
You can have the app behind your API check the http referrer, but that is easy to fake if somebody wants to.
If it's not a requirement for the pages to be static, you could try something where you have a short-lived "key" generated by the API and included in the HTML response of the first page which gets passed along as a parameter back to the API. This would add overhead to your API though as you would have to have the server on that end maintain a list of "keys" that are valid, how long they are valid for, etc.
So, you can take some steps which won't cost a lot but aren't hard to get around if someone really wants to, or you can spend more time to make it a tiny bit harder, but there is no perfect way to do this if your API has to be publically-accessible.
The short answer is: anyone who can access the pages of your website will also be able to access your API.
You can attempt to make using your API more difficult by encrypting it in various ways, but since you'll have to include JavaScript code for decrypting the output of your API, you're just going to be setting yourself up for an arms race with anyone who decides they want to use your API through other means. Even if you use short-lived keys, a determined "attacker" could always just scrape your HTML (along with the current key) just before using the API.
If all you want to do is prevent other websites from using your API on their web pages then you could use Referrer headers but keep in mind that not all browsers send Referrers (and some proxies strip them too!). This means you'd want to allow all requests missing a referrer, and this would only give you partial protection. Also, Referrers can be easily forged, so if some other website really wants to use your API they can always just spoof a browser and access your API from their servers.
Are you, or can you use a cookie based authentication? My experience is based on ASP.NET forms authentication, but the same approach should be viable with PHP with a little code.
The basic idea is, when the user authenticates through the web app, a cookie that has an encrypted value is returned to the client browser. The json api would then use that cookie to validate the identity of the caller.
This approach obviously requires the use of cookies, so that may or may not be a problem for you.
Sorry, maybe I'm wrong but... can it be made using HTTPS?
You can (?) have your API accessible via https://example.com/json/?var1=x&var2=y, thus only authenticated consumer can get your data...
Sorry, there's no DRM on the web :-)
You can not treat HTML as a trusted client. It's a plain text script interpreted on other people's computers as they see fit. Whatever you allow your "own" JavaScript code do you allow anyone. You can't even define how long it's "yours" with Greasemonkey and Firebug in the wild.
You must duplicate all access control and business logic restrictions in the server as if none of it were present in your JavaScript client.
Include the service in your SSO, restrict the URLs each user has access to, design the service keeping wget as the client in mind, not your well behaved JavaScript code.
Is it possible to check who is entering your website in PHP. I have a web application ( written in PHP) that should only allow users entering from some particular websites. Is it possible to get the referral websites by examining the _Request object? If yes, how?
Yes, but keep in mind some proxies and other things strip this information out, and it can be easily forged. So never rely on it. For example, don't think your web app is secure from CSRF because you check the referrer to match your own server.
$referringSite = $_SERVER['HTTP_REFERER']; // is that spelt wrong in PHP ?
If you want to only allow requests from a specific domain you'll need to parse some of the URL to get the top level domain. As I've learned more, this can be done with PHP's parse_url().
As andyk points out in the comments, you will also have to allow for www.example.com and example.com.
While you can look at $_SERVER['HTTP_REFERER'] to get the referring site, don't bet the farm on it. The browser sets this header and it's easily spoofed.
If it's critical that only people coming from specific referrers view your site, don't use this method. You'll have to find another way, like basic auth, to protect your content. I'm not saying that you shouldn't use this technique, just keep in mind that it's not fool-proof.
BTW, you can also block referrers at the apache level using mod_rewrite.
You cannot trust the referrer. Despite coming from the $_SERVER array, it is actually a user/browser supplied value and is easily faked, using such things as the Firefox RefControl addon.
You need to examine the $_SERVER array for the 'HTTP_REFERER' key.