安全加固

HTTP Headers

const express = require("express");
const PORT = process.env.PORT || 3000;
const app = express();

app.get("/", (req, res) => {
  res.send(`<h1>Hello World</h1>`);
});

app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}`);
});
...
const helmet = require('helmet');
...

app.use(helmet());

...
const express = require("express");
const PORT = process.env.PORT || 3000;
const app = express();

app.get("/", (req, res) => {
  res.send(`<h1>Hello World</h1>`);
});

app.listen(PORT, () => {
  console.log(`Listening on http://localhost:${PORT}`);
});

We’ll start by adding and removing a few HTTP headers that will help improve our security. To inspect these headers you can use a tool like curl by running:

curl http://localhost:3000 --include

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: text/html; charset=utf-8
Content-Length: 20
ETag: W/"14-SsoazAISF4H46953FT6rSL7/tvU"
Date: Wed, 01 Nov 2017 13:36:10 GMT
Connection: keep-alive

One header that you should keep an eye on is X-Powered-By. Generally speaking headers that start with X- are non-standard headers. This one gives away which framework you are using. For an attacker, this cuts the attack space down for them as they can concentrate on the known vulnerabilities in that framework.

...
const helmet = require('helmet');
...

app.use(helmet());

...

Now add the helmet middleware to your application. Modify the index.js accordingly:

curl http://localhost:3000 --inspect

HTTP/1.1 200 OK
X-DNS-Prefetch-Control: off
X-Frame-Options: SAMEORIGIN
Strict-Transport-Security: max-age=15552000; includeSubDomains
X-Download-Options: noopen
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Content-Type: text/html; charset=utf-8
Content-Length: 20
ETag: W/"14-SsoazAISF4H46953FT6rSL7/tvU"
Date: Wed, 01 Nov 2017 13:50:42 GMT
Connection: keep-alive

The X-Powered-By header is gone, which is a good start, but now we have a bunch of new headers.

X-DNS-Prefetch-Control

This header isn’t much of an added security benefit as much as an added privacy benefit. By setting the value to off it turns off the DNS lookups that the browser does for URLs in the page. The DNS lookups are done for performance improvements and according to MDN they can improve the performance of loading images by 5% or more. However this look up can make it appear like the user visited things they never visited.

The default for this is off but if you care about the added performance benefit you can enable it by passing { dnsPrefetchControl: { allow: true }} to the helmet() call.

X-Frame-Options

X-Frame-Options allows you to control whether the page can be loaded in a frame like <frame/> <iframe/> or <object/>. Unless you really need to frame your page you should just disable it entirely by passing the option to the helmet()call:

app.use(
  helmet({
    frameguard: {
      action: "deny"
    }
  })
);

X-Frame-Options is supported by all modern browsers. It can however also be controlled via a Content Security Policy as we’ll see later.

Strict-Transport-Security

This is also known as HSTS (HTTP Strict Transport Security) and is used to ensure that there is no protocol downgrade when you are using HTTPS. If a user visited the website once on HTTPS it makes sure that the browser will not allow any future communication via HTTP. This feature is helpful to avoid Man-In-The-Middle attacks.

You might have seen this feature in action if you tried to access a page like https://google.com while being on a public WiFi with a captive portal. The WiFi is trying to redirect you to their captive portal but since you visited google.combefore via HTTPS and it set the Strict-Transport-Security header, the browser will block this redirect.

You can read more about it on the MDN page or the OWASP wiki page.

X-Download-Options

This header is only protecting you from an old IE security vulnerability. Basically if you host untrusted HTML files for download, users were able open these directly (rather than saving them to disk first) and they would execute in the context of your app. This header ensures that users download files before they open them so that they can’t execute in your app’s security context.

You can find more information about this on the helmet page and this MSDN blog post.

X-Content-Type-Options

Some browsers perform “MIME sniffing” meaning that rather than loading things based on the Content-Type that the server will send, the browser will try to determine the content type based on the file content and execute it based on that.

Say your page offers a way to upload pictures and an attacker uploads some HTML instead, if the browser performs MIME sniffing, it could execute the code as HTML and the attacker would have performed a successful XSS attack.

By setting this header to nosniff we are disabling this MIME sniffing.

X-XSS-Protection

This header is used to turn on basic XSS protections in the user’s browser. It can’t avoid every XSS opportunity but it can determine basic ones. For example, if it detects that the query string contains something like a script tag, the browser could block the execution of the same code in the page knowing that it’s likely an XSS attack. This header can have three different values. 0, 1 and 1; mode=block. If you want to learn more about which mode you should choose, make sure to check out this blog post about X-XSS-Protection and it’s potential dangers.

下一页