How to detect if link is from a particular domain - php

I need to be able to detect with PHP if a link is from a particular domain. I can not just check if domain is present in the link because it can be faked by appending domain.
Thanks.

Just use parse_url() as konforce mentioned. For example:
$url = "http://www.google.com/";
$parts = parse_url ($url);
print $parts["host"]; // will print www.google.com
// Or, for PHP 5.1 and above
$host = parse_url ($url, PHP_URL_HOST); // returns www.google.com
Now, the good thing about this is that appending the domain to the end of an url like this:
http://www.google.com/?www.foo.com
Wont work as the host element will still say that the link points to www.google.com and not www.foo.com.
Hope this helps.

I believe you'd want check the referrer and make sure you check with double forward slashes, since that's part of the protocol (HTTP/HTTPS) and can't be faked.
Check this link for extra reference: Determining Referer in PHP
I would check against something like...
//www.mydomain.com
//mydomain.com

Related

Q: How to check the extension of an URL website?

I would like to know if there is a way to check the extension of an URL website ? For example, do something when the website is like http://example.es/ and do another thing when the website is like http://example.fr/
I have check that there is something like
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
which returns the current URL of the web page.
Thanks for help.
Use parse_url() function to get host part of the url then explode by . and get last element of an array
Example below:
$url = 'http://' . $_SERVER['SERVER_NAME'];
echo end(explode(".", parse_url($url, PHP_URL_HOST)));
// echos "com"
From your example I assume that you are using PHP, then you can use parse_url to get the components.
https://www.php.net/parse-url
For example you can get the host example.fr and example.com, then do explode on host string to get the tld, .fr or .com, which should help you to do further if-else.

external link sends me internally

I am have a form that requests a user to submit a website and then on a different page I send a mysql query to retrieve that website an and turn it into a link by doing this in PHP (V=5.6)
$link = '' . $school_website . '';
the problem is that when i try to click this link, instead of sending me to www.google.com for example, it directs me to www.mydomain.com/www.google.com.
I fixed it originally by using substr to see if the first part was "www" and if it was adding "http://" to it and it worked but now i realize that not all websites will start out with that.
I have tried googling this problem but Im not quite sure how to word the problem so I am not getting anything.
My apologies if this is a duplicate. I did not see anything here that fits my problem, so any help would be greatly appreciated. Thanks.
Could always check if it has http/s:// with regex, if it hasn't then add http:// and the link will work as it should. Or make it ugly but simple.
Simplest way is to remove any protocol and prepend // - that would mark the link as absolute and adopt your current protocol. Even if it didn't have http/s:// it would work as it should.
$school_website = '//' . str_ireplace(['https://', 'http://'], '', $school_website);
Example:
https://google.com becomes //google.com
google.com becomes //google.com
www.google.com becomes //www.google.com
In any of the above cases it would become a absolute url.
A better but longer way would be to validate the url with regex.
Until you add http:// or https://in front of url. It will remain the relative
Like if you re on www.mydomain.com and your href attribute value is www.google.com, The attribute value remain the relative and will target to
you url.
You need http:// or https:// at the beginning of the URL of external links - in fact that should be part of your variable "$school_website", and if that one is for example retrieved from a database, that value has to be changed in the database.

How to get full url along with # symbol in php

I am using AngularJS routing with php,
so that my urls look like
http://localhost/admin/home#/categories
When ever I am trying to get url it wont gave full url. It gives only /admin/home.
I am using $_SERVER['REQUEST_URI'] and codeigniter segment. Both are not working.
Can any one help?
This information is not being past to the server I'm afraid.
The url part after # is only for browser use. You can add GET or POST parameters to pass this information to your server like:
http://localhost/admin/home?hash=categories#/categories
use:
$_SERVER[PHP_SELF]
It will give the full url, including everything.
If you want to strip stuff from the url, use things like this:
$url = trim(strtok("$url", '?'));
$url = str_replace("#!/", "", "$url");

PHP referer url and redirect

I can't seem to work out why the below sends ALL traffic to the page-not-found page, even if referred by Paypal. Any ideas?
$refererUrl = $_SERVER['HTTP_REFERER'];
$Exploded = explode("/",$refererUrl);
$urlToCheck = $Exploded[3];
$findURL = strpos($urlToCheck,'paypal.com');
if($findURL === false){
header('location:/page-not-found');
} else {
/* Do something if page referred to by Paypal */
}
You are checking if 'paypal.com' is present in $Exploded[3]. Why do you expect that part of the referer url to be the hostname? Array indexes start at 0, so counting from left to right would give you the following, indicating that 2 would be the correct index.
$Exploded = explode('http://www.google.com/?q=foobar', '/');
// $Exploded now contains:
0: http:
1:
2: www.google.com
3: ?q=foobar
However, it would be more safe to use some utility that will parse arbitrary URLs and read the hostname from the interpreted url. You could do something like this (untested):
$referer = parse_url($_SERVER['HTTP_REFERER']);
if($referer['host'] != 'paypal.com')
header('location:/page-not-found');
else
/* Do something if page referred to by Paypal */
parse_url doc: http://php.net/manual/en/function.parse-url.php
Are you sure that HTTP_REFERER is set? If you have a look at the documentation it says
The address of the page (if any) which referred the user agent to the current page. This is set by the user agent. Not all user agents will set this, and some provide the ability to modify HTTP_REFERER as a feature. In short, it cannot really be trusted.
Is it correct?
$urlToCheck = $Exploded[3];
If your reffer looks like http://www.example.com/....
the by exploding by "/" you will never got domain in 3rd index. It should be 2.
Try using
$urlToCheck = $Exploded[2];

PHP Input validation for a single input for a url

I have this very simple script that allows the user to specify the url of any site. The the script replaces the url of the "data" attribute on an object tag to display the site of the users choice inside the object on the HTML page.
How could I validate the input so the user can't load any page from my site inside the object because I have noticed that it will display my code.
The code:
<?php
$url = 'http://www.google.com';
if (array_key_exists('_check', $_POST)) {
$url = $_POST['url'];
}
//gets the title from the selected page
$file = # fopen(($url),"r") or die ("Can't read input stream");
$text = fread($file,16384);
if (preg_match('/<title>(.*?)<\/title>/is',$text,$found)) {
$title = $found[1];
} else {
$title = "Untitled Document";
}
?>
Edit: (more details)
This is NOT meant to be a proxy. I am letting the users decide which website is loaded into an object tag (similar to iframe). The only thing php is going to read is the title tag from the input url so it can be loaded into the title of my site. (Don't worry its not to trick the user) Although it may display the title of any site, it will not bypass any filters in any other way.
I am also aware of vulnerabilities involved with what I am doing that's why im looking into validation.
As gahooa said, I think you need to be very careful with what you're doing here, because you're playing with fire. It's possible to do safely, but be very cautious with what you do with the data from the URL the user gives you.
For the specific problem you're having though, I assume it happens if you get an input of a filename, so for example if someone types "index.php" into the box. All you need to do is make sure that their URL starts with "http://" so that fopen uses the network method, instead of opening a local file. Something like this before the fopen line should do the trick:
if (!preg_match('/^http:\/\//', $url))
$url = 'http://'.$url;
parse_url: http://us3.php.net/parse_url
You can check for scheme and host.
If scheme is http, then make sure host is not your website. I would suggest using preg_match, to grab the part between dots. As in www.google.com or google.com, use preg_match to get the word google.
If the host is an ip, I am not sure what you want to do in that situation. By default, the preg match would only get the middle 2 numbers and the dot(assuming u try to use preg_match to get the sitename before the .com)
Are you aware that you are creating an open HTTP proxy, which can be a really bad idea?
Do you even need to fetch the contents of the URL? Why don't you let your user's browser do that by supplying it with the URL?
Assuming you do need to fetch the URL, consider validating against a known "whitelist" of URLs. If you can't restrict it to a known list, then you are back to the open proxy again...
Use a regular expression (preg) to ensure it is a good HTTP url, and then use the CURL extension to do the actual request.
Mixing the fopen() family of functions with user supplied parameters is a recipe for potential disaster.
You could use PHP filter.
filter_var($url, FILTER_VALIDATE_URL) or
filter_input(INPUT_POST, 'url', FILTER_VALIDATE_URL);
http://php.net/manual/en/function.filter-input.php
Also try these documents referenced by this PHP wiki post related to filter
https://wiki.php.net/rfc/add_validate_functions_to_filter?s[]=filter
by Yasuo Ohgaki
https://www.securecoding.cert.org/confluence/display/seccode/Top+10+Secure+Coding+Practices
https://www.owasp.org/index.php/OWASP_Secure_Coding_Practices_-_Quick_Reference_Guide
http://cwe.mitre.org/top25/mitigations.html

Categories