|
|
Racketeer
Neurotic (0) Inmate Newly admittedFrom: Insane since: May 2007
|
posted 05-23-2007 13:49
Cheers everyone!
I am adapting an existing site into a php environment. I want to do the navigation with variables and then include the appropriate content so that
www.server.net/index.php?page=services.php <- user sees the services content included on index.php
www.server.net/index.php?page=contact.php <- user sees the contact page content in index.php
As register_globals is OFF, I am using GET to obtain the $page variable:
code:
<?php
$page = ($_GET["page"]);
if (isset($page)) {
echo "Variable is set";
}
else {
$page="welcome.php";
}
echo $page;
?>
This works just fine as long as the variable is set (passed on in the URL like so: /index.php?page=contact.php)
It FAILS partially however when no variable is passed in the URL like so: /index.php
The intended page content (welcome.php) displays correctly, but an ugly warning line appears at the top of the site stating:
Notice: Undefined index: page in /home/s/server.net/user/htdocs/index.php on line 12
Line 12 is this one out of the above code:
code:
$page = ($_GET["page"]);
Since it basically works fine, I would be very happy with a way to get rid of the warning message OR some alternative coding.
HEEEEELP
|
poi
Paranoid (IV) InmateFrom: Norway Insane since: Jun 2002
|
posted 05-23-2007 14:00
What about checking if $_GET['page'] is set before assigning it to a variable ?
code:
$page="welcome.php";
if( isset( $_GET["page"] ) )
{
$page = $_GET["page"];
echo "Variable is set";
}
You could of course prefix the assignement in you line 12 by an @ but it's not the best way to go.
|
Racketeer
Obsessive-Compulsive (I) InmateFrom: Insane since: May 2007
|
posted 05-23-2007 15:52
It works! Thank you very much!
My knowledge of PHP is not very profound. I thought of assigning the "standard" variable first but I read somewhere that once a variable is assigned it cannot be changed.
Thanks for your help!
|
Tyberius Prime
Maniac (V) Mad Scientist with FinglongersFrom: Germany Insane since: Sep 2001
|
posted 05-23-2007 16:47
now... if you're doing an include ( $_GET[["page"} ) or any variant there of, chances are
very high you've just opened a grade A security hole.
|
Racketeer
Obsessive-Compulsive (I) InmateFrom: Insane since: May 2007
|
posted 05-23-2007 16:55
Well as I said, my knowledge of PHP is not very profound.
Here's the complete code:
code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>site title</title>
<style type="text/css" media="screen">
<!--
@import url("css/screen.css");
-->
</style>
<?php
$page="welcome.php";
if( isset( $_GET["page"] ) )
{
$page = $_GET["page"];
}
?>
</head>
<body>
<div class="container">
<div class="main">
<div class="header">
<div class="title">
<a href="index.php"><img src="/img/homelink.gif" alt="home" width="958" height="90" border="0" id="vtitle" /></a> </div>
<!-- close title -->
</div><!-- close header -->
<div class="content">
<?php include $page; ?>
</div><!-- close content -->
<?php include 'sidenav.php'; ?>
<div class="clearer"><span></span></div>
</div><!-- close main -->
<div class="footer">footer goes here</div>
</div><!-- close container -->
</body>
</html>
Is there a security hole?
|
Racketeer
Obsessive-Compulsive (I) InmateFrom: Insane since: May 2007
|
posted 05-23-2007 16:57
sidenav.php
code:
<div class="sidenav">
<h1>Services</h1>
<ul>
<li><a href="index.php?page=services.php">Services</a></li>
</ul>
<h1>About us</h1>
<ul>
<li><a href="index.php?page=contact.php">Contact</a></li>
</ul>
</div><!-- close sidenav -->
|
poi
Paranoid (IV) InmateFrom: Norway Insane since: Jun 2002
|
posted 05-23-2007 17:22
Sure there is a security hole if you don't check if $_GET['page'] points to a public page.
The following should pluck that hole: code:
$pagesWhiteList = Array( 'welcome.php', 'foo.php', 'bar.php', 'baz.php' );
$page="welcome.php";
if( isset( $_GET["page"] ) && in_array( $_GET["page"], $pagesWhiteList ) )
{
$page = $_GET["page"];
echo "Variable is set";
}
//...
HTH
|
poi
Paranoid (IV) InmateFrom: Norway Insane since: Jun 2002
|
posted 05-23-2007 17:35
Also you might consider doing some sort of URL rewriting. Nice URLs look more professionnal.
If you actually link directly to services.php, contact.php and so on you'll have to include the header and footer in each of these pages. No big deal.
Or you could do real URL rewriting using an .htaccess file
Or, as I tend to prefer, catch the 404 and check the $_SERVER['REQUEST_URI'] to include the header, serve the page you want and the footer. This way you can even check for typos in the REQUEST_URI. That's what I do on my site.
|
Racketeer
Nervous Wreck (II) InmateFrom: Insane since: May 2007
|
posted 05-23-2007 18:03
quote:
poi said:
If you actually link directly to services.php, contact.php and so on you'll have to include the header and footer in each of these pages. No big deal.
My original idea is to use index.php as a "frameset", containing all layout and styles and then calling the content with the above include.
The original site was done in Dreamweaver with Templates. Stripping excess and redundant code alone has reduced the overall size by more than 70%! Thats why I am quite happy about doing it this way.
I have seen URLs on other sites such as
/index.php?id=4
/index.php?id=5
I understand that it works by renaming the variable $page to $id but I simply don't know how to subsitute the *.php at the end of the variable or writing a "key" list containing ids for the actual files to be included.
I have never even remotely touched the subject of URL rewriting.
(Edited by Racketeer on 05-23-2007 18:04)
|
Tyberius Prime
Maniac (V) Mad Scientist with FinglongersFrom: Germany Insane since: Sep 2001
|
posted 05-24-2007 11:32
framesets are not only soooo 20ieth century, the also break acessibility.
Now, that line
code:
<?php include $page; ?>
is a massive security whole that allows anybody to see any file on your server - including /etc/shadow, containing (crypted )passwords and plaintext usernames. Add in a weak password on one account, and you just have found a valid username/password combo...
(Not to mention the other attack vectors... database password files)
And what's more: if php is misconfigured, $page could be an URL, pointing to a different server, allowing the attacker to include *any* code he wants!
Now take that thing down till you have at least read the documentation on php->include before your server get's hacked ( there are automated scripts for this... and they roam the net's endlessly. Don't believe you're save just because your url hasn't been published).
Those other pages probably pull their content out of databases... and the way you phrased your sentence, also shows me that you lack a concice concept of what parts urls consist of.
To make it short ( since I got some dna prep to attend to ) - you still have a lot to learn, "young Racketeer", and our ->faq is a decent place to start.
Don't hesitate with questions - we're quite eager to help out provided you've done your homework.
So long,
->Tyberius Prime
|
poi
Paranoid (IV) InmateFrom: Norway Insane since: Jun 2002
|
posted 05-24-2007 12:19
Tyberius Prime: Notice that Racketeer said "frameset", with quotes.
Racketeer: A site having pages like services.php, contact.php, welcome.php, ... seems small enough to not have to use ugly not-user-friendly-URLs.
To include the header, nav, footer, ... you can even use the Oh so convenient Apache directives: code:
php_value auto_prepend_file /path/of/the/scriptToPrepend.php
php_value auto_append_file /path/of/the/scriptToAppend.php
HTH
|
Racketeer
Nervous Wreck (II) InmateFrom: Insane since: May 2007
|
posted 05-24-2007 15:16
@Tyberius Prime
I will rethink the entire concept of using PHP at all. If I cannot use the include for security reasons then there is little reason in using PHP at all.
While I am very interested in learning PHP, I am simply lacking the time to do so. And my step by step learning by doing approach seems hardly feasible given the risks you pointed out.
@poi
I've read this tutorial http://www.yourhtmlsource.com/sitemanagement/urlrewriting.html last night so things are clearer now. It seems indeed a fine thing to do but I have yet to check whether the server supports it.
And the prepend and append looks interesting too. One learns new things every day!
|
poi
Paranoid (IV) InmateFrom: Norway Insane since: Jun 2002
|
posted 05-24-2007 16:38
you CAN use PHP! Just be careful. Check my code snippet with the $pagesWhiteList variable to see an easy way to pluck the security canyon you had.
|
Racketeer
Nervous Wreck (II) InmateFrom: Insane since: May 2007
|
posted 05-24-2007 17:32
quote:
poi said:
you CAN use PHP! Just be careful. Check my code snippet with the $pagesWhiteList variable to see an easy way to pluck the security canyon you had.
I did in fact integrate your fix for the security hole. Thank you for that. But does that fix the <?php include $page; ?> issue mentioned by Tyberius Prime?
|
poi
Paranoid (IV) InmateFrom: Norway Insane since: Jun 2002
|
posted 05-24-2007 18:05
Of course it does since it only allows $page to take a value that is in the $pagesWhiteList array, and falls back to "welcome.php"
|
Tyberius Prime
Maniac (V) Mad Scientist with FinglongersFrom: Germany Insane since: Sep 2001
|
posted 05-24-2007 18:14
yep, a whitelist as poi suggested is just the way to go ( sorry if I hadn't read all of this thread before pointing this hole out - but it's important to educate people (not just you, but the largish amount of lurkers we have ) .
So long,
->Tyberius Prime
|
Racketeer
Nervous Wreck (II) InmateFrom: Insane since: May 2007
|
posted 05-25-2007 21:50
Har har, I dug into the subject of URL rewriting and I must say: I love it!
Not everything seems to work however...
The custom 404 page works!
This...
code:
RewriteEngine on
RewriteRule ^(.*)\.html$ $1.php
also works!
But this (really useful)...
code:
RewriteEngine on
RewriteRule ^/contact.html$ /index.php?page=contact.php
doesn't work!
|
Tyberius Prime
Maniac (V) Mad Scientist with FinglongersFrom: Germany Insane since: Sep 2001
|
posted 05-25-2007 23:41
those are regexps... try escaping the . (by writing \. ) , so that it really means 'dot'.
Also, try appending [R] - that should get you a redirect that's visible in the browser - if you don't get it, the problem lies with the first part of the expression.
|
Racketeer
Nervous Wreck (II) InmateFrom: Insane since: May 2007
|
posted 05-28-2007 17:50
|
Racketeer
Nervous Wreck (II) InmateFrom: Insane since: May 2007
|
posted 05-28-2007 21:19
Success!
code:
<title>
<?php $title="Company Name Limited"; if(isset( $_GET["title"]))
{
$title = $_GET["title"];
print "$title - Company Name Limited";
}
else {print $title;}
?>
</title>
...works just fine!
What I wanted to achieve is that when someone calls the initial index page of the site, the title should say:
Company Name Limited
And when someone calls the contact page, the title should say:
Contact - Company Name Limited
The title variable is generated in .htaccess like so:
code:
RewriteRule ^contact\.html$ index.php?page=contact.php&title=Contact
My problem now is:
How can I pass a varibale consisiting of two words?
So that the title says About us - Company Name Limited. I've tried putting the title variable in ' ' or " " but it seems not to work. Also the trick in combining them with %20 doesn't work (it passes the variable but displays it with a 0 instead of a space: About0us - Company Name Limited
EDIT: I have unsuccessfully tried:
code:
RewriteRule ^contact\.html$ index.php?page=contact.php&title=About us
(Edited by Racketeer on 05-28-2007 21:20)
(Edited by Racketeer on 05-28-2007 21:25)
|
Racketeer
Nervous Wreck (II) InmateFrom: Insane since: May 2007
|
posted 05-30-2007 15:36
code:
RewriteRule ^contact\.html$ index.php?page=contact.php&title=About+us
works
|