Background
最近一直在看一些前端的知识,故以自己的理解写一篇文章来记录,如文章中有什么错误的观点,欢迎师傅们来指正
从源和同源策略开始说起
源的理解我们可以通过一个网址来理解
https://www.baidu.com:80 (web服务器默认都是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 消息头来阻止这种形式的跨域交互。
CORS策略
上文提到 我们在使用<script>嵌入跨域脚本的时候 因为干扰会造成很多麻烦 所以很多浏览器默认会直接限制请求,
跨域请求可能不是浏览器直接拦截掉了,而是跨站请求发起了,但是返回结果被浏览器拦截了,
请求实际上已经发送到了后端服务器。只是无法读取回复而已
但因为安全 很多https到Http的跨域会被火狐
谷歌这种浏览器直接干掉 发送不了请求
所以出现了 跨域资源共享(CORS)
原理:服务器设置Access-Control-Allow-Origin HTTP响应头之后,浏览器将会允许以下跨域请求
由XMLHttpRequest或Fetch等发起的跨域请求;
Web 字体,通过 @font-face 进行跨域调用;
WebGL 贴图;
使用 drawImage 将 Images/video 画面绘制到 canvas;
样式表(使用 CSSOM);
scripts;
值得一提的是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中查看一些满足的条件
CSP
Content Security Policy (CSP)内容安全策略,也是用于帮助解决注入xss漏洞这种的防护,csp可以进行规定允许的域
他的方法是只允许访问可信域 限制一些js的执行
引进lorexxar师傅的一篇文章
一个简单的书写类似如下
header("Content-Security-Policy: default-src 'self'; script-src 'self' https://lorexxar.cn;");
规则指令
指令的配置
那么问题来了 CSP可以bypass吗?
答案是可以的
我们看一条规则
header("Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline' ");
标准的只允许script处理内联脚本 我们的问题是如何bypass self
js linkprefetch预加载资源
表单&跳转
也就是我们使用跨域请求即可 满足上文提到cors的跨域请求都是可以的
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劫持
直接登录
p.s.(一般遇到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.anquanke.com/post/id/86078 同源策略安全攻防
建议阅读:http://www.ruanyifeng.com/blog/2016/04/cors.html
其他跨域方法:https://xz.aliyun.com/t/224
CSPbypass文章:https://paper.seebug.org/423/