Zap的使用与漏洞修复

这周POC了几个渗透测试工具,分别是Burp Suite,OWASP Zap。

其中Burp的很多功能都是收费的,免费版基本只是用来做请求拦截的。

所以最后选择Zap对一个Express项目进行了扫描了漏洞修复,这里简单记录一下Zap的使用教程,以及Express的一些安全实践。

安装

Zap的安装十分简单,直接去官网https://www.zaproxy.org/下载然后一步步安装就好。

代理配置

Zap的原理其实就是起了一个代理,然后我们通过配置浏览器的代理策略将需要测试的请求导向代理,Zap会记录并分析这些请求,并尝试进行攻击。

所以第一步就是配置代理,这一步可以去看官网的文档:https://www.zaproxy.org/docs/desktop/start/proxies/

这里要注意一点,Zap2.9.0只支持chrome和firefox浏览器,而且对于chrome的支持应该只到79版本,笔者的86版本chrome一启动就会crash。

关于firefox的代理配置,大家直接去看官网就行了,简直就是保姆级别的教程。

笔者这里需要提醒的一点是,文档中的一个提示,这个提示是关于localhost的配置,由于这个提示没有用特殊的格式,所以容易被忽略:

Note: To proxy localhost (and related addresses) with newer Firefox versions (>= 67) the preference network.proxy.allow_hijacking_localhost (accessible through the about:config page) must be set to true.

使用

Zap Hub

Zap Hub是zap提供的一个非常使用的工具集,它其实就是把Zap的客户端的功能都加了个入口添加在浏览器的两侧,可以让我们在测试过程中不需要来回切换浏览器和Zap。

当然我们不用Zap Hub也是可以的,但如果你想用却发现Zap Hub没有加载:

  • 检查下是不是Zap没有开Hub。
  • 如果开了,看看Hub是不是被项目本身的一些安全策略给拦截了,比如CSP

如果第一次加载Zap Hub,它还会提示你是否进入新手教程,这个教程做的非常详细,会指导你一步步操作,也比较啰嗦,如果急于使用,可以先看看我下面的截图说明:

客户端

Zap客户端得功能和Hub没什么出入,知道了怎么用Hub,自然就会用客户端

但这里要提醒大家一点:一开始最好使用被动扫描的形式去扫面一个网站,只有你确认你可以对一个网站进行出动扫描,再去进行主动扫描,因为主动扫描会尝试各种方案去对目标网站进行攻击。

Express安全实践

当我们完成对一个网站的扫描之后,就可以导出扫描报告,可以有很多种格式选择。

笔者导出报告之后,虽然没有几个漏洞,但是还是那些老生常谈的问题,XSS,SqlInjection,MIME嗅探等。

不过这也说明了这些问题的普遍性,甚至是防不胜防。

这里总结整理几点Express的安全实践:

请勿使用不推荐或者存在漏洞的 Express 版本

Express 2.x 和 3.x 不再得到维护。不会纠正这些版本中的安全问题和性能问题。请勿使用这些版本!如果您尚未迁移到 V4,请按照迁移指南进行迁移。

还请确保您未使用安全性更新页面中列出的任何存在漏洞的 Express 版本。如果在使用,请更新到某个稳定发行版,首选为最新版本。

使用 TLS

如果应用程序处理或传输敏感数据,请使用传输层安全性 (TLS) 来保护连接和数据。这种技术用于加密数据,然后将其从客户机发送到服务器,以防止某些常见的(而且容易的)黑客攻击。虽然 Ajax 和 POST 请求可能不是很明显,似乎“隐藏”在浏览器中,但是其网络流量很容易受到包嗅探攻击和中间人攻击

您可能很熟悉安全套接字层 (SSL) 加密。[TLS 就是下一代的 SSL](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380515(v=vs.85)。换言之,如果您以前使用 SSL,请考虑升级到 TLS。一般而言,我们建议使用 Nginx 来处理 TLS。要获取在 Nginx(和其他服务器)上配置 TLS 的优秀参考信息,请参阅 Recommended Server Configurations (Mozilla Wiki)。

此外,可以使用一种方便的 Let’s Encrypt 工具来获取免费的 TLS 证书,这是由因特网安全研究组 (ISRG) 提供的免费、自动化的开放式认证中心 (CA)。

使用 Helmet

Helmet 通过适当地设置 HTTP 头,帮助您保护应用程序避免一些众所周知的 Web 漏洞。

Helmet 实际上只使用以下九个较小中间件函数的集合,这些功能用于设置与安全相关的 HTTP 头:

  • csp 用于设置 Content-Security-Policy 头,帮助抵御跨站点脚本编制攻击和其他跨站点注入攻击。
  • hidePoweredBy 用于移除 X-Powered-By 头。
  • hsts 用于设置 Strict-Transport-Security 头,实施安全的服务器连接 (HTTP over SSL/TLS)。
  • ieNoOpen 用于为 IE8+ 设置 X-Download-Options
  • noCache 用于设置 Cache-Control 和 Pragma 头,以禁用客户端高速缓存。
  • noSniff 用于设置 X-Content-Type-Options,以防止攻击者以 MIME 方式嗅探浏览器发出的响应中声明的 content-type。
  • frameguard 用于设置 X-Frame-Options 头,提供 clickjacking 保护。
  • xssFilter 用于设置 X-XSS-Protection,在最新的 Web 浏览器中启用跨站点脚本编制 (XSS) 过滤器。

像安装其他模块一样安装 Helmet:

1
$ npm install --save helmet

然后将其用于您的代码:

1
2
3
4
...
var helmet = require('helmet');
app.use(helmet());
...

至少禁用 X-Powered-By 头

如果不希望使用 Helmet,那么至少应禁用 X-Powered-By 头。攻击者可能会使用该头(缺省情况下已启用)来检测运行 Express 的应用程序,然后发动针对特定目标的攻击。

所以,最佳实践是使用 app.disable() 方法禁用此头:

1
app.disable('x-powered-by');

如果使用 helmet.js,它会为您执行此功能。

要确保 cookie 不会打开应用程序使其暴露在风险之中,请勿使用缺省会话 cookie 名称并相应地设置 cookie 安全选项。

有两个主要的中间件 cookie 会话模块:

  • express-session,用于替换 Express 3.x 内置的 express.session 中间件。
  • cookie-session,用于替换 Express 3.x 内置的 express.cookieSession 中间件。

这两个模块之间的主要差异是它们保存 cookie 会话数据的方式。express-session 中间件将会话数据存储在服务器上;它仅将会话标识(而非会话数据)保存在 cookie 中。缺省情况下,它使用内存中存储,并不旨在用于生产环境。在生产环境中,需要设置可扩展的会话存储;请参阅兼容的会话存储列表。

相反,cookie-session 中间件实现 cookie 支持的存储:它将整个会话序列化到 cookie 中,而不只是会话键。仅当会话数据相对较小,且易于编码为原语值(而不是对象)时,才使用此中间件。尽管假设浏览器支持每个 cookie 至少 4096 字节以确保不会超过限制,但是每个域的大小不会超过 4093 字节。另外请注意,客户机可以访问 cookie 数据,所以,如果有任何理由将其保持安全或隐藏状态,那么 express-session 可能是更好的选择。

使用缺省会话 cookie 名称会使应用程序对攻击敞开大门。X-Powered-By 之类的值会造成问题:潜在攻击者可以利用这样的值对服务器采集“指纹”,并相应地确定攻击目标。

为避免此问题,请使用通用 cookie 名称;例如,使用 express-session 中间件:

1
2
3
4
5
6
7
var session = require('express-session');
app.set('trust proxy', 1) // trust first proxy
app.use( session({
secret : 's3Cur3',
name : 'sessionId',
})
);

设置以下 cookie 选项来增强安全性:

  • secure - 确保浏览器只通过 HTTPS 发送 cookie。
  • httpOnly - 确保 cookie 只通过 HTTP(S)(而不是客户机 JavaScript)发送,这有助于防御跨站点脚本编制攻击。
  • domain - 表示 cookie 的域;用于和请求 URL 的服务器的域进行比较。如果匹配,那么接下来检查路径属性。
  • path - 表示 cookie 的路径;用于和请求路径进行比较。如果路径和域都匹配,那么在请求中发送 cookie。
  • expires - 用于为持久性 cookie 设置到期日期。

以下是使用 cookie-session 中间件的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var session = require('cookie-session');
var express = require('express');
var app = express();

var expiryDate = new Date( Date.now() + 60 * 60 * 1000 ); // 1 hour
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: { secure: true,
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}
})
);

确保依赖项的安全

npm本身带有依赖检查工具,npm audit,非常好用,这是文档,文档很短,使用起来也很简单:https://docs.npmjs.com/cli/v6/commands/npm-audit/