总有办法破解您的 javascript 代码,并了解您的服务和 API 的后门。
JavaScript 为已经暴露在网络上的服务和 API 带来了一些新问题。您的服务器/服务不应该盲目地信任来自网络的请求,因此使用 javascript 不会改变您的安全状态,但它会使人们误以为他们控制了用户代理,从而使他们产生虚假的安全感。
客户端/服务器安全的基本规则还是一样的:不要信任用户代理;将服务器和客户端放在trust boundary 的不同侧。
可以将信任边界视为通过程序绘制的线。一方面,数据不受信任。另一方面,假设数据是可信的。验证逻辑的目的是让数据安全地跨越信任边界——从不信任转移到信任。
验证服务器从客户端接收到的所有内容,并且由于 XSS 漏洞很常见并且允许客户端访问发送给客户端的信息,因此尽可能少地向客户端发送敏感信息。
当您确实需要在服务器和客户端之间往返传输数据时,您可以使用多种技术。
- 对数据进行加密签名,以便服务器可以验证它没有被篡改。
- 将数据存储在边表中,并且只发送一个不透明的、不可猜测的标识符。
当你确实需要向客户端发送敏感数据时,你也有多种策略:
- 将数据存储在仅 HTTP 的 cookie 中,这些 cookie 附加到请求但 JavaScript 无法读取
- 将您的客户分成不同来源的 iframe,并将敏感信息隔离在一个 iframe 中,该 iframe 经过特别仔细的审查,并且具有最少的多余功能。
签名
签名解决了验证您从不受信任的来源收到的数据是否是您之前验证过的数据的问题。它不能解决窃听(因为您需要加密)或决定不返回数据或决定替换使用相同密钥签名的不同数据的客户端的问题。
Django 文档很好地解释了“传递”数据的加密签名,该文档还概述了如何使用它们的 API。
Web 应用程序安全的黄金法则是永远不要信任来自不受信任来源的数据。有时通过不受信任的介质传递数据可能很有用。加密签名的值可以通过不受信任的安全通道传递,因为知道任何篡改都会被检测到。
Django 提供用于签名值的低级 API 和用于设置和读取签名 cookie 的高级 API,这是 Web 应用程序中最常见的签名用途之一。
您可能还会发现签名对以下方面很有用:
- 生成“恢复我的帐户”URL 以发送给丢失密码的用户。
- 确保存储在隐藏表单字段中的数据未被篡改。
- 生成一次性秘密 URL 以允许临时访问受保护的资源,例如用户付费的可下载文件。
不透明标识符
不透明标识符和边表解决了与签名相同的问题,但需要服务器端存储,并且要求存储数据的机器可以访问与接收回标识符的机器相同的数据库。
通过查看此图可以很容易地理解带有不透明、不可猜测的标识符的边表
Server DB Table
+--------------------+---------------------+
| Opaque Primary Key | Sensitive Info |
+--------------------+---------------------+
| ZXu4288a37b29AA084 | The king is a fink! |
| ... | ... |
+--------------------+---------------------+
您使用random or secure pseudo-random number generator 生成密钥并将密钥发送给客户端。
如果客户端有密钥,他们只知道他们拥有一个随机数,并且可能与他们从您那里收到的其他随机数相同,但无法从中派生内容。
如果他们篡改(发回不同的密钥),那么它就不会出现在您的表中(可能性很高),因此您会检测到篡改。
如果您向同一个行为不端的客户端发送多个密钥,它们当然可以用一个替换另一个。
如果您不希望它意外泄露给其他用户代理,则发送每个用户代理的秘密时,仅 HTTP cookie 是一个不错的选择。
如果 HTTP 响应标头中包含 HttpOnly 标志(可选),则无法通过客户端脚本访问 cookie(同样,如果浏览器支持此标志)。因此,即使存在跨站脚本 (XSS) 漏洞,并且用户意外访问了利用此漏洞的链接,浏览器(主要是 Internet Explorer)也不会将 cookie 泄露给第三方。
现代浏览器广泛支持 HttpOnly cookie。
隔离的 iframe
将您的应用程序划分为多个 iframe 是当前允许富客户端操作敏感数据同时将意外泄漏风险降至最低的最佳方式。
基本思想是在一个较大的程序中包含小程序(安全内核),这样您的安全敏感代码可以比整个程序更仔细地审查。这与qmail's cooperating suspicious processes 的工作方式相同。
安全模式:分隔 [VM02]
问题
系统某一部分的安全故障允许
系统的另一部分被利用。
解决方案
将每个部分放在一个单独的安全域中。即使当
一个部分的安全性受到损害,其他部分
保持安全。
"Cross-frame communication the HTML5 way" 解释了 iframe 如何进行通信。由于它们在不同的域上,安全敏感的 iframe 知道其他域上的代码只能通过这些狭窄的通道与其通信。
HTML 允许您在元素中将一个网页嵌入到另一个网页中。它们基本上保持分离。容器网站只允许与其 Web 服务器通信,而 iframe 只允许与其源服务器通信。此外,由于它们具有不同的来源,浏览器不允许两个框架之间的任何接触。这包括函数调用和变量访问。
但是,如果您想在两个单独的窗口之间获取一些数据怎么办?例如,zwibbler 文档在转换为字符串时可能是兆字节长。我希望包含网页能够在需要时获取该字符串的副本,以便保存它。此外,它应该能够访问用户生成的已保存 PDF、PNG 或 SVG 图像。 HTML5 提供了一种在同一窗口的不同框架之间进行通信的受限方式,称为 window.postMessage()。
现在,安全敏感框架可以使用标准验证技术来审查来自(可能受到损害的)不太敏感框架的数据。
您可以让一大群程序员高效地开发出色的应用程序,而一小群程序员则致力于确保正确处理敏感数据。
一些缺点:
- 启动应用程序更加复杂,因为没有单一的“加载”事件。
- iframe 通信需要传递需要解析的字符串,因此对安全敏感的帧仍然需要使用安全的解析方法(postMessage 中的字符串没有
eval。)
- iframe 是矩形的,因此如果安全敏感的框架需要呈现 UI,那么它可能不容易整齐地融入更大的应用程序的 UI。