express安全处理之helmet中间件

使用nodejs express框架搭建网站应用,在处理安全问题的时候就离不开helmet中间件了,为什么这么讲呢?

主要是因为helmet集成了各种HTTP头信息来帮助保护Express应用程序, 如:XSS攻击、CSP内容安全策略、dns保护、iframe同源限制等,省得开发一个个处理了。

一、安装使用

> npm install helmet --save

在app.js引入使用,如果不想特殊设置就使用默认即可

const express = require("express");
const helmet = require("helmet");

const app = express();

app.use(helmet());

如果使用的是Koa框架,安装koa-helmet即可

二、方法介绍

helmet总共结合了11个小中间件

app.use(helmet());

等同于

app.use(helmet.contentSecurityPolicy());
app.use(helmet.dnsPrefetchControl());
app.use(helmet.expectCt());
app.use(helmet.frameguard());
app.use(helmet.hidePoweredBy());
app.use(helmet.hsts());
app.use(helmet.ieNoOpen());
app.use(helmet.noSniff());
app.use(helmet.permittedCrossDomainPolicies());
app.use(helmet.referrerPolicy());
app.use(helmet.xssFilter());

1、helmet(option)

option键为包含方法的方法名,值为该方法的选项值,不过里加了一个true/false用来启用/禁用该功能

app.use(
  helmet({
    frameguard: {
      action: 'sameorigin' // iframe设置同源
    },
    contentSecurityPolicy: false, // 关闭内容安全策略
    expectCt: { 
      maxAge: 86400 // 证书透明化最大时间为1天,单位秒
    }
  })
);

2、helmet.contentSecurityPolicy(options)

CSP(Content Security Policy)内容安全策略

主要用来预防跨站脚本攻击,不过这个中间件很少执行验证,完全依赖CSP设置

  • options.directives是一个对象,键为规则为defaultSrcdefault-src
  • options.reportOnly只读,是一个boolean值,默认为false

如果没有提供指令,则设置以下策略:

default-src 'self';
base-uri 'self';
block-all-mixed-content;
font-src 'self' https: data:;
frame-ancestors 'self';
img-src 'self' data:;
object-src 'none';
script-src 'self';
script-src-attr 'none';
style-src 'self' https: 'unsafe-inline';
upgrade-insecure-requests

示例:

// Sets "Content-Security-Policy: default-src 'self';script-src 'self' example.com;object-src 'none';upgrade-insecure-requests"
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", "example.com"],
      objectSrc: ["'none'"],
      upgradeInsecureRequests: [],
    },
  })
);

// Sets "Content-Security-Policy: default-src 'self';script-src 'self' example.com;object-src 'none'"
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      "default-src": ["'self'"],
      "script-src": ["'self'", "example.com"],
      "object-src": ["'none'"],
    },
  })
);

// Sets the "Content-Security-Policy-Report-Only" header instead
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      /* ... */
    },
    reportOnly: true,
  })
);

// Sets "Content-Security-Policy: default-src 'self';script-src 'self' 'nonce-e33ccde670f149c1789b1e1e113b0916'"
app.use((req, res, next) => {
  res.locals.cspNonce = crypto.randomBytes(16).toString("hex");
  next();
});
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: ["'self'", (req, res) => `'nonce-${res.locals.cspNonce}'`],
    },
  })
);

可以单独安装helmet-csp

3、helmet.expectCt(options)

helmet.expectCt设置了Expect-CT头,有助于减轻错误颁发的SSL证书,更多信息请参考MDN上的Expect-CT介绍

  • options.maxAge期望证书透明化的秒数,默认为0
  • options.enforce是一个布尔值。如果为true,用户代理(通常是浏览器)应该拒绝违反其证书透明策略的连接。默认值为false
  • options.reportUri是一个字符串,如果失败则向该URI报告

示例:

// Sets "Expect-CT: max-age=86400"
app.use(
  helmet.expectCt({
    maxAge: 86400,
  })
);

// Sets "Expect-CT: max-age=86400, enforce, report-uri="https://example.com/report"
app.use(
  helmet.expectCt({
    maxAge: 86400,
    enforce: true,
    reportUri: "https://example.com/report",
  })
);

可以单独安装expect-ct

4、helmet.referrerPolicy(options)

helmet.referrerPolicy设置Referrer-Policy头,更多信息请参考:Referer

  • options.policy字符串/数组,默认为no-referrer

示例:

// Sets "Referrer-Policy: no-referrer"
app.use(
  helmet.referrerPolicy({
    policy: "no-referrer",
  })
);

// Sets "Referrer-Policy: origin,unsafe-url"
app.use(
  helmet.referrerPolicy({
    policy: ["origin", "unsafe-url"],
  })
);

可以单独安装referrer-policy

5、helmet.hsts(options)

helmet.hsts设置Strict-Transport-Security头,告诉浏览器使用安全的https协议而不是http

  • options.maxAge浏览器应该记住使用HTTPS的秒数。如果传递的是非整数,则该值四舍五入。它的默认值是15552000,也就是180天。
  • options.includeSubDomains是一个布尔值,指定是否包含includeSubDomains指令,该指令使此策略扩展到子域。它默认为true。
  • options.preload是一个布尔值。如果为真,它会添加preload指令,表示将HSTS策略添加到浏览器。更多信息请参考Preloading Strict Transport Security。默认为false。

示例:

// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains"
app.use(
  helmet.strictTransportSecurity({
    maxAge: 123456,
  })
);

// Sets "Strict-Transport-Security: max-age=123456"
app.use(
  helmet.strictTransportSecurity({
    maxAge: 123456,
    includeSubDomains: false,
  })
);

// Sets "Strict-Transport-Security: max-age=123456; includeSubDomains; preload"
app.use(
  helmet.strictTransportSecurity({
    maxAge: 63072000,
    preload: true,
  })
);

可以单独安装hsts

6、helmet.noSniff()

helmet.noSniff设置X-Content-Type-Options头为nosniff,这减轻了MIME type sniffing可能导致安全漏洞的影响。

示例:

// Sets "X-Content-Type-Options: nosniff"
app.use(helmet.noSniff());

可以单独安装dont-sniff-mimetype

7、helmet.dnsPrefetchControl(options)

helmet.dnsPrefetchControl设置X-DNS-Prefetch-Control头帮助控制DNS预取,这会以牺牲性能为代价提高用户隐私。
更多信息请参考:X-DNS-Prefetch-Control

  • options.allow是一个布尔值,指定是否启用DNS预取。默认为false。

示例:

// Sets "X-DNS-Prefetch-Control: off"
app.use(
  helmet.dnsPrefetchControl({
    allow: false,
  })
);

// Sets "X-DNS-Prefetch-Control: on"
app.use(
  helmet.dnsPrefetchControl({
    allow: true,
  })
);

可以单独安装dns-prefetch-control

8、helmet.ieNoOpen()

helmet.ieNoOpen设置X-Download-Options头,这是Internet Explorer 8特有的。强制保存潜在不安全的下载,减少了HTML在站点上下文中的执行。更多信息请参考:IE8 Security

示例:

// Sets "X-Download-Options: noopen"
app.use(helmet.ieNoOpen());

可以单独安装ienoopen

9、helmet.frameguard(options)

helmet.frameguard设置X-Frame-Options头来预防点击劫持,这个功能被CSP的frame-ancestors替代了,不过对旧的浏览器仍然有用。更多信息请参考:X-Frame-Options

  • options.action是一个字符串,指定使用哪个安全策略(DENYSAMEORIGIN)不支持ALLOW-FROM,默认是SAMEORIGIN

示例:

// Sets "X-Frame-Options: DENY"
app.use(
  helmet.frameguard({
    action: "deny",
  })
);

// Sets "X-Frame-Options: SAMEORIGIN"
app.use(
  helmet.frameguard({
    action: "sameorigin",
  })
);

可以单独安装frameguard

10、helmet.permittedCrossDomainPolicies(options)

helmet.permittedCrossDomainPolicies设置X-Permitted-Cross-Domain-Policies头,告诉一些客户端(主要是Adobe产品)加载跨域内容策略。

  • options.permittedPolicies是一个字符串,值有:nonemaster-onlyby-content-typeall,默认为none

示例:

// Sets "X-Permitted-Cross-Domain-Policies: none"
app.use(
  helmet.permittedCrossDomainPolicies({
    permittedPolicies: "none",
  })
);

// Sets "X-Permitted-Cross-Domain-Policies: by-content-type"
app.use(
  helmet.permittedCrossDomainPolicies({
    permittedPolicies: "by-content-type",
  })
);

可以单独安装helmet-crossdomain

11、helmet.hidePoweredBy(options)

helmet.hidePoweredBy删除X-Powered-By头,这在Express框架是默认设置的,安全作用有限,主要是为了节省带宽。

示例:

// Removes the X-Powered-By header if it was set.
app.use(helmet.hidePoweredBy());

Express框架内置使用

app.disable("x-powered-by");

可以单独安装hide-powered-by

12、helmet.xssFilter(options)

helmet.xssFilter设置X-XSS-Protection头为0来禁用浏览器的错误XSS过滤,更多信息请参考:X-XSS-Protection

示例:

// Sets "X-XSS-Protection: 0"
app.use(helmet.xssFilter());

可以单独安装x-xss-protection

以上是关于helmet的总体介绍,在处理常规安全上基本都覆盖了,帮助开发者省了不少工作量。

参考链接:

PS:写作不易,如要转裁,请标明转载出处。
%{ comment.page.total }条评论

猜你想看

微信小程序:前端开发宝典

最近文章
工具操作
  • 内容截图
  • 全屏
登录
注册
回顶部