# Essential HTTP security headers

I received a security audit report from a client a few weeks ago, they were very worried as according to the report their website had plenty of high & medium severity vulnerabilities. 

I quickly realized that most of the reported issues are due to missing or miss configured  HTTP headers. It was a good opportunity to review and summarize the security headers any website or web app should use.

The HTTP headers can be configured on the server to enhance the overall security of the website or web application, adding them won't literally make the site or app more secure, but will prevent the exploitation of potential vulnerabilities.

There are 2 types of HTTP headers we have to pay attention to:

#### 1) The headers that protect against attacks

- X-Frame-Options
- X-Content-Type-Options
- X-XSS-Protection
- Content-Security-Policy
- Strict-Transport-Security
- Access-Control-Allow-Origin

#### 2) The headers that leak information

- Server
- X-Powered-By

## 1) The headers that protect against attacks

These headers can be quite easily set using .htaccess, just make sure you have Apache's mod_headers enabled.

### X-Frame-Options

Protects against [clickjacking](https://en.wikipedia.org/wiki/Clickjacking).

If a malicious website can embed your site as an iframe it may allow attackers to invoke unintended actions by the user with clickjacking.

To prevent your website from being embedded in an iframe set the X-Frame-Options to DENY.

```shell
Header always append X-Frame-Options DENY
```

### X-Content-Type-Options

Protects against [MIME sniffing](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing).

When a malicious HTML document is served from your domain (for example, if an image uploaded to a photo service contains valid HTML markup), some browsers will treat it as an active document and allow it to execute scripts in the context of the application. 

This is known as content sniffing, the automatic detection of the content type, we need to tell browsers to not sniff content.

```shell
Header set X-Content-Type-Options nosniff
```

### X-XSS-Protection (deprecated)

Protects against [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting).

The X-XSS-Protection header has been [deprecated](https://owasp.org/www-project-secure-headers/#x-xss-protection) by modern browsers and its use can introduce additional security issues on the client-side. (Better use Content-Security-Policy instead).

It is recommended to set the header as X-XSS-Protection: 0 in order to disable the XSS Auditor, and not allow it to take the default behavior of the browser handling the response.

```shell
Header set X-XSS-Protection 0
```

### Content-Security-Policy (CSP)

Protects against [cross-site scripting (XSS)](https://en.wikipedia.org/wiki/Cross-site_scripting), [clickjacking](https://en.wikipedia.org/wiki/Clickjacking) and HTML injection attacks.

The Content-Security-Policy provides an added layer to mitigate XSS attacks by restricting which scripts can be executed by the page. It's probably the most important header, but also the most tedious to configure.

Please note there's no one-size-fits-all CSP, you have to [generate CSP policy](https://report-uri.com/home/generate) specific to the resources loaded by your website.

```shell
Header set Content-Security-Policy "default-src * data: 'unsafe-inline' 'unsafe-eval'"
```

### Strict-Transport-Security (HSTS)

Protects against [man-in-the-middle](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) attacks.

HTTP Strict Transport Security instructs the browser to access the webserver over HTTPS only.

```shell
Header set Strict-Transport-Security "max-age=10886400; includeSubDomains; preload"
```

Learn more about HSTS [here](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security).

### Access-Control-Allow-Origin

Protects against [cross-site request forgery (CSRF)](https://en.wikipedia.org/wiki/Cross-site_request_forgery) attacks. 

This is a CORS (Cross-Origin Resource Sharing) header. By default, modern browsers enforce the [same-origin policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy) to prevent a web page from accessing cross-origin resources.

Many developers use a wildcard Access-Control-Allow-Origin header which explicitly opens up cross-origin requests from the attacker’s origin.

Don't set this header unless you need to allow AJAX requests from external origins, if so, be specific.

```shell
 Header set Access-Control-Allow-Origin "https://mysite.com"
```

### .htaccess

Enable the headers that protect against attacks using these directives:

```shell
<IfModule mod_headers.c>
    # Security Headers
    Header set X-XSS-Protection 0
    Header always append X-Frame-Options DENY
    Header set X-Content-Type-Options nosniff
    Header set Strict-Transport-Security "max-age=10886400; includeSubDomains; preload"
    #Header set Content-Security-Policy "default-src * data: 'unsafe-inline' 'unsafe-eval'"
</IfModule>
```

## 2) The headers that leak information

To update these headers you'll likely need to get your hands dirty with server configuration files.

### Server

This header contains information about the software used by the backend server that handles the request.

![Screenshot 2021-08-29 at 13.10.21.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630231845434/rP552xNB4.png)

An overly-detailed **Server** value might make it easier for attackers to exploit known security holes.

Update the server settings to show the least info possible.

In httpd.conf update ServerTokens to "Prod"

> ServerTokens Prod

Or, if you have WHM access, go to Service Configuration > Apache Configuration > Global Configuration and set Server Tokens to "Product Only".

### X-Powered-By

This header reveals information about the technology used in an application and can be a valuable hint for hackers who can exploit the security weaknesses of the technology, especially when using outdated software.

![Screenshot 2021-08-29 at 13.06.29.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1630231612289/wzg5fT9a2.png)

It's highly recommended to remove this header.

In php.ini set:

> expose_php = Off

Or, if you have WHM access, go to Software > MultiPHP INI Editor > Editor Mode tab and look for the expose_php directive and set it to "Off".
