PHP get the site that calls your script via file_get_contents - php

I have a PHP script hosted on my site that outputs a value based on the GET parameters passed.
Other sites call this script from within their own PHP scripts via the PHP function file_get_contents with the url and get params and are served back just the value requested.
I am trying to allow only certain domains access to this script and have been using HTTP_REFERER to check who's calling the script.
if (isset($_SERVER['HTTP_REFERER'])) // check if referrer is set
{
echo $_SERVER['HTTP_REFERER']; // echo referrer
}
else
{
echo 'No referrer set'; // echo failure message
}
I am getting No referrer set when I use file_get_contents but if I use a clicked link from a page to a script with the above code the referrer displays correctly.
Am I using the wrong function (file_get_contents) to call the external script and can someone suggest the correct one or should this work?
Any help much appreciated.
Thanks

Bear in mind that the HTTP "Referer" header is an optional header -- there's no need for a site to send it to you, and it can be easily faked. If you really only want certain people to use your resources, you're better off using some form of authentication.
Typically Referer: is sent by web browsers, but there's no need for it to be -- for example, they won't send it if the referer is a secure site. With a PHP file_get_contents() there isn't technically a referer anyway; you're not being "referred" from anywhere.
Consider instead either:
Locking down by IP address (but bear in mind that multiple domains can share a single IP, and that a domain's IP can change.)
Using some form of authentication (preferably not one that transmits passwords in plain text!)
You should consider how secure you need this service to be, and what threats might attack it when deciding the right security to apply.

You would be much better to restrict based on IP address rather than domain, much more reliable. Just keep an array of allowed IP's and call in_array($_SERVER['REMOTE_ADDR'],$allowedAddresses) to validate it.
Or just require authentication via a cookie or HTTP auth...

You can't do this using HTTP_REFERER.
The HTTP_REFERER it set by the client, and it can be anything the client wants.
You have to use a password / key authentication mechanism instead.

May want to use something along the lines of a stream context to set extra headers.
http://us.php.net/manual/en/function.stream-context-create.php
Additionally, if needed, you could set a 'secret' header to authenticate the requests, rather then the referer.

Related

Save cookies from specified site to file on my server

For my example , i'll use this variables :
first_site.com = my website where i will execute the cookie get commands
specified_site.com = my second website that the client is already logged in
my_server.com = my server adress where i have a php script to handle the received data
the user is already connected to first_site.com and specified_site.com
and i want to get cookies from "first_site.com" and save them to "my_server.com"
Any way to do that , with php or javascript ?!
Regards
If both sites are yours and you have access to the server-side code on both sites, then you can have the first server forward the cookies to the second server using server-to-server communication.
The "same origin" protections built into a browser try to prevent you from doing what you want to do from purely client code (without involving both servers).
This is because you can only retrieve cookies when your page is on the domain that the cookie belongs to. And, you can only send the cookie (using ajax) to a server on the same domain as the page. So, you can't send one domain's cookie to another server. This is an obvious security violation which the browser intends to block with its "same origin" protections. You can read about those protections here.
If, you have a cooperating server from the first site, you can have that server retrieve the cookie when it is sent along with the original page request and then that server could send the cookie along to your second site using server-to-server communications. If the first domain is not yours where you can modify the server-side code, then obviously you can't run code on that server to do this.
There is no way to do that, as it would be a hudge security flaw.
Imagine if I made a website saving all your PHPSESSIDs, I could access your profile on many websites...
These are few of the options. Not the best ones though. Some general pointers to get you started:
a. You can also consider setting up VPN. This whitelist the IPS from both the servers.
You can create a REST API containing your cookie info(not public though)!!
Make your cookie data available on App1;
Make your cookie available as a Cookie object that can be served through a Request/Response Object
using "same origin" policy; you can have app2 talk to app1

How to prevent access to script except for one IP in PHP?

I have a static form on a server that does not support php:
<form action="http://otherserver.com/process_form.php"
I need the script on the file process_form.php to only be processed if the request is being sent by the static IP of the server on which the static form is hosted. How to do this?
If anyone other then that ip is attempting to request the script the script should be killed immediately.
This will not work the way you want because the IP will be that of the client, never the server on which the form is hosted.
You are looking to test the
$_SERVER["HTTP_REFERER"]
header variable. That will tell you which page the originating form was hosted on - however, it is not safe. This header is set by the client, and can be freely manipulated.
As Pekka noted, the HTTP referer can be easily spoofed. From a security perspective, this would not solve anything.
Also note that some clients and browser plugins set the referer to an empty string. Make sure that these can still access your form.

How can I hide $_SERVER['HTTP_REFERER']

How can I hide $_SERVER['HTTP_REFERER'] when a user browses to another site via a link from my site?
You can't, you have no control over the headers that are sent to another site. Headers are sent from the browser, to the site being navigated. This means you cannot manipulate them in any way (short of a MITM attack).
You could redirect the user to the site via an intermediary proxy, but that proxy will become the new referrer. e.g.
Your Link -> Proxy -> End result
Not only should this generally not be done, but it is not possible, at least in the way you are describing. It is up to the client to decide what to send in the request headers to a different server, not you.
I should also point out that this has nothing to do with PHP. PHP makes this header variable accessible to you via $_SERVER['HTTP_REFERRER'], but the problem you are trying to solve is avoiding the client from sending the referrer URL to the next server.
A few options:
If your site utilizes HTTPS, then it won't be sent.
If you build a redirector script on your site and use the HTTP Refresh header, the browser will typically not send the referrer, and if it did, you would only be sending the URL of your redirector. For example:
http://www.yoursite.com/redir.php?url=http%3A%2F%2Fwww.google.com
<?php
if (isset($_GET['url'])) {
header("Refresh: 0; " . $_GET['url']);
}
?>
Now, you must be careful with this little script. Anyone could then use your site to make a redirect look like it was coming from you. Also, using this method, anyone can inject whatever headers they want to the client. This is just to give you an idea. Finally, using the refresh header for this goes against the grain of the standards and should not be done.
Finally, Google, Facebook, PayPal, etc. all have redirector scripts. They use some sort of encrypted hash on the URL to determine if they generated the redirect or not. If you don't specify that hash and just give the URL, then the user will be prompted before redirecting. Not friendly.
Look, the bottom line is, there isn't really a reason to do what you are doing. If you are trying to hide something in your URL, then you have bigger problems. Security through obscurity is bad, mmkay?
If you're working in a controlled (intranet say) environment you might benefit from fixing browser configs see eg. http://cafe.elharo.com/privacy/privacy-tip-3-block-referer-headers-in-firefox/ but this is far from ideal.

PHP - Source (hostname) of a GET request

I have a Javascript widget that people can embed on their site.
I want to use a simple cross domain get request to pull in a hash.
However I need my PHP script to only allow this cross domain request from a series of domains I have stored in an array.
What can I do in my PHP script (not in .htaccessor iptables) to find out the source (hostname) of the get request?
Considering the client (user's browser) can send you whatever it wants, I would say there is no way to be sure which website your script is called from :
As you want to know the URL of the website embedding your widget, and not the address of the user, $_SERVER['REMOTE_HOST'] will not help
$_SERVER['HTTP_REFERER'] could seem OK, but actually is not :
The client doesn't have to send it (and it doesn't always do)
As it is sent by the client, it can be forged / faked Quite easily
So, I'd say there is no real solution to this problem, at least on your server's side (If I'm wrong, I'm interested to know !)
But maybe you can do something on the client's side : when writing all this, I thought about google maps, and it's system of API Key :
you have an (unique) API key four your domain
When you load the JS scripts from google, your send this key
if the key is not registered for the domain on which you are trying to display the map, there is an alert message, saying "The Google Maps API server rejected your request. This could be because the API key used on this site was registered for a different web site."
but the map seems to be displayed anyway -- at least on my test server
this alert is really anoying for the end-user, and I don't think anyone would want an alert displayed on their site because they are using your service withot authorisation...
Maybe you can have a look at how this is done for google maps :-)
You could use the $_SERVER variable. In particular the $_SERVER['REMOTE_HOST'] but see below for caveat:
However, your web server must be
configured to create this variable.
For example in Apache you'll need
HostnameLookups On inside httpd.conf
for it to exist. See also
gethostbyaddr().
If the requests are coming from JavaScript, you could check the HTTP referrer header ($_SERVER['HTTP_REFERER']). However, it's optional - some proxies or security programs strip the referrer header out of HTTP requests.

How do I write a simple PHP transparent proxy?

I need to make a proxy script that can access a page hidden behind a login screen. I do not need the proxy to "simulate" logging in, instead the login page HTML should be displayed to the user normally, and all the cookies and HTTP GET/POST data to flow through the proxy to the server, so the login should be authentic.
I don't want the login/password, I only need access to the HTML source code of the pages generated after logging in.
Does anybody here know how this can be accomplished? Is it easy?
If not, where do I begin?* (I'm currently using PHP)*
Have your PHP script request the URL you want, and rewrite all links and form actions to point back to your php script. When receiving requests to the script that have a URL parameter, forward that to the remote server and repeat.
You won't be able to catch all JavaScript requests, (unless you implemented a JavaScript portion of your "proxy")
Eg: User types http://example.com/login.php into your proxy form.
send the user to http://yoursite.com/proxy.php?url=http://example.com/login.php
make sure to urlencode the parameter "http://example.com/login.php"
In http://yoursite.com/proxy.php, you make an HTTP request to http://example.com/login.php
$url = $_REQUEST['url'];
// make sure we have a valid URL and not file path
if (!preg_match("`https?\://`i", $url)) {
die('Not a URL');
}
// make the HTTP request to the requested URL
$content = file_get_contents($url);
// parse all links and forms actions and redirect back to this script
$content = preg_replace("/some-smart-regex-here/i", "$1 or $2 smart replaces", $content);
echo $content;
Note that /some-smart-regex-here/i is actually a regex expression you should write to parse links, and such.
The example just proxies the HTTP Body, you may want to proxy the HTTP Headers. You can use fsockopen() or PHP stream functions in PHP5+ (stream_socket_client() etc.)
You could check out http://code.google.com/p/php-transparent-proxy/ , I made it because I was asking myself that exact same question and I decided to make one. It's under BSD license, so have fun :)
What you are talking about is accessing pages for which you need to authenticate yourself.
Here are a few things that must be laid down:
you can't view those pages without authenticating yourself.
if the website (whose HTML code you want to see) only supports web login as an authentication method, you will need to simulate login by sending a (username,password) via POST/GET, as the case may be
if the website will let you authenticate yourself in other ways (like LDAP, Kerberos etc), then you should do that
The key point is that you cannot gain access without authenticating yourself first.
As for language, it is pretty doable in PHP. And as the tags on the question suggest, you are using the right tools to do that job already.
One thing I would like to know is, why are you calling it a "proxy"? do you want to serve the content to other users?
EDIT: [update after comment]
In that case, use phproxy. It does what you want, along with a host of other features.
I would recommand using Curl (php library that you might need to activate in your php.ini)
It's used to manipulate remote websites, handling cookies and every http parameters you need.
You'll have to write your proxy based on the web pages you're hitting, but it'll make the job.

Categories