The Express team's csrf and csurf modules frequently have issues popping up concerned about our usage of cryptographic functions. Express团队的csrf和csurf模块经常会出现一些问题,这些问题与我们对加密函数的使用有关。These concerns are unwarranted due to a misunderstanding of how CSRF tokens work. 由于对CSRF令牌如何工作的误解,这些担忧是没有根据的。So here's a quick run down!所以这里有一个快速运行!
Read this and still have questions? Want to tell us we're wrong? Open an issue!读了这篇文章,还有问题吗?想告诉我们我们错了吗?打开一个问题!
On their own (phishing site), an attacker could create an AJAX button or form that creates a request against your site:攻击者可以在自己的网站(仿冒网站)上创建一个AJAX按钮或表单,以创建针对您网站的请求:
<form action="https://my.site.com/me/something-destructive" method="POST">
<button type="submit">Click here for free money!</button>
</form>
This is worse with AJAX as the attacker could use other methods like AJAX的情况更糟,因为攻击者可以使用其他方法,如DELETE
as well as read the result. DELETE
和读取结果。This is particularly important when the user has some sort of session with very personal details on your site. 当用户在您的站点上有一些带有非常个人详细信息的会话时,这一点尤为重要。If this is in the context of a technologically illiterate user, there might be some inputs for credit card and social security info.如果这是在一个不懂技术的用户的情况下,可能会有一些信用卡和社会安全信息的输入。
AJAX calls use JavaScript and are CORS-restricted. AJAX调用使用JavaScript,并且受CORS限制。There is no way for a simple 简单的<form>
to send JSON
, so by accepting only JSON, you eliminate the possibility of the above form.<form>
要发送JSON
,只接受JSON,就消除了上述形式的可能性。
The first way to mitigate CSRF attacks is to disable cross-origin requests. 缓解CSRF攻击的第一种方法是禁用跨源请求。If you're going to allow CORS, only allow it on 如果你要允许CORS,只允许它在OPTIONS, HEAD, GET
as they are not supposed to have side-effects.OPTIONS, HEAD, GET
,因为他们不应该有副作用。
Unfortunately, this does not block the above request as it does not use JavaScript (so CORS is not applicable).不幸的是,这不会阻止上述请求,因为它不使用JavaScript(因此CORS不适用)。
Unfortunately, checking the referrer header is a pain in the ass, but you could always block requests whose referrer headers are not from your site. 不幸的是,检查referer标头是一件麻烦事,但是你总是可以阻止那些referer头不是来自你的站点的请求。This really isn't worth the trouble.这真的不值得费心。
For example, you could not load sessions if the referrer header is not your server.例如,如果referer头不是您的服务器,则无法加载会话。
Make sure that none of your 确保GET
requests change any relevant data in your database. GET
请求不会更改数据库中的任何相关数据。This is a very novice mistake to make and makes your app susceptible to more than just CSRF attacks.这是一个非常新手犯的错误,使您的应用程序容易受到CSRF攻击。
Because 因为<form>
s can only GET
and POST
, by using other methods like PUT
, PATCH
, and DELETE
, an attacker has fewer methods to attack your site.<form>
只有GET
和POST
,通过使用其他方法(如PUT
、PATCH
和DELETE
),攻击者可以使用较少的方法攻击您的站点。
Many applications use method-override to use 许多应用程序使用方法重写在常规表单上使用PUT
, PATCH
, and DELETE
requests over a regular form. This, however, converts requests that were previously invulnerable vulnerable!PUT
、PATCH
和DELETE
请求。但是,这会转换以前不受攻击的请求!
Don't use method-override
in your apps - just use AJAX!
Old browsers do not support CORS or security policies. 旧浏览器不支持CORS或安全策略。By disabling support for older browsers (which more technologically-illiterate people use, who are more (easily) attacked), you minimize CSRF attack vectors.通过禁用对旧浏览器的支持(更不懂技术的人使用旧浏览器,他们更容易受到攻击),可以最小化CSRF攻击向量。
Alas, the final solution is using CSRF tokens. How do CSRF tokens work?唉,最终的解决方案是使用CSRF令牌。CSRF代币如何工作?
An attacker would have to somehow get the CSRF token from your site, and they would have to use JavaScript to do so. 攻击者必须以某种方式从您的站点获取CSRF令牌,并且必须使用JavaScript来实现这一点。Thus, if your site does not support CORS, then there's no way for the attacker to get the CSRF token, eliminating the threat.因此,如果您的站点不支持CORS,则攻击者无法获得CSRF令牌,从而消除威胁。
Make sure CSRF tokens can not be accessed with AJAX!确保不能使用AJAX访问CSRF令牌!
Don't create a 不要仅仅为了获取令牌而创建/csrf
route just to grab a token, and especially don't support CORS on that route!/csrf
路由,尤其不要在该路由上支持CORS!
The token just needs to be "unguessable", making it difficult for an attacker to successfully guess within a couple of tries. 令牌只需要是“不可用的”,使得攻击者很难在几次尝试中成功猜测。It does not have to be cryptographically secure. 它不必是加密安全的。An attack is one or two clicks by an unbeknownst user, not a brute force attack by a server.攻击是未知用户的一次或两次单击,而不是服务器的暴力攻击。
This is where the salt comes along. The BREACH attack is pretty simple: if the server sends the same or very similar response over 这就是盐的来源。破坏攻击非常简单:如果服务器多次通过HTTPS+gzip
multiple times, an attacker could guess the contents of response body (making HTTPS utterly useless). HTTPS+gzip
发送相同或非常相似的响应,攻击者可能会猜到响应正文的内容(使HTTPS完全无用)。Solution? Make each response a tiny bit different.解决方案让每个反应都有一点点不同。
Thus, CSRF tokens are generated on a per-request basis and different every time. 因此,CSRF令牌是基于每个请求生成的,并且每次都不同。But the server needs to know that any token included with a request is valid. Thus:但是服务器需要知道请求中包含的任何令牌都是有效的。因此:
Read more here:请在此处阅读更多信息:
Note that CSRF doesn't solve the BREACH attack, but the module simply randomizes requests to mitigate the BREACH attack for you.请注意,CSRF并不能解决漏洞攻击,但该模块只是将请求随机化,以减轻漏洞攻击。
Because the client knows the salt!!!因为客户知道盐!!!
The server will send 服务器将发送<salt>;<token>
and the client will return the same value to the server on a request. <salt>;<token>
,而客户端将根据请求向服务器返回相同的值。The server will then check to make sure 然后服务器将进行检查以确保<secret>+<salt>=<token>
. <secret>+<salt>=<token>
。The salt must be sent with the token, otherwise the server can't verify the authenticity of the token.salt必须与令牌一起发送,否则服务器无法验证令牌的真实性。
This is the simplest cryptographic method. There are more methods, but they are more complex and not worth the trouble.这是最简单的加密方法。有更多的方法,但它们更复杂,不值得费心。
Because they are created on every request!因为它们是根据每个请求创建的!
Doing something as simple as 做一些简单的事情,比如Math.random().toString(36).slice(2)
is sufficient as well as extremely performant!Math.random().toString(36).slice(2)
就足够了,而且性能非常好!
You don't need OpenSSL to create cryptographically secure tokens on every request.您不需要OpenSSL在每个请求上创建加密安全的令牌。
But it is. If you're using a database-backed session store, the client will never know the secret as it's stored on your DB. 但事实确实如此。如果您使用的是数据库支持的会话存储,那么客户机将永远不会知道这个秘密,因为它存储在您的数据库中。If you're using cookie sessions, the secret will be stored as a cookie and sent to the client. 如果您正在使用cookie会话,则机密将存储为cookie并发送到客户端。Thus, make sure cookie sessions use 因此,请确保cookie会话使用httpOnly
so the client can't read the secret via client-side JavaScript!httpOnly
,以便客户端无法通过客户端JavaScript读取机密!
As noted above, if you don't support CORS and your APIs are strictly JSON, there is absolutely no point in adding CSRF tokens to your AJAX calls.如上所述,如果您不支持CORS,并且您的API严格使用JSON,那么将CSRF令牌添加到AJAX调用中是毫无意义的。
Don't ever create a 永远不要在应用程序中创建GET /csrf
route in your app and especially don't enable CORS on it. GET /csrf
路由,尤其不要在其上启用CORS。Don't send CSRF tokens with API response bodies.不要发送带有API响应主体的CSRF令牌。
As the web moves towards JSON APIs and browsers become more secure with more security policies, CSRF is becoming less of a concern. 随着web向JSON API的发展,浏览器变得更加安全,有了更多的安全策略,CSRF就不再那么令人担忧了。Block older browsers from accessing your site and change as many of your APIs to be JSON APIs, and you basically no longer need CSRF tokens. 阻止旧浏览器访问您的站点,并将尽可能多的API更改为JSON API,您基本上不再需要CSRF令牌。But to be safe, you should still enable them whenever possible and especially when it's non-trivial to implement.但是为了安全起见,您仍然应该尽可能地启用它们,尤其是在实现起来非常困难的情况下。