浅谈Web安全从SOP到CORS跨域再到CSP
0x00 从源和同源策略开始说起
源的理解我们可以通过一个网址来理解
https://www.baidu.com:80
https:// 协议
baidu.com 主机名
80端口
这样一个由协议主机名端口组成的三元组我们将它称之为源,根据源我们提出同源策略这么一个概念:当两个页面协议端口主机名都相同时 我们说两个页面拥有相同的源。同源策略只是一个模型不是标准,就算是标准,在实际情况下也会千差万别,只要是处理web内容的客户端都会采取同源策略
那么同源策略限制了什么呢?
同源的脚本执行是可以的,只是同源不会读取http回复,所以说只是限制读取回复而已,so sop在防止csrf的事情上起到的效果微乎其微,我不需要读取回复这种交互模式。目标执行那一刻。我的攻击就已经结束了,而静态资源不受同源策略的限制/css/jpg/..
就比如我们在用Boostrap时会很自然的引入其他网站的js css jpg等没任何问题,并且我们常见的about:blank
这种特殊的格式他们的源会继承自加载他们的源。
实际上同源策略限制的不同源之间的交互主要针对的是js中的XMLHttpRequest
等请求,像页面中的链接,重定向以及表单提交是不会受到同源策略限制的。
跨域资源嵌入是允许的,当然,浏览器限制了Javascript不能读写加载的内容,我们提到了跨域这个名词,其实就是在这个网站引入别的地方的脚本或者是一些其他图片等内容,这肯定是不安全的,以下三种都成为跨域:
跨域读 Cross-origin read
跨域写 Cross-origin write
跨域嵌入 Cross-origin embedding
我们上文也说到过了,这里面只有跨域读是不被允许的。我们提到不满足同源策略的提交表单/嵌入就是我们所说的跨域写和跨域嵌入,那么哪些是允许嵌入的资源呢?
<script src="..."></script>标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。
<link rel="stylesheet" href="...">标签嵌入 CSS。由于 CSS 的松散的语法规则,CSS 的跨域需要一个设置正确的Content-Type消息头,不同浏览器有不同的限制。
<img>嵌入图片。支持的图片格式包括 PNG,JPEG,GIF,BMP,SVG,...
<video> 和 <audio>嵌入多媒体资源。
<object>, <embed> 和 <applet>的插件。
@font-face引入的字体。一些浏览器允许跨域字体(cross-origin fonts),一些需要同源字体(same-origin fonts)
<frame>和<iframe>载入的任何资源。
站点可以使用 X-Frame-Options 消息头来阻止这种形式的跨域交互。
0x02 CORS策略
上文提到 我们在使用<script>嵌入跨域脚本的时候 因为干扰会造成很多麻烦 所以很多浏览器默认会直接限制请求,跨域请求可能不是浏览器直接拦截掉了,而是跨站请求发起了,但是返回结果被浏览器拦截了,请求实际上已经发送到了后端服务器,只是无法读取回复而已。但因为安全 很多https到Http的跨域会被火狐,谷歌这种浏览器直接干掉 发送不了请求,所以出现了跨域资源共享(CORS)
原理:
服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许一些跨域请求,值得一提的是CORS一般分两种,一种是带preflight的,我们称他为预检机制,另一种是simple,不需要预检的简单请求,不需要preflight机制
GET请求 HEAD请求
Content-Type为指定值的POST请求,包括text/plain,multipart/form-data以及application/x-www-form-urlencode
HTTP首部字段不能包含下列以外的值:
Accept Accept-Language Content-Language
Content-Type DPR Downlink Save-Data Viewport-Width Width
凡是不满足以上要求的被视为preflight,会预先发一个OPITIONS 在返回的preflight request中查看一些满足的条件
0x03 CSP
Content Security Policy(CSP)内容安全策略,也是用于帮助解决注入xss漏洞这种的防护,csp可以进行规定允许的域,他的方法是只允许访问可信域 限制一些js的执行
一个简单的书写类似如下
header("Content-Security-Policy: default-src 'self'; script-src 'self' https://lorexar.cn;");
规则指令
那么问题来了 CSP可以bypass吗?
答案是可以的,我们看一条规则
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' ");
标准的只允许script处理内联脚本,我们的问题是如何bypass self js linkprefetch
预加载资源,也就是我们使用跨域请求即可 满足上文提到cors的跨域请求都是可以的
0x04 jsonp劫持与CORS跨域漏洞
翻找了下漏洞库发现还是有很多的jsonp劫持漏洞,我们上文说到jsonp是可以跨域的 但有个缺点 jsonp只支持get请求
举例一个jsonp漏洞 是在乌云镜像找到
http://login.sina.com.cn/sso/login.php?entry=wbwidget&service=miniblog&encoding=UTF-8&gateway=1&returntype=TEXT&from=&callback=sinaSSOController.autoLoginCallBack3&useticket=1&client=ssologin.js(v1.4.2)&_=1462341848253
当returntype为text时 他会返回一个jsonp格式
sinaSSOController.autoLoginCallBack3({"retcode":"0","ticket":"ST-MM3MQ==-1462342428-xd-D71E5D7EB3C15","uid":"31*1
这里面替换url的ticket就会设置cookie 所以我们构造页面即可执行jsonp劫持直接登录(一般遇到ticket都会包含用户信息)
无独有偶,我在最近学习相关漏洞时候 也挖到了一个js动态的劫持用户信息,当我删除掉cookie时候发现ticket也没有参数,可以判断js是个动态内容,于是我搜索ticket所在函数 利用jsonp发送信息
Poc大概如下:
<script>
function xxx(data){
alert(data['函数名字'])
}
</script>
<script src="xxx.js"</script>
是可以成功获取cookie的,CORS本质来说就是个支持post版的jsonp
Access-Control-Allow-Origin: *
当这个响应头表示访问允许所有形式的请求,这样也就造成跨域读取敏感信息的漏洞,或者是当Origin字段和返回的response Access-Control-Allow-Origin
是相同的并且可以看到Access-Control-Allow-Credentials: true
这个设置cookie返回的是true
所以可以直接利用 这里面可以直接通过接口利用CrossSiteContentHijacking进行构造poc,所以总结一些常见的形式,可能存在利用点:
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
配置失误,但是几乎无法利用:
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
或者只有一个:
Access-Control-Allow-Origin: *
https://www.hackerpoet.com/index.php/archives/652/
往期推荐 ●●
// 1
// 2
// 3
// 4