原文出处Understanding CSRFhtml
对于Express团队的csrf模块和csurf模块的加密函数的用法咱们常常有一些在乎。 这些在乎是莫须有的,由于他们不了解CSRF token是如何工做的。 下面快速过一遍!git
读事后还有疑问?但愿告诉咱们错误?请开一个issue!github
在他们的钓鱼站点,攻击者能够经过建立一个AJAX按钮或者表单来针对你的网站建立一个请求:web
<form action="https://my.site.com/me/something-destructive" method="POST">
<button type="submit">Click here for free money!</button>
</form>
这是很危险的,由于攻击者可使用其余http方法例如 delete
来获取结果。 这在用户的session中有不少关于你的网站的详细信息时是至关危险的。 若是一个不懂技术的用户遇到了,他们就有可能会输入信用卡号或者我的安全信息。ajax
使用JavaScript发起AJAX请求是限制跨域的。 不能经过一个简单的<form>
来发送JSON
, 因此,经过只接收JSON,你能够下降发生上面那种状况的可能性。数据库
第一种减轻CSRF攻击的方法是禁用cross-origin requests(跨域请求)。 若是你但愿容许跨域请求,那么请只容许 OPTIONS, HEAD, GET
方法,由于他们没有反作用。express
不幸的是,这不会阻止上面的请求因为它没有使用JavaScript(所以CORS不适用)。json
不幸的是,检验referrer头部很麻烦, 可是你能够阻止那些referrer头部不是来自你的页面的请求。 这实在不值得麻烦。后端
举个例子,你不能加载session若是这个请求的referrer头部不是你的服务器。api
确保你的GET
请求不会修改你数据库中的相关数据。 这是一个初学者常犯的错误,使得你的应用不只是易于遭受CSRF攻击。
由于<form>
只能用GET
或是POST
, 而不能使用别的方法,例如PUT
, PATCH
, DELETE
, 攻击者很难有方法攻击你的网站。
许多应用程序使用复写方法来在一个常规表单中使用PUT
, PATCH
, 和DELETE
请求。 这会使得原先不易受攻击的方法变得易受攻击。
旧的浏览器不支持CORS或是其余安全政策。 经过不兼容旧浏览器 (那些不懂技术的人用的越多,咱们越容易被攻击), 你能够最小化受到攻击的可能性。
最终的解决办法是使用CSRF tokens。 CSRF tokens是如何工做的呢?
攻击者须要经过某种手段获取你站点的CSRF token, 他们只能使用JavaScript来作。 因此,若是你的站点不支持CORS, 那么他们就没有办法来获取CSRF token, 下降了威胁。
确保CSRF token不能经过AJAX访问到! 不要建立一个/CSRF
路由来获取一个token, 尤为不要在这个路由上支持CORS!
token须要是不容易被猜到的, 让它很难被攻击者尝试几回获得。 它不须要是密码安全的。 攻击来自从一个未知的用户的一次或者两次的点击, 而不是来自一台服务器的暴力攻击。
这也就是salt(加盐)出现的缘由。 Breach攻击至关简单:若是服务器经过HTTPS+gzip
屡次发送相同或者类似的响应,攻击者就能够猜想响应的内容(使得HTTPS彻底无用)。 解决办法?让每个响应都有那么一点不一样。 因而,CSRF tokens依据每个不一样的请求还有不一样的时间来生成。 可是服务器须要知道客户端请求中带的token是不是合法的。 所以:
了解更多:
注意,CSRF没有_解决_BREACH攻击, 可是这个模块经过随机化请求来为你减轻BREACH攻击。
由于客户端知道salt!!! 服务器会发送 <salt>;<token>
,而后客户端会经过请求返回相同的值给服务器。服务器而后会检验 <secret>+<salt>=<token>
。 salt必须跟token一块儿被发送给服务器,不然服务器不能验证这个token。 这是最简单的加密方式。 还有不少方法,不过他们更加复杂,犯不着那么麻烦。
由于每当进来一个请求他们就会被建立! 像Math.random().toString(36).slice(2)
这么作也是性能足够好的! 你不须要OpenSSL来为每个请求建立一个密码安全的token。
若是你正在使用一个数据库后端来存储session,客户端是不会知道秘钥的,由于它被存储在数据库中。 若是你正在使用cookie来存储session,那么秘钥就会被存储在cookie中发送给客户端。 所以, 确保cookie sessions 使用 httpOnly
那样客户端就不能经过客户端JavaScript来读取到秘钥!
正如上面提到的,若是你不支持CORS而且你的API是传输的严格的JSON, 绝没可能在你的AJAX 调用中加入CSRF token。
不要建立一个GET /csrf
路由 而且尤为不要在这个路由上支持CORS。 不要发送CSRF token在API响应的body中。
由于web正在向JSON API转移,而且浏览器变得更安全,有更多的安全策略, CSRF正在变得不那么值得关注。 阻止旧的浏览器访问你的站点,并尽量的将你的API变成JSON API, 而后你将再也不须要CSRF token。 可是为了安全起见,你仍是应该尽可能容许他们尤为是当难以实现的时候。