Protecting your website against attacks.
During the development and maintenance of websites today, various attacks and vulnerabilities must be considered to protect the vital information and functionality which lies within the web server. If left undefended, malicious users may exploit these in order to gain control and potentially cause irreparable damage to your website.
This post is designed to highlight some of the most common vulnerabilities and attacks which you may face, as well as providing some solutions which can defend your webpage from harm.
- Brute Force Password Attacks
- SQL Injection Attacks
- Cross-site Scripting
Brute Force Password Attacks are attacks designed to gain a user’s password by force. These attacks attempt to gain the password by trying millions of variations of combinations of characters and words Eventually the correct password combination will be found and the user will have gained access to the system. Although this form of attack sounds as if all passwords would be cracked eventually, there are several simple methods you can employ which can slow and prevent these forms of attacks.
For the examples below, we will assume that a user is attempting to acquire a login to your website by performing a brute force attack, which will attempt 100 passwords per second. Over a 1 hour period of time, they will have tried 360,000 password combinations. This will be our benchmark for comparing an unprotected system to a protected system.
Passwords attempted per hour = 100 attempts per second = 360,000 attempts per hour.
One of the best ways of preventing this form of attack is to limit the amount of incorrect attempts a user can have. Typically, there will be a limit set and once this limit is hit, a cooldown period would be in effect for that user or IP, which will prevent them from attempting to log in for a period of time. This can be easily implemented by recording the time of the 10th login attempt and storing this information with a record of the user’s IP. The cooldown period can then be added to this time. The website can reject all requests by that IP which occur before the cooldown time has been reached.
For example, if we imposed a limit of 10 incorrect attempts within a 5 minute period of time, whereby if the limit is hit the user must wait 5 minutes before they are allowed to attempt once more.
Our attacker is attempting 100 passwords per second, therefore they will hit this limit very fast. In this example, they will only be able to attempt 10 times per 5 minutes, which equates to 0.03 passwords per second.
Passwords attempted per hour = 0.03 attempts per second = 120 attempts per hour.
Another way to counter this attack is to use Multiple-Factor Authentication techniques, which are popular today in online banking. An Authentication Factor is a form of authentication which you can use for your system. There are several types of authentication which can be used:
- Knowledge Factor – Something the user knows (e.g. A password, A PIN Code)
- Possession Factor – Something the user owns (e.g. A card, A mobile phone which can receive an authentication code.
- Inherence Factor – Something the user is (e.g. User’s fingerprint, Retina scan
Although Inherence Factors will not be feasible for most people, Knowledge and Possession Factors can be extremely effective when used in conjunction against all forms of password attacks. If used correctly, they will completely prevent brute force attacks, as well as many other forms of password attacks.
For example, your website could require a password and a code which has been emailed to the user at the time of login. The brute force attack would fail every time as it would be extremely unlikely that the program would get the correct combination for the password and the constantly changing code. Additionally, as two attempts must be generated per attempt, this will half the number of passwords which can be attempted over any period of time.
Passwords attempted per hour = 50 attempts per second = 180,000 attempts per hour HOWEVER the password and code will be near impossible to get correct at the same time
Finally, another solution would be to ensure that the users of your website only use strong and long passwords. This solution has varying effect depending on how strong you enforce the password to be. The longer the password, the more possible combinations and therefore the longer time it could potentially take for an attacker to gain the password. A stronger password works in a similar way by introducing more characters which again increases the number of possible combinations. Below are some examples showing the effects of these techniques:
The time to crack is at the same rate as in the examples earlier in this post, with a rate of 100 attempts per second.
Password of letters with a length of 4 characters.
Possible characters: 26+26 = 52 (upper and lower case)
Possible combinations: 52^4 = 7311616
Time to crack: 7311616 / 100 = 73116.16 seconds = 20.3 hours
Now lets compare this to doubling the password length:
Password of letters with a length of 8 characters.
Possible characters: 26+26 = 52 (upper and lower case)
Possible combinations: 52^8 = 53459728531456
Time to crack: 53459728531456 / 100 = 534597285314.56 seconds = 16951.97 years
As you can see, just increasing the number of letters in the password by 4 has made a dramatic difference on the time it could take to crack the password. Although, you need to consider that the times given are the best case times, whereby the attacker gains the password on the last combination they try. The attacker has the same chance of guessing the password on the 1st attempt as they do on the 10,000th attempt. Therefore this doesn’t prevent the attack from happening, it just means that it could take the attacker longer to gain what they are after.
SQL Injection Attacks target code on your website. Any time an SQL query is run, it could be vulnerable to this form of attack. Attacks of this kind are designed to run any SQL query within valid SQL calls on your website.
For example, you may be selecting a handful of items from a search based upon the users input. You would be expecting the following information to be input:
User Input: websites
SQL Query: SELECT * FROM blog_posts WHERE name = ‘websites’
However, if left unsecured to this vulnerability, the user could use this SQL query to execute anything they wish:
User Input: ‘;DROP TABLE users;’
SQL Query: SELECT * FROM blog_posts WHERE name = ”;DROP TABLE users;”
The above code could be entered by any user on your website within this example search box and would result in the deletion of your entire users table. Without backups, this could cause irreparable damage to your website.
Prepared statements will prepare the SQL query to be executed before anything is run. This prevents malicious code from being run as the query code is sent to the server first, whereby the values contain placeholder data which will later be replaced by the query data. This method will protect you against SQL Injection attacks if used whenever the user can pass data which will eventually be used in a SQL query.
Below is an example of using prepared statements within PHP using MySQLi:
$conn contains a valid mysqli database connection.
This line creates the sql query with the placeholders, indicated by ‘?’
$sql = $conn->prepare(“INSERT INTO users (firstname, lastname, email) VALUES(?,?,?)”);
This line binds the values to the placeholders in the statement. The first variable (“sss”) indicated the data types of the input. In this example they are all string (‘s’), hence the (“sss”). This is followed by the variables in the order that they appear in the statement.
$sql->bind_param(“sss”, $firstname, $lastname, $email);
The sql statement is then executed.
Another method of preventing SQL Injection attacks is to escape all of the inputs which were received by the user. This works by ensuring that any user input is interpreted as an input and not as code. Therefore, any code which the user inputs will not be interpreted as code and will not be executed.
This will escape the passed string, making it safer for use within an SQL statement.
All you need to do is use the above function on every input which the user can give and you will be more secure against SQL Injection attacks.
Cross-site Scripting is similar to SQL Injection attacks, with the exception that malicious scripts are input rather than malicious SQL code. This technique is often used to steal cookies and session tokens from valid users to perform a session hijacking. This would allow the attacker to imitate the targeted user and perform actions which the valid user would be able to normally do.
Below is an example of a Cross-site Scripting attack:
In this example website, the user can search for data using the following form
<form action=”search.php” method=”GET”>
<input type=”text” name=”keyword”/>
<input type=”submit” value=”Search”/>
On the following search page, the search results are displayed alongside what the user had searched for
<h3>Search Results For: <?php echo($_GET[‘keyword’]);?></h3>
<!– Search Results Below –>
Should the user enter the following line of code, a simple Cross-site scripting attempt is made.
Entering this line will cause an alert stating ‘XSS Injection’, which indicates to the user that the input box is not protected and may be exploited by the user.
Cross-site Scripting can be easily prevented in PHP by using one of the existing functions – htmlspecialchars(). This function encodes all HTML tags and special characters into their HTML variants. For example, the character < would be encoded into < by this function. This would prevent Cross-site Scripting by encoding all of the HTML code which may be present within the user input and will therefore prevent it from being executed. The function needs to be used whenever a user input is taken (or can be taken) and is output.
For languages other than PHP, any similar technique to encode HTML tags and special characters will work identically to this existing function.
Cross-site Scripting can also be prevented by validating all user inputs. This will work by limiting the input to only inputs which you wish to receive. For example, an input where you expect to receive a number should be validated to only receive a number, therefore preventing anything other than a number from being input. This will prevent the user from entering their malicious code and the input should receive inputs which you expect.
In this post we have covered a handful of the ever-changing attacks and vulnerabilities which may pose threats to your website. As technologies and software develop, new methods are exposed to allow unauthorised access to your systems. Although the solutions covered in this post should help to protect your website, the only way to remain completely secure is to keep up-to-date with the latest vulnerabilities and ensuring you implement the latest methods of protection onto your website.
Date: April 17, 2015
Category: Web Development
Author: Ashley Peck