同源策略为什么可以防csrf_Spring Security 如何预防CSRF跨域攻击?

序言

前面我们学习了 spring security 与 springmvc 的整合入门教程。

spring secutity整合springboot入门

spring security 使用 maven 导入汇总

spring security 业界标准加密策略源码详解

这一节我们来学习一下 spring security 是如何预防 CSRF 攻击的。

拓展阅读

web 安全系列-04-CSRF 跨站请求伪造

什么是CSRF攻击?

了解CSRF攻击的最佳方法是看一个具体示例。

f832c538520dd2a6bd159103addaff6a.png

例子

假设您银行的网站提供了一种表格,该表格允许将资金从当前登录的用户转移到另一个银行帐户。

例如,转账表单可能如下所示:

http 的响请求可能如下:

POST /transfer HTTP/1.1Host: bank.example.comCookie: JSESSIONID=randomidContent-Type: application/x-www-form-urlencodedamount=100.00&routingNumber=1234&account=9876

现在,假装您对银行的网站进行身份验证,然后无需注销即可访问一个邪恶的网站。

恶意网站包含具有以下格式的HTML页面:

您想赢钱,因此单击“提交”按钮。

在此过程中,您无意中将 $100 转让给了恶意用户。

发生这种情况的原因是,尽管恶意网站无法看到您的cookie,但与您的银行关联的cookie仍与请求一起发送。

最糟糕的是,使用JavaScript可以使整个过程自动化。 这意味着您甚至不需要单击该按钮。

此外,在访问受XSS攻击的诚实站点时,也很容易发生这种情况。

那么,我们如何保护用户免受此类攻击呢?

web 安全系列-02-XSS 跨站脚本攻击

防范CSRF攻击

发生CSRF攻击的原因是受害者网站的HTTP请求与攻击者网站的请求完全相同。

这意味着无法拒绝来自邪恶网站的请求,也不允许来自银行网站的请求。

为了防御CSRF攻击,我们需要确保恶意站点无法提供请求中的某些内容,以便我们区分这两个请求

Spring提供了两种机制来防御CSRF攻击:

  • 同步器令牌模式
  • 在会话Cookie上指定SameSite属性

安全方法必须是幂等的

为了使针对CSRF的任何一种保护都起作用,应用程序必须确保“安全” HTTP方法是幂等的。

这意味着使用HTTP方法GET,HEAD,OPTIONS和TRACE进行的请求不应更改应用程序的状态。

idempotent 幂等性防止重复提交

同步器令牌模式

抵御CSRF攻击的最主要,最全面的方法是使用同步器令牌模式。

d3a3c0efc63bc47a73b0314d5da01923.png

解决方案

该解决方案是为了确保每个HTTP请求除了我们的会话cookie之外,还必须在HTTP请求中提供一个安全的,随机生成的值,称为CSRF令牌。

提交HTTP请求时,服务器必须查找预期的CSRF令牌,并将其与HTTP请求中的实际CSRF令牌进行比较。如果值不匹配,则应拒绝HTTP请求。

这项工作的关键是,实际的CSRF令牌应该位于浏览器不会自动包含的HTTP请求的一部分中。

ps: 这里可以发现防止重复提交和思想非常类似,甚至是验证码也是类似的思路。不过要确保这个信息不会被自动放到请求之中。

例如,在HTTP参数或HTTP标头中要求实际的CSRF令牌将防止CSRF攻击。在cookie中要求实际CSRF令牌不起作用,因为浏览器会自动将cookie包含在HTTP请求中。

我们可以放宽期望,仅对每个更新应用程序状态的HTTP请求仅要求实际的CSRF令牌。

为此,我们的应用程序必须确保安全的HTTP方法是幂等的。因为我们希望允许使用外部站点的链接来链接到我们的网站,所以这提高了可用性。

此外,我们不想在HTTP GET中包含随机令牌,因为这可能导致令牌泄漏。

让我们看一下使用同步令牌模式时示例将如何变化。

假设实际的CSRF令牌必须位于名为_csrf的HTTP参数中。

我们应用程序的转帐表单如下:

现在,该表单包含具有CSRF令牌值的隐藏输入。

外部站点无法读取CSRF令牌,因为相同的来源策略可确保恶意站点无法读取响应。

相应的HTTP汇款请求如下所示:

POST /transfer HTTP/1.1Host: bank.example.comCookie: JSESSIONID=randomidContent-Type: application/x-www-form-urlencodedamount=100.00&routingNumber=1234&account=9876&_csrf=4bfd1575-3ad1-4d21-96c7-4ef2d9f86721

您会注意到,HTTP请求现在包含带有安全随机值的_csrf参数。

恶意网站将无法为_csrf参数提供正确的值(必须在邪恶网站上明确提供),并且当服务器将实际CSRF令牌与预期CSRF令牌进行比较时,传输将失败。

SameSite属性

防止CSRF攻击的一种新兴方法是在cookie上指定SameSite属性。

设置cookie时,服务器可以指定SameSite属性,以指示从外部站点发出时不应发送该cookie。

170e2ffb423f349813befe788b739cb8.png

Spring Security不直接控制会话cookie的创建,因此它不提供对SameSite属性的支持。

Spring Session在基于servlet的应用程序中为SameSite属性提供支持。

Spring Framework的CookieWebSessionIdResolver为基于WebFlux的应用程序中的SameSite属性提供了开箱即用的支持。

例子

一个示例,带有SameSite属性的HTTP响应标头可能类似于:

Set-Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly; SameSite=Lax

属性值介绍

SameSite属性的有效值为:

Strict-指定后,来自同一站点的任何请求都将包含cookie。否则,cookie将不会包含在HTTP请求中。

Lax-当来自同一个站点的特定cookie将被发送,或者当请求来自顶层导航且方法是幂等时,将被发送。否则,cookie将不会包含在HTTP请求中。

真实案例

让我们看一下如何使用SameSite属性保护我们的示例。

银行应用程序可以通过在会话cookie上指定SameSite属性来防御CSRF。

在会话cookie上设置SameSite属性后,浏览器将继续发送JSESSIONID cookie和来自银行网站的请求。但是,浏览器将不再发送带有来自邪恶网站的传输请求的JSESSIONID cookie。由于会话不再存在于来自邪恶网站的传输请求中,因此可以保护应用程序免受CSRF攻击。

注意范围

使用SameSite属性防御CSRF攻击时,应注意一些重要注意事项。

(1)将SameSite属性设置为Strict可以提供更强的防御能力,但会使用户感到困惑。

考虑一个保持登录到托管在https://social.example.com上的社交媒体网站的用户。用户在https://email.example.org上收到一封电子邮件,其中包含指向社交媒体网站的链接。

如果用户单击链接,则他们理所当然地希望能够通过社交媒体站点进行身份验证。

但是,如果SameSite属性为Strict,则不会发送cookie,因此不会对用户进行身份验证。

另一个明显的考虑因素是,为了使SameSite属性能够保护用户,浏览器必须支持SameSite属性。

(2)大多数现代浏览器都支持SameSite属性。

但是,可能仍未使用较旧的浏览器。

因此,通常建议将SameSite属性用作深度防御,而不是针对CSRF攻击的唯一防护。

何时使用CSRF保护

什么时候应该使用CSRF保护?

我们的建议是对普通用户可能由浏览器处理的任何请求使用CSRF保护。

如果仅创建非浏览器客户端使用的服务,则可能需要禁用CSRF保护。

CSRF保护和JSON

一个常见的问题是“我需要保护由javascript发出的JSON请求吗?”

简短的答案是,这看情况。

但是,您必须非常小心,因为有些CSRF漏洞会影响JSON请求。

例子

例如,恶意用户可以使用以下格式使用JSON创建CSRF:

        

这将产生以下JSON结构

{ "amount": 100,"routingNumber": "evilsRoutingNumber","account": "evilsAccountNumber","ignore_me": "=test"}

如果应用程序未验证Content-Type,则该应用程序将被暴露。

根据设置的不同,仍然可以通过更新URL后缀以.json结尾的方式来利用验证Content-Type的Spring MVC应用程序,如下所示:

        

CSRF和无状态浏览器应用程序

如果我的应用程序是无状态的怎么办?

这并不一定意味着您受到保护。

实际上,如果用户不需要针对给定请求在Web浏览器中执行任何操作,则他们可能仍然容易受到CSRF攻击。

例如,考虑一个使用自定义cookie而不是JSESSIONID的应用程序,其中包含其中的所有状态用于身份验证。

进行CSRF攻击后,自定义cookie将与请求一起发送,其方式与在前面的示例中发送JSESSIONID cookie相同。

此应用程序容易受到CSRF攻击。

使用基本身份验证的应用程序也容易受到CSRF攻击。

该应用程序容易受到攻击,因为浏览器将以与前面示例中发送JSESSIONID cookie相同的方式在任何请求中自动包含用户名和密码。

CSRF注意事项

实施针对CSRF攻击的防护时,需要考虑一些特殊注意事项。

登录

为了防止伪造登录请求,应保护HTTP请求中的登录免受CSRF攻击。

必须防止伪造登录请求,以使恶意用户无法读取受害者的敏感信息。

攻击执行如下:

  1. 恶意用户使用恶意用户的凭据执行CSRF登录。现在,将受害者验证为恶意用户。
  2. 然后,恶意用户欺骗受害者访问受感染的网站并输入敏感信息
  3. 该信息与恶意用户的帐户相关联,因此恶意用户可以使用自己的凭据登录并查看vicitim的敏感信息

确保保护HTTP请求不受CSRF攻击的可能原因是,用户可能会遇到会话超时,从而导致请求被拒绝。会话超时对于不需要登录就需要会话的用户来说是令人惊讶的。

登出

为了防止伪造注销请求,应该保护注销HTTP请求免受CSRF攻击。

必须防止伪造注销请求,以便恶意用户无法读取受害者的敏感信息。

确保注销HTTP请求免受CSRF攻击的可能麻烦在于,用户可能会遇到会话超时,从而导致请求被拒绝。

会话超时对于不希望需要会话才能注销的用户来说是令人惊讶的

CSRF和会话超时

通常,预期的CSRF令牌存储在会话中。这意味着,会话期满后,服务器将不会找到预期的CSRF令牌并拒绝HTTP请求。

有很多选项可以解决超时问题,每个选项都需要权衡取舍。

减轻超时的最佳方法是使用JavaScript在表单提交时请求CSRF令牌。然后使用CSRF令牌更新该表单并提交。

另一个选择是使用一些JavaScript,让用户知道他们的会话即将到期。用户可以单击按钮以继续并刷新会话。

最后,预期的CSRF令牌可以存储在cookie中。这允许预期的CSRF令牌超过会话寿命。

有人可能会问为什么默认情况下预期的CSRF令牌没有存储在Cookie中。

这是因为存在已知的漏洞利用,其中另一个域可以设置标头(例如,用于指定cookie)。这与出现标题X-Requested-With时Ruby on Rails不再跳过CSRF检查的原因相同。请参阅此webappsec.org线程以获取有关如何执行漏洞利用的详细信息。

另一个缺点是,通过删除状态(即超时),您将失去在令牌遭到破坏时强制使令牌无效的能力。

分段(文件上传)

保护分段请求(文件上传)免受CSRF攻击会导致鸡和蛋的问题。

为了防止发生CSRF攻击,必须读取HTTP请求的正文以获得实际的CSRF令牌。

但是,读取正文表示文件将被上传,这意味着外部站点可以上传文件。

将CSRF保护与 multipart/form-data 一起使用有两种选择。

每个选项都有其取舍。

  • 将CSRF令牌放入 body
  • 将CSRF令牌放入URL

在将Spring Security的CSRF保护与分段文件上传集成之前,请确保您可以先上传而无需CSRF保护。

  • 将CSRF令牌放入 body

第一种选择是在请求正文中包含实际的CSRF令牌。通过将CSRF令牌放入正文中,将在执行授权之前读取正文。这意味着任何人都可以在您的服务器上放置临时文件。

但是,只有授权用户才能提交由您的应用程序处理的文件。

通常,这是推荐的方法,因为临时文件上传对大多数服务器的影响可以忽略不计。

  • 在网址中包含CSRF令牌

如果不允许未经授权的用户上传临时文件,则可以选择将预期的CSRF令牌作为查询参数包括在表单的action属性中。

这种方法的缺点是查询参数可能会泄漏。

更一般而言,将敏感数据放置在正文或标题中以确保不泄漏是最佳实践。

  • HiddenHttpMethodFilter

在某些应用程序中,可以使用form参数来覆盖HTTP方法。

例如,下面的 form 可用于将HTTP方法视为删除而不是 post。

        

覆盖HTTP方法在过滤器中进行。 该过滤器必须放在Spring Security支持之前。

请注意,覆盖仅发生在帖子上,因此实际上不太可能引起任何实际问题。

但是,仍然最好的方法是确保将其放置在Spring Security的过滤器之前。

小结

希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。

我是老马,期待与你的下次相遇。

ca687dec57b34b50112c6e430fd129b1.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/345224.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos移动文件到指定目录_Dynamo批量分离中心文件并另存到指定目录

我们在做项目的时候,为了方便协作,一般都会采用中心文件的方式,但是最终交付的时候,是需要把中心文件分离的,一个一个的分离,感觉还是他麻烦了,于是就想到用Dynamo来批量操作,简单测…

轻松监控Docker容器中的ADF应用程序

在这篇简短的文章中,我将展示一种简单的方法,以确保在Docker容器中运行的ADF应用程序在内存利用率方面是健康的Java应用程序。 我将使用标准工具JConsole,它是计算机上JDK安装的一部分。 如果存在问题(例如,内存泄漏&a…

int型 判断奇偶_XSS(Reflected) 反射型跨站攻击

今天我学习一下反射型XSS。1、low级别打开DVWA网站&#xff0c;先切换到low级别&#xff0c;选择XSS&#xff08;Reflected&#xff09;先查看其源代码&#xff1a;<?php header ("X-XSS-Protection: 0"); // Is there any input? if( array_key_exists( "…

junit 运行_运行,JUnit! 跑!!!

junit 运行JUnit与JavaScript和SVN一起是程序员经常开始使用的一些技术&#xff0c;甚至没有读过一篇博客文章&#xff0c;更不用说一本书了。 也许这是一件好事&#xff0c;因为它们看起来足够简单并且易于理解&#xff0c;因此我们可以立即使用它们而无需任何手册&#xff0c…

将Host Cobol批次和Monolith Webapps移动到云和微服务

在Amazon Event “从大型机到微服务– Vanguard迁移到云”中非常有趣的演示。 以下部分可用作迁移模式 &#xff1a;如何从大型机迁移到微服务的不同方式&#xff1a; 重新托管 再造 重构 使用Linux和Java重新平台 回购 退役 全部结合 该演示文稿还展示了Vanguard的Cloud…

flutterapp部分手机无法打开_Flutter应用程序在最新更新后无法运行

Environment DetailsWindows VS CodeFlutter 1.17.5 • channel stable • https://github.com/flutter/flutter.gitFramework • revision 8af6b2f038 (3 days ago) • 2020-06-30 12:53:55 -0700Engine • revision ee76268252Tools • Dart 2.8.4Error From Debug ConsoleE…

android动态添加的页面怎么加功能_Android跳转应用安装页面

一.低版本跳转方式Intent intent new Intent(Intent.ACTION_VIEW);intent.setDataAndType(uri,"application/vnd.android.package-archive");intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);startActivityForResult(intent, 666);uri是apk的uri记得不要忘了在mani…

字节数组转为二进制数 c#_如何使用字节序列化双精度数组(二进制增量编码,用于低差单调浮点数据集)...

字节数组转为二进制数 c#低延迟系统需要高性能的消息处理和传递。 由于在大多数情况下&#xff0c;数据必须通过有线传输或序列化才能保持持久性&#xff0c;因此编码和解码消息已成为处理管道的重要组成部分。 高性能数据编码的最佳结果通常涉及应用程序数据细节的知识。 本文…

java用户的登录图片_Java 如何用 token 做用户登录认证

1、什么是 token&#xff1f;&#xff1f;&#xff1f;Token 是服务端生成的一串字符串&#xff0c;以作客户端进行请求的一个令牌。2、token 做用户登录认证● 流程3、 Java 实现● 用户登录生成 token&#xff0c;保存到 Redis 中最简单的 token 可由 uid (用户唯一的身份标识…

服务器安装mysql要密码_在阿里云服务器上安装mysql及重置密码

参考链接&#xff1a;https://www.cnblogs.com/ljysy/p/10324854.html下载与安装MySQL&#xff1a;这里采用Yum管理好了各种rpm包的依赖&#xff0c;能够从指定的服务器自动下载RPM包并且安装&#xff0c;所以在安装完成后必须要卸掉&#xff0c;否则会自动更新。1.安装MySQL官…

Corda服务的异步流调用

如何使流程更快&#xff1f; 如果您已经与Corda合作了一段时间&#xff0c;那么您很有可能已经考虑过这一点。 您可以通过以下几方面进行合理的调整来提高性能&#xff1a;事务大小&#xff0c;优化查询并减少整个Flow执行过程中所需的网络跃点数。 在某种程度上&#xff0c;还…

jsf 后台参数到页面_JSF:直接从页面将参数传递给JSF操作方法,这是JavaEE 6+的一个不错的功能...

jsf 后台参数到页面其中一个JSF 2不错的特点出现在Java企业版的JavaEE 6 &#xff0c;是你可以传递参数给喜欢的commandButton和commandLink组件的任何动作元件操作方法。 基于此&#xff0c;您可以最小化托管bean中的方法数量。 另外&#xff0c;为了最小化在bean内部设置的…

mysql odbc ado性能差异_ODBC、OLEDB和ADO之间的关系 ,以及性能比较

学习了.net视频之后&#xff0c;对里面涉及到的数据库连接部分中的一些概念表示很无语。网上很多相关资料&#xff0c;但除了网站不一样外&#xff0c;基本上内容都神一样的一致。现在&#xff0c;我就通过结合看到的一些资料再加上自己的理解试图去解释一下&#xff0c;有不对…

轻松与外来客户进行REST通信

在这个例子中&#xff0c;我们将向您展示如何使用Feign客户端开发一个简单的Spring Boot Application&#xff0c;以使用Weather REST服务。 Spring Boot是基于Java的框架&#xff0c;可简化Web和企业应用程序的构建。 Spring Boot具有嵌入式Tomcat&#xff0c;提供“启动器”…

通过Spring Boot了解H2 InMemory数据库

介绍 基本上&#xff0c;数据库设置涉及几个步骤&#xff0c;然后才能在应用程序中通过已配置的数据源使用它。 在实际项目实施中&#xff0c;这实际上是必需的。 但是&#xff0c;在某些情况下&#xff0c;我们只需要为某些事情完成POC&#xff0c;而整个数据库设置工作仍然是…

mysql多数据源事务_多数据源一致性事务解决方案

spring 多数据源配置spring 多数据源配置一般有两种方案&#xff1a;1、在spring项目启动的时候直接配置两个不同的数据源&#xff0c;不同的sessionFactory。在dao 层根据不同业务自行选择使用哪个数据源的session来操作。2、配置多个不同的数据源&#xff0c;使用一个session…

www.how2j.com_HOW-TO:快速开始使用Spring 4.0,以构建简单的REST-Like API(演练)

www.how2j.comHOW-TO&#xff1a;快速开始使用Spring 4.0&#xff0c;以构建简单的REST-Like API&#xff08;演练&#xff09; 关于使用Spring MVC创建Web API的另一篇教程。 不太复杂。 只是一个演练。 生成的应用程序将提供简单的API&#xff0c;将Mongo作为其持久性&#x…

flutter 返回指定界面_Flutter页面路由导航及传参

转载请注明出处: https://learnandfish.com/概述 每个应用都有很多个页面&#xff0c;在flutter中同样也有很多页面&#xff0c;被称之为路由(Router)&#xff0c;页面之间的跳转通过导航器(Navigator)进行管理。其中 Navigator.push 和 Navigator.pop 是最简单的跳转到新页面和…

正确的工作流程:我应该使用哪个OAuth 2.0流程?

什么是OAuth 2.0 OAuth 2.0是一个已被广泛采用的委托授权框架&#xff0c;已经存在了很多年&#xff0c;并且似乎已经存在。 如果您不熟悉OAuth 2.0的基本概念&#xff0c;可以使用 川崎孝彦写的优秀文章 。 这只是OAuth 2.0各方的简要提醒&#xff1a; 资源所有者–受保护资…

mysql workbench入门_5分钟入门MySQL Workbench

接下来进入下一步&#xff0c;使用Workbench执行sql文件&#xff1a;1.打开Workbench&#xff0c;主页面上点击要connect的连接。2.注意系统偏好设置里&#xff0c;MySQL是running的状态&#xff0c;否则无法执行。创建数据库&#xff1a;点击创建数据库按钮&#xff0c;输入数…