编程语言
首页 > 编程语言> > CSRF防御(owasp)(一部分)

CSRF防御(owasp)(一部分)

作者:互联网

原文

基于令牌的措施

这种防御方式是防御CSRF方式中最受欢迎和推荐的。它能够通过有状态(同步令牌模式)或无状态(基于加密或哈希的令牌模式)实现。

使用内置或现有的CSRF实现。

同步令牌防御已经内置到许多框架中。**强烈建议,在尝试构建自定义的令牌生成系统前,先研究所使用的框架是否默认有实现CSRF保护的选项。**例如,.NET有内置保护,可以为易受CSRF影响的资源添加令牌。在使用这些内置的CSRF保护前,你负责正确的配置(比如密钥管理和令牌管理)。
将CSRF防御添加到现有应用中单外部组件也非常建议。
例如:
(原文有超链接,有要看的点击原文或搜索关键字)

同步令牌模式

CSRF令牌应该在服务器端生成。它们能够针对每个用户会话或个请求生成一次。每个请求一个令牌比每个会话一个要安全点,因为这样留给攻击者利用偷来的令牌的时间最少。但是,这可能会导致可用性的问题。例如:浏览器的“Back”按键功能可能会受到阻碍,因为前一个页面可能需要包含一个不再有效的令牌。与前一个页面交互将会导致服务器端产生CSRF误报事件。在每个会话一个令牌的场景中,令牌将存储在会话中,并且在每个子请求中使用,直到会话结束。

**当客户端发来一个请求,服务器端必须通过对比请求中的令牌和用户会话中的令牌,来核实令牌的存在和有效性。**如果令牌不存在请求中,或者令牌的值和用户会话中的令牌值不匹配,则该请求将被中止,该用户的会话也被终止,并将该事件记录为潜在的正在进行的CSRF攻击。

CSRF的令牌应该:

CSRF令牌能够阻止CSRF的原因在于,没有令牌,攻击者无法构建一个有效的请求发给服务器后端。

CSRF令牌应该通过cookies传递

CSRF令牌能够在隐藏字段、请求头中添加,并且能够在表单和AJAX调用中使用。确保令牌不会在服务器日志或者URL中泄露。GET请求中的CSRF令牌可能会会泄露在几个点中,如浏览器历史、日志、记录http请求第一行的网络设备,以及referer头中(如果受保护的站点连接到外部站点)。
举例:

<form action="/transfer.do" method="post">
<input type="hidden" name="CSRFToken" value="OWY4NmQwODE4ODRjN2Q2NTlhMmZlYWEwYzU1YWQwMTVhM2JmNGYxYjJiMGI4MjJjZDE1ZDZMGYwMGEwOA==">
[...]
</form>

通过JS将CSRF令牌插入到自定义的http请求中比在隐藏字段中添加要安全得多,因为它使用了自定义的请求头。
(一头雾水)

基于加密的令牌模式

基于加密的令牌模式利用了加密,而不是对比的方式来核实令牌有效性。它最适合不想在服务器端中维持任何状态的应用程序。

建议服务器使用仅在服务器上可用的唯一密钥生成包含用户会话ID和时间戳的令牌(以防止重发攻击)。(AES256-with GCM mode/GCM-SIV is recommended. Usage of ECB mode is strictly not recommended. If you would like to use any other block cipher mode of operation, refer here and here for more information)(总感觉自己这段翻译不好,简单地说就是推荐使用aes等高级的对称加密算法)

这个令牌返回给客户端,并嵌入到表单的隐藏字段中(再请求头或者请求参数中)。在接收到这个请求时,服务器读取并使用(生成此令牌的)密钥解密该令牌的值。

如果令牌不能被解密,则这表明有入侵企图(应该阻止并记录到日志,用于调试或事件响应的目的)。一旦成功解密,则令牌中的用户会话ID和时间戳是有效的。会话ID和当前登录用户相比较,时间戳和当前时间比较,以验证其并未超出令牌的有效时间。如果会话ID匹配,且时间戳在有效时间内,则请求通过。

基于HMAC的令牌模式

HMAC
密钥散列消息认证码
是一种通过特别计算方式之后产生的消息认证(MAC),使用密码散列函数,同时结合一个加密密钥。它可以用来保证资料的完整性,同时可以用来作某个消息的身份验证。------来自维基百科

以下摘自此文

通过哈希算法,我们可以验证一段数据是否有效,方法就是对比该数据的哈希值,例如,判断用户口令是否正确,我们用保存在数据库中的password_md5对比计算md5(password)的结果,如果一致,用户输入的口令就是正确的。

为了防止黑客通过彩虹表根据哈希值反推原始口令,在计算哈希的时候,不能仅针对原始输入计算,需要增加一个salt来使得相同的输入也能得到不同的哈希,这样,大大增加了黑客破解的难度。

如果salt是我们自己随机生成的,通常我们计算MD5时采用md5(message + salt)。但实际上,把salt看做一个“口令”,加salt的哈希就是:计算一段message的哈希时,根据不同口令计算出不同的哈希。要验证哈希值,必须同时提供正确的口令。

这实际上就是Hmac算法:Keyed-Hashing for Message Authentication。它通过一个标准算法,在计算哈希的过程中,把key混入计算过程中。

基于HMAC令牌的实现同样也不需要在服务器端维持任何状态(保存令牌)。它的工作原理和和基于加密的CSRF保护相似。一些不同的点在于:

  1. 它使用了强大的HMAC函数(推荐SHA-256等)(其实就是非对称加密函数?)而非加密函数来生成令牌。
  2. 令牌包含HMAC和时间戳。(HMAC应该就是HAMC函数加密后的值)

以下是正确实现基于HMAC的CSRF保护的步骤:

  1. 生成令牌:使用密钥K生成HMAC(会话ID+时间戳),并将相同时间戳添加到该值上,从而得到CSRF令牌。
  2. 包含令牌:在表单的隐藏字段包含令牌。在AJAX请求中,请求头中或者请求主体参数中包含令牌。
  3. 校验令牌当服务器端接收到请求,用相同的密钥K再生成令牌(参数是会话ID以及请求中令牌的时间戳)。如果接收到的HMAC和再生成的相匹配,且时间戳在规定的有效范围内,则成功验证,此请求是合法的且运行通过。否则,阻止此请求并记录此次攻击以进行事件响应。

做个小总结:

同步令牌模式:服务器端和请求包都各自有一个令牌,如果两个令牌相匹配则通过。否则失败。

加密令牌模式:服务器端加密一个令牌给请求包(客户端),服务器端不存储此令牌。当接收到请求包的时候,使用对应的密钥解密然后对比令牌内的用户会话id和当前登录的用户id是否是同一个,以及令牌是否还在有效期内。不过查找对应密钥这一步好像没看到有细说的。

基于HMAC的令牌模式:HMAC其实就是加盐hash,不过这里的盐被当成密钥。用过密钥加密(当前会话ID+时间戳)的值,然后发给客户端,同时也发送时间戳。当接收到带此令牌的请求,则使用密钥再次加密(当前会话ID+请求中令牌的时间戳)的值。如果相匹配且在有效范围内则此请求通过。

深度防御技术

SamSite Cookie 属性

SameSite是一个cookie熟悉(和HTTPOnly相似),用来防御CSRF攻击。他在RFC6265bis中定义。这个属性帮助浏览器决定是否发送跨域请求的cookie。此属性的可能值为Lax、Strict、None。

Strict值将在所有跨站点浏览请求中,阻止cookie从浏览器发送请求。举例,对类似github的网站,这意味着如果一个已登录用户从公司论坛或邮件的链接进入到一个个人的github项目中,则gihub将不会接收会话cookie,并且用户无法访问此项目。银行网站不希望任何交易页面能够从外部站点链接到,因此Strict值是最合适的

默认的Lax值在网站的安全和易用性间提供了一个合理的权衡,网站想在用户从其他链接访问过来时维持用户的登录会话。在上述github的场景中,从外部链接访问网站时,会话cookie将被允许通过,但当在容易出现CSRF的请求中将会被阻止,如POST请求。

For more details on the SameSite values, check the following section from the rfc.(别问,懒)

使用此属性的例子:

Set-Cookie: JSESSIONID=xxxxx; SameSite=Strict
Set-Cookie: JSESSIONID=xxxxx; SameSite=Lax

所有台式浏览器和几乎所有移动浏览器都支持SameSite属性。

重要的一点是,这个属性应该当成附加层防御来实现。这个属性通过支持该属性的浏览器来实现,所以它有两种方法饶过它。这个属性不应该替代CSRF令牌。反而应该同时存在,以更可靠的方式保护用户。

使用标准请求头来验证来源

这个防御有两步,两步都依赖检查HTTP请求头的值。

  1. 确定请求的来源。通过origin或referer
  2. 确定请求的目标

标签:令牌,请求,哈希,owasp,会话,防御,CSRF,HMAC
来源: https://blog.csdn.net/qq_28824589/article/details/113896520