Forum Moderators: coopster
Well I am trying to secure my PHP site a bit better and I wanted to ask a few peoples oppinions on security. I have read the PHP Manual security page and a few tutorials for securing my site a bit better.
What I wanted some oppinions on was the Address that is displayed in the browser....
[***********.com...]
I was curious if there is any way I can hide that so maybe it says [********...] Is there a way in PHP I can fake the address bar at the top? Or, is this even the most effective way. Is there a better way of doing something with the address bar so it doesnt reveal so much information about my website layout.
Thanks. :)
I'm sure I will have more questions to come along the way too :P
Wes
[httpd.apache.org...]
www.site.com
is "faking" an IP number. It's not even remotely a "trick", but a completely legit (even preferred) way of presenting visitors with a port into your site.
That said, keep in mind that, as the PHP manual says, security through obscurity is one of the weakest forms of protection. The reason to do this is 98.2% usability and "future protection" (can change technology, architecture without losing links) and 1.8% security. Those precise percentages are the result of extensive testing by Jakob Nielsen ;-)
this is EXACTLY what you said, so be warned accessing any page other than itemdetails.php will be redirected
/product to /itemdetails.php?products_id=product
/index.php to /itemdetails.php?products_id=index.php
If you code www.site.com?product_id=11 then you are require to know that product_id can be between say 6 and 12 (whatever your requirements are), and that the page www.site.com?product_id=anything should only have been called by a page within your own site (if that is the case). Therefore your page www.cite.com?product_id=11 should first TEST the DATA TYPE of product_id to make sure it is INT (or you could cast it to INT yourself), then TEST to make sure it is g.t. 6 and l.t. 12, and then test who called the page (if it wasn't your site then deny it), and then if all is ok go ahead and process. Anything that fails the tests should trigger an alarm and an apropriate action, and an alert to the webmaster (important step!)
Since it is alot of work to be so careful, programmers skimp and leave these parameters open (untested). That is why crackers will hit your site with www.site.com?product_id={a bunch of javascript to crash your site, or perhaps a huge string to crash your bufers, etc...}. If your code is dumb enough to process product_id without testing it first, it is insecure.
Changing POST to GET or using hidden vars or jumping to sessions or obfuscating through mod_rewrite are all fine -- if done properly, for good reasons, and if performance is acceptable. But you should not seek out these as a means of hiding an insecure website.
First is boundary checks, or data validation, which is done within your code anyway, and must be applied to any and all data that come from outside of the code - GET or POST, database, imported CSV, XML, you name it.
Second is URL rewriting, which is more SEO thing than anything else. You can combine the two to your heart's content but the first one is necessary
I really know nothing about all this but I'm slowly learning. Currently though my hosting company doesn't use APACHE. They use Microsoft NT.
I guess the only thing I can do now is validating the product_id of www.site.com?product_id=11. Does anyone have a tutorial link on doing this? And also on checking to see if it came from your site?
Thanks again for your help :)
Wes
Validating the ID is done in your code, so you need to use whatever language you're using.. search for form validation and field validation in your technology of choice (jscript, for example).
As for knowing which site, check your ISP's control panel for something called "hot linking control". That is similar... it allows you to block direct links to your pages from outside your site. Perhaps you can configure hotlinking OFF for everything but your known incoming pages.
Unfortunetly visitors aren't required to reveal their referrer (although most do) so if you try and block those who don't reveal referrer, you will lose some legitimate traffic. If you want to selectively block based on what the referrer was (as it sounds like you do) then that is why you need mod_rewrite. There is a similar config section for Windows servers as well.
$query = "SELECT product_id, field2 FROM products WHERE product_id='" . $_GET['product_id'] . "'";
Assuming you are using mysql, you can protect yourself by using the function mysql_escape_string() which will prevent people sending malicious SQL commands via your query.
You can be even more restrictive if you wish, in that you could ensure that product_id is always an integer and only an integer as in
if (is_numeric($_GET['product_id']) && is_int($_GET['product_id'] + 0) )
{
$product_id = $_GET['product_id'];
}
else
{
$product_id = 0;
}
<page loads with product_id passed in on the URL>
// cast incoming productID to INT
$_GET['product_ID']=(int)$_GET['product_ID'];
switch ($_GET['product_ID']) {
case "1":
// define appropriate product page
$inc = 'product_1_page.html';
break;
case "2":
// define appropriate product page
$inc = 'product_2_page.html';
break;
default:
$_GET['go']=0; //firmly set the var to ZERO
// load page that links to product pages
$inc = 'product_sitemap.html';
break;
}
include ($inc);
<page continues...>
Explained: product_id is passed in (and therefore presumed unsafe), so I never use it. I first cast it to INT right in the GET array, so anything but an INT will be lost forever.
In the switch test, I only act when the value matches an expected value. I have the default case load a sitemap page (so they can pick a product and continue). Notice here I explicitly types the individual product html files - in reality it is an array where the switch simply sets $inc to the appropriate array element.
If product_id is stuffed (junk, superlarge content, js code, malware html, breakout commands, whetever) it gets set to an INT equal to ZERO, and the page executes as the default case. If product_id is anything but "1" or "2", it executes the default case.
Casting the $_GET var to INT protects me from internal security flaws that might exist within PHP, such as might happen if the switch command was susceptible to buffer overruns, or something like that. With just that one line I am confident that wherever my program operates on the GET var, I don't have to worry about testing it.
Turn error reporting up to E_ALL and then run your page without a get parameter. You will get a warning or a notice. You can avoid that, if you choose to do so, by checking as in my previous post.
PHP is very friendly in this respect and you can usually count on unset vars to default to predictable values, but I think it helps create more robust code to consistently test variables, especially those dependent on user input.
I'm not sure how common the practice is among the more experienced PHP programmers. Perhaps it's old-fashioned from programming in stricter languages, but it seems like a good idea. I started out loving the loose typing of PHP and the dynamic variable creation and all that, but then I thought it allowed (did not encourage, merely did not prohibit) certain sloppy practices. I've gone back to being a bit stricter in my coding because I think it makes me stricter in my logic. That is, it forces me to run through a wider range of "what ifs" and then programming a response. I think it helps me write more solid code. You, of course, may not agree.
Tom