网页攻击 和 跨域 的相关问题梳理

之前对 XSS攻击 和 CSRF攻击 了解地不透彻,导致有些原理似懂非懂。最近刚好查了一些资料,解开了心里的疑问,顺便在这记录一下。

一般常见的网页攻击方式有 XSS攻击 和 CSRF攻击,具体可以先了解一下:

疑问1:CSRF攻击 能获取到用户所在域的cookie吗?

我们知道,cookie用于存储用户登录成功后的会话等信息,那么 CSRF攻击者 在第三方网站伪造用户的请求,是如何获取到用户所在域的cookie呢?

首先,这种攻击方式是跨域的,所以攻击者在第三方网站是获取不到用户cookie的(浏览器的同源策略规定 不允许获取 跨域cookie、localStorage、sessionStorage等信息),但浏览器会为该请求自动携带上对应域的cookie

也就是说,攻击者并不需要获取到用户cookie,只需利用 浏览器的默认行为(即 cookie策略)即可实施攻击。

浏览器的 cookie 有两种类型,CSRF 利用的就是第 2种(浏览器cookie策略

  • Session Cookie
  • Third-party Cookie

需要注意的是:并非所有的浏览器都会自动带上第三方cookie,比如 IE6/7/8、Safari、chrome80 以上版本(参考文章),默认会拦截第三方cookie的。不同的浏览器厂商,各自的cookie策略也不一样。

如果想获取跨域cookie,单纯靠CSRF攻击是做不到的,但结合XSS就可以

需要注意一点:在防御CSRF攻击的方法中,服务器检查 referer 这种方法并不靠谱,因为有些浏览器可以改 referer,或者用 postman 这种工具,也可以随意设置 referer。

疑问2:三种 XSS攻击 到底如何理解?

持久型

  • 存储型-xss:恶意代码被保存到数据库,后续每次访问,服务器都会返回带有恶意代码的页面。举个例子,博客文章编辑保存时,注入恶意代码。

非持久型

  • 反射型-xss:在 前端(输入框等)或者 url参数中 先注入恶意代码,然后向后端发起请求。后端拿到参数解析,并动态生成问题页面(后端必须是 类似php等动态网页语言 生成的页面。如果只是返回静态页面,后端无需解析,则不算反射型xss),接下来只要别人一访问该页面,后端就会返回 带着恶意代码的问题页面。
  • dom型-xss:只能在url参数中 先注入恶意代码,并将该链接(转成美女图片等等)发给用户。用户点击图片请求网页,当页面返回给前端浏览器后,浏览器就会用url中的参数去解析页面,并被注入恶意代码。

2种非持久型xss的区别:反射型-xss是由后端动态网页语言解析恶意代码(服务器重启可以清掉恶意代码),dom型-xss是前端浏览器解析恶意代码(服务器重启没用)。

持久型与非持久型xss的区别:取决于 恶意代码 是否被存入到数据库。

 题外话

由于现在的开发模式 基本都是前后端分离,很多 非计算机专业 的同学,学的都是 纯前端技术(如 vue、react 等),在理解XSS攻击原理的时候,就会觉得似懂非懂,因为有些XSS攻击是需要结合 后端网页语言(如 php 等)实现的。

纯前端技术(如 vue、react 等)是提前把项目 打包成 静态资源(html / css / js 文件等),并放到服务器上;而后端网页语言(如 php 等)是根据 浏览器的 url 在服务器上动态生成 html 文件等资源,再返回给浏览器。也就是说,对用户而言是无感知的,用户只是输入url,然后服务器返回页面显示,但中间生成页面的过程是不一样的

 疑问3:浏览器的 同源策略 限制什么?不限制什么?

限制

  • Cookie、LocalStorage、sessionStorage和 IndexDB 只能读取同源的
  • DOM 节点只能读取和设置同源的
  • AJAX只能发起同源的请求

不限制

  • form表单提交跨域请求(无论 post 还是 get)
  • 页面中的跨域链接(如标签 <script> | <img> | <link>)、跨域资源引入(如标签 <iframe>)

为何form表单请求不限制,而AJAX请求限制呢?

 因为 同源策略 就是 限制你获取其他域的资源,而AJAX跨域请求之后,页面可以拿到AJAX返回的跨域数据,相当于绕过了同源策略,所以默认被限制了。当然,限制可以解开的(如CORS),疑问4中会具体说明。

form表单提交跨域请求 不被同源策略限制,是因为 form表单提交有个默认行为,当 submit 成功之后,页面会自动跳转到该请求的域名页面下,原来的页面就拿不到form请求返回的跨域数据,所以不被限制(其实也有办法拿到的)。

 疑问4:AJAX跨域请求 是 发出前 还是 返回后 被浏览器拦截?

网页的源与请求的源,只要 协议、IP地址、端口号 中有一个不同,即认为是跨域。在疑问3中咱们聊到,同源策略限制了AJAX的跨域请求,那么 AJAX跨域请求 到底可以实现么?

这就需要我们了解一个W3C标准:CORS参考《CORS详解 - 阮一峰》)。

CORS跨域资源共享,全称Cross-origin resource sharing,它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。该标准由W3C制定。目前所有浏览器几乎都支持CORS标准(IE10 以下 不支持)。

了解完CORS,我们知道 AJAX跨域请求 肯定可以实现,只不过取决于服务器如何配置

另外,CORS只是解决了 AJAX跨域请求 的问题,如果 只想 获取跨域的数据(非AJAX),方法就很多了(比如 JSONP、WebSocket、设置代理 等等)。

疑问4解答

 AJAX跨域请求,其实要分2种情况来阐述:

如果是 简单请求浏览器会发出该request请求,服务器收到并返回response给浏览器。浏览器检查response中的字段,看是否允许 AJAX跨域请求:

  • 允许,则使用服务器返回的跨域内容
  • 不允许,则浏览器会拦截掉返回的内容,并在console提示不允许跨域

如果是 复杂请求浏览器会先将该request请求拦截,同时会 自动生成 并 发出一个预检请求(即type为preflight,method为options),用于询问后台服务器是否允许 AJAX跨域请求。服务器同样会返回response,浏览器检查response中的字段:

  • 允许,则继续发起复杂请求,获取跨域数据
  • 不允许,则该复杂请求被丢弃,并在console提示

也就是说,在服务器不允许跨域的情况下,AJAX跨域请求 是 发出前 还是 返回后 被浏览器拦截,取决于该请求是 简单请求 还是 复杂请求

疑问5:如何让 复杂请求 对应的 预检请求preflight 只发一次?

在控制台可以看到,每个复杂请求发出之前,都会先发出一个预检请求(preflight)。但每次都发,其实挺浪费网络资源的。如何让它只发送一次呢?

解决办法:在服务器上可以通过设置 Access-Control-Max-Age 字段(单位秒)来指定预检请求在浏览器的缓存时间。当同一个复杂请求 下一次被发出时,如果其对应的 preflight 还没过期,那么复杂请求就可以直接被发出。

需要注意一点:比如在chrome浏览器,开发人员习惯 勾选“Disable Cache”(表示禁用浏览器缓存,如下图),这样Access-Control-Max-Age就失效了,预检请求 还是会每次都被发出。所以想看到测试效果的话,记得先 取消“Disable Cache”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值