我目前正在使用ReactJS构建一个单页应用程序。

我读到不使用localStorage的原因之一是因为XSS漏洞。

既然React会转义所有用户输入,那么现在使用localStorage是否安全呢?


当前回答

只要加密,将令牌存储在localStorage中是安全的。下面是一个压缩的代码片段,展示了许多方法中的一种。

    import SimpleCrypto from 'simple-crypto-js';

    const saveToken = (token = '') => {
          const encryptInit = new SimpleCrypto('PRIVATE_KEY_STORED_IN_ENV_FILE');
          const encryptedToken = encryptInit.encrypt(token);

          localStorage.setItem('token', encryptedToken);
     }

然后,在使用令牌之前,使用PRIVATE_KEY_STORED_IN_ENV_FILE对其进行解密

其他回答

要记住的一件事是jwt是否:

第一方。简单地访问您自己的服务器命令) 第三方;谷歌,Facebook, Twitter等的JWT)

如果智威汤逊是第一方:

那么,将JWT存储在本地存储还是安全的cookie(例如。HttpOnly, SameSite=严格,安全)[假设你的网站已经在使用HTTPS,它应该]。

This is because, assuming an XSS attack succeeds (ie. an attacker was able to insert Javascript code through a JS dependency that is now running on all visitor browsers), it's "game over" anyway; all the commands which were meant to be secured by the "JWT token verifications", can now be executed by the attacker just by having the script they've inserted into the frontend JS call all the needed endpoints. Even though they can't read the JWT token itself (because of the cookie's http-only flag), it doesn't matter because they can just send all the needed commands, and the browser will happily send the JWT token along with those commands.

现在,虽然xss攻击的情况可以说是“游戏结束”了(无论是本地存储还是安全cookie),但cookie还是稍微好一点,因为攻击者只有在用户在浏览器中打开网站时才能执行攻击。

这会给攻击者带来以下“烦恼”:

"My XSS injection worked! Okay, time to collect private data on my boss and use it as blackmail. Dang it! He only ever logs in while I'm here at work. I'll have to prepare all my code ahead of time, and have it run within the three minutes he's on there, rather than getting to poke around into his data on the platform in a more gradual/exploratory way." "My XSS injection worked! Now I can change the code to send all Bitcoin transfers to me instead! I don't have any particular target in mind, so I don't need to wait for anyone. Man though, I wish I could access the JWT token itself -- that way I could silently collect them all, then empty everyone's wallets all at once. With these cookie-protected JWTs, I may only be able to hijack a few dozen visitors before the devs find out and suspend transfers..." "My XSS injection worked! This'll give me access to even the data that only the admins can see. Hmmm, unfortunately I have to do everything through the user's browser. I'm not sure there's a realistic way for me to download those 3gb files using this; I start the download, but there are memory issues, and the user always closes the site before it's done! Also, I'm concerned that client-side retransfers of this size might get detected by someone."

如果JWT是第三方:

在这种情况下,这实际上取决于第三方jwt允许持有者做什么。

如果他们所做的一切只是让某人“访问每个用户的基本配置文件信息”,那么如果攻击者能够访问它,那么它就不是那么糟糕;一些电子邮件可能会泄露,但攻击者可能会通过导航到用户的“帐户页面”,其中数据显示在UI中。(使用JWT令牌只是让他们避免了上一节中列出的“烦恼”)

相反,如果第三方jwt允许您做更实质性的事情——例如完全访问它们的云存储数据、在第三方平台上发送消息、在第三方平台上读取私有消息等等,那么访问jwt确实比仅仅能够“发送经过身份验证的命令”差得多。

这是因为,当攻击者无法访问实际的JWT时,他们必须通过您的第一方服务器路由所有命令。这样做有以下优点:

Limited commands: Because all the commands are going through your server, attackers can only execute the subset of commands that your server was built to handle. For example, if your server only ever reads/writes from a specific folder in a user's cloud storage, then the attacker has the same limitation. Easier detection: Because all the commands are going through your server, you may be able to notice (through logs, sudden uptick in commands, etc.) that someone has developed an XSS attack. This lets you potentially patch it more quickly. (if they had the JWTs themselves, they could silently be making calls to the 3rd-party platforms, without having to contact your servers at all) More ways to identify the attacker: Because the commands are going through your server, you know exactly when the commands are being made, and what ip-address is being used to make them. In some cases, this could help you identify who is doing the attacks. The ip-address is the most obvious way, though admittedly most attackers capable of XSS attacks would be aware enough to use a proxy. A more advanced identification approach might be to, say, have a special message pop up that is unique for each user (or, at least, split into buckets), of such a nature that the attacker (when he loads up the website from his own account) will see that message, and try to run a new command based on it. For example, you could link to a "fake developer blog post" talking about some "new API" you're introducing, which allows users to access even more of their private data; the sneaky part is that the URL for that "new API" is different per user viewing the blog post, such that when the API is attempted to be used (against the victim), you know exactly who did it. Of course, this relies on the idea that the attacker has a "real account" on the site alongside the victim, and could be tempted/fooled by this sort of approach (eg. it won't work if the attacker knows you're onto him), but it's an example of things you can do when you can intercept all authenticated commands. More flexible controlling: Lets say that you've just discovered that someone deployed an XSS attack on your site. If the attackers have the 3rd-party JWTs themselves, your options are limited: you have to globally disable/reset your OAuth/JWT configuration for all 3rd-party platforms. This causes serious disruption while you try to figure out the source of the XSS attack, as no one is able to access anything from those 3rd-party platforms. (including your own server, since the JWT tokens it may have stored are now invalid) If the JWT tokens are instead protected in http-only cookies, you have more options: You can simply modify your server to "filter out" any reads/writes that are potentially dangerous. In some cases added this "filtering" is a quick and easy process, allowing your site to continue in "read-only"/"limited" mode without disrupting everything; in other cases, things may be complex enough that it's not worth trusting the filter code for security. The point though is that you have more options. For example, maybe you don't know for sure that someone has deployed an XSS attack, but you suspect it. In this case, you may not want to invalidate the JWT tokens of every user (including those your server is using in the background) simply on the suspicion of an XSS attack (it depends on your suspicion level). Instead, you can just "make things read-only for a while" while you look into the issue more closely. If it turns out nothing is wrong, you can just flip a switch and re-enable writes, without everyone having to log back in and such.

无论如何,由于这四个好处,我决定始终将第三方jwt存储在“安全cookie”中,而不是本地存储中。虽然目前第三方jwt的作用域非常有限(因此如果它们被窃取也不是什么大问题),但这样做是很好的未来证明,以防我希望我的应用程序在未来请求访问更多特权功能(例如。访问用户的云存储)。

Note: The four benefits above (for storing third-party JWTs in secured cookies) may also partially apply for first-party JWTs, if the JWTs are used as authentication by multiple backend services, and the domains/ip-addresses of these other servers/services are public knowledge. In this case, they are "equivalent to third-party platforms", in the sense that "http-only cookies" restrict the XSS attacker from sending direct commands to those other servers, bringing part of the benefits of the four points above. (it's not exactly the same, since you do at least control those other servers, so you can activate read-only mode for them and such -- but it'll still generally be more work than making those changes in just one place)

localStorage和httpOnly cookie都不能接受吗?关于一个妥协的第三方库,我所知道的唯一能减少/防止敏感信息被窃取的解决方案是强制执行子资源完整性。

子资源完整性(SRI)是一种安全特性 浏览器验证它们获取的资源(例如从CDN) 交付时没有意外的操作。它通过允许 您可以提供所获取资源必须的加密散列 匹配。

只要受感染的第三方库在您的网站上是活跃的,键盘记录程序就可以开始收集信息,如用户名,密码,以及您输入到网站的任何其他内容。

httpOnly cookie将阻止来自另一台计算机的访问,但不会阻止黑客操纵用户的计算机。

我对所有建议不要存储在本地存储的答案感到不安,因为这很容易受到XSS攻击或恶意库的攻击。其中一些问题甚至会进入冗长的讨论,尽管答案非常小/简单,我很快就会讲到。

这就相当于说:“不要用煎锅做饭,因为如果你某天晚上喝醉了,决定用煎锅做饭,你会把自己和房子都烤焦的。” 如果jwt由于XSS攻击或恶意库而泄露,那么站点所有者就有更大的问题:他们的站点容易受到XSS攻击或正在使用恶意库。

答案是:如果你确信你的网站不存在这些漏洞,那就去做吧。

裁判:https://auth0.com/docs/security/data-security/token-storage # browser-local-storage-scenarios

Localstorage被设计成可以通过javascript访问,所以它不提供任何XSS保护。正如在其他回答中提到的,有很多可能的方式来进行XSS攻击,默认情况下,本地存储不受保护。

However, cookies have security flags which protect from XSS and CSRF attacks. HttpOnly flag prevents client side javascript from accessing the cookie, Secure flag only allows the browser to transfer the cookie through ssl, and SameSite flag ensures that the cookie is sent only to the origin. Although I just checked and SameSite is currently supported only in Opera and Chrome, so to protect from CSRF it's better to use other strategies. For example, sending an encrypted token in another cookie with some public user data.

因此,cookie是存储身份验证数据的更安全的选择。

看待这个问题的一种方法是考虑风险或伤害的水平。

你是否正在创造一款没有用户的应用,即POC/MVP?你是一家需要快速进入市场并测试应用程序的初创公司吗?如果是,我可能只会实施最简单的解决方案,并继续专注于寻找适合市场的产品。使用localStorage,因为它通常更容易实现。

你是在开发一款拥有大量日活跃用户的应用的v2版本,还是一款人们/企业非常依赖的应用?被黑客攻击是否意味着几乎没有恢复空间?如果是这样,我会仔细研究一下您的依赖关系,并考虑将令牌信息存储在仅http的cookie中。

使用localStorage和cookie/session存储都有各自的优缺点。

正如第一个答案所述:如果您的应用程序有XSS漏洞,那么两者都不能保护您的用户。由于大多数现代应用程序都有十几个或更多不同的依赖项,因此越来越难以保证应用程序的某个依赖项不受XSS攻击。

如果您的应用程序确实存在XSS漏洞,并且黑客已经能够利用它,那么黑客将能够代表您的用户执行操作。黑客可以通过从localStorage检索令牌来执行GET/POST请求,或者如果令牌存储在http-only cookie中,则可以执行POST请求。

在本地存储中存储令牌的唯一缺点是黑客将能够读取您的令牌。