1.35.1 cors

案例演示

首先这是一个登录页面

登录后是这个样子

请求这个当前页面,抓到这个的请求

可以看到Orgin发生变化,存在CORS跨域劫持,那么我们就可以劫持他里面的手机号

打开CORS验证脚本之前(注意:打开这个脚本必须是你登录这个网站的浏览器打开)

因为这里是get请求,直接copy url

然后把链接放在这里面就可以读取出来

假设如果这里是公网的ip,那么我们把这条链接发给别人,别人点击后,就会在这个文件所在的目录创建一个txt文件,把劫持到内面写入到txt里面

客户端缓存中毒

这种配置允许攻击者利用其他的漏洞。

比如,一个应用返回数据报文头部中包含“X-User”这个字段,这个字段的值没有经过验证就直接输出到返回页面上。

GET /login HTTP/1.1
Host: www.target.local
Origin: https://attacker.domain/
X-User: <svg/onload=alert(1)>

返回报文(注意:“Access-Control-Allow-Origin”已经被设置,但是“Access-Control-Allow-Credentials: true”并且“Vary: Origin”头没有被设置)

HTTP/1.1 200 OK

Access-Control-Allow-Origin: https://attacker.domain/

Content-Type: text/html

Invalid user: <svg/onload=alert(1)

攻击者可以把xss的exp放在自己控制的服务器中的JavaScript代码里面然后等待受害者去触发它。


var req = new XMLHttpRequest();
req.onload = reqListener;
req.open('get','http://www.target.local/login',true);
req.setRequestHeader('X-User', '');
req.send();
function reqListener() {
location='http://www.target.local/login';
}

如果在返回报文中头部没有设置“Vary: Origin”,那么可以利用上面展示的例子,可以让受害者浏览器中的缓存中存储返回数据报文(这要基于浏览器的行为)并且当浏览器访问到相关URL的时候就会直接显示出来。(通过重定向来实现,可以用“reqListener()”这个方法)

如果没有CORS的话,上面的缺陷就没法利用,因为没有办法让受害者浏览器发送自定义头部,但是如果有了CORS,就可以用“XMLHttpRequest”做这个事情。

服务器端缓存中毒

另一种潜在的攻击方式是利用CORS的错误配置注入HTTP头部,这可能会被服务器端缓存下来,比如制造存储型xss 下面是攻击的利用条件:

  • 存在服务器端缓存

  • 能够反射“Origin“头部

不会检查“Origin”头部中的特殊字符,比如”\r"有了上面的先决条件,JamesKettle展示了http头部注入的利用方式,他用这种方式攻击IE/Edge用户(因为他们使用“\r"(0x0d)作为的HTTP头部字段的终结符请求

GET / HTTP/1.1 Origin: z[0x0d]Content-Type: text/html; charset=UTF-7

IE处理过后返回报文

HTTP/1.1 200 OK Access-Control-Allow-Origin: z Content-Type: text/html; charset=UTF-7

上面的请求不能直接拿来利用,因为攻击者没有办法保证受害者浏览器会提前发送畸形的头部。 如果攻击者能提前发送畸形的“Origin”头部,比如利用代理或者命令行的方式发送,然后服务器就会缓存这样的返回报文并且也会传递给其他人。 利用上面的例子,攻击者可以把页面的编码变成”UTF-7",周所周知,这可能会引发xss漏洞

绕过技术

NULL源

CORS的规范中还提到了“NULL”源。触发这个源是为了网页跳转或者是来自本地HTML文件。 目标应用可能会接收“null"源,并且这个可能被测试者(或者攻击者)利用,意外任何网站很容易使用沙盒iframe来获取”null“源

使用上面的iframe产生一个请求类似于下面这样

GET /handler Host: target.local Origin: null

如果目标应用接收”null"源,那么服务器将返回类似下面的数据报文

HTTP/1.1 200 OK Acess-Control-Allow-Origin: null Access-Control-Allow-Credentials: true

使用目标域名作为子域名

如果目标应用只检查只检查“Origin”中的字符串是否包含“target.local”,那么就可以在自己控制的服务器上创建一个子域名。 用这样的方式,请求一般产生自JavaScript代码,并且请求中的“Origin”会像下面这样

Origin: https://target.local.attacker.domain

注册一个同名的域名

假设,目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:

^https?:\/\/.*.?target.local$

这个?只影响".“这个字符串,因此在“target.local”前面的任何字符串都是被允许的,而不管是否有”."把他们分开。 因此,只需要在“origin”末尾包含目标域名就可以绕过上面的限制(这个场景的的目标域名是“ target.local”),比如:

Origin: https://nottarget.local

攻击者只需要注册一个末尾包含目标域名的新域名就可以利用这样的漏洞了。

控制目标的子域名

现在目标应用实现是基于下面的正则表达式去检测“Origin”头部的话:

^https?:\/\/(.*.)?target.local$

这个允许来自”target.local“的跨域访问并且包含所有的子域名(来自HTTP和HTTPS协议)。 在这个场景中,如果攻击者能控制目标的有效的子域名(比如:“subdomain.target.local”),比如接管一个子域名,或者找到一个有xss漏洞的子域名。攻击者就可以产生一个有效的CORS请求。

总结

更多利用技术请点击

https://www.sxcurity.pro/advanced-cors-techniques/

Last updated