If you own or run a website, then security should be near the top of the list in terms of daily priorities. You far too often hear stories of old and unsecure websites falling victim to data breaches or getting taken down with relative ease.
While you can't really prevent every single type of threat, there are still plenty of things that you can do to keep your websites safe and to decrease the amount of damage that can potentially be done.
So here's a list of my 7 best practices to start implementing today.
7. You should be using HTTPS
In the not too long past, you could easily get away with not having an SSL certificate on your websites. Not that it didn't matter, because it did and still does. But more so, there was no actual penalty for not doing so.
That isn't the case anymore. Most modern browsers pretty much require you to have an SSL certificate installed so that you can direct traffic through HTTPS. If you don't, most browsers will warn users before they even reach your website that a potential security threat is upcoming.
You can either purchase your SSL certificate, or go with a free version, but in any case you need to have one set up and configured.
Most cloud hosting providers these days do in fact offer free SSL certificates to their clients. Once you have your certificate configured, you'll more than likely also want to redirect all non-https traffic to its equivalent HTTPS version.
6. Set file/folder permissions
Not every single file on a web application needs to be public facing. And in some cases, entire directories should be kept private.
These can include admin only directories or member content. Some browsers will list the entire directory structure of a URL path which isn't an ideal scenario as it can give away too much internal information.
Setting permissions will solely depend on the environment that you are hosting your websites on, but the usual settings include modifying:
- Read
- Write
- Full access
Certain folders are required to be public, such as any storing image files that are displayed on the website. And in most cases, hosting providers do allow you to turn off the directory listing feature.
5. Validate all incoming data
If you have any type of user entry forms on your web pages, then you need to verify each and every field to ensure that it is of the right data type and value.
If you have an email entry form, for example, then ideally you would want to verify that only valid email addresses are added and saved in your database.
<input type='email' />
<input type='number' />
In the case of an email address, browsers will have built in validation that will do the actual checking for you. You just have to set the type property to 'email' in this case.
Setting the correct type attribute on your forms is a great starting point in ensuring data integrity.
Other potential type values include:
<input type="button">
<input type="checkbox">
<input type="color">
<input type="date">
<input type="datetime-local">
<input type="email">
<input type="file">
<input type="hidden">
<input type="image">
<input type="month">
<input type="number">
<input type="password">
<input type="radio">
<input type="range">
<input type="reset">
<input type="search">
<input type="submit">
<input type="tel">
<input type="text">
<input type="time">
<input type="url">
<input type="week">
And in some cases, you will need to set your own validation rules based on your required business logic.
Note also that client-side validation is only half of the equation. Validation should also be added to the server-side code, and the database layer as well, to ensure that data integrity is maintained throughout.
4. Set proper ranges
This step goes hand in hand with the validation mentioned above, but it's a bit more specific to one particular area.
Often times you require a user to enter a value that must fall between two other endpoints. If you are entering the quantity of an item, as an example, then you need to ensure that there is no negative value entered. And you should also cap the amount to something realistic to your particular needs.
Let's take the quantity in a shopping cart as an example. At the lowest level, you can only have 0 quantity. And at the highest level, you should set a threshold that you are comfortable with. You shouldn't allow for a quantity of 1 million as an example, unless you can handle that load.
One of the simplest methods to create this restriction, is by using the min and max attributes in an input control.
<input type='number' min='2' max='10' />
The max and min attributes works with the following input types: number, range, date, datetime-local, month, time and week.
Again, you should also include those same restrictions in your server-side and database layers as well.
3. Authentication
This is often where most websites vulnerabilities begin. Authentication is the process of verifying that the current user actually has access to the data they are looking at.
Often times this involves having the user log in to a website. This creates a short-lived token that typically gets stored in a cookie and that follows the user around only showing them content that they indeed have access to.
Internally, it might look something like the following:
SELECT * FROM Data d INNER JOIN User u ON d.UserId = u.UserId WHERE u.UserToken = '234823AB40Y2342349';
Every table with sensitive information should be joined with the user table and queried against the current user token.
The problem happens when either, the database isn't set up correctly, or when a developer avoids querying against a token.
Often times, brute force attacks can also be used to 'guess' a users token. In this case, a potential attacker will attempt to query against every possible known combination of characters until something works.
This is when tracking login attempts comes into play. You will notice that most websites these days typically allow around 5 login attempts before locking an account out for a period of time. It becomes essentially impossible to attempt billions of permutations, when you only have access to 5 attempts at at time.
2. Encode/decode content
Script injection attacks, or cross-site scripting (XSS), occur when unwanted scripts (JavaScript) are run on unknowing websites.
And depending on their implementations, they can usually go unnoticed for a long time.
The only real solution to that problem is to properly encode all user generated input before you process or store it to your database.
Most programming languages have built in encoding and decoding methods which take any string as a given input and produce the resulted encoded version.
Console.WriteLine("Enter a string having '&', '<', '>' or '\"' in it: ");
string myString = Console.ReadLine();
// Encode the string.
string myEncodedString = HttpUtility.HtmlEncode(myString);
You don't have to encode/decode all data that your websites work with, just the data that comes from any external source that is outside of your control.
1. Backup your data
And lastly, the simplest thing that you can do to secure your websites is to keep your code and your data backed up as frequently as you can.
That means adding your code to a private repo and making frequent commits.
Backing up your databases will vary depending on the host provider that you have chosen, so doing your research early on, before you have a large amount of data is important.
Even the best and most expensive security systems eventually get bi-passed. You aren't looking for the most bulletproof system, but more so to mitigate the amount of damage that can be done and to find the fastest ways to recover when something does go south.