Solutions to Cross-Site Scripting (XSS) Attack

Recently i wrote an article on Solutions to SQL Injection Attack that have all the great solutions to tackle SQL Injection Attack. In this article, i would like to discuss with you about Cross-Site Scription attack which is also known as XSS attack.

Cross-Site Scripting Attack

What is cross-site scripting attack? You can easily get a definition written on Wikipedia. It is a type of computer security vulnerability typically found in web applications which allow code injection by malicious web users into the web pages viewed by other users. Often look perfectly fine on the end-users side who may be subject to unauthorized access, theft of sensitive data, and financial loss. Here are a few cross-site scripting attack scenarios you may find interesting.

Simple persistent attack

  1. Mallory posts a message to a social network.
  2. When Bob reads the message, Mallory's XSS steals Bob's cookie.
  3. Mallory can hijack Bob's session and impersonate Bob.

DOM-based attack

  1. Mallory sends the URL of a maliciously constructed web page to Alice, using email or another mechanism.
  2. Alice clicks on the link.
  3. The malicious web page's JavaScript opens a vulnerable HTML page installed locally on Alice's computer.
  4. The vulnerable HTML page contains JavaScript which executes in Alice's computer's local zone.
  5. Mallory's malicious script now may run commands with the privileges Alice holds on her own computer.

Non-Persistent

  1. Alice often visits a particular website, which is hosted by Bob. Bob's website allows Alice to log in with a username/password pair and store sensitive information, such as billing information.
  2. Mallory observes that Bob's website contains a reflected XSS vulnerability.
  3. Mallory crafts a URL to exploit the vulnerability, and sends Alice an email, enticing her to click on a link for the URL.
  4. Alice visits the URL provided by Mallory while logged into Bob's website.
  5. The malicious script embedded in the URL executes in Alice's browser, as if it came directly from Bob's server. The script can be used to send Alice's session cookie to Mallory. Mallory can then use the session cookie to steal sensitive information available to Alice (authentication credentials, billing info, etc) without Alice's knowledge.

Persistent

  1. Bob hosts a web site which allows users to post messages and other content to the site for later viewing by other members.
  2. Mallory notices that Bob's website is vulnerable to a type 2 XSS attack.
  3. Mallory posts a message to Bob's website.
  4. Later, Alice views Mallory's message.
  5. Alice's session cookies or other credentials can be taken and sent to Mallory, without her knowledge.
  6. Mallory logs into Bob's website as Alice, and can see sensitive information (billing info etc.), or post messages on her behalf.

Identity Attack

  1. Bob hosts a site that allows users to post messages which includes a stored list of user names as recommendations.
  2. Alice is a regular visitor to the recommendation-based site; she uses an alias to protect her identity.
  3. Mallory knows one or more of Alice's email addresses but not her identity alias.
  4. Mallory uses social engineering to send a disguised recommendation link or the link to a carefully constructed redirect page which recommends a staged posting to Bob's site.
  5. Alice clicks on the link. Her session cookies or willing-login trigger the recommendation.
  6. Mallory reads the recommendation list and discovers Alice's online identity.

The above scenarios are taken from Wikipedia itself which i find it most appropriate to demonstrate the danger of XSS attack.

Solutions

It is well said that the responsibility of preventing XSS attack should not only be held by the developers. End user will really required to know this to better protect themselves from such attacks. It is always better to believe in yourself than others when it comes to security. In this article, we will discuss solutions to better secure ourselves and our web application. Although there are many risk with XSS attack, defending against it is much easier than you might though.

Developers

Filter all foreign data

Anything that will store in our database for future display to other user entered by users are consisted as foreign data. Ensure that all these data are being filter correctly will greatly prevent XSS attack from occurring on your website. Although it may sound easy but it does take discipline to always filter these data whenever there is such input. Especially on larger system where many developers are working on it. Simple filter such as htmlentities() can help eliminate many Cross-site scripting concern.

$filter_input = htmlentities($post['userinput'])
#use $filter_input

Use existing functions

Always use existing functions exist on PHP. Functions like htmlentities(), strip_tags(), and utf8_decode() can be useful. Try not to create your own function for filtering purposes as the functions in build in PHP are usually much faster and more secure to be used. Here are some functions that within PHP that are great for valid or filter user input

  • htmlentities()
  • strip_tags ()
  • utf8_decode ()
  • htmlspecialchars()
  • ctype_digit()
  • ctype_alnum()

Use a whitelist approach

Always assume data to be invalid until it is proved valid. This means that checking the length of the given input, validate the correct type, using regular expression to further validate the creditability till the extreme case you can imagine. This will help prevent any circumstances when the filter failed and caused the script to access your website.

Use a strict naming convention

We all know big systems are usually build by a few developers. Hence, it is important to use a strict naming convention so that whenever a developer look at the code he is able to identify what the other developer is trying to accomplished (you never know what some developer will do during refactoring to make the code more efficient. Yes, they remove these important stuff) and whether the data has been tainted.A lack of clarity yields confusion, and this breeds vulnerabilities. It is a good practice for developer to always be suspicious towards these global variables ($_POST, $_GET, $_REQUEST, etc.). An example of such strict naming convention can be illustrate below,

<?php
$clean = array();
#check whether it is a float, this is just a demo and more validation should be applied before it is clean.
if ($_POST['num'] == strval(floatval($_POST['num'])))
{
$clean['num'] = $_POST['num'];
}
#we use clean array onwards.
?>

Initialize your data

It is a good practice to always initialize your data although it is not necessary to do that in PHP. Since any variable that has not been initialize should always be considered as tainted. It is important to untainted it by initialize them. The user does not have another opportunity to send data as the entire HTTP request has been received, hence no data can be injected into your script (even if register_globals is enabled). Assume register_globals is enabled an attacker can easily make our clean variable into a malicious code if we did not initialize it. Consider the following code,

domain.com?clean=malicious_code

because we did not initialize clean array, clean now contains malicious code that may caused damage to our system.

#this part was invalid
if ($_POST['num'] == strval(floatval($_POST['num'])))
{
$clean['num'] = $_POST['num'];
}
#we use clean array onwards.
?>

Cookie Security

Another form of cross-site scripting attack is through cookie security. Many website uses cookie for various reason such as store information, retrieve information, track activities and etc,. However, most web applications rely on session cookies for authentication between individual HTTP requests (the remember me box on login page). We all are aware that client script have access to such cookie and simple XSS script can be made to retrieve such authentication to fake user access. To mitigate this particular threat, we can tie session cookies to the IP address of the user who originally logged in, and only permit that IP to use that cookie. but it will obviously break when an attacker is behind the same NATed IP address or web proxy.

Use BBCode

Many website such as forums, blogs, CMS or other communication system provides the ability to enhance that content by posting formatted text. However, these formatted text is vulnerable against Cross-site scripting attack. Many will uses BBCode on their system to provide user with formatted text and at the same time protect themselves against such attack. Consider the following example of BBCode

[b]bold[/b] text 
to
<b>bold</b> text

[color=blue]blue text[/color]
to
<span style="color: blue">blue text</span>

You can know more about BBCode in Wikipediawhere more example and explanation is being provided on BBCode. However, using such tag doesn't guarantee XSS security. Consider the following attack example within BBCode,

[url=http://hungred.com]Web development bookmark[/url]
to
<a href="http://hungred.com">Web development bookmark</a>.

The above illustrate a normal anchor tag BBCode. However, if i placed a JavaScript into the BBCode, it is still valid in BBCode,

[url=javascript:alert('Got you!')]Web development bookmark[/url]
to
<a href="javascript:alert('Got you!')">Web development bookmark</a>.

That is why whitelist approach is needed to always prevent such attack from coming. Similarly, in some lower versions of Internet Explorer (IE6 and below), URL format is allowed and will execute Javascript which we will have to take care as well.

XSS CheatSheet

For developers who are concern about XSS attack. (which you should) Please visit this XSS (Cross Site Scripting) Cheat Sheet to further test and protect against XSS attack.

End User

Disabled JavaScript

Many end-users (includes developers) who are well aware of XSS attack and the harm that it may bring upon the user will have their JavaScript disabled on their browsers. Since Cross-Site scripting is using JavaScript to harm users. Disabled such feature is the best way to prevent any attack from Cross-Site scripting. Although this will means that many newer site which only deploy JavaScript may not be accessible, this will also means that many developer will have to ensure that their site is fully protected against such attack. Users can disabled JavaScript and only allows those that are trusted. This approach act as a white list approach where only trusted website has JavaScript enabled to prevent any damage from occurring.

Disabled Cookie

User may want to disabled cookie in order to protect themselves against XSS attack or older browser may not even support cookies. Developers will have to think of alternative ways to provides functionality that required cookies than depending on it.

Summary

Developer must ensure the safety of its visitors and build a safer system for end users. On the other hand, end-user (including developers) will need to know the type of attacks used by attackers to prevent such attacks. The solutions above might not be full bullet proof solution for future Cross site scripting attack. Nonetheless, it can be used for discussion on solutions of future such attack.

Solutions to SQL Injection Attack

Security is one of the major issue we want to take care of other than meeting dateline. Especially when it comes to server data. We always want our data to be correct and secure. No one should be able to manipulate these data and these data should only be confine to people that have access to it. One should need to know the attacks on server data in order to better secure them. In this article, we will discuss SQL injection attack on databases.

SQL Injection Attack

SQL Injection Attack is the most common type of problem most web system face. Let's consider the following code

<?php
$name = ''test'; DELETE FROM users;';
mysql_query('SELECT * FROM users WHERE name='.$name.' ');
?>

Basically, the query above will caused all the data in your the users table to be deleted. This is usually due to inconsistency during development by different people. Lucky, there are many ways to prevent this.

The Solutions

Escape Mechanism

In order to prevent SQL injection attack, PHP's automatic input escape mechanism, magic_quotes_gpc, can provides some rudimentary protection (this is required to be enabled on php.ini). The magic quote will append a backslash to characters that is used to break out of a value identifier. eg, ', ", . etc. However, this is not always automatically enabled due to various reason. If you are using MySQL, it has a built-in function mysql_real_escape_string() to escape input characters that are special to MySQL. However, before calling a database's own escaping mechanism, it is important to ensure that no two escape mechanism is being used at the same time.

Escape Without Discipline

We talk about how escape mechanism can help us prevent SQL injection attacks. However, with the help of escape mechanism doesn't means that we are free from SQL Injection. We can still do some code injection even though we have implemented escape mechanism. Let's consider this example,

<?php
$id= '0; DELETE FROM users;';
$id = mysql_real_escape_string($id);
mysql_query('SELECT * FROM users WHERE id='.$id.' ');
?>

Similarly, SQL Injection attack is still possible since the escape mechanism only add additional backslash to characters that is used to break out of a value identifier such as single or double quote. There are no particular character that will need a backslash on the $id variable string. Thus, nothing was being added and the query will run as usual (danagerous). The solution to this situation is pretty simple, Discipline. Many times developers will like to skip the important process of adding quote in the SQL query. Being discipline and add these particular characters into your query will definitely save yourself from SQL injection attack. Example,

<?php
$id= '0; DELETE FROM users;';
$id = mysql_real_escape_string($id);
mysql_query('SELECT * FROM `users` WHERE id="'.$id.'" ');
?>

This will prevent the SQL from running the second query since there is no such id(int) as '0; DELETE FROM users'. The other way is to valid whether the particular $id is an integer.

<?php
$id= '0; DELETE FROM users;';
$id = (int) $id;
$id = mysql_real_escape_string($id);
mysql_query('SELECT * FROM users WHERE id='.$id.' ');
?>

This will cast $id into integer If the input is not entirely numeric, only the leading numeric portion is retrieved. eg, '999; DELETE FROM users;" will return 999. If the input doesn't start with a numeric value or there is no numeric values, 0 is returned. This is the best way to determine whether a particular value is an numeric value. No escape mechanism is required for this method but this can only be used for numeric validation.

LIKES Operator Danger

The LIKES Operator in SQL is a very powerful filter instruction that allows the query to use '%' for any characters that occurs zero or more times or '_' for a single character. However, both magic quote and built-in escape mechanism will skip these two special character. Thus, denial of services attack can be launch into the web server using SQL injection attack. Consider the following example,

$para= mysql_real_escape_string('%12'); // still %12
mysql_query('SELECT * FROM document WHERE number LIKE "'.$para.'%"');

Imagine this is a transaction table which has millions of documents. Searching number 12 in a particular number for a million times will definitely denial the access of this web portal services. Hence, we will need something that will escape these two special characters. We can use addcslashes() in PHP to add the required backslash onto these special characters!

$para= addcslashes mysql_real_escape_string('%12_')); // it will be \%12\_
mysql_query('SELECT * FROM document WHERE number LIKE "'.$para.'%"');

The above correct solution will provides no result due to the additional of \% and \_ into the query.

MySQL Exception

Fortunately, if you use MySQL, the mysql_query() function does not permit executing multiple queries in a single function call. If you try to stack queries, the call fails. However, other PHP database extensions, such as SQLite and PostgreSQL will permit such action.

Base64-encode

A common techniques is to use base64_encode in PHP to encode all data that are stored in the database. This will prevent any special character from damaging your query statement as any new query to the database will have to be encoded before the database recognize.

<?php
mysql_query('INSERT INTO users (name) VALUES "'.base64_encode('test').'"');
$name = base64_encode('test'; DELETE FROM users;');
mysql_query('SELECT * FROM users WHERE name=''.$name.'"');
?>

However, base64 encode will roughly increase data size by 33%, requiring bigger storage space. Moreover, PostgreSQL query with LIKE will fail due to base64.

Prepared Statements

The most efficient and powerful way to solve SQL injection attack, i would said it would be prepard statements. Prepared statements will only required to set up a statement once, and then it can be executed many times with different parameters. They are designed to replace building ad hoc query strings, and do so in a more secure and efficient manner. A typical prepared statement is shown below,

#MySQL
SELECT * FROM Users WHERE name = ?

The ? is what is a called a placeholder. You would need to supply the value for it during execution. You can read more about Prepared statements in MySQL at their website. Here is one example,

<?php
mysql_query('PREPARE search_template FROM "SELECT name FROM Users WHERE name = ?"');
mysql_query('SET @param = "test"');
mysql_query('EXECUTE search_template USING @param');
mysql_query('SET @param = "hello"');
mysql_query('EXECUTE search_template USING @param');
mysql_query('DEALLOCATE PREPARE search_template;');
?>

Unlike ad-hoc query string, the second query being executed with 'hello' as parameter doesn't add on the additional overhead of the search template which was prepared previously.

SQL Error Handling

How do hackers know your table name and the query you wrote? The answer is pretty simple and straight forward. It is mainly due to poor SQL error handling by the developers. The hackers will try their very best to break your SQL query in any way that will result in an error. Once the error is displayed, they will have many information to launch a proper attack. Let's consider an example,

<?php
#query=test;DELETE FROM breakplease;
$query = 'SELECT * FROM user WHERE name ='. base64_decode($_GET['query']);
mysql_query('$query);
?>

This will caused a decent error to be display on the page. And the user will have an idea what is being passed into the query string and what table is being used. Both structure, fields and GET parameter were exposed to the hacker in this way.

The best way is to prevent such embarassement by providing a more end-user type of message with a php error handling function.

function sql_failure_handler($query, $error) {
$msg = htmlspecialchars('Failed Query: {$query}<br>SQL Error: {$error}');
error_log($msg, 3, '/home/site/logs/sql_error_log');
if (defined('debug')) {
return $msg;
}
return 'Requested page is temporarily unavailable, please try again later.';
}

#query=test;DELETE FOM breakplease;
$query = 'SELECT * FROM user WHERE name ='. base64_decode($_GET['query']);
mysql_query('$query) or die(sql_failure_handler($query, mysql_error()));

This will provides us developer with relevant message on our TEST environment and provides the end-users with a more standard message on LIVE environment.

Authenticate Data Connection

This concern on how we store our application's database credentials. Some will placed it into an external files and gives it a non-PHP extension such as .inc. This post a problem as the file can be access directly outside of the server and it will be shown with plain text since it is not interpreted by PHP machine. Hence, we will have to better secure these database credentials from unauthorized access. One solution is to restrict the access of .inc in that particular folder defined in your web server (which many might not have in a shared hosting environment).

<Files ~ '\.inc$'>
Order allow,deny
Deny from all
</Files>

Or just changed it into .php extension so that it will not be exposed in plain text. However, if there is code written in that file, the same issue might still happen. If you have root access, you can do the following in your apache configuration file, httpd.conf

<VirtualHost ilia.ws>
Include /home/ilia/sql.cnf
</VirtualHost>

Now, set the file sql.cnf with the following codes,

SetEnv DB_LOGIN 'login'
SetEnv DB_PASSWD 'password'
SetEnv DB_DB 'my_database'
SetEnv DB_HOST '127.0.0.1'

This way, the details can be access via $_SERVER or getenv() in your PHP script without hardcoding it somewhere in your system.

echo $_SERVER['DB_LOGIN']; // login
echo getenv('DB_LOGIN'); // login

A more powerful way is to hide them even from the script that needs them. How to do that? we stored it into PHP.ini directives by specify the default login. These also can be set inside of Apache configuration file.

php_admin_value mysql.default_host '127.0.0.1'
php_admin_value mysql.default_user 'login'
php_admin_value mysql.default_password 'password'

Now you will connect to your database without any parameter and it will takes the default value from your apache configuration file.

mysql_connect()

Reduce the damage

It is a good practice to always indicate the number of results needed to retrieved from the table. Consider the following example,

<?php
$name = '"test"; SELECT * FROM users;';
mysql_query('SELECT * FROM users WHERE name='.$name.' LIMIT 1');
?>

Limiting the number of result return can help minimize the damage of SQL injection attack. Especially during authentication process. On the other hand, it is also a good idea to restricting the database permissions. By limiting the users permission, the damage of SQL injection attack can greatly minimized. Eg, only select access should be given to the user on the above query. Therefore, if the attacker tried to change the password by doing a SQL injection, it will fail (unauthorizes access).

Another alternative is to enhance the performance between your database and the script. We see Denial of service attack can be launch against the system due to the usage of LIKES operator. Having a good performance between the database and the web server is strongly advisable to minimize the impact on our business. Thus, to minimize database overloading, we can look at a few simple rules.

  1. Only retrieved the field you need. '*' is always misused by lazy developers
  2. try unbuffered query. It speeds up query but limit the work with only one query
  3. You can speed up connection process by using persistence connection. Eg, in MySql
    mysql_pconnect('host', 'login', 'passwd');
    

    However, if the database is not configure to allow many connection, further connection request will be rejected (since persistence connection is hooking the line). Hence, denial of services occurs.

MYSQL User account

For different action in the system, different MYSQL user account should be used. This will greatly help minimize the risk of damage done to the database if certain page was compromised. For example, a login page should only have SELECT access as other action is redundant. However, if you provide a full access level to a simple login page where any unauthorized user can access, malicious user can easily change the password through the text box provided to gain access to your portal if SQL injection vulnerability was found. Hence, brute force is not necessary to break down the door. They simply ring the bell! You are just inviting guess into your portal.

Summary

Although SQL injection attack is a common attack launch against many website, web developers have to ensure that these attack is minimize and eliminated. The solutions above might not be full bullet proof solution for future SQL injection attacks. Nonetheless, it can be used for discussion on solutions of future SQL Injection attack.

Secure File Upload Check List With PHP

Uploading file on your website is a very common thing nowadays. Image, zip and many other common file type are the usual things we want our users to be able to upload. However, potential evil files such as .exe, .php and other script files are those that we wish they can never be able to upload on to our server. And i am sure you are like me who will wonder whether my upload handler is secure enough to prevent attacks from coming in. In this article, i will try to list down most of the secure ways to protect our server and business from these potential threat. On the other hand, feel free to share your experience with the readers and me on the security tips you have.

Content Type Verification

Checking the content-type of a file is the first level of verification that many of us will do.

<?php
#easiest way to verify it is a image file
if(!eregi('image/', $_FILES['hpt_files']['type'])) 
{
	echo 'Please upload a valid file!';
	exit(0);
}
?>

Although, this can be easily bypass by attacker by changing the Content-type header which we will look at later. Nonetheless, it is something we must always check. Please take note that different MIME type may differ in different web browsers.

Verify Image File Content

Uploading image file is something most application will allow. An attacker can change the content-type to a valid one in order for your script to accept the file. Thus, we will have to ensure that this is really an image file by using getimagesize() in PHP.

<?php
$imageinfo = getimagesize($_FILES['uploadfile']['tmp_name']);
if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && isset($imageinfo)) 
{
	echo 'Sorry, we only accept GIF and JPEG images\n';
	exit(0);
}
?>

You might want to check on other information as well. However, a file can be a proper GIF or JPEG image and at the same time a valid PHP script. Most image formats allow a text comment. It is possible to create a perfectly valid image file that contains some PHP code in the comment. How? By taking an image file (.jpg) and upload as a php extension file(.php). When getimagesize() look at it, it is a valid image file but when the PHP interpreter looks at it, the PHP code in the comment will be executed and other binary code will be discarded as junk (similar to HTML + PHP + JavaScript). Thus, getimagesize() only provides certain level of verification while many more have to be there in order to fully protect yourself.

Verify File Extension

This is something every upload handler in PHP must do. An attacker can fake the content-type of a file to the server, the extension must be a valid extension for PHP machine to interpret it correctly. Although this is not all of the security measure, this is definitely one of the important verification. I have included both white and black list on the code (although only one of them is required usually) since we won't know what will happen to the server configuration especially in a shared hosting environment.

<?php
$filename = strtolower($_FILES['uploadfile']['name']);
$whitelist = array('jpg', 'png', 'gif', 'jpeg'); #example of white list
$backlist = array('php', 'php3', 'php4', 'phtml','exe'); #example of black list
if(!in_array(end(explode('.', $fileName)), $whitelist))
{
	echo 'Invalid file type';
	exit(0);
}
if(in_array(end(explode('.', $fileName)), $backlist))
{
	echo 'Invalid file type';
	exit(0);
}
?>

This way even if an attacker fake their way by changing the content-type, they will not be able to change the fact that the extension is required for the file to be interpreted by the machine. However, what file extensions will be passed on to the PHP interpreter will depend on the server configuration. A developer will have no knowledge or control over the web server configuration. Some web application may require that files with .gif or .jpg extension are interpreted by PHP. Thus, any comment in the image file will be interpreted by the PHP machine as a valid instruction to be executed.

Basically, we can't guarantee that knowing what file extension is being interpreted by PHP machine can help eliminate all attack and it does not change at some point in the future, when some other application is installed on the web server.

The Upload Folder

We want to prevent users from requesting uploaded files directly. This means that the best place to keep these uploaded files is somewhere outside of the web root (www, public_html, etc.) or creating a directory under the web root and blocking web access to it in the Apache configuration or in a .htaccess file. If the attackers is able to upload some harmful file into your system, this will prevent them from executing the files and enter arbitrary code into the system as they are unable to access the location. Consider the following example,

<?php
$upload_dir = '/var/domainame/uploads/'; # Outside of web root
$upload_file = $uploaddir . basename($_FILES['uploadfile']['name']);
if (move_uploaded_file($_FILES['uploadfile']['tmp_name'], $uploadfile)) 
{
	echo 'Upload Successfully.';
	exit(0);
} 
else 
{
	echo 'Upload Fail';
	exit(0);
}
?>

This is somehow good but now the web server will not be able to access the directory too! Therefore, we need to provide another file for web server to access and display the file if necessary.

<?php
$upload_dir = '/var/domainame/uploads/'; # Outside of web root
$name = $_GET['name'];
readfile($uploaddir.$name);
?>

Now, both users and system will be able to access the directory provided that they know the name of the file. However, the above suffer from directory traversal vulnerability where a malicious user can use this script to read any readable file on the system. Consider the following example,

http://www.example.com/readfile.php?name=../secret/passwd 

This will most probably return the password stored in the server. Therefore, always remember to secure your POST and GET in your PHP script.

IIS PUT Function

If you are running PHP on Microsoft IIS, you will have to take particular care on your writable web directories. Unlike Apache, Microsoft IIS supports 'PUT' HTTP requests, which allows users to upload files directly, without using an upload PHP page. However, 'PUT' requests can only be used to upload a file to your web directory if the file system permissions allow IIS to write to the directory and if IIS permission allowed writing for that directory.

To prevent this, we have to ensure that IIS permissions do not allow writing although we will have to allow the directory to be writable in order to upload using PHP script. This will caused one of the condition to fail and 'PUT' request will not be enable by IIS which is used to bypass all the check you have done on PHP script by using 'PUT' request to upload into your directory.

The Include Function

In some script, we tend to use the receive value from users to determine which file to include into the PHP script. This is usually not a good idea as the attacker can execute certain file in your web server. Consider the following example,

<?php
# ... some code here
if(isset($_COOKIE['lang'])) 
	$lang = $_COOKIE['lang'];
elseif (isset($_GET['lang'])) 
	$lang = $_GET['lang'];
elseif (isset($_GET['lang'])) 
	$lang = $_GET['lang'];
else 
	$lang = 'english';

include('language/$lang.php');
# ... some more code here
?>

Assuming no filter is done on the data received, we determine the language and include the language file into the page which is a common piece of code for some of you. An attacker can take this flaws and enter a path on the URL to execute certain file in the system. Therefore, it is important to secure your upload function to prevent attacker from execute any file that are harmful to your system.(imagine they are able to upload certain shell or execution command and activate it via the URL)

Random File Name

We talk about how a file name should not be access directly by the users to prevent any form of attack. However, we can still access these file indirectly with the help of another script. But if the attacker do not know the name of the file that he have just uploaded, they might not be able to execute these arbitrary code into your web server. Thus, it is always good to randomly rename your file with md5 or other encryption algorithm. Consider the following example,

<?php
$filename = $_FILES[$uploadfile]['name'];
$save_path = '/var/domainame/uploads/'; # Outside of web root
$extension = end(explode('.', $filename)); #extension of the file
$renamed = md5($filename. time());		#rename of the file
if (!@move_uploaded_file($_FILES[$uploadfile]['tmp_name'], $save_path.$renamed. $extension)) 
{
	echo 'File could not be saved.';
	exit(0);
}
?>

However, if the uploading is done by yourself through an upload function, renaming these uploaded files might not be good for SEO purposes. Thus, the security measure here are for upload function that allows visitors or external users to upload certain file into your web server. ( basically you don't trust others than yourself )

Disable Script Execution

You can also try to disabled script execution on the uploaded folder where all the files go. You can do this by writing a .htacess file on the folder.

AddHandler cgi-script .php .php3 .php4 .phtml .pl .py .jsp .asp .htm .shtml .sh .cgi
Options -ExecCGI

This will gives you an extra layer of protection. You can also restrict certain file to be placed into the folder and only allows certain file to be placed into the folder. But remember that if some web application allows your 'white list' extension file to be interpreted by php machine, the chances of this protection might not be very useful. Nonetheless, this still serve as one of the many layer of protection for your web serverr.

HTML Upload Size

Although not all browsers do not support this but some still does. This can help provides certain level of protection against upload restriction.

<!-- allow 100kb -->
<input type='hidden' name='MAX_FILE_SIZE' value='100000' />

PHP Upload Size

We must also restrict the upload size on PHP to prevent any harmful file that is large enough to caused a sever damage to our server (any attack can caused a huge damage anyway). Checking the file size can also help you minimize the amount of disk space needed for your server.

<?php
#check for appropriate size with php.ini
$POST_MAX_SIZE = ini_get('post_max_size');
$mul = substr($POST_MAX_SIZE, -1);
$mul = ($mul == 'M' ? 1048576 : ($mul == 'K' ? 1024 : ($mul == 'G' ? 1073741824 : 1)));
if ($_SERVER['CONTENT_LENGTH'] > $mul*(int)$POST_MAX_SIZE && $POST_MAX_SIZE) $error = true; 
$max_file_size_in_bytes = 2147483647;				// 2GB in bytes
if(!$error)
{
	#restrict the limit
	$file_size = @filesize($_FILES[$upload_name]['tmp_name']);
	if (!$file_size || $file_size > $max_file_size_in_bytes) {
		HandleError('File exceeds the maximum allowed size');
		exit(0);
	}
}
else
{
	HandleError('File exceeds the maximum allowed size in php.ini');
	exit(0);
}
?>

You can visit the PHP handing file uploads for more information.

Limit File Upload

DOS attack (Denial of service) might be one of the concern that you have. Users might be able to upload a lot of large files and consume all available disk space which prevented other users from using the service. Hence, certain restriction should be imposed to prevent such cases from happening. The application designer might want to implement a limit on
the size and number of files one user can upload in a given period (a day)

BLOB Type Storage

An alternative to storing files on the file system is keeping file data directly in the database as a BLOB. This approach has the advantage that everything related to the application is stored either under the web root or in the database. However, this approach probably wouldn't be a good solution for large files or if the performance is critical.

Verify The Session

You may wish to impose certain security measure by having a session between the upload form and the upload handler to ensure that the user is authenticate to proceed with the upload.

Verify Upload

We must also verify that there is indeed a file being uploaded into the server to process the upload handler script.

<?php
if (!isset($_FILES[$upload_name])) {
	echo 'No upload found in \$_FILES for ' . $upload_name;
	exit(0);
} else if (isset($_FILES[$upload_name]['error']) && $_FILES[$upload_name]['error'] != 0) {
	echo $uploadErrors[$_FILES[$upload_name]['error']];
	exit(0);
} else if (!isset($_FILES[$upload_name]['tmp_name']) || !@is_uploaded_file($_FILES[$upload_name]['tmp_name'])) {
	echo 'Upload failed is_uploaded_file test.';
	exit(0);
} else if (!isset($_FILES[$upload_name]['name'])) {
	echo 'File has no name.';
	exit(0);
}
?>

The above is an example to verify whether there is an upload file and whether it is secure to proceed the file that the user has uploaded.

Upload Folder within www

Don't want your folder to be located outside of www or public_html? There is another solution for this. However, you might need to have dedicated or vps which has root access in order for this to work. Rather than giving write permission to the users, we give to apache instead. You can do this with a chown on the writable folder to apache or nobody and assign 770 permission.

Basically, this will disable public access to file in the directory. Short to say, external users will not be able to execute, read or write on the directory, only Apache is allowed to since it is the owner of the folder.

My Upload Handler

This is the upload handler that i usually rely on which you might be interested.

<?php
	#check for session
	if (isset($_POST['PHPSESSID'])) 
		session_id($_POST['PHPSESSID']);
	else if (isset($_GET['PHPSESSID'])) 
		session_id($_GET['PHPSESSID']);
	else
	{
		HandleError('No Session was found.');
	}
	session_start();
// Check post_max_size (http://us3.php.net/manual/en/features.file-upload.php#73762)
	$POST_MAX_SIZE = ini_get('post_max_size');
	$unit = strtoupper(substr($POST_MAX_SIZE, -1));
	$multiplier = ($unit == 'M' ? 1048576 : ($unit == 'K' ? 1024 : ($unit == 'G' ? 1073741824 : 1)));

	if ((int)$_SERVER['CONTENT_LENGTH'] > $multiplier*(int)$POST_MAX_SIZE && $POST_MAX_SIZE) 
		HandleError('POST exceeded maximum allowed size.');
	
// Settings
	$save_path = getcwd() . '/uploads/';				// The path were we will save the file (getcwd() may not be reliable and should be tested in your environment)
	$upload_name = 'Filedata';							// change this accordingly
	$max_file_size_in_bytes = 2147483647;				// 2GB in bytes
	$whitelist = array('jpg', 'png', 'gif', 'jpeg'); 	// Allowed file extensions
	$backlist = array('php', 'php3', 'php4', 'phtml','exe'); // Restrict file extensions
	$valid_chars_regex = 'A-Za-z0-9_-\s ';// Characters allowed in the file name (in a Regular Expression format)
	
// Other variables	
	$MAX_FILENAME_LENGTH = 260;
	$file_name = '';
	$file_extension = '';
	$uploadErrors = array(
        0=>'There is no error, the file uploaded with success',
        1=>'The uploaded file exceeds the upload_max_filesize directive in php.ini',
        2=>'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
        3=>'The uploaded file was only partially uploaded',
        4=>'No file was uploaded',
        6=>'Missing a temporary folder'
	);

// Validate the upload
	if (!isset($_FILES[$upload_name])) 
		HandleError('No upload found in \$_FILES for ' . $upload_name);
	else if (isset($_FILES[$upload_name]['error']) && $_FILES[$upload_name]['error'] != 0) 
		HandleError($uploadErrors[$_FILES[$upload_name]['error']]);
	else if (!isset($_FILES[$upload_name]['tmp_name']) || !@is_uploaded_file($_FILES[$upload_name]['tmp_name'])) 
		HandleError('Upload failed is_uploaded_file test.');
	else if (!isset($_FILES[$upload_name]['name']))
		HandleError('File has no name.');

// Validate the file size (Warning: the largest files supported by this code is 2GB)
	$file_size = @filesize($_FILES[$upload_name]['tmp_name']);
	if (!$file_size || $file_size > $max_file_size_in_bytes)
		HandleError('File exceeds the maximum allowed size');
	
	if ($file_size <= 0)
		HandleError('File size outside allowed lower bound');
// Validate its a MIME Images (Take note that not all MIME is the same across different browser, especially when its zip file) 
	if(!eregi('image/', $_FILES[$upload_name]['type'])) 
		HandleError('Please upload a valid file!');

// Validate that it is an image
	$imageinfo = getimagesize($_FILES[$upload_name]['tmp_name']);
	if($imageinfo['mime'] != 'image/gif' && $imageinfo['mime'] != 'image/jpeg' && $imageinfo['mime'] != 'image/png' && isset($imageinfo)) 
		HandleError('Sorry, we only accept GIF and JPEG images');

// Validate file name (for our purposes we'll just remove invalid characters)
	$file_name = preg_replace('/[^'.$valid_chars_regex.']|\.+$/i', '', strtolower(basename($_FILES[$upload_name]['name'])));
	if (strlen($file_name) == 0 || strlen($file_name) > $MAX_FILENAME_LENGTH)
		HandleError('Invalid file name');

// Validate that we won't over-write an existing file
	if (file_exists($save_path . $file_name))
		HandleError('File with this name already exists');

// Validate file extension
	if(!in_array(end(explode('.', $file_name)), $whitelist))
		HandleError('Invalid file extension');
	if(in_array(end(explode('.', $file_name)), $backlist))
		HandleError('Invalid file extension');
// Rename the file to be saved	
	$file_name = md5($file_name. time());
	
// Verify! Upload the file
	if (!@move_uploaded_file($_FILES[$upload_name]['tmp_name'], $save_path.$file_name)) {
		HandleError('File could not be saved.');
	}
	exit(0);

/* Handles the error output. */
function HandleError($message) {
	echo $message;
	exit(0);
}
?>

Conclusion

This is not a full proof solution for your file upload handler. However, this can used as references and also discussion that can help enhance the overall security of our web application today.

Review On Hostgator And Tips On Web Hosting Service

Well, this is a personal experience with Hostgator that i am sharing with you. And this is also the only product that i wrote in Hungred.com which i strongly think it is necessary in every web development. Without a hosting service, there won't be a need for web development. Seriously, there are just too many host services available on the internet. Each and everyone of their marketing strategy are strong and powerful. This means that they all seems to be reliable, supportive, trustworthy, etc. and etc. BECAUSE OF MARKETING. I did market research online for a week searching for good web hosting to get all my domain up and running. I nearly get trick by these advertisement they used. Here are some of the things i learn during my research and i would to share my tips on web hosting with you

  • Never trust a single source! Search for more information, most product online just seems too good to be true.
  • Never look at top 10 chart for web hosting. Most of them are owned by companies on the top 10 list
  • Never trust review blog. Blog that are dedicated to review products are not trustworthy, they are paid to do that! Status and facts that they provides doesn't really mean anything. Everything can be modify with Photoshop
  • Look for reliable sources. Sources that are supported by many people
  • Always look for the bad things people say about a company. Good thing are just everywhere online. Especially with marketing around
  • Listen to users who have experience with the services and check whether they are really using that service!
  • Do not trust even magazine which have many ads and good review. Most of them are paid to be even in magazine!
  • Ask question with their support. Ask everytime! This will help to ensure they really provides good support for all area. Don't just do it a single day!
  • Do not believe what you see. Find out yourself. Look for outside sources
  • List out all the good web hosting that you have found. Minimize them along the way.
  • Do not trust sources that other users cannot comment. You can try to look at blog that allows other users to comment to know more about the hosting
  • Look at the relevancy of the review by other people
  • Look at the site of the commenter who commented bad about the hosting services, you may be surprise that they are actually the competitors from other hosting site. This happened to blogs review most of the time
  • Checkout the duration of the reviewer with the service
  • Look at each web hosting service company total hosted domains
  • Always look at the rule and regulation VERY carefully
  • New Hosting company always has all the good things since its new but it will gets horrible in the long run
  • Find reputation company
  • Seems like everything is bad. But its the truth! You can only trust multiple review by users of that hosting services which is the only most reliable sources you can get

My list can goes on but i believe these are the most important ones. You can try finding how many people have been a victim on getting bad web hosting services. You might be surprise on the number of people there are. Try not to be one of them. Here are two site which i finally look upon with each and every good host services i have

Please look at the comment given by the users. Although these can be tempered with but it is more reliable than those that do not allow others to review them. Enough of tips of finding good hosting. Its time for the review of Hostgator

Review of Hostgator

Here are the reasons that i find you should host your website with Hostgator.

Excellent Support

I am a missing bird on the internet without any friends or guidance from anyone so i ask a lot of question. And they are 24/7/365 Upgraded Support. If you don't believe Hostgator provides excellent support you can always try and look at my chat transcript with their operator Son at first,

Welcome to GatorChat!
You are being connected to a representative in our 'Sales' department right now.

For immediate answers to your questions, check out our knowledge base and video tutorials at http://support.hostgator.com.


(11:43:07 PM) System: There currently are 0 people in front of you.
There are currently 25 chat technicians assisting customers.
(11:43:18 PM) System: There currently are 0 people in front of you.
There are currently 25 chat technicians assisting customers.
(11:43:21 PM) Son Le: has entered the chat.
(11:43:22 PM) Son Le: Hello, welcome to HostGator Live Chat.
(11:43:22 PM) Son Le: How may I assist you today?
(11:43:28 PM) Clay: Hi Son
(11:43:31 PM) Son Le: Hello Clay.
(11:43:47 PM) Clay: I am interested with your Business web hosting plan but i have some question and hope you can assist me
(11:43:53 PM) Son Le: Sure.
(11:44:41 PM) Clay: May i know what is the speed of the server on the Business plan?
(11:44:48 PM) Clay: as in bandwidth speed
(11:45:16 PM) Son Le: Speed on all servers is 100mbps both up and down.
(11:45:59 PM) Clay: shared or dedicated?
(11:46:15 PM) Son Le: It's shared.
(11:46:27 PM) Clay: should be alright
(11:46:34 PM) Clay: how about backup
(11:46:42 PM) Son Le: We run backup every Sunday.
(11:46:45 PM) Clay: do Hostgator backup files in the server for each account?
(11:47:01 PM) Son Le: Yes.
(11:47:05 PM) Clay: so we can request Hostgator to recover for us right?
(11:47:11 PM) Son Le: Correct.
(11:47:27 PM) Clay: How long does it take for recovering the data back to the account?
(11:48:06 PM) Son Le: I'm sorry I don't have ETA but it depends on the ticket que at the time you request.
(11:48:24 PM) Son Le: But it should be very quick.
(11:48:29 PM) Son Le: The restore que usually low.
(11:48:31 PM) Clay: oh alright
(11:49:10 PM) Clay: So is Hostgator server secure enough? what kind of security measure are we talking here?
(11:50:14 PM) Son Le: I'm pretty sure our server very secure. We monitor the servers 24/7.
(11:50:35 PM) Clay: hmm..alright
(11:50:47 PM) Clay: that's good for supporting businesses
(11:50:55 PM) Clay: i notice there isn't any SFTP
(11:51:00 PM) Clay: does Hostgator support SFTP?
(11:51:31 PM) Son Le: We have mod_security install, /tmp secured, firewall with inbound/outbound, and others bruteforce detection.
(11:51:52 PM) Son Le: SFTP is support.
(11:52:00 PM) Clay: wow. that's great!
(11:52:19 PM) Clay: on the backup section in the control panel of the demo
(11:52:34 PM) Clay: i notice we can manually backup the files, can we schedule them as well?
(11:52:53 PM) Clay: so that it automatically backup every particular day and send to our email?
(11:53:02 PM) Son Le: I'm sorry not for now.
(11:53:14 PM) Clay: oh
(11:53:33 PM) Clay: but should be alright you guys are doing automatic backup anyway
(11:53:39 PM) Clay: last few question
(11:53:59 PM) Clay: in the demo control panel i notice a few things i'm not quite sure..
(11:54:19 PM) Clay: what's processes running? what if it reaches 25/25?
(11:54:52 PM) Son Le: Once in a while you can go to Backup section and click on "Download or Generate a Full Web Site Backup" and logoff. It will do the backup and when it done, it will send notification email.
(11:55:41 PM) Clay: oh that's good. so i won't have to wait for it to complete? it will automatically send an email to me and inform me? i just have to click 1 button?
(11:55:49 PM) Son Le: After it reach 25 processes, your site will be showing error "Internal server error".
(11:55:54 PM) Son Le: Right.
(11:56:09 PM) Clay: Internal server error >< "
(11:56:13 PM) Clay: then what happen?
(11:56:50 PM) Son Le: You will have to optimize your site or move to dedicated server because your site is too big to handle by shared server.
(11:57:02 PM) Clay: oh..
(11:57:34 PM) Clay: if i host 40 website will it reach 25 although all 40 are optimize?
(11:58:01 PM) Son Le: It depends on how many visitors your sites have and how well your script perform.
(11:58:33 PM) Clay: is the moving of dedicate server difficult?
(11:58:48 PM) Clay: all my data will be lost? will Hostgator help to move them for me?
(11:59:22 PM) Son Le: Yes we will move the data for you if you purchase our dedicated server.
(12:00:04 AM) Clay: how about CPU Usage and Memory usage? 25%? what happen went it blow up to 25%?
(12:00:44 AM) Son Le: If your site exceed the resources usage of 25% more than 90 seconds, your account will get suspended and you will be notified by our security team.
(12:01:53 AM) Clay: suspend for how long may i ask?
(12:02:05 AM) Son Le: Until you reply to the email.
(12:02:23 AM) Clay: so once i reply the email it will be resume :D
(12:02:30 AM) Son Le: Yes.
(12:02:36 AM) Clay: i see!
(12:02:42 AM) Clay: one last 1
(12:02:46 AM) Clay: how about Inodes?
(12:02:51 AM) Clay: what's that
(12:03:01 AM) Clay: and what will happen when its over 250 000?
(12:03:10 AM) Son Le: Inodes is the number of files, folders, emails you have on the server.
(12:03:27 AM) Son Le: The use of more than 250,000 inodes on any shared account may potentially result in a warning first, and if no action is taken future suspension. Accounts found to be exceeding the 50,000 inode limit will automatically be removed from our backup system to avoid over-usage. Every file (a webpage, image file, email, etc) on your account uses up 1 inode.
(12:03:48 AM) Son Le: We will recommend that you upgrade or clear out your email boxes.

i got disconnected and went to support again, now its Herbert

(12:10:31 AM)  Herbert Cr: has entered the chat.
(12:10:35 AM) Herbert Cr: Welcome to HostGator Live Chat.
(12:10:39 AM) Herbert Cr: How may I assist you today?
(12:10:41 AM) Clay: Hi Herbert
(12:10:45 AM) Herbert Cr: Hi Clay
(12:11:03 AM) Clay: i was chatting with Son just now and something went wrong
(12:11:15 AM) Clay: i was asking him 250 000 node is around how much disk space
(12:11:42 AM) Herbert Cr: disk space isn't a factor there
(12:11:59 AM) Herbert Cr: as INODE can be anything from 512 bytes to 2 gigs
(12:12:16 AM) Clay: oh..so its the number of files but not the size?
(12:12:19 AM) Herbert Cr: or larger just depend on the disk it is on.
(12:12:25 AM) Herbert Cr: correct
(12:12:35 AM) Clay: oh i see!
(12:12:42 AM) Clay: that's explain
(12:13:14 AM) Clay: 250 000 inodes is equal to 250 000 file, folder, email in the server?
(12:13:41 AM) Herbert Cr: correct 250,000 files or email or folders or web pages
(12:14:12 AM) Clay: i see!
(12:14:36 AM) Herbert Cr: after you cross the 50,000 mark you are at risk as the backup stops for everything but the database.
(12:15:23 AM) Clay: i notice tha there is an initial order 20% by placing certain code
(12:15:44 AM) Clay: will i be entitle this after my member with Hostgator is over?
(12:15:47 AM) Herbert Cr: yes the coupon
(12:16:13 AM) Herbert Cr: the coupon is good on the first payment
(12:16:37 AM) Herbert Cr: seems to be Beach until Sep 1
(12:17:10 AM) Clay: so after 3 years of member can i use the latest code at that time to receive 20% discount again?
(12:17:39 AM) Herbert Cr: if it is a new package you are signing up for
(12:18:16 AM) Clay: i was asking about the business web hosting plan
(12:18:21 AM) Clay: so i was thinking
(12:18:51 AM) Clay: if i sign up for 3 years for 12.95 per month
(12:18:55 AM) Clay: after 3 years
(12:19:04 AM) Clay: what is the price of the plan again?
(12:20:29 AM) Herbert Cr: it will be 466.20 no discount on renew
(12:20:49 AM) Clay: 466.20 for a month?
(12:21:06 AM) Herbert Cr: it is for the 36 months
(12:21:13 AM) Herbert Cr: 3 years
(12:21:42 AM) Clay: so it will be 12.95 per month again if i sign up another 3 year right?
(12:22:47 AM) Herbert Cr: correct
(12:23:13 AM) Clay: i see
(12:23:31 AM) Clay: so for other plans
(12:23:46 AM) Clay: what is the differences between Dedicated IP and no dedicated IP?
(12:24:04 AM) Herbert Cr: share IP lots of other domains are on it.
(12:24:41 AM) Clay: so what will happen if there are other domains on a shared IP compared to a dedicated one?
(12:28:24 AM) Herbert Cr: nothing will happen the dedicated has the advantage of less traffic on the IP
(12:28:57 AM) Clay: i see.
(12:29:19 AM) Clay: the business plan seems to provides a free SSL
(12:29:40 AM) Clay: may i know what certificate it is providing?
(12:30:54 AM) Herbert Cr: Positive SSL from Comodo is the one that comes on the business package
(12:31:14 AM) Clay: i see!
(12:31:27 AM) Clay: Thanks Herbert that's all of my question
(12:31:29 AM) Herbert Cr: Differences:

1. Instant SSL can authenticate (verify) your domain's WHOIS information, but Positive SSL can only authenticate the domain name.
2. Instant SSL comes with Comodo Warranty, but Positive SSL does not.
(12:31:45 AM) Herbert Cr: Okay, take care and have a great day!
(12:31:54 AM) Clay: oh that's a great information there
(12:31:56 AM) Clay: thank again
(12:32:04 AM) Herbert Cr: You're welcome!
(12:32:11 AM) Herbert Cr: and have a great day!
(12:32:17 AM) Clay: You too!

Well, i contact them several times and this is just one of them. Most of the time i will rank them quite highly after a support. They allows you complain or rank their support after an online conversation. I contacted them almost anything and they are cool enough to share with me what they know about the issues.

45 Day Money Back Guarantee

Many offer such services but if you did your research, there are also many who delay the refund. But Hostgator are cool enough to return your money if you are not pleased with their services.

Discount Coupon

They offer 20% discount coupon EVERY SINGLE TIME so try not to miss this out. If you are signing up to Hostgator , be sure to grab their 20% code to be placed into your order form to receive this discount. It really help save a lot for long term sign up.

Host Your Website For 1 Cent

What's more? The baby plane for Hostgator cost you ONLY 1 CENT! No kidding but it's only for the first month. Great for experiencing your hosting with Hostgator . For most existing users, we might all know this. During your sign up with Hostgator, just write in '404PAGE' into the coupon code.

Other Special Coupon Codes

Here are some other codes offer you can try.
FREETRIAL, ICEISHOT, JURY, HGC25, 404PAGE

Reliable Uptime

If you are regular on hungred.com, do you ever see this site went down before? I spend almost all of my time on this site and never seen it went down. I can personally guarantee that Hostgator is Reliable. Hostgator themselves also guarantee a 99% uptime which is trustworthy for me.

Upload and Download Speed

Other than my internet speed suck sometimes because of my country internet provider, i do not see any speed problem uploading and downloading contents to my site. No issue at all.

Hostgator controls usage

In case you are not aware, web hosting usually are shared hosting plan. This means that a server is shared among multiple users. Some control should be implemented. This can be bad for some people who uses very large bandwidth for streaming or download server but great for many others users in Hostgator (web hosting is to host website and not for other type of server). Hostgator has control over these so that each account is responsible enough not to hog up all the resources towards their account and affect other account website within the server. Personally as a developer i think this is great for majority users out there who are going to host their site with Hostgator .
static

Unlimited Space and Bandwidth

Many website provides unlimited space and bandwidth but its always unreliable since they do not have control for each account and allows other accounts to abuse the server which affect other account greatly to the extend that other website will not load. But Hostgator takes care of this and ensure reliable speed and the space is really unlimited (but you won't want to store your stuff in there, trust me i will explain why later). The actual speed can be seen on the conversation i posted above with the operator.

Many Satisfy Customers

Search around the internet, you will find most of Hostgator users are pleased with their services. But i can't really tell you they are pleased. Search around the internet or use the link i provided above. You will find many good testimonials. I am one of them of course. Here are some of them from the site i suggested which people voted more relevant.

review3
review2
review1

One of the largest web hosting service on the internet

There are over 2,200,000 domains hosted on Hostgator currently. Many people trusted Hostgator services, it was also one of the criteria i looked when during my research.
domain
You can also look at Web Hosting Top for their statistic of domains per month.
estimate-domain

Everything is available

We technical people look at whether they have all the required web development application and other network related issues on the server. Hostgator seems to have all the required languages ready to be used. Statistic,log,ftp,sftp, etc. are all available on their control panel.

Regular Backup

They also helps you to backup your files regularly as seen on my conversation with their operator. It will only stop backup once you have exceed a certain potion of your usage. Nonetheless, you can still backup yourself manually and allow them to send it to your gmail when they are ready. (this is done with a click) Although it will stop auto backup for you, you still have the unlimited storage to use.

Excellent Forum

They have a excellent forum that can assist you with all your needs. If you don't feel like visiting their 24 hours support channel, you may like to post your enquiry on the forum for their moderator to help you. You can visit their forum and check each and every post for certain responds from their moderator.

Hostgator Do Poorly Too!

Enough of Good things about Hostgator, let's look at the things they do fairly.

Average Web builder

Well, the free web builder are great for beginners who have absolutely no knowledge of building website. However, for developers and designers you will agree with me that you might not want to use this service.

Apply For certain services

In Hostgator, you will have to submit ticket to request these services to be activated in your account even though it might be free.

  • SSH Request
  • SSL Request
  • Site Builder/Site Studio Request

These are what i requested but here are the overall list.
request

Disable Directory index

You will have to inquire the support to assist you to disable directory index in PHP. This way, users will not be able to access your sub directory using the URL. I think this should be done automatically.

Pricing

Pricing was a major issue for me while searching for a web hosting service. But definitely reliability is marked first as i won't want my users to be unabled to access my website and leave. It will be bad for my business reputation. Although i sign up with Hostgator but i still feel that the pricing is a bit higher than other hosting services. Nonetheless, its worth it at the end of the day. (unless they suddenly give me downtime. RAWR!)

Reseller

Many people complains on Hostgator reseller service. You might want to look out for this if you are thinking of getting a reseller package. I personally cannot comment on this.

Email

This is really IMPORTANT for my business if i were to join Hostgator. People has been complaining on their Email services previously, but currently this has been resolved! Well, i haven't had any problem with it.

Rule and Regulation

Well, i do not believe this is being done poorly by Hostgator . It just that people don't tend to read what they are signing up for. May be this can be placed somewhere better for people to notice. eg. highlight certain words with red.

CPU Usage

Well, in Hostgator your site might get locked up if it takes up too much resources. This means that your site won't be accessible and the representative will send you an email to request you to fix it before enable your site to run on the server again. The good thing about this part is other website will not be affected by you. The bad thing is your site is unable to access. In case you have no idea what i am talking about here is a picture of the panel that might explain.
cpu
Basically, your site cannot exceed the limit of 25% of resources usage. Here, you might think 'what the hell! It won't be enough'. But its really will be MORE THAN ENOUGH for a few hundred site running at the same time. It will most likely exceed this limit when one of your site is performing tricks that will go into infinity loop or just takes more than 90 second to run. Pure inefficient, you should definitely look into it. development always bring the danger of entering into these categories. Getting locked is not fun. (may be i'm just very demanding)

Services

Their customer support were great! But there are some operators that i notice are not very technical. They will then provide you with standard answers like its written in a cook book. May be the cook book answer fit you well and they manage to solve your problem but what if it doesn't? This is when we have to submit support ticket or enquire the forum for better more technical people to assist us. BUT i like this,

Every web hosting plan comes with a 45 day money back guarantee, 99.9% uptime guarantee, and is fully guaranteed by the owner himself. If you ever have a problem with regular support just ask that your ticket be assigned to Brent and he will personally take the time to give you the VIP attention that you deserve.

Summary

I was aiming to look for a hosting for business purposes that are reliable, secure and can support my business. I ended up signing up with Hostgator and was very happy with it which i believe my experiences should be shared to people out there. But if you are thinking of hosting something illegal or pornographical, don't try Hostgator you will surely make a lot of noise. On the other hand, there are no unlimited resources in web hosting services. In Hostgator, the unlimited is being limited by cpu, memory and processor. So you can say that you have unlimited bandwidth and disk space but if your traffic reaches 1 million unique users, your cpu and other resources will still peak and you would have to change to a more expensive plan. Solution is to use third party services and integrate them to all of your site. This way, you can use all the unlimited things in the package while the resources will not depreciate so quickly. If i miss up anything, inform me i will write it up here.

Other than all the things above, i believe most of the users of Hostgator will have other feedbacks on their experiences with them.

Understanding Preloading For Web Components

We heard preloading almost every time! But do you really understand what is preloading and how does preloading actually work? In this article, we will talk about preloading and how it should and can be use.

What is Preloading

Most of us will know but there are many that are unclear. Preloading is an action that will load components which are not visible available to the users. This means that any component that are already in the HTML document will be loaded and preloading doesn't help speeding up these components. What we would like to preload are those components that do not resist within the document and components for future pages.

Why Preload component

Why do we want to preload a component if it doesn't help speeding up the existing components on the HTML document?! Simple, let's say we have a gallery which has the following code in our document

<img src='example.jpg'/>

compare to document that has these codes

<img src='example.jpg'/>
<img src='example1.jpg'/>
<img src='example2.jpg'/>
<img src='example3.jpg'/>
<img src='example4.jpg'/>
<img src='example5.jpg'/>
<img src='example6.jpg'/>

Assuming each image in these example are 800kb in size (If you have a script that wait for an onload event to occurs, i wonder when will the script start running). It will be obvious which one will finish first (the first example). So your user gets to see the result like less than 1 minute. The sub sequence images will be preload into the document while the user is still viewing the first one. Thus, clicking the next button will show a loading in progress or immediately displayed the second image depending on how you construct your script to accomplish this.

Although we didn't speed up the image loading time but we manage to speed up the overall waiting time for the whole page to be display completely. Thus, preloading allows us to practice 'load only when needed' concept. This means that those that are not going to display first should be loaded last and allow the page to be fully loaded before their turn is up to run.

If you have very big file size page, it will serve as a notification to the users that the site is loading. On the other hand, preloading allows you to cache them onto the user browser for better responsiveness. (although there are disadvantages of doing this too) This way, sub sequence pages will have better 'speed'.

What component can be preloaded?

Basically you will want these components to be preloaded first since they usually take up the most loading time.

  • Images files
  • Flash files
  • Sound files

There are not much reason to preload other type of document unless they are very big in size. Most document are small enough to load within a few seconds but the one mention above are usually the one we are concern with during web development.

What are the methods for preloading

This depend on which components are you trying to preload. There are all sort of ways to preload certain components such as JavaScript, ActionScript, CSS, Ajax or HTML tag. So depend on which one are you trying to preload and what are you trying to accomplish. Flash files will most likely be ActionScript. For Images, people tend to use CSS, JavaScript for caching and Ajax for preloading with loading image. While sound files will be using embed tag.

How Preloading work

In a way, preloading can be describe as work behind the scene. Basically, the user will not be able to notice. But different way of preloading work differently,

CSS

In CSS, the objective is to hide those component you want to preload. And you might want it to be placed at the last row in your HTML document (means it will load only all relevant component has loaded). Methods used are usually,

  1. Visibility: hidden
  2. display: none
  3. width:0px;height:0px;
  4. top: -99999px; or left: -999999px

The objective is to hide it so that it will store in the cache.

JavaScript

In JavaScript, we used the image object. (this method can also be used to preload flash files into the cache)

var obj = new Image();
obj.src = 'test.jpg';

This way it will preload the images for sub sequence pages as the images are cached. This method can also be used to produce loading image before applying the following code

document.getElementById('container').innerHTML = '<img src='test.jpg/>';

Ajax

Ajax let the server script to load the image page, cached and send it back to the document for display.

function preload(url) {
  // display loading image
  // send the url to be open on the server side. hence, cached.
  document.getElementById('loading').style.visibility = 'visible';
  document.getElementById('container').innerHTML = '';
  var obj =  new XMLHttpRequest();
  obj.open('GET', url, true);

  obj.onreadystatechange = function() {		
    if (obj.readyState == 4 && obj.status == 200) {
      // once cached, we hide the loading image and display the content
      if (obj.responseText) {
        document.getElementById('container').innerHTML = '<img src=''+url+''/>';
        document.getElementById('loading').style.visibility = 'hidden';
      }
    }
  };
  obj.send(null);
}

During the request, we can display a loading in progress image until the new image has loaded. However, this doesn't seems to work on IE 7. (this is shown later on demo section)

HTML tag

This is usually used for sound files.

<EMBED NAME='mySound' SRC='mySound.mid' 
LOOP=FALSE AUTOSTART=FALSE HIDDEN=TRUE MASTERSOUND>

Action Script

If you are interested, here is a video.

The Demonstration

i will demonstrate using Ajax which the code has been written above. Please click the image to see the loading. Here are the files and demo