Website Security: 11 Steps to protect your Website from Attacks 🐱‍💻
Tags: security, webdev, javascrtip, php
Published: 2021-05-07 09:05:28

<sub>_Originally published at [webdeasy.de](https://webdeasy.de/?referer=dev-207d)._</sub>

_At this very moment, countless websites become targets of hacker attacks. Often, uninstalled updates and ignorance are to blame. What you can do to prevent hacker attacks on your website, you can learn here._

Hacker attacks are very unpleasant for those affected and can lead to loss of revenue, loss of customer confidence and other unpleasant consequences. Therefore, you should regularly check your website security for potential security vulnerabilities and fix them as soon as possible.

Some weak points can be eliminated quite easily with a few small steps. There are also certain techniques that should be observed when implementing (programming) the website in order to protect your website from hackers in the best possible way.

# Table of Contents 🛡️
* [Website Security Check](#website-security-check) ✔️
* [Possible attack scenarios ⚔️](#attack-scenarios)
* __Improve Website Security__ 🔒
 * [1. Use TLS (SSL) certificate](#tls)
 * [2. Avoid SQL Injection](#sql)
 * [3. XSS (CORS) Issue](#xss)
 * [4. Prevent DDOS Attacks](#ddos-protection)
 * [5. Use strong passwords](#secure-passwords)
 * [6. Session Management & Cookie Handling](#session-management)
 * [7. Hide public (sensitive) information](#informations)
 * [8. Validate user input](#validate-user-data)
 * [9. Install updates regularly](#updates)
 * [10. Create Regular Backups](#backups)
 * [11. Prevent Spam in Contact Form](#spam-form)
* [Conclusion](#conclusion) 📝

#Website Security Check ✔️ <a name="website-security-check"></a>
Website security is a very complex topic and in general: __no system is unhackable!__

However, you can make it very difficult for attackers and especially against mass attacks, such as Brute-Force-Attacks, you can protect yourself relatively easily, you just have to go about it.

It is best to close security holes as soon as possible, before someone discovers them and can exploit them maliciously. To detect them, there are now many tools online, such as [Siwecos](https://siwecos.de/) or [VirusTotal](https://www.virustotal.com/gui/home/url).

These tools check a whole range of possible vulnerabilities. Many of them are only recommendations, others should definitely be fixed. However, really critical vulnerabilities are not always detected by such tools, so manual checking is definitely necessary.

You should check and implement the following safety aspects in any case.


#Possible attack scenarios <a name="attack-scenarios"></a> ⚔️
There are an almost infinite number of attack scenarios on websites or web servers. In the following, I will briefly discuss the most common scenarios and briefly explain what happens during an attack. In “good” attacks, often a combination of a variety of different ways is tried to hack the system.

__SQL Injection (SQLi):__ Malicious database queries are injected to read data or gain access.

__Brute-Force-Attacks:__ Trial and error is used to try to gain access to a system.

__Local File Inclusion (LFI):__ Malicious source code is executed on the target system and can have various consequences – such as system takeover.

__Cross-Site-Scripting (XSS):__ Execution of malicious JavaScript code in the browser of the website visitor.

__Defacement:__ Infiltrating/altering information on a website, e.g. to spread political propaganda.

__DDoS Angriff:__ The aim is to crash the target system by overloading it.

__Take over website/web server and use as bot:__ Web server becomes part of a botnet to spread malware, for example.

The goals of the attack types can be different: Some are aimed at tapping user data, others try to overload the system and crash it, and others simply want to cause chaos.

#Improve Website Security 🔒
##1. Use TLS (SSL) certificate <a name="tls"></a>
TLS certificates (also known as SSL – SSL is the older version of the protocol) for websites are responsible for secure communication between client and server and are a very important part of website security. The certificate encrypts all data exchanged between the browser (client) and the website (server). Without this encryption, all passwords or even bank data could be intercepted in plain text by attackers.

Secure (encrypted) connections can be recognized by the lock in front of the domain and the preceding __https://__ like here:
![https:// of the domain webdeasy.de](https://webdeasy.de/wp-content/uploads/2019/05/ssl.png)
In addition, certification authorities (CA) such as [GlobalSign](https://www.globalsign.com/en) confirm the authenticity of a domain or even the entire company. This ensures that it is a real website and not, for example, a phising site or similar. Especially for sites with login you should always make sure that this lock appears in front of the domain.

If your website deals with personal data, __you definitely need an TLS certificate__. Its use must also be mentioned in the privacy policy in a corresponding paragraph. For more information, please contact your data protection officer.

Most hosters have a free TLS certificate included. Otherwise you can rent it there for a small fee. Alternatively, you can also generate a free certificate from [Let’s Encrypt](https://letsencrypt.org/). If you use [Plesk](https://docs.plesk.com/de-DE/onyx/customer-guide/websites-und-domains/sichern-von-verbindungen-mit-ssltlszertifikaten/abrufen-eines-kostenlosen-ssltlszertifikats-von-let%E2%80%99s-encrypt.77233/) to manage your website, you can install the extension for free and use it to protect domains and mail servers.
> __FunFact:__ Google is its own certification authority (CA), so they virtually certify themselves. 🤯 ![*.google.com Certificate](https://webdeasy.de/wp-content/uploads/2019/05/Google-SSL.png)

##2. Avoid SQL Injection <a name="sql-injections"></a>
An SQL injection is an attack in which foreign SQL code is executed on the server-side system of the server. In this way, the attacker can execute SQL queries on the server and thus modify or read data.

Whhhaaaaattt? Don’t worry, here’s a little example:
```sql
SELECT name, place, phone FROM index WHERE ID=4;
```
“4” was written to the SQL statement by a user input and everything is fine. However, the user can also enter the following into an HTML input or HTML textarea: _“4; UPDATE name SET place=’somewhere’ WHERE ID=4”_.

Our SQL statement would look like this:
```sql
SELECT name, place, phone FROM index WHERE ID=4; UPDATE name SET place='somewhere' WHERE ID=4;
```
The update command was inserted into the statement. An attacker simply used it to change a record from the database.

In this example, only an unimportant value is changed. However, such attacks can also change passwords and read confidential data from the database. Attackers do not do this manually, of course, but use tools for this purpose. You can also use them to see if your website is vulnerable.

To protect against this, it is essential that you mask all user input before it is executed in the database. How this works depends on the programming language.

- Here you can find a [PHP database class](https://webdeasy.de/en/php-database-class/) that is secured against SQL Injections and that you can use for your website for free.
- [Prevent SQL-Injection in Node.js](https://www.veracode.com/blog/secure-development/how-prevent-sql-injection-nodejs)
- [Prevent SQL-Injection in Python](https://realpython.com/prevent-python-sql-injection/)

##3. XSS (CORS) Issue <a name="xss"></a>
XSS stands for __Cross-Site Scripting__ and is an attack that executes malicious code in the visitor’s browser. How this happens is quite simple. Here’s an example: In a form on a website, you can write normal text. Let’s assume we have a guestbook where the text is simply displayed on the website. I.e. the user input is loaded 1: 1 into the website. However, if the attacker enters JavaScript tags (e.g. `<script>alert('HIHIHAHA H4CK3D! 😈');</script>`) with malicious code instead of a text and it is embedded in the website, it will be executed for all users in the browser.

CORS stands for __Cross-Origin Resource Sharing__ and can prevent such attacks. It prohibits (or allows) connections for certain scripts or URLs. Therefore, you should definitely check your CORS configuration on the server.

Since this malicious code enters the server via user input, it is beneficial to check every user input. You can use either a __blacklist__ or a __whitelist__ for this purpose. If you only want to allow a few inputs, you should use the whitelist and check whether the input is on the whitelist. If you have a lot of entries and want to reject only a few, you can write “Forbidden” on the blacklist and reject entries with contents of the blacklist.

This is how it might look in JavaScript for a blacklist:
```javascript
let userInput = '<script></script>';  // this variable comes from your html input
let blacklist = ['<script>', '<link>'];  // These are the FORBIDDEN words
blacklist.forEach(blacklistEntry => {
  if(userInput.includes(blacklistEntry)) {
    console.log('You used a forbidden word! Stop it!');
    return false;
  }
});
console.log('Everything is great! Go on!');
```
And for a whitelist like this:
```javascript
let userInput = 'edit';  // this variable comes from your html input
let whitelist = ['delete', 'add', 'edit'];  // only these words are ALLOWED
let isValid = false;
for(let i = 0; i < whitelist.length; i++) {
  if(userInput.includes(whitelist[i])) {
    isValid = true;
  }
}
if(isValid) {
  console.log('Everything is great! Go on!');
} else {
  console.log('You have not used the right word!');
}
```
You can find more information about CORS [here](https://www.securai.de/veroeffentlichungen/blog/was-ist-cors-und-welche-sicherheitsauswirkungen-hat-es-auf-web-applikationen/).

##4. Prevent DDOS Attacks <a name="ddos-protection"></a>
DDOS stands for Distributed Denial of Service and is an attack in which the server is brought to its knees by overload. This happens because a huge computer network (botnets) “spams” the server with connections.
![Visualized DDOS Attack, Source: https://de.wikipedia.org/wiki/Denial_of_Service#/media/File:Stachledraht_DDos_Attack.svg](https://webdeasy.de/wp-content/uploads/2019/05/800px-Stachledraht_DDos_Attack.svg_.png)
_Source: https://de.wikipedia.org/wiki/Denial_of_Service#/media/File:Stachledraht_DDos_Attack.svg_

Fortunately, there are services that cannot completely stop such attacks, but can at least dampen them to a certain point. One provider is [Cloudflare](https://www.cloudflare.com/ddos/), for example. As a rule, however, these services are subject to a fee. Therefore, you should carefully consider whether you need protection against DDOS attacks.

##5. Use strong passwords<a name="secure-passwords"></a>
This step is important for everyone. Not only administrators, but also private individuals should pay attention to secure passwords. This includes upper and lower case letters, numbers, digits and special characters. In my opinion, passwords should be at least 8 characters or even longer. Here you can [generate passwords easily and securely](https://www.lastpass.com/de/password-generator).

Since you then have a large number of passwords and they are hard to remember, you can make your life easier with a password manager like [KeePass](https://keepass.info/download.html).

##6. Session Management & Cookie Handling<a name="session-management"></a>
Logins require sessions to know which user is logged in and what actions they are allowed to perform. A unique session ID is stored to uniquely identify a user. In the past, these were often appended to the URL. For example, it looks like this: `example.com/dashboard?sid=89234nFJK98nkdf823njkFsdn387$`

However, if you send this link to show friends this page, they are logged in directly. The session ID was sent with the link and the server thinks that it is the same user. If you send such a link to a close friend it is often not tragic. But imagine you share this link in a social network… 💥

Therefore, many years ago, it was decided to find a better solution. That’s why links should look like this today: `https://example.com/dashboard`

Here the session ID is not included in the URL, but stored in a cookie that is only stored in the user’s temporary memory. Others who call the link have no possibility (this way) to take over his session.

Here you can take a look at how to implement a [secure login system with Node.js](https://webdeasy.de/en/complete-login-system-with-node-js-vue-js-restapi-jwt-part-1-2/).

##7. Hide public (sensitive) information<a name="public-informations"></a>
There is information that does not belong in the public domain. For websites, for example, this is the PHP version, the absolute file path of the website (e.g. /var/www/html/webroot/site1990/new/stage/) or the server operating system.

To illustrate this, I have a frightening example here. With Google I have the possibility to search not only for specific keywords, but also with parameters e.g. file extensions and citations. So with this search I can display pages that have a publicly accessible phpinfo file. In this file the complete PHP configuration of a server is disclosed and we get a lot of interesting information about the server.

I typed “ext:php intitle:phpinfo” into Google search and get a few results. One result gave me this page:
![Public phpinfo.php of a page
](https://webdeasy.de/wp-content/uploads/2019/05/php4.png)
Among them are hundreds of lines with all PHP settings. This is fatal, because this server is still running PHP version 4.4.2. Support and further development of this PHP version has already been discontinued since 2008 and contains serious security vulnerabilities.

Source: [https://de.wikipedia.org/wiki/PHP#PHP_4](https://de.wikipedia.org/wiki/PHP#PHP_4)

You should therefore delete these sensitive files after use or protect them with a password (e.g. via an [.htaccess file](https://www.lcn.com/support/articles/how-to-password-protect-a-folder-on-your-website-with-htaccess/)).

You should also make sure that the `display_errors` variable is set to `Off` on live systems. This is because attackers also receive information about the internal file system there. It is even worse with database errors. Here, in the worst case, even the access data is output. __Of course, this should be prevented at all costs!__ In your PHP settings you can instead specify that error messages should be written to a log file.

With an Apache web server you can change the line in your _php.ini_ to `Off`:
```
display_errors = Off
```
If you do not have access to this file, you can insert the following line at the beginning of the file in individual PHP scripts. It is important that this command is executed before the first output:
```javascript
ini_set('display_errors', 0);
```
This disables all error messages for the time being. From time to time, however, you need an output to debug a script. In this case it is a good idea to output the output only for your own IP. Under PHP it works like this:
```php
if($_SERVER["REMOTE_ADDR"] == "YOUR.IPV4.ADDRESS.HERE") {
  print_r("your debug output");
}
```

##8. Validate user input<a name="validate-user-data"></a>
The topic of validation is a large one and is interesting and even essential for developers. Validation is about checking and validating the data sent from the client to the server according to certain rules. Invalid input is rejected in the process, as it may also contain malicious code. This step is also important against [XSS attacks](#xss).

Especially when data is written to a database, validation is even more important. This way, even server commands can be executed. In the worst case, even data can be deleted or the server can be shut down. We have already covered this in [2. Avoid SQL Injection](#sql-injections).

To make it clear what I mean by validation, here is an example in PHP:
```php
<?php
$id = $_GET["id"];
$type = $_GET["type"];
// if id is not a number
if(!is_numeric($id)) {
    exit("id not valid");
}
// type must be one of the following strings
$types = array("slow", "slower", "normal", "fast", "faster");
if(!in_array($type, $types)) {
    exit("invalid type");
}
// Parameters successfully validated
// Code goes here
exit("success");
?>
```
Here the parameters `id` and `type` are passed as GET parameters. The script is aborted if `id` is not a number or `type` is not in the `$types` whitelist. The script is then terminated with `exit()`. If the conditions do not apply, the rest of the code can be executed.

##9. Install updates regularly<a name="updates"></a>
Many websites are based on a CMS (Content Management System), such as [WordPress](https://webdeasy.de/en/wordpress-code-snippets-en/), [Drupal](https://www.drupal.org/) or [Joomla](https://www.joomla.de/). To ensure security, there are regular updates. Again and again new security holes are found and closed by the developers as soon as possible. For this reason, your CMS installation should always be up to date. With most CMS you can set email notifications to be informed about new updates. You should take advantage of this and manually check your pages for updates at regular intervals.

>With the tool [WPHackedHelp](https://secure.wphackedhelp.com/) you can check your WordPress site for security vulnerabilities.

The same applies to the installed plugins. As soon as stable updates are available, you should install them.

Also, your host system (server system) should always be up to date. It is not a big deal if you still have Ubuntu 18.04 instead of the latest Ubuntu 20.04. The important thing is that you use a version that still gets active security updates. On the manufacturer’s pages you can usually find overviews, in which details of individual releases are listed. If you read the abbreviation __LTS__ (Long Term Support), everything is usually good. This means that your version is supported longer, i.e. it is provided with current updates longer than other versions.

> Before you update your website and plugins to the latest version, you should create a backup in case something goes wrong during the update and you need to restore the original version.

##10. Create Regular backups<a name="backups"></a>
Regular backups indirectly contribute to the security of your website. If you find out today that your website has been compromised, you can easily revert to an old state and close the security holes.

Many hosters offer regular snapshots for free or for an additional charge. If you manage your hosting through Plesk, you can use the backup manager or directly create a shell script that backs up directories like _/var/www/vhosts_ to an external backup storage. Your hoster will surely help you choose the right backup solution.

External backups are backups that are saved on a completely different system. In the best case, they are even in another data center. Because as we have seen in the past, even a data center is not safe from [external influences](https://constellix.com/news/massive-fire-destroyed-ovh-strasbourg-data-center).

##11. Prevent Spam in Contact Form<a name="spam-form"></a>
Many (well-known) websites have a big problem with bots that leave spam in all kinds of forms on the website. This can be very annoying.

To protect yourself against this, you can easily install the [Google reCAPTCHA](https://webdeasy.de/en/hide-google-recaptcha-badge/) or if you use WordPress, I can recommend the plugin [Antispam Bee](https://wordpress.org/plugins/antispam-bee/). Just install and set up, done.

#Conclusion<a name="conclusion"></a> 📝
Whew! That was quite a few steps to improve your website security. Which security aspects are implemented on your website and which ones are you catching up on? Or maybe you have some more steps to protect yourself from attacks?

>__Disclaimer__: All information is compiled to the best of our knowledge. These are tips, but cannot replace a complete safety check by an expert! <sub>(A similar post was published by me about 2 years ago, this is an update and improvement)</sub>

___

####_If you liked the article, I would be happy if you check out [my blog webdeasy.de](https://webdeasy.de/) and follow me on [Twitter](https://twitter.com/webdeasy)._ 😃