网络安全 101 - 第一部分:秘密
开启我的网络安全系列,分享我的秘密——开个玩笑!我们来聊聊如何保护我们的秘密吧。
环境变量
环境变量就像全局服务器变量一样,通常用于存储机密和敏感信息。虽然有方法可以将它们暴露给浏览器的前端代码,但之后它们就不再是机密了。任何人都可以找到它们。
有一些像dotenv这样的软件包允许你在文件中配置环境变量(只需记住将它们放在你的 中)。你可以在使用Heroku或Netlify.gitignore
等平台托管网站时配置它们。
您也可以在终端环境中手动设置它们,或者在终端使用的文件中设置它们。
环境变量的另一个常见用例是用于存储随环境变化的信息。例如,你有一个表示环境的环境变量,例如NODE_ENV=testing
或NODE_ENV=production
。那么你将得到如下代码:
if (NODE_ENV=testing) {
URL_BASE=http://localhost:3000
} else {
URL_BASE=http://mydomain.net
}
根据您的部署方式,还可以为每个环境设置单独的项目,只需更改变量的值即可。
秘密服务器
您可能会被要求使用密钥服务器来存储您的密钥。有些服务器的设置类似于密码管理器——仅用于共享凭证。其他服务器允许您通过经过身份验证的 HTTP 请求检索密钥。
像Google Cloud这样的产品在您用于部署代码的系统中内置了身份验证、授权、秘密存储和秘密检索功能。
如果以这种方式存储秘密,而不是将其硬编码在环境变量中,则更容易频繁地轮换它们。
代币
令牌是一个表示已加密信息的字符串,通常使用加密哈希值。该信息用于身份验证和授权。当您是应用用户时,他们通常会使用令牌对您进行身份验证和授权。您通常会从 API 获取密钥或令牌,以便以开发者身份对您的应用进行身份验证和授权。
加密算法有很多,但在 Web 开发中,你最常遇到的是 JWT。JSON Web Token 具有 JSON 相关的加密特性。换句话说,它们设计紧凑、URL 安全,并且易于在 JavaScript 中使用。非常适合 Web 开发中的 HTTP 请求。它们的格式甚至类似于 HTTP 请求,包含标头、包含 JSON 数据的有效负载和签名。签名是另一种加密技术,即代码签名。简而言之,代码签名旨在通过验证来源来确保您可以信任信息。
与许多加密标准一样,JWT 算法并非秘密。您可以将 JWT 粘贴到Auth0 的 JWT 调试器中,查看其中的信息。因此,您应该对 JWT 以及收到的所有令牌进行保密。请经常轮换它们,并仅通过 HTTPS 发送。
令牌作为机密信息,应该保留在服务器中,但我们经常需要在浏览器中存储用户信息。我们来谈谈 Cookie。
曲奇饼
登录后,服务器收到您的身份验证/授权令牌后,会将前端所需的信息重新打包到 cookie 中并通过 HTTP 发送。
有一个特定的set-cookie
标头。您可以使用多个set-cookie
标头,每个标头都包含一个键值对(例如 JavaScript 对象或 Python 元组)。
最安全的 Cookie 具有设置secure
、SameSite
和HttpOnly
属性。第一个属性表示它只能通过 HTTPS 发送。第二个属性设置为 ,则阻止 CORS 请求访问该 Cookie strict
。该lax
属性值会在用户导航到同一来源时发送该 Cookie。该属性值none
不会限制对 Cookie 的请求。
HttpOnly
仅允许通过 HTTP 请求读取 Cookie。您将无法使用Cookie API访问它。换句话说,如果您未设置HttpOnly
和SameSite=strict
,任何人都可以使用 JavaScript 在浏览器中访问您的 Cookie。
如果您需要在前端存储用户的会话信息,则无需在 Cookie 中存储任何机密信息。相反,前端会存储一个会过期的令牌或 ID,本质上是一个公钥。如果私钥存储在后端用于验证,那么即使有人知道公钥也没关系。只有当两者结合在一起时,才会泄露敏感信息。
中间人
为什么要如此严密地保护你的 token 和 cookie?中间人攻击。这种攻击有很多名字,我个人最喜欢的是“中间人怪物”。
以 HTTP 为例,这些怪物会在发送者和接收者之间截取信息。然后,它们会重新打包信息,就像从未打开过一样,并将其发送出去。有时,它们想要获取你 Cookie 中的机密信息。有时,它们更感兴趣的是你如何对信息进行代码签名或编码。
查看OWASP 文章以获取更多信息。
Web存储API
如果您已经计划在前端存储非秘密信息,那么您也可以使用 Web 存储 API。
Web 存储 API 包含两部分:会话存储和本地存储。会话存储仅存储会话内的数据,一旦关闭浏览器或标签页,数据就会消失。本地存储没有过期时间。两者都存储键值对。
由于有内置方法,因此在 Web Storage 中存储和访问信息非常简单:
localStorage.setItem(key, value)
sessionStorage.getItem(key)
IndexedDB API
IndexedDB API类似于 Web Storage API,但功能更强大。它是一个完整的面向对象数据库,直接在浏览器中运行。这意味着您可以存储大量非机密信息。
它是持久存储,可在线和离线工作。更多信息,请参阅Mozilla 开发者网络指南。
会话劫持
为什么我这么坚持你不应该在浏览器中存储机密信息?会话劫持。
中间人攻击有多种类型,包括中间人攻击。一种常见的攻击方式是获取存储在浏览器中的会话信息。其目标是要么将信息发送到服务器并获取访问权限,要么冒充您,维持您的会话。
攻击者还可以使用木马、点击劫持/UI 篡改以及XSS来劫持会话。务必假设浏览器中存储的所有内容都已遭到泄露。
结论
这个建议来自我的经验。我曾经把密钥暴露给浏览器,却没有意识到这样做有多危险。我丈夫就曾遭遇过会话劫持。
我想先从概述一下机密以及它们不该存储在哪里开始。网络安全的本质在于,它耗费大量时间,不值得你付出,而且你还假设你的机密会被泄露。令牌及其编码算法和建议的频繁轮换就是一个很好的例子。
我将在本系列的其他博客中详细讨论服务器、HTTP、JavaScript 和 HTML 漏洞。
文章来源:https://dev.to/abbeyperini/web-security-101-part-1-secrets-5e39