使用 HTTPS 和 HTTP 严格传输安全协议迷惑恶意中间人

Mike West

鉴于大量个人数据通过互联网这一巨大的管道流动,我们不能或不应轻易忽视加密。现代浏览器提供了多种机制,可用于确保用户数据在传输过程中的安全性:安全的 Cookie严格传输安全是其中最重要的两种机制。借助这些功能,您可以无缝保护用户,将其连接升级为 HTTPS,并保证用户数据绝不会以明文形式发送。

为何值得关注?请考虑以下情况:

通过未加密的 HTTP 连接传送网页,与将未密封的信封交给您在街上看到的第一个看起来像是在朝邮局方向走的人大同小异。如果您很幸运,她可能会自己将包裹送到目的地,或者将包裹交给下一个朝着正确方向行驶的路人。对方可能会照样做,以此类推。

这个临时信箱链中的大多数陌生人都是值得信赖的,他们绝不会偷看你的公开信件或对其进行篡改。不过,信件转手的次数越多,拥有您所发信件完整访问权限的人员就越多。最终,您信件的收件人很可能会在邮件中收到某样东西,但这件东西是否与您最初交付的一样,是一个悬而未决的问题。也许您应该密封该信封…

中间商

无论好坏,互联网的大量内容都依赖于陌生人的可信度。服务器之间并非直接连接,而是像玩电话游戏一样,将请求和响应从路由器传递到路由器。

您可以使用 traceroute 查看这些跃点的实际运行情况。从我的计算机到 HTML5Rocks 的路线如下所示:

$ traceroute html5rocks.com
traceroute to html5rocks.com (173.194.71.102), 30 hops max, 60 byte packets
 1  router1-lon.linode.com (212.111.33.229)  0.453 ms
 2  212.111.33.233 (212.111.33.233)  1.067 ms
 3  217.20.44.194 (217.20.44.194)  0.704 ms
 4  google1.lonap.net (193.203.5.136)  0.804 ms
 5  209.85.255.76 (209.85.255.76)  0.925 ms
 6  209.85.253.94 (209.85.253.94)  1.226 ms
 7  209.85.240.28 (209.85.240.28)  48.714 ms
 8  216.239.47.12 (216.239.47.12)  22.575 ms
 9  209.85.241.193 (209.85.241.193)  36.033 ms
10  72.14.233.180 (72.14.233.180)  43.222 ms
11  72.14.233.170 (72.14.233.170)  43.242 ms
12  *
13  lb-in-f102.1e100.net (173.194.71.102)  44.523 ms

13 个跳跃其实还不错。但是,如果我通过 HTTP 发送请求,则这些中间路由器中的每一个都拥有对我请求和服务器响应的完整访问权限。所有数据均以未加密的明文形式传输,并且这些中介中的任何一个都可能充当中间人,读取我的数据,甚至在传输过程中对其进行操纵。

更糟糕的是,这种拦截几乎无法检测到。恶意修改的 HTTP 响应看起来与有效响应完全一样,因为没有任何机制可让您确保收到的数据 _完全_ 是发送的数据。如果有人决定为了娱乐而破坏我的互联网,那我基本上就只能认命了。

这是安全的通话线路吗?

从明文 HTTP 切换到安全的 HTTPS 连接是防范中间人攻击的最佳方式。HTTPS 连接会在发送任何数据之前对整个通道进行端到端加密,这样一来,您与目的地之间机器就无法读取或修改传输中的数据。

Chrome 的 Omnibox 会详细显示连接状态。
Chrome 的多功能框会提供有关连接状态的大量详细信息。

HTTPS 提供的安全性源于公钥和私钥的概念。幸运的是,本文无法深入讨论相关细节,但核心前提非常简单:使用给定公钥加密的数据只能使用相应的私钥解密。当浏览器发起 HTTPS 握手以创建安全信道时,服务器会提供一个证书,该证书会向浏览器提供验证其身份所需的所有信息,方法是检查服务器是否拥有正确的私钥。从该点开始,所有通信都会以一种方式加密,以证明请求已传送到经过身份验证的服务器,并且已从该服务器收到响应。

因此,HTTPS 可让您确信自己在与您认为在与之通信的服务器通信,并且没有其他人正在窃听或篡改网络上的位。这种加密是确保网络安全的绝对前提;如果您的应用目前未通过 HTTPS 传送,则容易受到攻击。解决该问题。Ars Technica 提供了一份出色的关于获取和安装证书(免费)的指南,建议您查看该指南,了解相关技术细节。配置因提供商和服务器而异,但证书请求流程在所有位置都是相同的。

默认安全

请求并安装证书后,请确保您的用户能从您的辛勤工作中受益:通过 HTTP 重定向的魔力,透明地将现有用户迁移到 HTTPS 连接,并确保通过安全连接传送 Cookie。

请这边走

当用户访问 http://example.com/ 时,通过发送包含适当 Location 标头的 301 Moved Permanently 响应将其重定向到 https://example.com/

$ curl -I http://mkw.st/
HTTP/1.1 301 Moved Permanently
Server: nginx/1.3.7
...
Keep-Alive: timeout=20
Location: https://mkw.st/

您可以在 Apache 或 Nginx 等服务器中轻松设置此类重定向。例如,从 http://example.com/ 重定向到 https://example.com/ 的 Nginx 配置如下所示:

server {
    listen [YOUR IP ADDRESS HERE]:80;
    server_name example.com www.example.com;
    location "/" {
        rewrite ^(.*) https://www.example.com$1 permanent;
    }
}

借助 Cookie,我们能够通过无状态 HTTP 协议为用户提供流畅的已登录体验。Cookie 中存储的数据(包括会话 ID 等敏感信息)会随每个请求一起发送,以便服务器了解自己目前正在响应哪位用户。确保用户通过 HTTPS 访问我们的网站后,我们还应确保存储在 Cookie 中的敏感数据只能通过安全连接传输,绝不能明文发送。

设置 Cookie 通常涉及一个 HTTP 标头,如下所示:

set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT

您可以通过附加一个关键字来指示浏览器限制 Cookie 的使用,以确保会话安全:

Set-Cookie: KEY=VALUE; path=/; expires=Sat, 01-Jan-2022 00:00:00 GMT; secure

使用 secure 关键字设置的 Cookie 绝不会通过 HTTP 发送。

关闭打开的窗口

透明重定向到 HTTPS 意味着,用户在您网站上的绝大多数时间都会使用安全连接。不过,这会留下一个小小的攻击机会:初始 HTTP 连接处于完全打开状态,容易受到 SSL 剥离和相关攻击。由于中间人拥有对初始 HTTP 请求的完整访问权限,因此它可以充当您和服务器之间的代理,无论服务器的意图如何,都会使您保持不安全的 HTTP 连接。

您可以要求浏览器强制执行 HTTP 严格传输安全协议 (HSTS),以降低此类攻击的风险。发送 Strict-Transport-Security HTTP 标头会指示浏览器在客户端执行 HTTP 到 HTTPS 重定向,而无需接触网络(这对性能也有很大帮助;最好的请求是您无需发出的请求):

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

支持此标头的浏览器(目前包括 Firefox、Chrome 和 Opera:caniuse 中提供了详细信息)会注明此特定网站已请求仅限 HTTPS 访问权限,这意味着无论用户以何种方式访问该网站,都将通过 HTTPS 访问。即使她在浏览器中输入 http://example.com/,最终也会通过 HTTPS 连接,而不会建立 HTTP 连接。更好的是,如果浏览器检测到无效证书(可能尝试伪造服务器的身份),则不允许用户通过 HTTP 继续操作;这是一个非此即彼的选择,非常棒。

浏览器会在 max-age 秒(在此示例中约为 1 个月)后使服务器的 HSTS 状态过期;请将此值设置为一个合理的高值。

您还可以通过向标头添加 includeSubDomains 指令来确保保护来源的所有子网域:

$ curl -I https://mkw.st/
HTTP/1.1 200 OK
Server: nginx/1.3.7
...
Strict-Transport-Security: max-age=2592000

安全前行

只有使用 HTTPS,您才能稍微放心地确信您发送的数据会完好无损地到达预期收件人。您应立即为自己的网站和应用设置安全连接。该流程非常简单,有助于保障客户数据的安全。建立加密信道后,您应发送 301 HTTP 响应,无论用户通过何种方式访问您的网站,都将其透明地重定向到此安全连接。然后,在设置 Cookie 时添加 secure 关键字,确保所有用户的敏感会话信息使用该安全连接。完成所有这些操作后,请确保用户不会意外掉队:通过确保其浏览器发送 Strict-Transport-Security 标头来正确处理,从而保护用户。

设置 HTTPS 不需要太多工作,并且对您的网站及其用户有很大的好处。这非常值得。

资源

  • StartSSL 提供免费的经过网域验证的证书。免费的价格谁也比不了。当然,您也可以升级到更高级别的验证,价格合理。
  • SSL 服务器测试:为服务器设置 HTTPS 后,请通过 SSL Labs 的服务器测试来验证设置是否正确。您会收到详细的报告,其中会显示您的网站是否已正常运行。
  • 不妨阅读 Ars Technica 最近发表的文章“使用 SSL/TLS 保护 Web 服务器”,详细了解设置服务器的方方面面。
  • 不妨浏览 HTTP 严格传输安全规范 (RFC6797),了解您可能需要的有关 Strict-Transport-Security 标头的所有技术信息。
  • 真正了解自己在做什么后,下一步可以考虑告知用户,您的网站只能通过一组特定的证书访问。IETF 正在开展一些工作,可让您通过 Public-Key-Pins 标头执行此操作;虽然目前还处于起步阶段,但很有趣,值得关注。