27.2. How to use PHP-Nuke under SSL

SSL encrypts data at layer 6 of the OSI model (FIXME: image!). SSL doesn't necessarily keep hackers out, but rather encrypts the data so that IF a hacker is listening, it renders the data useless to the hacker. SSL is mainly used for e-commerce but is not limited to it, so you can certainly use it with PHP-Nuke.

To install SSL on your system, you need the openSSL package and the Apache modSSL module.

SSL will, by default, slow a site down. However not considerably, it does slow a site down due to encryption algorythms (don't worry, it's not a slowdown analogous to broadband vs. dialup).

SSL will NOT protect you from a user that knows the PHP-Nuke password of a user or is determined to apply the latest exploit to your site. It will only protect the traffic from eavesdroppers on the line. Nothing can totally protect you from this kind of attack - unless you probably sit the whole day in front of your computer, reading security advisories and taking action the very minute you read something about a new PHP-Nuke vulnerability. Of course you can take security measures for your site (and you should take them, see Section 23.4.2), but you should not conclude that your site is now secure just because you are using SSL!

After installing Apache with openSSL and modSSL to make your site more secure, you will be connecting to it with the HTTPS protocol and, accordingly, your site will be accessible as https://www.yoursite.com (notice the extra “s” after “http”). But now every page of your site popps up with a Seuciryt Information Alert like this:

This Page contains both secure and nonsecure items.
Do you want to display the nonsecure items?
Yes - No - More Info

Of course, this is normal after installation of SSL. The reason is that many PHP-Nuke blocks get their images from other sites (e.g. weather blocks (Section 8.2.2), comics blocks (Section 8.2.3, Section 8.3.1), daily babe blocks ...). You will find out that the browser will nerve you with questions like the above and will NOT display images, showing rather a broken key in their place, if the images come from outside the SSL domain.

The only solution to this annoyance is to write "SSL versions" of the relevant blocks that will store the image in a local directory and then display the image from that directory, instead from the remote one.

To save the image locally, you can use for example:

  require_once "includes/SSL.php";
  $myurl = "http://www.someremotesite.com/somedir/someimage.jpg";
  $myfile = "localtmpdir/mylocalimage.jpg";
  $content = "";
  saveimage($myurl, $myfile, $content);

in the block code, where includes/SSL.php is

<?php
function saveimage($imagefileurl, $tempfile, &$content) {
if (time() - filemtime($tempfile) > 3600); {
    if (!($imagefile = fopen( "$imagefileurl",  "rb"))) {
        $content .= "$imagefileurl<br> could not be opened<br>";
        die();
    }
    $imagecontent .= fread($imagefile, 300000);
    fclose($imagefile);
    if (!($localimagefile = fopen($tempfile ,  "wb"))) {
        $content .= "$tempfile<br> could not be opened<br>";
        die();
    }
    fwrite($localimagefile, $imagecontent);
    fclose($localimagefile);
}
return 1;
}
?>

the idea being that we only download the remote file to the local one if the remote file's modification time is older that one hour (3600 sec.).

There are probably better ways to do this - you could for example use Cache-Lite (Section 24.1.2) to cache the image file in a local cache directory, see Section 24.1 and How to accelerate PHP-Nuke. A discussion thread is in SSL on a phpnuke site.

If you want to restrict SSL only on certain directories for the above reasons, you wil have to find a way to enforce the HTTPS protocol in some directories and enforce HTTP on others. Note that will have to enforce HTTP on the directories that don's need encryption, otherwise a secure (and slow) connection will still be possible and your users might not notice that they are still using encryption in pages that don't matter (if they come to those pages from an encrypted page through a relative link, for example).

You can try mod_rewrite Section 25.2) to force HTTPS on some URLs and force HTTP on others: using SERVER_PORT, you can check the current port is not 443 (the standard HTTPS port), and thus to force HTTPS when entering the /dir/ directory, use:

# /dir/.htaccess
RewriteEngine On
RewriteCond %{SERVER_PORT}!443
RewriteRule ^(.*)$ https://www.x.com/dir/$1 [R,L]

And because HTTPS is slower than HTTP, take the users out of HTTPS mode when they leave the /dir/ directory by:

# /.htaccess
RewriteEngine On
RewriteCond %{SERVER_PORT} 443
RewriteRule ^(.*)$ https://www.x.com/$1 [R,L]

The above code should be in a .htaccess file (Section 25.4) in the respective directory, but you can achieve the same result much faster if you have access to the web server configuration file and use the <Directory> directive, as described in Section 25.4. See also Using mod_rewrite to force SSL and More on rewrites.