Archive for the ‘Code’ Category

The ICO ignore their new Cookie law!

Wednesday, May 25th, 2011

Today the law changed in the UK and Europe as a whole with regards cookies. To be enforced by the Information Commissioner’s Office.

In theory all websites must request permission from the user to set a cookie on the users machine unless the cookie is for a service explicitly requested by the user i.e. adding an item to a basket.

I have a few issues with this:

1. Practically all Content Managed sites start a session with a session cookie before the first page has loaded. How do we ask permission for this? Or are we to re-code every site we have built or manage so we don’t set it until we have permission.

2. If the user doesn’t give us permission what should we do? Just leave a popup on screen asking for permission whilst still allowing full function of the site, or kick them off?

3. The ICO have no idea how to be completely compliant yet, EVEN THOUGH THIS IS NOW LAW with regards 3rd party cookies:
“This may be the most challenging area in which to achieve
compliance with the new rules and we are working with industry
and other European data protection authorities to assist in
addressing complexities and finding the right answers.”

4. Should we ask permission to set a cookie to remember the user has been asked permission? I don’t want the same user to keep getting the same request, even though they will every time they use another machine/browser/device or empty their cookies!

5. In theory it is acceptable that permission can be obtained in the web browser, BUT to quote the ICO:
“At present, most browser settings are not sophisticated enough to allow you to assume that the user has given their consent to allow your website to set a cookie”

6. THE BIGGIE! The ICO website itself www.ico.gov.uk sets a session cookie before having my permission. If this is acceptable you have just created another repetitive annoying popup for no reason!

I could imagine some bright spark coming up with this legislation in the 90’s, the early days, but to do it now, when most web sites are dynamic, intelligent and in the true spirit of web 2.0 share information to enhance the user experience seems stupid!

To quote Al Murray, the pub landlord:

“BACK OFF BRUSSELS!”

ICO Document on this subject

Monitor Apache and MySQL and restart automatically with PHP CLI cron script

Thursday, March 10th, 2011

We found ourselves recently wanting to better monitor our dedicated Linux servers, specifically Apache and MySQL. There are many paid-for services out there, but with these services being hosted elsewhere they cannot attempt an automatic restart of the affected services. To solve this we have quickly rattled out a PHP script designed to be run from command line, php-cli. It works for us, it may be a solution for you. It is designed to work on our set-ups so there are some assumptions made:

  • You have PHP-CLI installed
  • You have access to create a new CRONTAB entry
  • mail() function works on your box
  • It uses fopen(), fwrite() and file_get_contents() to store information in a serialized data file and exec() to restart services
  • This has only been tested on our Linux Ubuntu boxes, it may work elsewhere and is basic so probably will.

We will update this in future, but for now you may find it useful, let us know:

/*
	This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see .
*/
### Created by Stuart Cross of Motionlab www.motionlab.co.uk - Do what you want with it! (But please keep my name and Motionlab in as credit)
### Simple mysql and Apache status checker
###	Restarts services automatically if required.
### Excuse the coding - mostly typed in one hit off-the-cuff
### Place file in root home folder ~/ or in the Path if you wish
### chmod 755 service_monitor.php
###	Call with a crontab e.g. (for 5 minute checks)
### */5 * * * *   root    php ~/service_monitor.php >> /var/log/service_monitor.log
###
### Call more often if you like - but advisable to set $failsBeforeEmail higher e.g. 10
### If this file has to run in 'limited mode' - it's because it cannot use a file as data storage and will therefore run singularly,
### with no memory of previous fails or sent emails.
### So sending an email on every single fail.
###
### This service monitor requires CURL installed on the server, and mail() function to be working
###
### SETTINGS
### Identifier or name of this server - So you know where you got the email from!
$serverName = 'YourServerName';
### Web monitor company name
$coName = 'YourCompany';
### Server admin emails - get email every fail - a heads up before the client if you want.
$adminEmails = array('yourEmail@yourdomain.co.uk');
### All the email addresses that will be informed of the Fail/Restart of Apache
$apacheEmails = array('yourEmail@yourdomain.co.uk','yourclientsemail@theirdomain.co.uk');
###
### All the email addresses that will be informed of the Fail/Restart of MySQL
$mysqlEmails = $apacheEmails;
###
### Mail successful Apache responses (Warning: You will get email every 5 minutes! Use for check on first install)
$onApacheSuccess = false;
### Mail successful MySQL responses (Warning: You will get email every 5 minutes! Use for check on first install)
$onMysqlSuccess = false;
#### Number of fails before sending an email - Minimum of 1
$failsBeforeEmail = 2;
###
#### CHECK MySQL?
$checkMysql = true;
#### CHECK Apache?
$checkApache = true;
###
#### RUN limited (No file access for database)?  Can't think of a reason why you would manually set this true
$limitedMode = false;
###
#### Mysql Credentials
$host = 'localhost';
$user = 'service_monitor';
$pass = 'service';

### Apache Test URL - Set this url to a small file that won't disappear - if it is deleted you will get a lot of email and Apache will keep restarting!
$apacheTestUrl = 'http://yourdomain/img/transparent.gif';

### Path to file used for stats keeping - leave it like this to store in the same folder as this script
$dataStore = 'monitor.data';

if(!$limitedMode)
{
	### If database file doesn't exist create it
	if(!is_file($dataStore))
	{
		if(!$fh = fopen($dataStore, 'w'))
		{
			echo("can't create data storage file - Running in limited mode.\r\n");
			$limited = true;
		}
		else
		{
			$limited = false;
		}
		$data = array('SM'=>array());
		fwrite($fh, serialize($data));
		fclose($fh);
	}
	else
	{
		### Read database file
		if(!$data = file_get_contents($dataStore))
		{
			echo("can't open data storage file - Running in limited mode.\r\n");
			$limited = true;
		}
		else
		{
			$limited = false;
			$data = unserialize($data);
		}

	}

}
else
{
	$limited = true;
}

### Make sure no-one ignores the instructions!
if($failsBeforeEmail==0)$failsBeforeEmail=1;
### If we have no database file - make a quick fake one
if($limited)$data = array('SM'=>array());

##############################
####### Apache Checker - This is usually kicked off by Apache hitting MaxClients - Or when services restart during the night
##############################
if($checkApache)
{
	$ch = curl_init($apacheTestUrl);
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	$res = curl_exec($ch);
	$status = curl_getinfo($ch);
	curl_close($ch); 

        if($status['http_code']==200)
        {
				$data['SM']['Apache']['TotalSuccessCounter']++;
				if((isset($data['SM']['Apache']['hasFailed']) && $data['SM']['Apache']['hasFailed']==true) && !$limited)
				{
					$data['SM']['Apache']['hasFailed'] = false;
					$data['SM']['Apache']['FailCounter'] = 0;

					if($data['SM']['Apache']['EmailSent'] == true)
					{
						foreach($apacheEmails as $e)
						{
							mail($e,$coName.' WEB MONITOR: '.$serverName.' Apache Web Server is working correctly again',print_r($status,true)."\r\n\r\n\r\n".$serverName);
						}
					}
					else
					{
						### Admin heads-up email
						foreach($adminEmails as $e)
						{
							mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': Apache Web Server is working correctly again.',"The quiet Apache restart seems to have worked"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
						}
					}
					$data['SM']['Apache']['EmailSent'] = false;
					echo("\r\n".date('r',mktime()).': Apache is back up!'."\r\n");
				}
				if($onApacheSuccess)
				{
					foreach($apacheEmails as $e)
					{
						mail($e,$coName.' WEB MONITOR: '.$serverName.' Apache Web Server is working correctly',print_r($status,true)."\r\n\r\n\r\n".$serverName);
					}
				}
                echo("\r\n".date('r',mktime()).': Apache connected');
        }
        else
        {
				$data['SM']['Apache']['TotalFailCounter']++;
				$data['SM']['Apache']['FailCounter']++;
				$outputStop = array();
				$outputStart = array();

				################### TURN OFF WHEN DEBUGGING #########################
				exec('apache2ctl -k restart',$outputStop);
				#####################################################################

				### Admin heads-up email
				foreach($adminEmails as $e)
				{
					mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': Apache Web Server has been automatically restarted: You should probably check the website is operating correctly.',"THIS IS AN ADVANCED WARNING SENT ON EVERY FAIL, YOU COULD WAIT FOR AN AUTOMATIC RETURN TO SERVICE"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
				}

				if(($data['SM']['Apache']['FailCounter']==$failsBeforeEmail) || $limited)
				{
					$data['SM']['Apache']['FailCounter'] = 0;
					$data['SM']['Apache']['EmailSent'] = true;
					foreach($apacheEmails as $e)
					{
						### If it hasn't failed on the previous call this is a new Apache outage
						if(!$data['SM']['Apache']['hasFailed'] || $limited)
						{
						mail($e,$coName.' WEB MONITOR: '.$serverName.': Apache Web Server has been automatically restarted: You should probably check the website is operating correctly.',print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
						}
						else
						{
						### This is a continuance of an Apache outage
						mail($e,$coName.' WEB MONITOR: '.$serverName.': Apache Web Server appears to be STILL down after restart - ADMIN REQUIRED',"Apache has either failed to come back up after restart, or has failed again between checks - ADMIN REQUIRED"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
						}
					}
				}

				if(!$data['SM']['Apache']['hasFailed'])$data['SM']['Apache']['hasFailed'] = true;
				echo("\r\n".date('r',mktime()).': not connected');
        }
}
##############################
####### MySQL Checker
##############################
if($checkMysql)
{
		$output = array();
        $error = '';
        if($db = mysql_connect($host,$user,$pass))
        {
				$data['SM']['Mysql']['TotalSuccessCounter']++;
				if((isset($data['SM']['Mysql']['hasFailed']) && $data['SM']['Mysql']['hasFailed']==true) && !$limited)
				{
					$data['SM']['Mysql']['hasFailed'] = false;
					$data['SM']['Mysql']['FailCounter'] = 0;
					if($data['SM']['Apache']['EmailSent'] == true)
					{
						foreach($mysqlEmails as $e)
						{
							mail($e,$coName.' WEB MONITOR: '.$serverName.' MySQL Database is working correctly again',print_r($error,true)."\r\n\r\n\r\n".$serverName);
						}
					}
					else
					{
						### Admin heads-up email
						foreach($adminEmails as $e)
						{
							mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': MySQL Database is working correctly again.',"The quiet Mysql restart seems to have worked"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
						}
					}
					$data['SM']['Mysql']['EmailSent'] = false;

					echo("\r\n".date('r',mktime()).': MySQL is back up!'."\r\n");
				}
				if($onMysqlSuccess)
				{
					foreach($mysqlEmails as $e)
					{
                		mail($e,$coName.' WEB MONITOR: '.$serverName.' MySQL Database is working correctly',print_r($error,true)."\r\n\r\n\r\n".print_r($output,true));
					}
				}
                echo("\r\n".date('r',mktime()).': MySQL connected success');
        }
        else
        {
				$data['SM']['Mysql']['TotalFailCounter']++;
				$data['SM']['Mysql']['FailCounter']++;
				$data['SM']['Mysql']['EmailSent'] = true;
                $error = mysql_error();

				### Admin heads-up email
				foreach($adminEmails as $e)
				{
					mail($e,'*ADMIN* '.$coName.' WEB MONITOR: '.$serverName.': MySql has been automatically restarted: You should probably check the website is operating correctly.',"THIS IS AN ADVANCED WARNING SENT ON EVERY FAIL, YOU COULD WAIT FOR AN AUTOMATIC RETURN TO SERVICE"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
				}

				################### TURN OFF WHEN DEBUGGING #########################
                exec('/etc/init.d/mysql restart',$output);
				#####################################################################

				if(($data['SM']['Mysql']['FailCounter']==$failsBeforeEmail) || $limited)
				{
					$data['SM']['Mysql']['FailCounter'] = 0;
					foreach($mysqlEmails as $e)
					{
						### If it hasn't failed on the previous call this is a new MySql outage
						if(!$data['SM']['Mysql']['hasFailed'] || $limited)
						{
							mail($e,$coName.' WEB MONITOR: '.$serverName.': MySQL Database has been automatically restarted. You should probably check the website is operating correctly',print_r($error,true)."\r\n\r\n\r\n".print_r($output,true));
						}
						else
						{
							### This is a continuance of a MySql outage - or limited mode
							mail($e,$coName.' WEB MONITOR: '.$serverName.': MySql Database appears to be STILL down after restart - ADMIN REQUIRED',"MySql has either failed to come back up after restart, or has failed again between checks - ADMIN REQUIRED"."\r\n\r\n".print_r($outputStop,true)."\r\n\r\n\r\n".print_r($outputStart,true));
						}
					}

				}
				if(!$data['SM']['Mysql']['hasFailed'])$data['SM']['Mysql']['hasFailed'] = true;
                echo("\r\n".date('r',mktime()).': MySQL not connected - FAIL');
        }
}

		###Save data for next run
		if(!$limited)
		{
			$fh = fopen($dataStore, 'w');
			fwrite($fh, serialize($data));
			fclose($fh);
		}

die();

Server Security- passing the audits

Tuesday, October 20th, 2009

Whilst passing a server through Barclaycard PCI-CSS security audits we came across a possible method of server attack:

Any server that supports TRACE and TRACK methods over HTTP is possibly open to a security vulnerability known as an XST attack (Cross Site Tracing). This allows a carefully crafted TRACE request to intercept a users cookie information. All web servers types can be vulnerable, IIS and Apache.

To test:

telnet www.example.com 80

After the response

Trying 12.34.56.78…
Connected to www.example.com.
Escape character is ‘^]’.

enter these commands:

TRACE /index.html HTTP/1.1
Host: www.example.com
[CR]

[CR] = Carriage Return, for a blank line to signify the end of the headers being sent

If your server is “vulnerable” you will get a response back similar to this one (status 200):

HTTP/1.1 200 OK
Date: Sat, 17 Dec 2005 23:51:29 GMT
Server: Apache/1.3.33 Sun Cobalt (Unix) mod_ssl/2.8.22 OpenSSL/0.9.6 PHP/4.3.10 mod_auth_pam_external/0.1 mod_perl/1.29
Connection: close
Transfer-Encoding: chunked
Content-Type: message/http

30
TRACE /index.html HTTP/1.1
Host: www.example.com

0

Connection closed by foreign host.

If your server is not vulnerable you will get:

HTTP/1.1 403 Forbidden
Date: Sat, 17 Dec 2005 00:01:06 GMT
Server: Apache/1.3.33 Sun Cobalt (Unix) mod_ssl/2.8.22 OpenSSL/0.9.6 PHP/4.3.10 mod_auth_pam_external/0.1 mod_perl/1.29
Last-Modified: Fri, 11 Feb 2005 05:30:57 GMT
ETag: “601d904-4dd-420c4311″
Accept-Ranges: bytes
Content-Length: 1245
Content-Type: text/html

If you are vulnerable the solution is  (for Apache at least):

Inside of all VirtualHost containers <VirtualHost> add the following
lines (there is a way of doing it in apache2.conf / httpd.conf but it
didn’t work for me – TraceEnable “off”):

<VirtualHost>

# Block TRACE/TRACK XSS vector
RewriteEngine On
RewriteCond %{REQUEST_METHOD} ^TRAC(E|K)
RewriteRule .* – [F]

</VirtualHost>

thanks to http://cobaltfaqs.com/ for the solution

 HTTP/1.1 403 Forbidden
 Date: Sat, 17 Dec 2005 00:01:06 GMT
 Server: Apache/1.3.33 Sun Cobalt (Unix) mod_ssl/2.8.22 OpenSSL/0.9.6 PHP/4.3.10 mod_auth_pam_external/0.1 mod_perl/1.29
 Last-Modified: Fri, 11 Feb 2005 05:30:57 GMT
 ETag: "601d904-4dd-420c4311"
 Accept-Ranges: bytes
 Content-Length: 1245
 Content-Type: text/html

What Every Web Design Client Should Know

Thursday, September 10th, 2009

For many clients when they sign a web design/development contract they will have no prior experience in the area of designing and developing websites. There are a few basic concepts that every client should be aware of. Below is a list of the things that every client should know about.

Like all things in life you get what you pay for. Yes there probably is a bloke who lives round the corner who dabbles a bit in web design that could make you a website for you. On the surface it might look ok but it probably wouldn’t work very well. The internet is becoming more and more important to the success of businesses. Often your website will be the first time a potential customer is introduced to your company and it is important that you make a good first impression.

In order for a website to be successful it takes time to design and develop as it needs to work in all browsers and platforms, be search engine friendly, meet current web standards and download quickly to name but a few of the many factors which need to be considered. And then there is the design and navigation of your website do you require special features and functionality to be added? These things all take time and cannot be rushed if you want a quality site.

Behind all websites there is a large amount of code. When you visit a web page you are only seeing the end result and behind this there will be HTML, style sheets, php scripts, java scripts and databases. All of this is invisible to the end user but is essential to ensure the site functions correctly.

Before you visit your web designer it can be really beneficial if you have some ideas of what you want. Think about the different feature you want your website to have. Do you have corporate branding and colours that you want the site to stick to? Maybe have a look at your competitor’s websites and take note of what you like and dislike about their sites. If you can give your web designer some initial ideas of the sort of things you are looking for this will make their job a whole lot easier.

Internet Explorer is not the only browser. There are now more browsers than ever and different people will use different browsers to view your website. The problem is that not all browsers display sites in the same way. So a site viewed in IE may look different to when it is viewed in Firefox or Safari. Therefore it is the job of the developer to ensure that the site operates in all the different browsers.

Not only do different users use different browsers but they also use different sized monitors and that monitor may be set to a higher or lower resolution. Again this will affect the way a site looks to different users. The graphics card and colour settings can also impact on how the site will look. It is therefore important that your site is designed to take this into consideration and no matter what size screen or resolution a visitor is using they will be able to view the site.

Different fonts may look different on different computers. There are some fonts that are standard across all browsers that will work fine. However, if you opt for a font which is not standard and that font is not installed on the web browser in a computer it will display a different font. The issue is that different fonts are different sizes, short, tall, fat ,thin therefore when a different font is displayed it can upset the layout of a page.

It is no point in having a fantastic website if nobody ever gets to see it. Appearing within the search engine results pages is essential to the success of a website. Almost 90% of all web users use search engines. The major search engines have guidelines which must be adhered to in order for a site to appear within the search engine results pages. Once your site is live the work has only just begun. The site needs to be marketed to ensure it is a success. You will need to ensure that the site appears when people enter keywords relating to your industry into the major search engines this is known as search engine optimisation or SEO.

Have you considered adding a news section or blog? The most successful websites are those that are updated regularly and have valuable content which people will keep coming back for.